Python3从PID获取进程基址

2024-10-05 14:27:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用Python3在Windows(64位)中获取进程的基址,假设知道PID。 我查看了堆栈上的所有问题,但解决方案是旧的/不起作用的

我假设进程的PID在一个名为PID的变量中

我尝试过的许多代码之一是

PROCESS_ALL_ACCESS = 0x1F0FFF
processHandle = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
modules = win32process.EnumProcessModules(processHandle)
fileName = win32process.GetModuleFileNameEx(processHandle, modules[0])
base_address = win32api.GetModuleHandle(fileName)
processHandle.close()

但是我在GetModuleHandle上得到错误:“不可能找到指定的模块”

谢谢你的帮助


Tags: modulesaccess进程windowsallfilenameprocesspid
1条回答
网友
1楼 · 发布于 2024-10-05 14:27:47

根据[MS.Docs]: GetModuleHandleW function重点是我的):

Retrieves a module handle for the specified module. The module must have been loaded by the calling process.

这意味着它对于当前进程可以正常工作,但是对于任何其他进程,您都会得到未定义的行为,因为您尝试检索:

  1. 来自另一个进程(GetModuleFileNameEx调用)的.dll(或.exe)名称
  2. 上一步(GetModuleHandle调用)中的名称句柄,但在当前进程中(如果已加载),这没有意义

虽然没有关于这个主题的明确文档(或者至少我找不到任何文档),但是句柄是基址。这是一个您也依赖的原则(调用GetModuleHandle),但是您可以直接使用EnumProcessModules返回的值(请看下面的示例,这些值是相同的)

如果您想要严格,可以使用[MS.Docs]: GetModuleInformation function。不幸的是,PyWin32没有导出它,另一种方法是使用[Python 3.Docs]: ctypes - A foreign function library for Python

code00.py

#!/usr/bin/env python3

import sys
import win32api as wapi
import win32process as wproc
import win32con as wcon
import ctypes as ct
from ctypes import wintypes as wt
import traceback as tb


class MODULEINFO(ct.Structure):
    _fields_ = [
        ("lpBaseOfDll", ct.c_void_p),
        ("SizeOfImage", wt.DWORD),
        ("EntryPoint", ct.c_void_p),
    ]

get_module_information_func_name = "GetModuleInformation"
GetModuleInformation = getattr(ct.WinDLL("kernel32"), get_module_information_func_name, getattr(ct.WinDLL("psapi"), get_module_information_func_name))
GetModuleInformation.argtypes = [wt.HANDLE, wt.HMODULE, ct.POINTER(MODULEINFO)]
GetModuleInformation.restype = wt.BOOL


def get_base_address_original(process_handle, module_handle):
    module_file_name = wproc.GetModuleFileNameEx(process_handle, module_handle)
    print("    File for module {0:d}: {1:s}".format(module_handle, module_file_name))
    module_base_address = wapi.GetModuleHandle(module_file_name)
    return module_base_address


def get_base_address_new(process_handle, module_handle):
    module_info = MODULEINFO()
    res = GetModuleInformation(process_handle.handle, module_handle, ct.byref(module_info))
    print("    Result: {0:}, Base: {1:d}, Size: {2:d}".format(res, module_info.lpBaseOfDll, module_info.SizeOfImage))
    if not res:
        print("    {0:s} failed: {1:d}".format(get_module_information_func_name, getattr(ct.WinDLL("kernel32"), "GetLastError")()))
    return module_info.lpBaseOfDll


def main(*argv):
    pid = int(argv[0]) if argv and argv[0].isdecimal() else wapi.GetCurrentProcessId()
    print("Working on pid {0:d}".format(pid))
    process_handle = wapi.OpenProcess(wcon.PROCESS_ALL_ACCESS, False, pid)
    print("Process handle: {0:d}".format(process_handle.handle))
    module_handles = wproc.EnumProcessModules(process_handle)
    print("Loaded modules: {0:}".format(module_handles))
    module_index = 0  # 0 - the executable itself
    module_handle = module_handles[module_index]
    get_base_address_funcs = [
        #get_base_address_original,  # Original behavior moved in a function
        get_base_address_new,
    ]
    for get_base_address in get_base_address_funcs:
        print("\nAttempting {0:s}".format(get_base_address.__name__))
        try:
            module_base_address = get_base_address(process_handle, module_handle)
            print("    Base address: 0x{0:016X} ({1:d})".format(module_base_address, module_base_address))
        except:
            tb.print_exc()
    process_handle.close()
    #input("\nPress ENTER to exit> ")


if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    main(*sys.argv[1:])
    print("\nDone.")

输出

e:\Work\Dev\StackOverflow\q059610466>"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

