Skip to content

Instantly share code, notes, and snippets.

@markrwilliams
Created February 25, 2015 08:08
Show Gist options
  • Save markrwilliams/01f1d9ff1084b7ea8cc4 to your computer and use it in GitHub Desktop.
Save markrwilliams/01f1d9ff1084b7ea8cc4 to your computer and use it in GitHub Desktop.
from spyce import (Rights, CAP_READ, CAP_LOOKUP, CAP_SEEK, CAP_MMAP,
CAP_FSTAT, CAP_MMAP_RX, enterCapabilityMode)
import imp
import re
import cffi
import ctypes
import os
import sys
from fsnix import fs
ffi = cffi.FFI()
ffi.cdef('''
static const int RTLD_NOW;
static const int RTLD_LAZY;
struct __dlfunc_arg {
...;
};
typedef void (*dlfunc_t)(struct __dlfunc_arg);
typedef void (*initmodule_func_t)(void);
void *
fdlopen(int fd, int mode);
dlfunc_t
dlfunc(void * restrict handle, const char * restrict symbol);
void *
dlsym(void * restrict handle, const char * restrict symbol);
char *
dlerror(void);
initmodule_func_t
convert(dlfunc_t f);
void
invoke(dlfunc_t f);
''')
lib = ffi.verify('''
#include <dlfcn.h>
typedef void (*initmodule_func_t)(void);
initmodule_func_t
convert(dlfunc_t f)
{
return (initmodule_func_t)f;
}
void
invoke(dlfunc_t f)
{
initmodule_func_t initfunc;
initfunc = (initmodule_func_t)f;
initfunc();
}
''')
ADDR_EXTRACTOR = re.compile('<.+ 0x((?:[0-9]|[A-H]|[a-h])+)>')
def _addr_of(cdata):
match = ADDR_EXTRACTOR.search(repr(cdata))
if not match:
raise RuntimeError("could not hack out an addr for %r" % cdata)
return int(match.group(1), 16)
fdlopen = lib.fdlopen
dlfunc = lib.dlfunc
def _import_so(path_fd, module_fn, module_name):
imp.acquire_lock()
try:
so_fd = fs.openat(path_fd, module_fn, os.O_RDONLY)
loaded_so = fdlopen(so_fd, lib.RTLD_NOW)
if loaded_so == ffi.NULL:
raise RuntimeError(ffi.string(lib.dlerror()))
initmodule_pointer = dlfunc(loaded_so, 'init%s' % module_name)
initmodule = ctypes.PYFUNCTYPE(None)(_addr_of(initmodule_pointer))
initmodule()
return sys.modules[module_name]
finally:
imp.release_lock()
def test():
dynload = os.open("/usr/local/lib/python2.7/lib-dynload/",
os.O_RDONLY)
Rights([CAP_READ, CAP_LOOKUP, CAP_FSTAT, CAP_SEEK,
CAP_MMAP_RX, CAP_MMAP]).limitFile(dynload)
enterCapabilityMode()
mmap = _import_so(dynload,
"mmap.so", 'mmap')
print mmap.mmap(-1, 1024)
test()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment