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/.buildozer
# Byte-compiled / optimized / DLL files
*.pyc
*.pyo
__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
# do not ignore package & templates files

View File

@ -1,75 +1,99 @@
CC=cl.exe
PYTHONPATH=C:\\Python27
PYTHON=python.exe
BUILDENV ?= $(PWD)/buildenv
BUILDENV_READY = $(BUILDENV)/.ready
PYTHONPATH := C:\\Python27
TEMPLATE_OUTPUT_PATH=../../pupy/payload_templates
ifndef ARCH
$(error You must specify an architecture.)
else
ifeq "$(ARCH)" "x64"
CFLAGS:=$(CFLAGS) /DWIN_X64 /D_WIN64
else
CFLAGS:=$(CFLAGS) /DWIN_X86
$(error You must specify an architecture - win64 or win32)
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
ifdef DEBUG
DEBUG_ADD:=DEBUG
CFLAGS:= $(CFLAGS) /DDEBUG
LINKER_OPTS:=
DEBUG_ADD :=DEBUG
CFLAGS := $(CFLAGS) /DDEBUG
LINKER_OPTS :=
PPARCH := $(PPARCH)d
else
DEBUG_ADD:=
LINKER_OPTS:=/link /subsystem:windows /ENTRY:mainCRTStartup
DEBUG_ADD :=
LINKER_OPTS :=/link /subsystem:windows /ENTRY:mainCRTStartup
PPARCH := $(PPARCH)
endif
PYOBJS=_memimporter.obj MyLoadLibrary.obj Python-dynload.obj pupy_load.obj pupy.obj base_inject.obj
COMMON_OBJS=resources_bootloader_pyc.obj resources_python27_dll.obj MemoryModule.obj resources_library_compressed_string_txt.obj actctx.obj list.obj thread.obj remote_thread.obj LoadLibraryR.obj resources_msvcr90_dll.obj
PYOBJS := \
_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
resources/library_compressed_string.txt: resources/library_compressed_string_$(ARCH).txt
cp $< $@
resources_library_compressed_string_txt.c: gen_resource_header.py resources/library_compressed_string.txt resources/library${ARCH}.zip
resources/library.zip: build_library_zip.py $(BUILDENV_READY)
$(PYTHON) build_library_zip.py
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
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)
resources_bootloader_pyc.c: gen_resource_header.py resources/bootloader.pyc
$(PYTHON) $+
resources/python27.dll: resources/python27_$(ARCH).dll
resources_bootloader_pyc.c: resources/bootloader.pyc gen_resource_header.py $(BUILDENV_READY)
$(PYTHON) gen_resource_header.py $<
resources/python27.dll: $(BUILDENV)/$(ARCH)/drive_c/Python27/python27.dll $(BUILDENV_READY)
cp $< $@
resources_python27_dll.c: gen_resource_header.py resources/python27.dll
$(PYTHON) $+
resources/msvcr90.dll: resources/msvcr90_$(ARCH).dll
resources/msvcr90.dll: $(BUILDENV)/$(ARCH)/drive_c/Python27/msvcr90.dll $(BUILDENV_READY)
cp $< $@
resources_msvcr90_dll.c: gen_resource_header.py resources/msvcr90.dll
$(PYTHON) $+
resources_python27_dll.c: resources/python27.dll gen_resource_header.py $(BUILDENV_READY)
$(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
$(CC) /c $(CFLAGS) /I$(PYTHONPATH)/include $<
main_exe.obj: main_exe.c
$(CC) /c $(CFLAGS) $<
%.obj: %.c
$(CC) /c $(CFLAGS) $<
ReflectiveLoader.obj: ReflectiveLoader.c
$(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)
$(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
.PHONY: clean
@ -79,8 +103,15 @@ ifneq "$(QUICK)" "1"
endif
clean:
rm *.obj
rm *.exp
rm pupy$(ARCH).exe
rm pupy$(ARCH).dll
rm resources/bootloader.pyc
rm -f *.obj
rm -f *.pyo
rm -f *.pyc
rm -f *.txt
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
# -*- coding: UTF8 -*-
# -*- coding: utf-8 -*-
import StringIO, zipfile, os.path, imp, sys
import marshal
import zlib
def get_encoded_library_string(arch):
def get_encoded_library_string():
filepath=None
if arch=="x86":
filepath=os.path.join("resources","libraryx86.zip")
elif arch=="x64":
filepath=os.path.join("resources","libraryx64.zip")
else:
raise Exception("unknown arch %s"%arch)
filepath=os.path.join("resources","library.zip")
f = StringIO.StringIO()
f.write(open(filepath, "rb").read())
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)
try:
with open(os.path.join("resources","library_compressed_string_x86.txt"),'wb') as w:
w.write(get_encoded_library_string("x86"))
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)
with open(os.path.join("resources","library_compressed_string.txt"),'wb') as w:
w.write(get_encoded_library_string())

View File

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