Machine code: Difference between revisions
Content added Content deleted
m (Updated whitespace.) |
m (Updated whitespace, removed comments as language is explanatory enough.) |
||
Line 773: | Line 773: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
{{works with|CPython|3.x}} |
{{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 |
<lang Python>import ctypes |
||
import os |
import os |
||
from ctypes import c_ubyte, c_int |
from ctypes import c_ubyte, c_int |
||
code = bytes([0x8b, 0x44, 0x24, 0x04, 0x03, 0x44, 0x24, 0x08, 0xc3]) |
code = bytes([0x8b, 0x44, 0x24, 0x04, 0x03, 0x44, 0x24, 0x08, 0xc3]) |
||
code_size = len(code) |
code_size = len(code) |
||
# copy code into an executable buffer |
|||
if (os.name == 'posix'): |
if (os.name == 'posix'): |
||
import mmap |
import mmap |
||
executable_map = mmap.mmap(-1, code_size, mmap.MAP_PRIVATE | mmap.MAP_ANON, mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC) |
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) |
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)) |
func_address = ctypes.addressof(c_ubyte.from_buffer(executable_map)) |
||
elif (os.name == 'nt'): |
elif (os.name == 'nt'): |
||
# the mmap module doesn't support protection flags on Windows, so execute VirtualAlloc instead |
|||
code_buffer = ctypes.create_string_buffer(code) |
code_buffer = ctypes.create_string_buffer(code) |
||
PAGE_EXECUTE_READWRITE = 0x40 |
PAGE_EXECUTE_READWRITE = 0x40 |
||
MEM_COMMIT = 0x1000 |
MEM_COMMIT = 0x1000 |
||
executable_buffer_address = ctypes.windll.kernel32.VirtualAlloc(0, code_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE) |
executable_buffer_address = ctypes.windll.kernel32.VirtualAlloc(0, code_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE) |
||
Line 807: | Line 796: | ||
func_address = executable_buffer_address |
func_address = executable_buffer_address |
||
else: |
else: |
||
# for other platforms, we just hope DEP isn't enabled |
|||
code_buffer = ctypes.create_string_buffer(code) |
code_buffer = ctypes.create_string_buffer(code) |
||
func_address = ctypes.addressof(code_buffer) |
func_address = ctypes.addressof(code_buffer) |
||
⚫ | |||
func = prototype(func_address) |
|||
⚫ | |||
⚫ | |||
func = prototype(func_address) # build an actual function from the prototype by specifying the address |
|||
⚫ | |||
⚫ | |||
⚫ | |||
</lang> |
|||
=={{header|Racket}}== |
=={{header|Racket}}== |