Я изучаю книгу "Python Grey Hat"
, это одна из моих функций, я долго искал эту проблему или не решался.
def func_resolve(self,dll,function):
GetModuleHandle = kernel32.GetModuleHandleA
GetModuleHandle.argtypes = [c_char_p]
GetModuleHandle.restype = c_void_p
handle = GetModuleHandle(dll)
print(handle)
GetProcAddress = kernel32.GetProcAddress
GetProcAddress.argtypes = [c_void_p,c_char_p]
GetProcAddress.restype = c_void_p
address = GetProcAddress(handle,function)
print(address)
Мое значение дескриптора вывода - 140707194077184
, значение адреса - 140707194386736
Я использую OllyDbg для просмотра адреса функции wprintf в msvcrt.dll, является 0x73D178A0
, но значение адреса преобразуется в шестнадцатеричное, также намного больше, чем 0x73D178A0
, надеюсь, что кто-то может помоги мне, спасибо
Никогда не отвечая на мой комментарий, я нашел причину. От OllyDbg (акцент мой):
OllyDbg - это 32-разрядный ассемблер, анализирующий отладчик для Microsoft Windows .
Это означает, что он может загружать (работать с) 32-битные процессы (и/или DLL) только. Адрес wprintf подтверждает это (0x 73D178A0 - 32 бит, поскольку он имеет (самое большее) 8 шестнадцатеричных цифр).
С другой стороны, в Python вы получаете (намного) большие значения для указателей или адресов (например, handler = 140707194077184 (0x 7FF8F256B930)), которые не соответствуют 32-битовому диапазону, поэтому 64 бит. Для получения дополнительной информации о том, как запустить Python-архитектуру, проверьте [SO]: Как определить, выполняется ли моя оболочка python в 32-битном или 64-битном режиме на OS X? (Ответ @CristiFati) (даже если вопрос касается OSX, Win также покрывается).
Итак, какой улов? Это [MS.Docs]: редиректор файловой системы, который смутил вас в отношении msvcr (t ###). Dll location:
Используя инструмент, созданный для 32-разрядных и 64-битных, которые вы можете запускать параллельно (я использую Dependency Walker), вы можете увидеть различия.
Возвращаемое значение - дескриптор Windows. Значение большое, потому что вы используете 64-битный Python. Значение не имеет значения, если вы правильно указали свои ctypes. Этот код будет работать Python 2 или 3, 32- или 64-бит:
from __future__ import print_function
import sys
from ctypes import *
print(sys.version)
kernel32 = WinDLL('kernel32')
GetModuleHandle = kernel32.GetModuleHandleW
GetModuleHandle.argtypes = [c_wchar_p]
GetModuleHandle.restype = c_void_p
GetProcAddress = kernel32.GetProcAddress
GetProcAddress.argtypes = [c_void_p,c_char_p]
GetProcAddress.restype = c_void_p
handle = GetModuleHandle(u'user32')
address = GetProcAddress(handle,b'MessageBeep')
print(hex(address))
MessageBeep = WINFUNCTYPE(c_int,c_uint)(address)
MessageBeep(0)
Выход с двумя Pythons, которые я установил (звуковой сигнал воспроизводится каждый раз):
C:\>py -2 test.py
2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:19:30) [MSC v.1500 32 bit (Intel)]
0x756e56d0
C:\>py -3 test.py
3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)]
0x7fff6ca29a40
GetModuleHandleW
с Unicodec_wchar_p
, особенно в Python 3, где строки являются Unicode. Кроме того, вы должны определять прототипы только один раз для указателей на функцииkernel32
, а не каждый раз, когда вы вызываетеfunc_resolve
. Это работает, потому что когда вы в первый раз просматриваете атрибутGetModuleHandleW
вkernel32
, он кэширует созданный объект-указатель функции, поэтому при последующем доступе используется тот же объект.