Execute binary code

sturlamolden sturlamolden at yahoo.no
Tue Jan 9 10:04:11 EST 2007


Jorgen Grahn wrote:

> For what it's worth[1], under Unix it /is/ impossible. The only way to bring in
> new code (short of dynamic libraries) is to call exec(2) or its variations,
> and all need a file system object to load the code from.

The x86 processor cannot tell the difference between code segments and
data segments. If the executable code is stored in string, all you need
is a pointer to the string holding the code. You can cast the string
address to a function pointer (possibly through a void* if the compiler
complains), then dereference (call) the function pointer.

Trojans, viruses and JIT compilers do this all the time. Here is an
(untested) example:

static PyObject*
call_code_in_string(PyObject *self, PyObject *args)
{
    char *s;
    int size;
    int arg1, arg2, arg3;
    typedef int (*func_t)(int,int,int);
    func_t pfunc;
    if(!PyArg_ParseTuple(args, "s#(iii)", &s, &size, &arg1, &arg2,
&arg3)) return NULL;
    pfunc = (func_t)((void *)s); /* if it fails, try
memcpy(&pfunc,&s,sizeof(void*)) instead */
    return PyInt_FromLong((long)pfunc(arg1, arg2, arg3));
}

Another possibility would be to just return the string address, and
then make the call possibly using ctypes.

static PyObject*
get_string_addr(PyObject *self, PyObject *args)
{
    char *s;
    int size;
    if(!PyArg_ParseTuple(args, "s#", &s, &size)) return NULL;
    return PyInt_FromLong((long)((void*)s));
}




More information about the Python-list mailing list