Pwnstaller

32
Pwnstaller 1.0 Will @harmj0y Veris Group Adaptive Threat Division

description

This talk was given at BSides Boston '14

Transcript of Pwnstaller

Page 1: Pwnstaller

Pwnstaller 1.0

Will@harmj0y

Veris GroupAdaptive Threat Division

Page 2: Pwnstaller

$ 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

Page 3: Pwnstaller

tl;dr Why we use Pyinstaller

DEP, Pyinstaller, and a weird Veil-Evasion bug

How Pyinstaller works

Pwnstaller v1.0

Questions

Page 4: Pwnstaller

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

Page 5: Pwnstaller

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

Page 6: Pwnstaller

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

Page 7: Pwnstaller

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

Page 8: Pwnstaller

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

Page 9: Pwnstaller

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/

Page 10: Pwnstaller

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

Page 12: Pwnstaller

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

Page 13: Pwnstaller

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!

Page 14: Pwnstaller

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/

Page 15: Pwnstaller

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

Page 16: Pwnstaller

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

Page 17: Pwnstaller

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”

Page 18: Pwnstaller

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?

Page 19: Pwnstaller

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

Page 20: Pwnstaller

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

Page 21: Pwnstaller
Page 22: Pwnstaller

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

Page 23: Pwnstaller

Finishing Touches The Pyinstaller icon is kind

of recognizable

How about some randomized .ico’s instead?

Page 24: Pwnstaller

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

Page 25: Pwnstaller

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

Page 26: Pwnstaller

ssdeep comparison

20 30 40 50 60 70 80 90 1000

5000

10000

15000

20000

25000

30000

35000

40000

45000

ssdeep matches

match %

occu

ran

ces

Page 27: Pwnstaller

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!

Page 28: Pwnstaller

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

Page 29: Pwnstaller

Pwnstaller in Veil-Evasion

Page 30: Pwnstaller

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

Page 31: Pwnstaller

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

Page 32: Pwnstaller

Questions? Contact me:

@harmj0y [email protected]

Read more: http://www.harmj0y.net/blog/python/pwnstaller-1-0/

Get Pwnstaller: https://github.com/HarmJ0y/Pwnstaller Now in Veil-Evasion!