用python编写内存扫描程序
(编辑) 很抱歉更改了内容 我已经更改了密码用python编写内存扫描程序,python,Python,(编辑) 很抱歉更改了内容 我已经更改了密码 nameprocess = 'calc.exe' def getpid(): for proc in psutil.process_iter(): if str(nameprocess) in str(proc.name): print nameprocess,'pid = ', proc.pid return proc.pid PID = getpid() PROCESS_
nameprocess = 'calc.exe'
def getpid():
for proc in psutil.process_iter():
if str(nameprocess) in str(proc.name):
print nameprocess,'pid = ', proc.pid
return proc.pid
PID = getpid()
PROCESS_QUERY_INFORMATION = 0x0400
PROCESS_VM_READ = 0x0010
process = windll.kernel32.OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,False,PID)
readprocess = windll.kernel32.ReadProcessMemory
rdbuf = ctypes.c_uint()
bytread = ctypes.c_ulong(0)
for i in range(11):
num = int('0x%08X'%(0x00400000+i),16)
try:
if readprocess(process,hex(num),ctypes.byref(rdbuf),
ctypes.sizeof(rdbuf),ctypes.byref(bytread)):
print hex(num),rdbuf.value
except:None
print '----------------done---------------'
结果输出为:
calc.exe pid = 4552
0x400000 4293587451
0x400001 4293587451
0x400002 4293587451
0x400003 4293587451
0x400004 4293587451
0x400005 4293587451
0x400006 4293587451
0x400007 4293587451
0x400008 4293587451
0x400009 4293587451
0x40000a 4293587451
----------------done---------------
[Finished in 0.2s]
但我希望它看起来像这样
00400000 AE SCAS BYTE PTR ES:[EDI]
00400001 0001 ADD BYTE PTR DS:[ECX],AL
00400003 0000 ADD BYTE PTR DS:[EAX],AL
00400005 0000 ADD BYTE PTR DS:[EAX],AL
00400007 01EE ADD ESI,EBP
00400009 FFEE JMP FAR ESI ; Illegal use of register
0040000B FF01 INC DWORD PTR DS:[ECX]
就像调试器一样。
我希望你们能理解我的意图。
读取processmemory时,is'rdbuf'获取所有信息
我想要什么?它到底从进程中得到了什么?当使用
ReadProcessMemory
时,您正在读取特定内存地址的一些值。根据你所说的,你想要的是反汇编二进制代码。我会使用一个简单但功能强大的用于x86和x64的反汇编程序库。查看一个简单的示例:
>>>Decode(0x400000, 'b800000000'.decode('hex'), Decode32Bits)
[(4194304L, 5L, 'MOV EAX, 0x0', 'b800000000')]
请注意,无需打开进程,只需使用标准文件输入读取二进制文件内容即可
希望有帮助 您的代码中存在严重错误。您正在将
(const char*)“0xde2d6c”
传递到ReadProcessMemory
此处:
if readprocess(process,hex(num),ctypes.byref(rdbuf),
ctypes.sizeof(rdbuf),ctypes.byref(bytread)):
hex
将整数转换成十六进制字符串;因此,您最终从calc.exe
进程中读取字节的位置与Python进程中存储“0xde2d6c”
字符串的位置相同,由于CPython内存分配的工作方式,Python进程中的地址始终相同
您只需要传入地址,即,ctypes.cvoid\u p(num)
您的代码可以更清晰地写成:
base = 0x00400000
for addr in range(base, base + 11):
try:
if readprocess(process, ctypes.cvoid_p(addr), ctypes.byref(rdbuf),
ctypes.sizeof(rdbuf),ctypes.byref(bytread)):
您的代码目前输出了什么?输出是-----------------calc.exe pid=5656 f1e49fff1e4d9fff1e49fff1e4d9fff1e49fff1e4d9fff1e49fff1e4d9fff1e49fff1e4d9fff1e4d9ff--------------------再次打印相同的地址..哦,我感觉向前迈进了一步。我有一个问题要你回答。对未运行的进程进行解扰时。这不意味着我会得到一个文件内存而不是一个虚拟内存吗?这和调试器的PE View intead不一样吗?@KyungHoonBaek我不这么认为,因为你会像调试器一样读取二进制文件来获取ASM代码。非常感谢。我很感激(v)
bytread
是错误的类型和尺寸。它应该是bytread=ctypes.c\u size\u t()
。碰巧,您可以安全地使用c_ulong
,因为所有简单类型在内部都使用16字节的缓冲区,因此不存在写入未分配地址的风险。另外,不声明argtypes
ctypes.sizeof(rdbuf)的值被限制在Cint
的范围内,而不是支持的size\t
范围内。如果您决定正确声明ReadProcessMemory.argtypes
,并定义一个ReadProcessMemory.errcheck
函数,该函数实际上会在出错时引发异常(如ctypes文档中所述),那么请不要使用windell
。使用kernel32=ctypes.windell('kernel32',Use\u last\u error=True)
并通过ctypes.get\u last\u error()
获取失败调用的最后一个错误。