首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >python中的ReadProcessMemory读取64位进程内存的麻烦

python中的ReadProcessMemory读取64位进程内存的麻烦
EN

Stack Overflow用户
提问于 2015-11-22 14:09:30
回答 2查看 9.8K关注 0票数 1

当使用ERROR_NOACCESS读取64位进程(Minesweeper)的内存时,我得到了错误代码998 ( ReadProcessMemory )。我在windows 7 64位上使用python 3.5 64位。

奇怪的是,这个错误只发生在较高的地址上,例如0x0000 FF3E 0000。较低的地址,如0x0000 0012 AE40不会抛出错误并返回正确的扫雷数据。

当我在C#.NET中使用几乎相同的代码编写相同的程序并查看相同的地址时,它会工作,并且不会出现错误!

我知道我看到的地址是正确的,因为我可以通过欺骗引擎和VMMap看到它。我不知道这是否相关,但我所看到的更高的地址是Minesweeper中MineSweeper.exe模块的基本模块地址。

为什么python代码不能工作?

Python代码(为较高的地址抛出错误,但对较低的地址使用错误):

代码语言:javascript
运行
复制
import ctypes, struct

pid = 3484  # Minesweeper
processHandle = ctypes.windll.kernel32.OpenProcess(0x10, False, pid)

addr = 0x00000000FF3E0000  # Minesweeper.exe module base address
buffer = (ctypes.c_byte * 8)()
bytesRead = ctypes.c_ulonglong(0)
result = ctypes.windll.kernel32.ReadProcessMemory(processHandle, addr, buffer, len(buffer), ctypes.byref(bytesRead))
e = ctypes.windll.kernel32.GetLastError()

print('result: ' + str(result) + ', err code: ' + str(e))
print('data: ' + str(struct.unpack('Q', buffer)[0]))

ctypes.windll.kernel32.CloseHandle(processHandle)

# Output:
# result: 0, err code: 998
# data: 0

C#.NET代码(64位项目,没有错误):

代码语言:javascript
运行
复制
[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

[DllImport("kernel32.dll")]
static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);

[DllImport("kernel32.dll")]
static extern bool CloseHandle(IntPtr hObject);

static void Main(string[] args)
{
    var pid = 3484;  // Minesweeper
    var processHandle = OpenProcess(0x10, false, pid);

    var addr = 0x00000000FF3E0000;  // Minesweeper.exe module base address
    var buffer = new byte[8];
    IntPtr bytesRead;
    var result = ReadProcessMemory(processHandle, new IntPtr(addr), buffer, (uint)buffer.Length, out bytesRead);

    Console.WriteLine("result: " + result);
    Console.WriteLine("data: " + BitConverter.ToInt64(buffer, 0).ToString());

    CloseHandle(processHandle);

    Console.ReadLine();
}

// Output:
// result: 1
// data: 12894362189
EN

Stack Overflow用户

发布于 2015-11-22 18:08:42

在使用ctypes时,最好是明确的。适当设置argtypesrestype将有助于检查参数的数量和类型,就像C#中的DllImport语句一样。

下面是一个迂腐的例子:

代码语言:javascript
运行
复制
import ctypes as c
from ctypes import wintypes as w

pid = 4568  # Minesweeper

k32 = c.WinDLL('kernel32', use_last_error=True)

OpenProcess = k32.OpenProcess
OpenProcess.argtypes = w.DWORD,w.BOOL,w.DWORD
OpenProcess.restype = w.HANDLE

ReadProcessMemory = k32.ReadProcessMemory
ReadProcessMemory.argtypes = w.HANDLE,w.LPCVOID,w.LPVOID,c.c_size_t,c.POINTER(c.c_size_t)
ReadProcessMemory.restype = w.BOOL

CloseHandle = k32.CloseHandle
CloseHandle.argtypes = [w.HANDLE]
CloseHandle.restype = w.BOOL

processHandle = OpenProcess(0x10, False, pid)

addr = 0x00000000FF900000  # Minesweeper.exe module base address
data = c.c_ulonglong()
bytesRead = c.c_ulonglong()
result = ReadProcessMemory(processHandle, addr, c.byref(data), c.sizeof(data), c.byref(bytesRead))
e = c.get_last_error()

print('result: {}, err code: {}, bytesRead: {}'.format(result,e,bytesRead.value))
print('data: {:016X}h'.format(data.value))

CloseHandle(processHandle)

输出:

代码语言:javascript
运行
复制
result: 1, err code: 0, bytesRead: 8
data: 0000000300905A4Dh

还请注意,您可以传递数据变量的地址,而不是创建缓冲区并用struct模块解压缩它。

票数 2
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33855690

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档