|
|
Line 735: |
Line 735: |
|
Output: |
|
Output: |
|
<pre>19</pre> |
|
<pre>19</pre> |
|
|
|
⚫ |
|
|
|
|
|
⚫ |
{{works with|CPython|3.x}} |
|
|
|
|
⚫ |
The ctypes module is meant for calling existing native code from Python, but you can get it to execute your own bytes with some tricks. The bulk of the code is spent establishing an executable memory area - once that's done, the actual execution takes just a few lines. |
|
|
|
|
⚫ |
<lang Python>import ctypes |
|
⚫ |
|
|
⚫ |
from ctypes import c_ubyte, c_int |
|
|
|
|
⚫ |
code = bytes([0x8b, 0x44, 0x24, 0x04, 0x03, 0x44, 0x24, 0x08, 0xc3]) |
|
|
|
|
⚫ |
|
|
⚫ |
# copy code into an executable buffer |
|
⚫ |
|
|
⚫ |
|
|
⚫ |
executable_map = mmap.mmap(-1, code_size, mmap.MAP_PRIVATE | mmap.MAP_ANON, mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC) |
|
⚫ |
# we must keep a reference to executable_map until the call, to avoid freeing the mapped memory |
|
⚫ |
executable_map.write(code) |
|
⚫ |
# the mmap object won't tell us the actual address of the mapping, but we can fish it out by allocating |
|
⚫ |
# some ctypes object over its buffer, then asking the address of that |
|
⚫ |
func_address = ctypes.addressof(c_ubyte.from_buffer(executable_map)) |
|
⚫ |
|
|
⚫ |
# the mmap module doesn't support protection flags on Windows, so execute VirtualAlloc instead |
|
⚫ |
code_buffer = ctypes.create_string_buffer(code) |
|
⚫ |
PAGE_EXECUTE_READWRITE = 0x40 # Windows constants that would usually come from header files |
|
⚫ |
|
|
⚫ |
executable_buffer_address = ctypes.windll.kernel32.VirtualAlloc(0, code_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE) |
|
⚫ |
if (executable_buffer_address == 0): |
|
⚫ |
print('Warning: Failed to enable code execution, call will likely cause a protection fault.') |
|
⚫ |
func_address = ctypes.addressof(code_buffer) |
|
⚫ |
|
|
⚫ |
ctypes.memmove(executable_buffer_address, code_buffer, code_size) |
|
⚫ |
func_address = executable_buffer_address |
|
⚫ |
|
|
⚫ |
# for other platforms, we just hope DEP isn't enabled |
|
⚫ |
code_buffer = ctypes.create_string_buffer(code) |
|
⚫ |
func_address = ctypes.addressof(code_buffer) |
|
|
|
|
⚫ |
prototype = ctypes.CFUNCTYPE(c_int, c_ubyte, c_ubyte) # build a function prototype from return type and argument types |
|
⚫ |
func = prototype(func_address) # build an actual function from the prototype by specifying the address |
|
⚫ |
|
|
⚫ |
|
|
⚫ |
|
|
|
|
|
|
|
=={{header|PureBasic}}== |
|
=={{header|PureBasic}}== |
Line 830: |
Line 785: |
|
ecode: |
|
ecode: |
|
EndDataSection</lang> |
|
EndDataSection</lang> |
|
|
|
|
⚫ |
|
|
|
|
|
⚫ |
{{works with|CPython|3.x}} |
|
|
|
|
⚫ |
The ctypes module is meant for calling existing native code from Python, but you can get it to execute your own bytes with some tricks. The bulk of the code is spent establishing an executable memory area - once that's done, the actual execution takes just a few lines. |
|
|
|
|
⚫ |
<lang Python>import ctypes |
|
⚫ |
|
|
⚫ |
from ctypes import c_ubyte, c_int |
|
|
|
|
⚫ |
code = bytes([0x8b, 0x44, 0x24, 0x04, 0x03, 0x44, 0x24, 0x08, 0xc3]) |
|
|
|
|
⚫ |
|
|
⚫ |
# copy code into an executable buffer |
|
⚫ |
|
|
⚫ |
|
|
⚫ |
executable_map = mmap.mmap(-1, code_size, mmap.MAP_PRIVATE | mmap.MAP_ANON, mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC) |
|
⚫ |
# we must keep a reference to executable_map until the call, to avoid freeing the mapped memory |
|
⚫ |
executable_map.write(code) |
|
⚫ |
# the mmap object won't tell us the actual address of the mapping, but we can fish it out by allocating |
|
⚫ |
# some ctypes object over its buffer, then asking the address of that |
|
⚫ |
func_address = ctypes.addressof(c_ubyte.from_buffer(executable_map)) |
|
⚫ |
|
|
⚫ |
# the mmap module doesn't support protection flags on Windows, so execute VirtualAlloc instead |
|
⚫ |
code_buffer = ctypes.create_string_buffer(code) |
|
⚫ |
PAGE_EXECUTE_READWRITE = 0x40 # Windows constants that would usually come from header files |
|
⚫ |
|
|
⚫ |
executable_buffer_address = ctypes.windll.kernel32.VirtualAlloc(0, code_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE) |
|
⚫ |
if (executable_buffer_address == 0): |
|
⚫ |
print('Warning: Failed to enable code execution, call will likely cause a protection fault.') |
|
⚫ |
func_address = ctypes.addressof(code_buffer) |
|
⚫ |
|
|
⚫ |
ctypes.memmove(executable_buffer_address, code_buffer, code_size) |
|
⚫ |
func_address = executable_buffer_address |
|
⚫ |
|
|
⚫ |
# for other platforms, we just hope DEP isn't enabled |
|
⚫ |
code_buffer = ctypes.create_string_buffer(code) |
|
⚫ |
func_address = ctypes.addressof(code_buffer) |
|
|
|
|
⚫ |
prototype = ctypes.CFUNCTYPE(c_int, c_ubyte, c_ubyte) # build a function prototype from return type and argument types |
|
⚫ |
func = prototype(func_address) # build an actual function from the prototype by specifying the address |
|
⚫ |
|
|
⚫ |
|
|
⚫ |
|
|
|
|
|
|
=={{header|Racket}}== |
|
=={{header|Racket}}== |