如何在 Windows 上使用 Python 调用汇编代码
how to call assembler code with Python on Windows
this link 给出了在 Linux 平台上使用 Python 执行 asm 的一个很好的例子,但我不知道如何在 return 上调用具有 return 值的 asm func =17=],你能告诉我怎么做或者给我一个例子吗?
import ctypes
import mmap
buf = mmap.mmap(-1, mmap.PAGESIZE, prot=mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC)
ftype = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int)
fpointer = ctypes.c_void_p.from_buffer(buf)
f = ftype(ctypes.addressof(fpointer))
buf.write(
b'\x8b\xc7' # mov eax, edi
b'\x83\xc0\x01' # add eax, 1
b'\xc3' # ret
)
r = f(42)
print(r)
del fpointer
buf.close()
好吧,Unix 和 Windows OS 之间有很多差异,所以这样的 low-level 东西通常附加到平台上。
让我们从汇编列表开始。
mov eax, <b>edi</b>
add eax, 1
ret
这段代码是专门为 Unix 编写的OS。为什么?因为假设第一个参数使用 edi
寄存器传递。在 Windows 系统中,第一个参数使用 ecx
传递,因此 Windows 系统的正确汇编是:
mov eax, <b>ecx</b>
add eax, 1
ret
因此,修补“已编译”程序集:
asm_function = (
b'\x8b\xc1' # mov eax, ecx
b'\x83\xc0\x01' # add eax, 1
b'\xc3' # ret
)
关于 mmap
. I have tried to make it work, but any attempt ended up with Access Violation message. I even tried to set PAGE_EXECUTE_READWRITE
protection to allocated (using mmap()
) memory using VirtualProtect()
but WinAPI function failed with ERROR_INVALID_PARAMETER
(0x57
) 错误代码。
因为我不能让它与 nmap
一起工作,为什么不向下一层并使用 WinAPI 分配内存?很简单,我们只需要调用 VirtualAlloc()
to allocate memory and RtlMoveMemory()
将“预编译”程序集复制到分配的内存中即可。
我们需要修补默认 argtypes
and restype
of ctypes.windll.kernel32.VirtualAlloc
and ctypes.windll.kernel32.RtlMoveMemory
to match signatures from MSDN. We have to do this, because on x64 systems pointers is 64 bit, but default return value is 32 bit, so address returned by VirtualAlloc()
won't be processed correctly. Special thanks to lifemaker, he/she pointed it out in his answer。
最终代码:
import ctypes
asm_function = (
b'\x8b\xc1' # mov eax, ecx
b'\x83\xc0\x01' # add eax, 1
b'\xc3' # ret
)
# https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc#MEM_COMMIT
MEM_COMMIT = 0x00001000
# https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc#MEM_RESERVE
MEM_RESERVE = 0x00002000
# https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants#PAGE_EXECUTE_READWRITE
PAGE_EXECUTE_READWRITE = 0x40
# https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc
ctypes.windll.kernel32.VirtualAlloc.argtypes = (
ctypes.c_void_p, # LPVOID
ctypes.c_size_t, # SIZE_T
ctypes.c_long, # DWORD
ctypes.c_long, # DWORD
)
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p # LPVOID
memory_buffer = ctypes.windll.kernel32.VirtualAlloc(
0, # lpAddress - NULL
len(asm_function), # dwSize
MEM_COMMIT | MEM_RESERVE, # flAllocationType
PAGE_EXECUTE_READWRITE # flProtect
)
if not memory_buffer: # VirtualAlloc returned NULL
print("VirtualAlloc call failed. Error code:", ctypes.GetLastError())
exit(-1)
c_buffer = ctypes.c_char_p(asm_function)
# https://docs.microsoft.com/en-us/windows/win32/devnotes/rtlmovememory
ctypes.windll.kernel32.RtlMoveMemory.argtypes = (
ctypes.c_void_p, # VOID*
ctypes.c_void_p, # VOID*
ctypes.c_size_t # SIZE_T
)
ctypes.windll.kernel32.RtlMoveMemory(
memory_buffer, # Destination
c_buffer, # Source
len(asm_function) # Length
)
f = ctypes.cast(
memory_buffer,
ctypes.CFUNCTYPE(
ctypes.c_int, # return type
ctypes.c_int # argument type
)
)
r = f(42)
print(r)
P.S. 如果有人能回答如何使用 mmap
.
我将不胜感激
你可以帮助我的国家,检查my profile info。
this link 给出了在 Linux 平台上使用 Python 执行 asm 的一个很好的例子,但我不知道如何在 return 上调用具有 return 值的 asm func =17=],你能告诉我怎么做或者给我一个例子吗?
import ctypes
import mmap
buf = mmap.mmap(-1, mmap.PAGESIZE, prot=mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC)
ftype = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int)
fpointer = ctypes.c_void_p.from_buffer(buf)
f = ftype(ctypes.addressof(fpointer))
buf.write(
b'\x8b\xc7' # mov eax, edi
b'\x83\xc0\x01' # add eax, 1
b'\xc3' # ret
)
r = f(42)
print(r)
del fpointer
buf.close()
好吧,Unix 和 Windows OS 之间有很多差异,所以这样的 low-level 东西通常附加到平台上。
让我们从汇编列表开始。
mov eax, <b>edi</b>
add eax, 1
ret
这段代码是专门为 Unix 编写的OS。为什么?因为假设第一个参数使用 edi
寄存器传递。在 Windows 系统中,第一个参数使用 ecx
传递,因此 Windows 系统的正确汇编是:
mov eax, <b>ecx</b>
add eax, 1
ret
因此,修补“已编译”程序集:
asm_function = (
b'\x8b\xc1' # mov eax, ecx
b'\x83\xc0\x01' # add eax, 1
b'\xc3' # ret
)
关于 mmap
. I have tried to make it work, but any attempt ended up with Access Violation message. I even tried to set PAGE_EXECUTE_READWRITE
protection to allocated (using mmap()
) memory using VirtualProtect()
but WinAPI function failed with ERROR_INVALID_PARAMETER
(0x57
) 错误代码。
因为我不能让它与 nmap
一起工作,为什么不向下一层并使用 WinAPI 分配内存?很简单,我们只需要调用 VirtualAlloc()
to allocate memory and RtlMoveMemory()
将“预编译”程序集复制到分配的内存中即可。
我们需要修补默认 argtypes
and restype
of ctypes.windll.kernel32.VirtualAlloc
and ctypes.windll.kernel32.RtlMoveMemory
to match signatures from MSDN. We have to do this, because on x64 systems pointers is 64 bit, but default return value is 32 bit, so address returned by VirtualAlloc()
won't be processed correctly. Special thanks to lifemaker, he/she pointed it out in his answer。
最终代码:
import ctypes
asm_function = (
b'\x8b\xc1' # mov eax, ecx
b'\x83\xc0\x01' # add eax, 1
b'\xc3' # ret
)
# https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc#MEM_COMMIT
MEM_COMMIT = 0x00001000
# https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc#MEM_RESERVE
MEM_RESERVE = 0x00002000
# https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants#PAGE_EXECUTE_READWRITE
PAGE_EXECUTE_READWRITE = 0x40
# https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc
ctypes.windll.kernel32.VirtualAlloc.argtypes = (
ctypes.c_void_p, # LPVOID
ctypes.c_size_t, # SIZE_T
ctypes.c_long, # DWORD
ctypes.c_long, # DWORD
)
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p # LPVOID
memory_buffer = ctypes.windll.kernel32.VirtualAlloc(
0, # lpAddress - NULL
len(asm_function), # dwSize
MEM_COMMIT | MEM_RESERVE, # flAllocationType
PAGE_EXECUTE_READWRITE # flProtect
)
if not memory_buffer: # VirtualAlloc returned NULL
print("VirtualAlloc call failed. Error code:", ctypes.GetLastError())
exit(-1)
c_buffer = ctypes.c_char_p(asm_function)
# https://docs.microsoft.com/en-us/windows/win32/devnotes/rtlmovememory
ctypes.windll.kernel32.RtlMoveMemory.argtypes = (
ctypes.c_void_p, # VOID*
ctypes.c_void_p, # VOID*
ctypes.c_size_t # SIZE_T
)
ctypes.windll.kernel32.RtlMoveMemory(
memory_buffer, # Destination
c_buffer, # Source
len(asm_function) # Length
)
f = ctypes.cast(
memory_buffer,
ctypes.CFUNCTYPE(
ctypes.c_int, # return type
ctypes.c_int # argument type
)
)
r = f(42)
print(r)
P.S. 如果有人能回答如何使用 mmap
.
你可以帮助我的国家,检查my profile info。