Will presented on using Pyinstaller and introducing Pwnstaller, a tool he created to dynamically generate unique Python payload executables. Pyinstaller packages Python scripts into standalone executables but its loader binaries could be detected by antivirus. Pwnstaller obfuscates and recompiles the Pyinstaller loader source each time to avoid static signatures. It has been integrated into Veil-Evasion so Python payloads benefit from dynamically generated unique loaders that are harder for antivirus to detect.
2. $ whoami
Security researcher and penetration tester/red teamer
for Veris Group’s Adaptive Threat Division
Co-founder of the Veil-Framework #avlol
www.veil-framework.com
Shmoocon ‘14: AV Evasion with the Veil Framework
co-wrote Veil-Evasion, wrote Veil-Catapult and Veil-
PowerView
BSides ATX ‘14: Wielding a Cortana
Defcon ‘14 (accepted): Post-Exploitation 2.0
3. tl;dr
Why we use Pyinstaller
DEP, Pyinstaller, and a weird Veil-Evasion bug
How Pyinstaller works
Pwnstaller v1.0
Questions
4. Caveat
This is a proof of concept based off of an idea
Going to detail through the problem that prompted
thinking about this, and walk through the thought
process that led to the PoC solution
Probably a better way to do this, but seemed like an
interesting concept and wanted to get the idea out there
5. Pyinstaller 101
Pyinstaller is “a program that converts (packages) Python
programs into stand-alone executables”
http://www.pyinstaller.org/
Packages Python scripts into OSX, Linux, or Windows
self-extracting executables
Lets developers distribute projects without relying on an
existing Python installation
6. Pyinstaller Repurposed
Pentesters realized a few years ago that we could use it
to package malicious scripts
advantageous, as legitimate projects use Pyinstaller
www.pyinstaller.org/wiki/ProjectsUsingPyInstaller
Dave Kennedy’s “PyInjector” was released in 2012 based
on Debasish Mandal’s original post:
https://www.trustedsec.com/august-2012/new-tool-
pyinjector-released-python-shellcode-injection/
http://www.debasish.in/2012_04_01_archive.html
7. Pyinstaller in Veil-
Evasion
Veil-Evasion sets up Pyinstaller under Wine so Python
payloads can be compliled natively to Windows .exe’s
Generation is transparent to the user
Allows for the dynamic generation of Windows Python
payloads, all on Kali!
We always want to preserve a single attack platform
8. Veil Payloads and DEP
Void pointer casting for shellcode injection may fail, as
the memory location used is not explicitly marked X
(*(void(*)()) shellcode)();
Most systems tend to default to an opt-in DEP
enforcement policy
if the executable you're running opts-in, void pointer
casting will fail with a memory access violation
9. A Weird Veil Bug
Python void pointer payloads worked as .py files, but
failed as Pyinstaller executables
The python.exe interpreter used by Pyinstaller is not
DEP enabled, but the resulting Pyinstaller payloads do
in fact opt in to this protection
see http://www.veil-evasion.com/dep-pyinstaller/
10. How Pyinstaller Works
Pyinstaller uses the CArchive data structure to package
up the main python .dll, any necessary libraries, and
your target script
Basically like a compressed ZIP container
This CArchive is attached to then end of a “launcher”
executable
We use the runw.exe version so we can hide the window,
making execution transparent to the user
12. How Pyinstaller Works
On execution, the launcher executable:
Decompresses the CArchive to a temporary location
Loads the python15.dll using LoadLibraryExA
Maps all the entry points in the python .dll for necessary
methods
Sets up env stuff and starts the Python process
Imports all specified necessary modules
Runs the extracted script using PyRun_SimpleString
13. How Pyinstaller Works:
English
When the Pyinstaller produced executable is run, a
minimal Python environment is extracted from a
compressed attachment
Components necessary for the environment are
registered and set up
The script attached is run
Lets you run Python scripts without Python being
installed on a target machine!
14. Solving The Veil Bug
So the DEP opt-in policy is determined by the launcher
.exe, not the Python interpreter
Our next step was to generate a Pyinstaller launcher that
didn’t opt-in to DEP
Luckily Pyinstaller is open source
https://www.veil-framework.com/dep-pyinstaller/
15. Solving The Veil Bug
Pyinstaller holds precompiled copies of 32-bit and 64-bit
loaders for Linux, OSX and Windows in
pyinstaller/support/loader/*
The sources for the loaders are included in
pyinstaller/source/*
runw.exe is the loader we want to regenerate
used for “windowed” executables
DEP
16. Turning Off DEP
The binaries utilize the WAF build system to build the
loaders
./pyinstaller/source/wscript
add conf.env.append_value('LINKFLAGS',
'/NXCOMPAT:NO') right after the other flags on lines 209
and 211
This will instruct the Visual Studio linker to turn off DEP
compatibility
17. Problem?
Sweet, we have a shiny new launcher.exe
But our project is focused on evading AV
Including a static, custom-compiled launcher executable
is a GREAT way to say “Hey vendors, check out this
Veil-Evasion payload! Signatures lolz”
18. Solution
Besides running Pyinstaller itself natively on Kali, we
can dynamically recompile the Pyinstaller launcher on
using mingw!
This makes it trivial to makes some small changes and
get a different SHA1 signature each time
Why don’t we make it *a little* harder to flag on?
19. Obfuscation: Phase 1
There are only a handful of source files needed to
recompile runw.exe
utils.c - some helper methods (246 lines)
launch.c - “where the magic happens” (1617 lines)
main.c - invokes launch.c (165 lines)
./zlib/* - extract of zlib v1.2.3
Lets start with some basic obfuscation
20. Obfuscation: Phase 1
The initial goal: make ssdeep as useless as possible
against “families” of our generated launcher
Any unnecessary code was stripped out (i.e. code for
OSX and Linux binaries)
Thought process: randomize/shuffle wherever we can
A selection of random libraries imports thrown in
21.
22. Obfuscation: Phase 2
Let’s go just a bit further and have a some fun with
anything doing basic dynamic analysis
How about interspersing lots of nested processing
methods throughout the code
similar to our c/meterpreter/* payloads
This mucks up the call tree of the program without
altering the actual execution
23. Finishing Touches
The Pyinstaller icon is kind
of recognizable
How about some randomized .ico’s instead?
24. Putting It All Together
The end result, every time the generator runs:
obfuscated code for all* source files associated with the
Pyinstaller launcher are generated
a randomized icon is chosen for the final packaged result
mingw32 is used to compile everything into a new
runw.exe, all on Kali
the new runw.exe is copied into the correct resource
location to be used by Pyinstaller
*except some known zlib libraries
25. ssdeep comparison
ssdeep is a ‘fuzzy hashing’ static malware comparison tool,
allowing for the comparison of malware families
Generated a run of 1000 runw.exe loaders
(1000 choose 2) = 499500 possible comparison combinations
367,073 pairings (74%) scored 30/100 or better
228,961 pairings (46%) scored 50/100 or better
34,420 pairings (7%) scored 70/100 or better
0 pairings scored at 90/100 or better
What this means: none of the loader pairings scored as a
closely ‘similar’ malware family
27. In Plain English
Each generated Pyinstaller loader is reasonably unique
from a basic static malware analysis perspective
Competent reversers will be able to figure out what’s
going on in very little time
But hopefully this is relatively resistant against static
signatures
I’m sure there are better obfuscation methods, so go
implement them!
28. Pwnstaller v1.0
http://www.harmj0y.net/blog/python/pwnstaller-1-
0/
The code is up on github:
https://github.com/HarmJ0y/Pwnstaller
And it’s been integrated into Veil-Evasion
In the development branch now, hitting the master branch
on the 5/15/2014 V-Day
All Python payloads can now utilize a dynamically
generated Pwnstaller loader by choosing “2 - Pwnstaller”
from the Python compilation menu
30. Recap
Pyinstaller is some cool stuff
Pwnstaller will hopefully extend the lifetime of Veil-
Evasion Python payloads by making static signatures
reasonably difficult to write
“This is script-kiddie garbage that will harm users of
Pyinstaller when AVs flag it without benefiting
anyone who matters. Hope you get booed off at
Bsides.” – The Internet
31. Shameless Sidebar
Want to research cool stuff like this?
Want to work with 9 x OSCPs and 4 x OSCEs?
Want to do some sweet red teaming?
Hit me up to join the Adaptive Threat Division
32. Questions?
Contact me:
@harmj0y
will@harmj0y.net
Read more:
http://www.harmj0y.net/blog/python/pwnstaller-1-0/
Get Pwnstaller:
https://github.com/HarmJ0y/Pwnstaller
Now in Veil-Evasion!