Python3 получить базовый адрес процесса из PID - PullRequest
2 голосов
/ 06 января 2020

Я пытаюсь получить базовый адрес процесса в Windows (64-битном) с Python3, предполагая, что известен 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: «Невозможно найти указанный модуль».

Спасибо за помощь.

1 Ответ

2 голосов
/ 07 января 2020

Согласно [MS.Docs]: функция GetModuleHandleW ( выделение принадлежит мне):

Извлекает дескриптор модуля для указанного модуля. Модуль должен быть загружен вызывающим процессом .

Это означает, что он будет работать нормально для текущего процесса, но для любого другого вы получите Неопределенное поведение , поскольку вы пытаетесь получить:

  1. Имя .dll (или .exe ) из другого процесса ( GetModuleFileNameEx). вызов)
  2. Дескриптор имени на предыдущем шаге ( GetModuleHandle вызов) , но в текущем процессе (если загружен), что не имеет смысла

Хотя нет четкой документации по этой теме c (или, по крайней мере, я не смог ее найти) , дескриптор является базовым адресом. Это принцип, на который вы также полагаетесь (вызывая GetModuleHandle ), но вы можете напрямую использовать значения, возвращаемые EnumProcessModules (посмотрите на приведенный ниже пример, значения те же).

Если вы хотите быть строгим, вы можете использовать [MS.Docs]: функция GetModuleInformation . К сожалению, это не экспортируется PyWin32 , и альтернативой является использование [Python 3.Docs]: ctypes - библиотека сторонних функций для 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 ( Замечания раздел, выделение все еще мое):

Адрес загрузки модуля совпадает со значением HMODULE .

Итак, все выглядит довольно просто.

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.
...