使用 Python 从进程的内存中读取数据

Doc*_*vil 5 python ctypes process python-2.7

我试图通过输入进程名称从进程的内存中读取数据,然后使用 psutil 查找 PID。到目前为止,我有这个:

import ctypes
from ctypes import *
from ctypes.wintypes import *
import win32ui
import psutil # install, not a default module
import sys

# input process name
nameprocess = "notepad.exe"

# find pid
def getpid():
    for proc in psutil.process_iter():
        if proc.name() == nameprocess:
            return proc.pid

PROCESS_ID = getpid()

if PROCESS_ID == None:
    print "Process was not found"
    sys.exit(1)


# read from addresses
STRLEN = 255

PROCESS_VM_READ = 0x0010
process = windll.kernel32.OpenProcess(PROCESS_VM_READ, 0, PROCESS_ID)
readProcMem = windll.kernel32.ReadProcessMemory
buf = ctypes.create_string_buffer(STRLEN)

for i in range(1,100): 
    if readProcMem(process, hex(i), buf, STRLEN, 0):
        print buf.raw
Run Code Online (Sandbox Code Playgroud)


如果我做对了,最后一个 for 循环应该读取并打印进程中前 100 个地址的内容。唯一的问题是,输出看起来完全是胡言乱语。


这里有两个问题:首先,我是否真的以这种方式读取所选进程中的地址?其次,如果可能有某种结束地址,我如何确定我应该在循环中走多长时间?

Mar*_*nen 7

我没有安装psutil,只是使用 Task Manager 和SysInternals VMMap提取了一个进程 ID 和有效的虚拟地址。数字当然会有所不同。

ctypes 的良好做法是通过.argtypesand定义参数类型和返回值.restype。获取您自己的 kernel32 库实例,因为更改缓存windll.kernel32实例的属性可能会导致其他使用 ctypes 和 kernel32 的模块出现问题。

您需要一个有效的虚拟地址。为了回答你的第二个问题,我认为 VMMap 证明有办法做到这一点。拿起一份 Windows Internals 来学习这些技术。

from ctypes import *
from ctypes.wintypes import *

PROCESS_ID = 9476 # From TaskManager for Notepad.exe
PROCESS_HEADER_ADDR = 0x7ff7b81e0000 # From SysInternals VMMap utility

# read from addresses
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)):
    print(s.value,buf.raw)
Run Code Online (Sandbox Code Playgroud)

输出(注意“MZ”程序头的开始):

255 b'MZ\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xff\xff\x00\x00\xb8\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x00\x00\x00\x0e\x1f\xba\x0e\x00\xb4\t\xcd!\xb8\x01L\xcd!This program cannot be run in DOS mode.\r\r\n$\x00\x00\x00\x00\x00\x00\x00\xd0\x92\xa7\xd1\x94\xf3\xc9\x82\x94\xf3\xc9\x82\x94\xf3\xc9\x82\x9d\x8bZ\x82\x8a\xf3\xc9\x82\xfb\x97\xca\x83\x97\xf3\xc9\x82\xfb\x97\xcd\x83\x83\xf3\xc9\x82\xfb\x97\xcc\x83\x91\xf3\xc9\x82\xfb\x97\xc8\x83\x8f\xf3\xc9\x82\x94\xf3\xc8\x82\x82\xf2\xc9\x82\xfb\x97\xc1\x83\x8d\xf3\xc9\x82\xfb\x976\x82\x95\xf3\xc9\x82\xfb\x97\xcb\x83\x95\xf3\xc9\x82Rich\x94\xf3\xc9\x82\x00\x00\x00\x00\x00\x00\x00\x00PE\x00\x00d\x86\x06\x00^\'\x0f\x84\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x00"'
Run Code Online (Sandbox Code Playgroud)

这是VMMap的截图,显示了notepad.exe的头地址:

VMMap 截图

这是与程序输出匹配的 notepad.exe 内容的十六进制转储屏幕截图:

notepad.exe 二进制文件的 hedump