ReadProcessMemory ничего не возвращает - PullRequest
0 голосов
/ 05 августа 2020

Я следил за этим вопросом Stackoverflow здесь . Я пытаюсь прочитать данные, хранящиеся в области памяти notepad.exe. Но моя функция get_data, похоже, ничего не возвращает. У меня есть текст, хранящийся в блокноте, я хотел бы получить этот текст из ОЗУ и сохранить его в переменной в Python. Это код:

import os
from ctypes import *
from ctypes.wintypes import *

def get_pid(exe_name):
    x = os.popen('tasklist /FI "ImageName eq '+process_name+'"').read()
    if not x.find("No tasks are running") >= 0:
        return int(list(filter(None, x[x.find(process_name):-1].split(" ")))[1])
    return -1

def get_data(PROCESS_ID, PROCESS_HEADER_ADDR, STRLEN=255, PROCESS_VM_READ=0x0010):
    k32 = WinDLL('kernel32')
    k32.OpenProcess.argtypes = DWORD,BOOL,DWORD
    k32.OpenProcess.restype = HANDLE
    k32.ReadProcessMemory.argtypes = HANDLE,LPVOID,LPVOID,c_size_t,POINTER(c_size_t)
    k32.ReadProcessMemory.restype = BOOL

    process = k32.OpenProcess(PROCESS_VM_READ, 0, PROCESS_ID)
    buf = create_string_buffer(STRLEN)
    s = c_size_t()
    if k32.ReadProcessMemory(process, PROCESS_HEADER_ADDR, buf, STRLEN, byref(s)):
        return (s.value,buf.raw)


process_name = "notepad.exe"
pid = get_pid(process_name)
process_header_addr = 0x7FF79A1E0000 # address from VMMap

data = get_data(pid, process_header_addr)

когда я запускаю этот код, данных нет, он просто ничего не печатает:

>>> print(data)
None
>>> 

как я могу получить данные?

1 Ответ

0 голосов
/ 06 августа 2020

[MS.Docs]: функция ReadProcessMemory состояния:

В случае сбоя функции возвращаемое значение - 0 (ноль). Чтобы получить расширенную информацию об ошибках, вызовите GetLastError .

Вот небольшой пример.

code00.py :

#!/usr/bin/env python

import sys
import ctypes as ct
from ctypes import wintypes as wt


PROCESS_VM_READ = 0x0010


def main(*argv):
    kernel32 = ct.WinDLL("kernel32")

    OpenProcess = kernel32.OpenProcess
    OpenProcess.argtypes = [wt.DWORD, wt.BOOL, wt.DWORD]
    OpenProcess.restype = wt.HANDLE

    ReadProcessMemory = kernel32.ReadProcessMemory
    ReadProcessMemory.argtypes = [wt.HANDLE, wt.LPCVOID, wt.LPVOID, ct.c_size_t, ct.POINTER(ct.c_size_t)]
    ReadProcessMemory.restype = wt.BOOL

    GetLastError = kernel32.GetLastError
    GetLastError.argtypes = []
    GetLastError.restype = wt.DWORD

    CloseHandle = kernel32.CloseHandle
    CloseHandle.argtypes = [wt.HANDLE]
    CloseHandle.restype = wt.BOOL

    np_pid = 34376  # Got it from a process monitoring tool
    np = OpenProcess(PROCESS_VM_READ, 0, np_pid)
    if not np:
        print("OpenProcess failed: {0:d}".format(GetLastError()))
        return

    buf_len = 0x0F # 0xFF  # Lower value for display purposes
    buf = ct.create_string_buffer(buf_len)
    read = ct.c_size_t()
    addr = 0x00001CF26F20000  # Got a readable address from VMMap as well, but I don't know the one where the actual text is stored

    res = ReadProcessMemory(np, addr, buf, buf_len, ct.byref(read))
    if res:
        print("Read ({0:d} bytes) from process ({1:d}) address 0x{2:016X}:".format(read.value, np_pid, addr))
        text = ""
        for i in range(read.value):
            text += " 0x{0:02X}".format(ord(buf[i]))
        print(text)
    else:
        print("ReadProcessMemory failed: {0:d}".format(GetLastError()))

    CloseHandle(np)


if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    main(*sys.argv[1:])
    print("\nDone.")

Выход :

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q063273381]> "e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py
Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32

Read (15 bytes) from process (34376) address 0x000001CF26F20000:
 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xC2 0x3B 0x78 0x62 0xE6 0xFA 0x00

Done.

Обновление # 0

Я не знаю, как Блокнот организует внутреннюю память. Я могу предположить, что текст хранится в буфере (или, может быть, больше, может быть по одному на строку, ...), который должен находиться в области кучи. Но где именно, сказать не могу. Вы можете проверить память процесса с помощью инструмента (я знаю, что CheatEngine может это сделать), сопоставить содержимое памяти и текст, получить этот адрес и вставить его в код, но я думаю что бы:

  • Обойти саму цель скрипта (поскольку скрипты используются для автоматизации, чтобы выполнять работу вместо пользователя)
  • Не будет надежным. Буфер выделяется с указанной длиной c. Если пользователь продолжает вводить данные в Блокноте , в конечном итоге этот буфер будет заполнен и (за кулисами) он будет перемещен, что (скорее всего) изменит его адрес


В общем, я не думаю, что это путь к go. Вы можете искать альтернативы, например, использовать WinAPI s для отправки сообщений (возможно, WM_GETTEXT ) в окно Блокнот для получения текста. Я точно не знаю, как это сделать, но я помню, что мог программно вставлять символы в Блокнот , используя WM_CHAR .
Или вы можете отправить Ctrl + A , Ctrl + C, а затем получить содержимое буфера обмена.

...