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 # Windows constants that would usually come from header files
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)
prototype = ctypes.CFUNCTYPE(c_int, c_ubyte, c_ubyte)

func = prototype(func_address)
prototype = ctypes.CFUNCTYPE(c_int, c_ubyte, c_ubyte) # build a function prototype from return type and argument types
res = func(7, 12)
func = prototype(func_address) # build an actual function from the prototype by specifying the address
print(res)</lang>
res = func(7,12)
print(res)
</lang>


=={{header|Racket}}==
=={{header|Racket}}==