Working on pid 59608
Process handle: 452
Loaded modules: (140696816713728, 140714582343680, 140714572513280, 140714535354368, 140714547544064, 140713592946688, 140714443341824, 140714557898752, 140714556325888, 140714550362112, 140714414964736, 140714562486272, 140714532798464, 140714555473920, 140714548592640, 140714533322752, 140714531946496, 140714553769984, 140714555670528, 140714558750720, 140714581426176, 140714556129280, 140714546036736, 140714518052864, 140714532601856, 140714524737536, 140714210361344, 1797128192, 140714574151680, 140714535026688, 140714557046784, 140714538172416, 140714531291136, 140714530963456, 140714530766848, 140714530832384, 1796931584, 140714561044480, 140714573299712, 140714215014400, 140714529849344, 1798438912, 140714559995904, 140714167042048)

Attempting get_base_address_new
    Result: 1, Base: 140696816713728, Size: 110592
    Base address: 0x00007FF687C80000 (140696816713728)

Done.

e:\Work\Dev\StackOverflow\q059610466>:: Attempting to run with Task Manager pid
e:\Work\Dev\StackOverflow\q059610466>"e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py 22784
Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32

Working on pid 22784
Process handle: 480
Loaded modules: (140699900903424, 140714582343680, 140714572513280, 140714535354368, 140714547544064, 140714573299712, 140714531946496, 140714550362112, 140714562486272, 140714532798464, 140714530963456, 140714530766848, 140714556981248, 140714557898752, 140714556325888, 140714555473920, 140714365222912, 140714548592640, 140714496753664, 140714533322752, 140714553769984, 140714574151680, 140714535026688, 140714557046784, 140714538172416, 140714581426176, 140714558750720, 140714531291136, 140714530832384, 140714546036736, 140714444521472, 140714567467008, 140714532601856, 140714468966400, 140714452385792, 140714267115520, 140714510843904, 140714478731264, 140713698263040, 140714510254080, 140714556129280, 140714565435392, 140714110091264, 140714491379712, 140714455007232, 140714514382848, 140714459529216, 140714281140224, 140714370859008, 140714471260160, 140714566746112, 140713839362048, 140714555670528, 140714171695104, 140714508615680, 140714514841600, 140714029154304, 140714036625408, 140714329636864, 140714447011840, 140714434691072, 140714470866944, 140714561044480, 140714520870912, 140714469883904, 140714494787584, 140714293592064, 140713999335424, 140714400743424, 140714497605632, 140714502193152, 140714197254144, 140714415030272, 140714035576832, 140714065854464, 140714513006592, 140714529652736, 140714512809984, 140714495049728, 140714038657024, 140714371448832, 140714421911552, 140714325966848, 140714196074496, 140714057924608, 140714058317824, 140714064281600, 140714058121216, 140714519756800, 140714327539712, 140714311614464, 140714501079040, 140714546167808, 140714531422208, 140714531553280, 140714557767680, 140714518052864, 140714524737536, 140714167631872, 140714528669696, 140714331865088, 140714310369280, 140714310238208, 140714520018944, 140714458939392, 2018133999616, 140714401988608, 2018141863936, 140714514644992, 140714454810624, 140714294640640)

Attempting get_base_address_new
    Result: 1, Base: 140699900903424, Size: 1105920
    Base address: 0x00007FF73F9D0000 (140699900903424)

Done.



更新#0

根据[MS.Docs]: MODULEINFO structure备注部分,强调仍然是我的):

The load address of a module is the same as the HMODULE value.

所以,事情似乎很简单

code01.py

#!/usr/bin/env python3

import sys
import win32api as wapi
import win32process as wproc
import win32con as wcon


def main(*argv):
    pid = int(argv[0]) if argv and argv[0].isdecimal() else wapi.GetCurrentProcessId()
    print("Working on pid {0:d}".format(pid))
    process_handle = wapi.OpenProcess(wcon.PROCESS_ALL_ACCESS, False, pid)
    print("  Process handle: {0:d}".format(process_handle.handle))
    module_handles = wproc.EnumProcessModules(process_handle)
    module_handles_count = len(module_handles)
    print("  Loaded modules count: {0:d}".format(module_handles_count))
    module_index = 0  # 0 - the executable itself
    if module_index > module_handles_count:
        module_index = 0
    module_handle = module_handles[module_index]
    module_file_name = wproc.GetModuleFileNameEx(process_handle, module_handle)
    print("  File [{0:s}] (index {1:d}) is loaded at address 0x{2:016X} ({3:d})".format(module_file_name, module_index, module_handle, module_handle))
    process_handle.close()


if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    main(*sys.argv[1:])
    print("\nDone.")

输出

e:\Work\Dev\StackOverflow\q059610466>"e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code01.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

Working on pid 7184
  Process handle: 456
  Loaded modules count: 43
  File [e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe] (index 0) is loaded at address 0x00007FF687C80000 (140696816713728)

Done.

e:\Work\Dev\StackOverflow\q059610466>:: Attempting to run with Task Manager pid
e:\Work\Dev\StackOverflow\q059610466>"e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code01.py 22784
Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32

Working on pid 22784
  Process handle: 624
  Loaded modules count: 111
  File [C:\WINDOWS\system32\taskmgr.exe] (index 0) is loaded at address 0x00007FF73F9D0000 (140699900903424)

Done.

相关问题 更多 >