Python ReadProcessMemory不返回任何内容

Python ReadProcessMemory不返回任何内容,python,ctypes,readprocessmemory,openprocess,Python,Ctypes,Readprocessmemory,Openprocess,我一直在关注这个问题。我正在尝试读取存储在notepad.exe内存空间中的数据。但是我的get_data函数似乎什么也不返回。我在记事本中存储了一些文本,我想从RAM中检索这些文本,并将其存储在Python中的一个变量中。代码如下: import os from ctypes import * from ctypes.wintypes import * def get_pid(exe_name): x = os.popen('tasklist /FI "ImageName

我一直在关注这个问题。我正在尝试读取存储在
notepad.exe
内存空间中的数据。但是我的
get_data
函数似乎什么也不返回。我在记事本中存储了一些文本,我想从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
>>> 
如何检索数据?

说明:

如果函数失败,则返回值为0(零)。要获取扩展错误信息,请调用

这里有一个小例子

代码00.py:

#/usr/bin/env python
导入系统
将ctypes导入为ct
从ctypes将wintypes作为wt导入
进程\虚拟机\读取=0x0010
def主(*argv):
kernel32=ct.windell(“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\u size\t、ct.POINTER(ct.c\u 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#从过程监控工具获得
np=OpenProcess(进程\u虚拟机\u读取,0,np\u pid)
如果不是np:
打印(“OpenProcess失败:{0:d}”。格式(GetLastError())
返回
buf#U len=0x0F#0xFF#用于显示的较低值
buf=ct.创建字符串缓冲区(buf\u len)
read=ct.c_size_t()
addr=0x00001CF26F20000#也从VMMap获得了一个可读地址,但我不知道实际文本存储的地址
res=ReadProcessMemory(np、addr、buf、buf_len、ct.byref(read))
如果有的话:
打印(“从进程({1:d})地址0x{2:016X}读取({0:d}字节):.format(Read.value,np_-pid,addr))
text=“”
对于范围内的i(读取值):
text+=“0x{0:02X}”。格式(ord(buf[i]))
打印(文本)
其他:
打印(“ReadProcessMemory失败:{0:d}”。格式(GetLastError())
闭合手柄(np)
如果名称=“\uuuuu main\uuuuuuuu”:
打印(“Python{0:s}{1:d}位在{2:s}\n.format(“.”join(sys.version.split(“\n”)中的elem的elem.strip()),如果sys.maxsize>0x100000000,则为64,否则为32,sys.platform))
main(*sys.argv[1:])
打印(“\n完成”)
输出

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q063273381]>“e:\Work\Dev\VEnvs\py\u pc064\u 03.07.06\u test0\Scripts\python.exe”code00.py
win32上的Python 3.7.6(tags/v3.7.6:43364a7ae0,2019年12月19日,00:42:30)[MSC v.1916 64位(AMD64)]64位
从进程(34376)地址0x000001CF26F20000读取(15字节):
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xC2 0x3B 0x78 0x62 0xE6 0xFA 0x00
完成。


更新#0 我不知道记事本是如何在内部组织内存的。我可以假设文本存储在一个缓冲区中(或者更多,可以是每行一个,…),该缓冲区应该位于堆区域。但具体在哪里我不能说。您可以使用工具检查进程内存(我知道CheatEngine可以做到这一点),在内存内容和文本之间进行匹配,然后获取该地址,并将其粘贴到代码中,但我认为这会:

  • 超越脚本的目的(因为脚本用于自动化,用于完成工作而不是用户)
  • 不可靠。缓冲区分配有特定的长度。如果用户继续在记事本中输入内容,最终缓冲区将被填满,并且(在幕后)它将被重新定位,这将(很可能)改变它的地址

总之,我认为这不是一条路。您可以搜索其他方法,例如使用WinAPI将消息(可能是WM_GETTEXT)发送到记事本窗口以获取文本。我不知道具体怎么做,但我记得我能够使用WM_CHAR以编程方式在记事本中插入字符
或者您可以发送Ctrl+a、Ctrl+C,然后获取剪贴板内容。

说明:

如果函数失败,则返回值为0(零)。要获取扩展错误信息,请调用

这里有一个小例子

代码00.py:

#/usr/bin/env python
导入系统
将ctypes导入为ct
从ctypes将wintypes作为wt导入
进程\虚拟机\读取=0x0010
def主(*argv):
kernel32=ct.windell(“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\u size\t、ct.POINTER(ct.c\u 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#从过程监控工具获得
np=OpenProcess(进程\u虚拟机\u读取,0,np\u pid)
如果不是np:
打印(“OpenProcess失败:{0:d}”。格式(GetLastError())
返回
buf#U len=0x0F#0xFF#用于显示的较低值
buf=ct.创建字符串缓冲区(buf\u len)
read=ct.c_size_t()
addr=0x00001CF26F20000#也从VMMap获得了一个可读地址,但我不知道实际文本存储的地址
res=ReadProcessMemory(np、addr、buf、buf_len、ct.byref(read))
如果有的话:
打印(“从进程({1:d})地址0x{2:016X}读取({0:d}字节):.format(Read.value,np_-pid,addr))
text=“”
对于范围内的i(读取值):
text+=“0x{0:02X}”。格式(ord(buf[i]))
打印(文本)
其他:
打印(“ReadProcessMemory失败:{0:d}”。格式(GetLastError())
闭合手柄(np)
如果名称=“\uuuuu main\uuuuuuuu”:
打印({2:s}\n上的Python{0:s}{1:d}位)