Start to implement proper build script to compile windows binaries using wine

This commit is contained in:
Oleksii Shevchuk 2016-10-21 19:21:54 +03:00
parent 076d3d2438
commit 1a17eb93a3
7 changed files with 281 additions and 83 deletions

10
.gitignore vendored
View File

@ -30,15 +30,9 @@ client/sources/resources/libraryx86.zip
client/android_sources/bin client/android_sources/bin
client/android_sources/.buildozer client/android_sources/.buildozer
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
*.pyc
*.pyo
__pycache__/ __pycache__/
client/**/*.py[cod]
pupy/*.py[cod]
pupy/pupylib/**/*.py[cod]
pupy/modules/*.py[cod]
pupy/modules/lib/*.py[cod]
pupy/modules/lib/**/*.py[cod]
pupy/network/**/*.pyc
pupy/scriptlets/**/*.pyc
pupy/pupy.conf pupy/pupy.conf
# do not ignore package & templates files # do not ignore package & templates files

View File

@ -1,58 +1,82 @@
CC=cl.exe BUILDENV ?= $(PWD)/buildenv
BUILDENV_READY = $(BUILDENV)/.ready
PYTHONPATH=C:\\Python27 PYTHONPATH := C:\\Python27
PYTHON=python.exe
TEMPLATE_OUTPUT_PATH=../../pupy/payload_templates TEMPLATE_OUTPUT_PATH=../../pupy/payload_templates
ifndef ARCH ifndef ARCH
$(error You must specify an architecture.) $(error You must specify an architecture - win64 or win32)
else
ifeq "$(ARCH)" "x64"
CFLAGS:=$(CFLAGS) /DWIN_X64 /D_WIN64
else
CFLAGS:=$(CFLAGS) /DWIN_X86
endif endif
CC := $(BUILDENV)/$(ARCH)/cl.sh
PYTHON := $(BUILDENV)/$(ARCH)/python.sh -O
ifeq "$(ARCH)" "win64"
CFLAGS:=$(CFLAGS) /DWIN_X64 /D_WIN64 /nologo
PPARCH := x64
else
CFLAGS:=$(CFLAGS) /DWIN_X86 /nologo
PPARCH := x86
endif endif
ifdef DEBUG ifdef DEBUG
DEBUG_ADD :=DEBUG DEBUG_ADD :=DEBUG
CFLAGS := $(CFLAGS) /DDEBUG CFLAGS := $(CFLAGS) /DDEBUG
LINKER_OPTS := LINKER_OPTS :=
PPARCH := $(PPARCH)d
else else
DEBUG_ADD := DEBUG_ADD :=
LINKER_OPTS :=/link /subsystem:windows /ENTRY:mainCRTStartup LINKER_OPTS :=/link /subsystem:windows /ENTRY:mainCRTStartup
PPARCH := $(PPARCH)
endif endif
PYOBJS=_memimporter.obj MyLoadLibrary.obj Python-dynload.obj pupy_load.obj pupy.obj base_inject.obj PYOBJS := \
COMMON_OBJS=resources_bootloader_pyc.obj resources_python27_dll.obj MemoryModule.obj resources_library_compressed_string_txt.obj actctx.obj list.obj thread.obj remote_thread.obj LoadLibraryR.obj resources_msvcr90_dll.obj _memimporter.obj \
MyLoadLibrary.obj \
Python-dynload.obj \
pupy_load.obj \
pupy.obj \
base_inject.obj
all: $(TEMPLATE_OUTPUT_PATH)/pupy$(ARCH).exe $(TEMPLATE_OUTPUT_PATH)/pupy$(ARCH).dll COMMON_OBJS := \
resources_bootloader_pyc.obj \
resources_python27_dll.obj \
MemoryModule.obj \
resources_library_compressed_string_txt.obj \
actctx.obj list.obj thread.obj remote_thread.obj \
LoadLibraryR.obj resources_msvcr90_dll.obj
resources/library_compressed_string_$(ARCH).txt: gen_library_compressed_string.py resources/library$(ARCH).zip all: $(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH).exe $(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH).dll
$(BUILDENV_READY):
./buildenv.sh $(BUILDENV)
resources/library_compressed_string.txt: gen_library_compressed_string.py resources/library.zip $(BUILDENV_READY)
$(PYTHON) gen_library_compressed_string.py $(PYTHON) gen_library_compressed_string.py
resources/library_compressed_string.txt: resources/library_compressed_string_$(ARCH).txt resources/library.zip: build_library_zip.py $(BUILDENV_READY)
cp $< $@ $(PYTHON) build_library_zip.py
resources_library_compressed_string_txt.c: gen_resource_header.py resources/library_compressed_string.txt resources/library${ARCH}.zip resources_library_compressed_string_txt.c: gen_resource_header.py resources/library_compressed_string.txt resources/library.zip $(BUILDENV_READY)
$(PYTHON) gen_resource_header.py resources/library_compressed_string.txt $(PYTHON) gen_resource_header.py resources/library_compressed_string.txt
resources/bootloader.pyc: gen_python_bootloader.py ../../pupy/packages/all/pupyimporter.py ../../pupy/pp.py resources/bootloader.pyc: ../../pupy/packages/all/pupyimporter.py ../../pupy/pp.py gen_python_bootloader.py $(BUILDENV_READY)
$(PYTHON) gen_python_bootloader.py $(DEBUG_ADD) $(PYTHON) gen_python_bootloader.py $(DEBUG_ADD)
resources_bootloader_pyc.c: gen_resource_header.py resources/bootloader.pyc resources_bootloader_pyc.c: resources/bootloader.pyc gen_resource_header.py $(BUILDENV_READY)
$(PYTHON) $+ $(PYTHON) gen_resource_header.py $<
resources/python27.dll: resources/python27_$(ARCH).dll resources/python27.dll: $(BUILDENV)/$(ARCH)/drive_c/Python27/python27.dll $(BUILDENV_READY)
cp $< $@ cp $< $@
resources_python27_dll.c: gen_resource_header.py resources/python27.dll resources/msvcr90.dll: $(BUILDENV)/$(ARCH)/drive_c/Python27/msvcr90.dll $(BUILDENV_READY)
$(PYTHON) $+
resources/msvcr90.dll: resources/msvcr90_$(ARCH).dll
cp $< $@ cp $< $@
resources_msvcr90_dll.c: gen_resource_header.py resources/msvcr90.dll resources_python27_dll.c: resources/python27.dll gen_resource_header.py $(BUILDENV_READY)
$(PYTHON) $+ $(PYTHON) gen_resource_header.py $<
resources_msvcr90_dll.c: resources/msvcr90.dll gen_resource_header.py $(BUILDENV_READY)
$(PYTHON) gen_resource_header.py $<
$(PYOBJS): %.obj: %.c $(PYOBJS): %.obj: %.c
$(CC) /c $(CFLAGS) /I$(PYTHONPATH)/include $< $(CC) /c $(CFLAGS) /I$(PYTHONPATH)/include $<
@ -66,10 +90,10 @@ main_exe.obj: main_exe.c
ReflectiveLoader.obj: ReflectiveLoader.c ReflectiveLoader.obj: ReflectiveLoader.c
$(CC) /c $(CFLAGS) /DREFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN /DREFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR /O2 /Ob1 $< $(CC) /c $(CFLAGS) /DREFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN /DREFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR /O2 /Ob1 $<
$(TEMPLATE_OUTPUT_PATH)/pupy$(ARCH).exe: main_exe.obj $(PYOBJS) $(COMMON_OBJS) $(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH).exe: main_exe.obj $(PYOBJS) $(COMMON_OBJS)
$(CC) $(CFLAGS) $+ /Fe$@ $(LINKER_OPTS) $(CC) $(CFLAGS) $+ /Fe$@ $(LINKER_OPTS)
$(TEMPLATE_OUTPUT_PATH)/pupy$(ARCH).dll: main_reflective.obj $(PYOBJS) ReflectiveLoader.obj $(COMMON_OBJS) $(TEMPLATE_OUTPUT_PATH)/pupy$(PPARCH).dll: main_reflective.obj $(PYOBJS) ReflectiveLoader.obj $(COMMON_OBJS)
$(CC) $(CFLAGS) $+ /Fe$@ /LD $(CC) $(CFLAGS) $+ /Fe$@ /LD
.PHONY: clean .PHONY: clean
@ -79,8 +103,15 @@ ifneq "$(QUICK)" "1"
endif endif
clean: clean:
rm *.obj rm -f *.obj
rm *.exp rm -f *.pyo
rm pupy$(ARCH).exe rm -f *.pyc
rm pupy$(ARCH).dll rm -f *.txt
rm resources/bootloader.pyc rm -f *_txt.c
rm -f resources/*.pyo
rm -f resources/*.pyc
rm -f resources/*.txt
rm -f resources/*_txt.c
rm -f resources/library.zip
rm -f resources/python27.dll
rm -f resources/msvcr90.dll

5
client/sources/build.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
make -f Makefile.linux ARCH=win32 clean
make -f Makefile.linux ARCH=win32
make -f Makefile.linux ARCH=win64 clean
make -f Makefile.linux ARCH=win64

View File

@ -0,0 +1,58 @@
import sys
from distutils.core import setup
import os
from glob import glob
import zipfile
import shutil
sys.path.insert(0, os.path.join('resources','library_patches'))
sys.path.insert(0, os.path.join('..','..','pupy'))
import pp
import additional_imports
import Crypto
all_dependencies=set(
[
x.split('.')[0] for x,m in sys.modules.iteritems() if not '(built-in)' in str(m) and x != '__main__'
] + [
'Crypto', 'yaml', 'rpyc', 'pyasn1', 'rsa'
]
)
all_dependencies = list(set(all_dependencies))
all_dependencies.remove('pupy')
all_dependencies.remove('additional_imports')
print "ALLDEPS: ", all_dependencies
zf = zipfile.ZipFile(os.path.join('resources','library.zip'), mode='w', compression=zipfile.ZIP_DEFLATED)
zf.write('C:\\Python27\\Lib\\site-packages\\pywin32_system32\\pywintypes27.dll', 'pywintypes27.dll')
try:
for dep in all_dependencies:
mdep = __import__(dep)
print "DEPENDENCY: ", dep, mdep
if hasattr(mdep, '__path__'):
print('adding package %s'%dep)
path, root = os.path.split(mdep.__path__[0])
for root, dirs, files in os.walk(mdep.__path__[0]):
for f in list(set([x.rsplit('.',1)[0] for x in files])):
found=False
for ext in ('.pyc', '.pyd', '.pyo', '.py', '.dll', '.so'):
if ext == '.py' and found:
continue
if os.path.exists(os.path.join(root,f+ext)):
zipname = os.path.join(root[len(path)+1:], f.split('.', 1)[0] + ext)
print('adding file : {}'.format(zipname))
zf.write(os.path.join(root, f+ext), zipname)
found=True
else:
if '<memimport>' in mdep.__file__:
continue
_, ext = os.path.splitext(mdep.__file__)
print('adding %s -> %s'%(mdep.__file__, dep+ext))
zf.write(mdep.__file__, dep+ext)
finally:
zf.close()

117
client/sources/buildenv.sh Executable file
View File

@ -0,0 +1,117 @@
#!/bin/sh
unset WINEARCH WINEPREFIX
set -e
SELF=`readlink -f $0`
CWD=`dirname $0`
SOURCES=`readlink -f $CWD/../../`
PYTHON64="https://www.python.org/ftp/python/2.7.12/python-2.7.12.amd64.msi"
PYTHON32="https://www.python.org/ftp/python/2.7.12/python-2.7.12.msi"
PYTHONVC="https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi"
PYCRYPTO32="http://www.voidspace.org.uk/downloads/pycrypto26/pycrypto-2.6.win32-py2.7.exe"
PYCRYPTO64="http://www.voidspace.org.uk/downloads/pycrypto26/pycrypto-2.6.win-amd64-py2.7.exe"
PACKAGES="rpyc psutil pyaml rsa pefile image rsa netaddr pypiwin32"
BUILDENV=${1:-`pwd`/buildenv}
if [ -f $BUILDENV/.ready ]; then
echo "Buildenv at $BUILDENV already prepared"
exit 0
fi
WINE=${WINE:-wine}
WINE32="$BUILDENV/win32"
WINE64="$BUILDENV/win64"
DOWNLOADS="$BUILDENV/downloads"
mkdir -p "$BUILDENV"
mkdir -p "$DOWNLOADS"
WINEARCH=win32 WINEPREFIX=$WINE32 wineboot
if [ ! $? -eq 0 ]; then
echo "apt-get install wine32"
exit 1
fi
WINEARCH=win64 WINEPREFIX=$WINE64 wineboot
if [ ! $? -eq 0 ]; then
echo "apt-get install wine64"
exit 1
fi
for dist in $PYTHON32 $PYTHON64 $PYTHONVC $WINETRICKS; do
wget -cP $DOWNLOADS $dist
done
for prefix in $WINE32 $WINE64; do
rm -f $prefix/dosdevices/d:
rm -f $prefix/dosdevices/e:
ln -s ../../downloads $prefix/dosdevices/d:
ln -s $SOURCES $prefix/dosdevices/e:
done
for prefix in $WINE32 $WINE64; do
[ ! -f $prefix/drive_c/.vc ] && \
WINEPREFIX=$prefix msiexec /i D:\\VCForPython27.msi /q && \
touch $prefix/drive_c/.vc
done
[ ! -f $WINE32/drive_c/.python ] && \
WINEPREFIX=$WINE32 msiexec /i D:\\python-2.7.12.msi /q && \
touch $WINE32/drive_c/.python
[ ! -f $WINE64/drive_c/.python ] && \
WINEPREFIX=$WINE64 msiexec /i D:\\python-2.7.12.amd64.msi /q && \
touch $WINE64/drive_c/.python
for prefix in $WINE32 $WINE64; do
WINEPREFIX=$prefix wine python -m pip install --upgrade pip
WINEPREFIX=$prefix wine pip install --upgrade $PACKAGES
done
WINEPREFIX=$WINE32 wine easy_install -Z $PYCRYPTO32
WINEPREFIX=$WINE64 wine easy_install -Z $PYCRYPTO64
cat >$WINE32/python.sh <<EOF
#!/bin/sh
unset WINEARCH
export WINEPREFIX=$WINE32
exec wine python.exe "\$@"
EOF
chmod +x $WINE32/python.sh
cat >$WINE32/cl.sh <<EOF
#!/bin/sh
export WINEPREFIX=$WINE32
export VCINSTALLDIR="C:\\\\Program Files\\\\Common Files\\\\Microsoft\\\\Visual C++ for Python\\\\9.0\\\\VC"
export WindowsSdkDir="C:\\\\Program Files\\\\Common Files\\\\Microsoft\\\\Visual C++ for Python\\\\9.0\\\\WinSDK"
export INCLUDE="\$VCINSTALLDIR\\\\Include;\$WindowsSdkDir\\\\Include"
export LIB="\$VCINSTALLDIR\\\\Lib;\$WindowsSdkDir\\\\Lib"
export LIBPATH="\$VCINSTALLDIR\\\\Lib;\$WindowsSdkDir\\\\Lib"
exec wine "\$VCINSTALLDIR\\\\bin\\\\cl.exe" "\$@"
EOF
chmod +x $WINE32/cl.sh
cat >$WINE64/python.sh <<EOF
unset WINEARCH
export WINEPREFIX=$WINE64
exec wine python.exe "\$@"
EOF
chmod +x $WINE64/python.sh
cat >$WINE64/cl.sh <<EOF
export WINEPREFIX=$WINE64
export VCINSTALLDIR="C:\\\\Program Files (x86)\\\\Common Files\\\\Microsoft\\\\Visual C++ for Python\\\\9.0\\\\VC"
export WindowsSdkDir="C:\\\\Program Files (x86)\\\\Common Files\\\\Microsoft\\\\Visual C++ for Python\\\\9.0\\\\WinSDK"
export INCLUDE="\$VCINSTALLDIR\\\\Include;\$WindowsSdkDir\\\\Include"
export LIB="\$VCINSTALLDIR\\\\Lib\\\\amd64;\$WindowsSdkDir\\\\Lib\\\\x64"
export LIBPATH="\$VCINSTALLDIR\\\\Lib\\\\amd64;\$WindowsSdkDir\\\\Lib\\\\x64
exec wine "\$VCINSTALLDIR\\\\bin\\\\amd64\\\\cl.exe" "\$@"
EOF
chmod +x $WINE64/cl.sh
touch $BUILDENV/.ready

View File

@ -1,34 +1,26 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: UTF8 -*- # -*- coding: utf-8 -*-
import StringIO, zipfile, os.path, imp, sys import StringIO, zipfile, os.path, imp, sys
import marshal import marshal
import zlib import zlib
def get_encoded_library_string(arch): def get_encoded_library_string():
filepath=None filepath=None
if arch=="x86": filepath=os.path.join("resources","library.zip")
filepath=os.path.join("resources","libraryx86.zip")
elif arch=="x64":
filepath=os.path.join("resources","libraryx64.zip")
else:
raise Exception("unknown arch %s"%arch)
f = StringIO.StringIO() f = StringIO.StringIO()
f.write(open(filepath, "rb").read()) f.write(open(filepath, "rb").read())
zip = zipfile.ZipFile(f) zip = zipfile.ZipFile(f)
modules = dict([(z.filename, zip.open(z.filename,).read()) for z in zip. infolist() if os.path.splitext(z.filename)[1] in [".py",".pyd",".dll",".pyc",".pyo"]]) modules = dict([
(z.filename, zip.open(z.filename,).read()) for z in zip.infolist() \
if os.path.splitext(z.filename)[1] in [
".py",".pyd",".dll",".pyc",".pyo"
]
])
return zlib.compress(marshal.dumps(modules),9) return zlib.compress(marshal.dumps(modules),9)
try:
with open(os.path.join("resources","library_compressed_string_x86.txt"),'wb') as w: with open(os.path.join("resources","library_compressed_string.txt"),'wb') as w:
w.write(get_encoded_library_string("x86")) w.write(get_encoded_library_string())
print "x86 encoded library generated"
except Exception as e:
print str(e)
try:
with open(os.path.join("resources","library_compressed_string_x64.txt"),'wb') as w:
w.write(get_encoded_library_string("x64"))
print "x64 encoded library generated"
except Exception as e:
print str(e)

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: UTF8 -*- # -*- coding: utf-8 -*-
import sys import sys
import marshal import marshal
import struct import struct
@ -21,15 +21,17 @@ sys.stdout = Blackhole()
sys.stderr = Blackhole() sys.stderr = Blackhole()
del Blackhole del Blackhole
""" """
if len(sys.argv)==2 and sys.argv[1].strip().lower()=="debug": if len(sys.argv)==2 and sys.argv[1].strip().lower()=="debug":
remove_stdout="print 'DEBUG activated'\n" remove_stdout="print 'DEBUG activated'\n"
def get_load_module_code(code, modulename): def get_load_module_code(code, modulename):
loader=""" loader="""
import imp, sys import marshal, imp, sys
fullname={} fullname={}
mod = imp.new_module(fullname) mod = imp.new_module(fullname)
mod.__file__ = "<bootloader>\\%s" % fullname mod.__file__ = "<bootloader>\\%s" % fullname
exec {} in mod.__dict__ exec marshal.loads({}) in mod.__dict__
sys.modules[fullname]=mod sys.modules[fullname]=mod
""".format(repr(modulename),repr(code)) """.format(repr(modulename),repr(code))
return loader return loader
@ -38,19 +40,18 @@ sys.modules[fullname]=mod
if __name__=="__main__": if __name__=="__main__":
code_bytes=[] code_bytes=[]
code="" code=""
#code_bytes.append(compile("import sys; print repr(sys._GetCompressedLibraryString())"+"\n", "<string>", "exec"))
code_bytes.append(compile(remove_stdout, "<string>", "exec")) code_bytes.append(compile(remove_stdout, "<string>", "exec"))
code_bytes.append(compile("import sys;sys.argv=[]", "<string>", "exec")) code_bytes.append(compile("import sys; sys.argv = [];", "<string>", "exec"))
with open(os.path.join("..", "..", "pupy", "packages","all", "pupyimporter.py")) as f: with open(os.path.join("..", "..", "pupy", "packages","all", "pupyimporter.py")) as f:
code=f.read() code=f.read()
code=marshal.dumps(compile(code, '<string>', 'exec'))
code_bytes.append(compile(get_load_module_code(code,"pupyimporter")+"\n", "<string>", "exec")) code_bytes.append(compile(get_load_module_code(code,"pupyimporter")+"\n", "<string>", "exec"))
code_bytes.append(compile("import pupyimporter;pupyimporter.install();pupyimporter.load_pywintypes()\n", "<string>", "exec")) code_bytes.append(compile("import pupyimporter;pupyimporter.install();\n", "<string>", "exec"))
#code_bytes.append(compile("print 'plop'\n", "<string>", "exec"))
with open(os.path.join("..",'..','pupy',"pp.py")) as f: with open(os.path.join("..",'..','pupy',"pp.py")) as f:
code=f.read() code=f.read()
code_bytes.append(compile(code+"\n", "<string>", "exec")) code_bytes.append(compile(code+"\n", "<string>", "exec"))
code_bytes=marshal.dumps(code_bytes) code_bytes=marshal.dumps(code_bytes)
with open(os.path.join("resources","bootloader.pyc"),'wb') as w: with open(os.path.join("resources","bootloader.pyc"),'wb') as w:
w.write(code_bytes) w.write(code_bytes)