Skip to content

Instantly share code, notes, and snippets.

@NicolasT
Created November 27, 2009 19:42
Show Gist options
  • Save NicolasT/244194 to your computer and use it in GitHub Desktop.
Save NicolasT/244194 to your computer and use it in GitHub Desktop.
# No warranties on this code whatsoever...
import ctypes
py_valloc = ctypes.pythonapi.valloc
py_free = ctypes.pythonapi.free
py_memmove = ctypes.pythonapi.memmove
py_mprotect = ctypes.pythonapi.mprotect
NULL = 0x0
PROT_NONE, PROT_READ, PROT_WRITE, PROT_EXEC = 0, 1, 2, 4
class X86Function(object):
__slots__ = '_page', '_fun',
def __init__(self, opcodes, prototype):
self._page = NULL
self._fun = None
opcode_string = ''.join(map(chr, opcodes))
opcode_bytes = ctypes.create_string_buffer(opcode_string)
opcode_size = len(opcode_bytes) # This includes ending \0,
# we might want to drop it
page = py_valloc(opcode_size)
page = ctypes.c_void_p(page)
if page == NULL:
raise RuntimeError('valloc error')
py_memmove(page, opcode_bytes, opcode_size)
if py_mprotect(page, opcode_size, PROT_READ | PROT_EXEC) != 0:
raise RuntimeError('mprotect error')
self._page = page
self._fun = ctypes.cast(page, ctypes.CFUNCTYPE(*prototype))
def __del__(self):
if self._page != NULL:
if py_free:
py_free(self._page)
def __call__(self, *args):
return self._fun(*args)
PUSHL_EBP = 0x55,
MOVL_ESP_EBP = 0x89, 0xe5,
SUBL_NN_ESP = 0x83, 0xec,
MOV_NN_NN_NN_NN_EAX = 0xb8,
LEAVE = 0xc9,
RET = 0xc3,
# The code:
#
# pushl %ebp
# movl %esp,%ebp
# subl $0x08,%esp
# movl 0xdeadbeef,%eax
# leave
# ret
#
# or in C:
# int _() { return 0xdeadbeef; }
#
opcodes = PUSHL_EBP, \
MOVL_ESP_EBP, \
SUBL_NN_ESP, (0x08,), \
MOV_NN_NN_NN_NN_EAX, (0xef, 0xbe, 0xad, 0xde,), \
LEAVE, \
RET
import itertools
opcodes = itertools.chain(*opcodes)
fun = X86Function(opcodes, (ctypes.c_uint32,))
print hex(fun())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment