ReadProcessMemory returns 无
ReadProcessMemory returns nothing
我正在关注这个 Whosebug 问题 here。我正在尝试读取存储在 notepad.exe
内存 space 中的数据。但是我的 get_data
函数似乎 return 什么都没有。我在记事本中存储了一些文本,我想从 RAM 中检索该文本并将其存储在 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
>>>
如何检索数据?
[MS.Docs]: ReadProcessMemory function 状态:
If the function fails, the return value is 0 (zero). To get extended error information, call 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\Whosebug\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
我不知道 Notepad 是如何在内部组织内存的。我可以假设文本存储在一个缓冲区中(或者可能更多,每行一个,...),它应该位于堆区域中。但是具体在哪里我也说不准。您可以使用工具检查进程内存(我知道 CheatEngine 可以做到这一点)在内存内容和文本之间进行匹配,并获取该地址,并将其粘贴到代码中,但我认为那会:
- 打败脚本的真正目的(因为脚本用于自动化,代替用户完成工作)
- 不可靠。缓冲区分配有特定长度。如果用户继续在 记事本 中输入内容,最终该缓冲区将变满并且(在幕后)它将被重新定位,这将(很可能)改变其地址
总而言之,我不认为这是要走的路。您可以搜索替代方案,例如使用 WinAPIs 将消息(可能是 WM_GETTEXT)发送到 Notepad window 获取文本。我不知道具体怎么做,但我记得我能够使用 WM_CHAR 以编程方式在 Notepad 中插入字符。
或者你可以发送Ctrl + A、Ctrl + C,然后获取剪贴板内容。
我正在关注这个 Whosebug 问题 here。我正在尝试读取存储在 notepad.exe
内存 space 中的数据。但是我的 get_data
函数似乎 return 什么都没有。我在记事本中存储了一些文本,我想从 RAM 中检索该文本并将其存储在 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
>>>
如何检索数据?
[MS.Docs]: ReadProcessMemory function 状态:
If the function fails, the return value is 0 (zero). To get extended error information, call 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\Whosebug\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
我不知道 Notepad 是如何在内部组织内存的。我可以假设文本存储在一个缓冲区中(或者可能更多,每行一个,...),它应该位于堆区域中。但是具体在哪里我也说不准。您可以使用工具检查进程内存(我知道 CheatEngine 可以做到这一点)在内存内容和文本之间进行匹配,并获取该地址,并将其粘贴到代码中,但我认为那会:
- 打败脚本的真正目的(因为脚本用于自动化,代替用户完成工作)
- 不可靠。缓冲区分配有特定长度。如果用户继续在 记事本 中输入内容,最终该缓冲区将变满并且(在幕后)它将被重新定位,这将(很可能)改变其地址
总而言之,我不认为这是要走的路。您可以搜索替代方案,例如使用 WinAPIs 将消息(可能是 WM_GETTEXT)发送到 Notepad window 获取文本。我不知道具体怎么做,但我记得我能够使用 WM_CHAR 以编程方式在 Notepad 中插入字符。
或者你可以发送Ctrl + A、Ctrl + C,然后获取剪贴板内容。