the programmer is compiled to a simple bytecode representation This is what the .pyc’s/.pyo’s are • Python bytecode is portable between platforms & architectures As long as major & minor versions are the same (micro can vary) 36
• import statement is used to access them & resolve their dependency tree • An import hook is custom importer that can be used to ﬁnd & load modules in non-standard ways Importer protocol deﬁned in PEP302 37
in the *** Worth a whole talk in itself, see ‘Import this, that and the other thing’ by Brett Cannon PyCon2010 – it’s excellent • Python 3.x reduces this pain via importlib • Not available in Python 2.x so you need to implement from scratch using PEP 302 Available since v2.3 to better customize the __import__ builtin Given 2.x is in the widest use this is what I did 38
Finder Tends to be pretty straightforward Locate the module/package code A Loader More complex Compile to bytecode if needed Insert module into namespace Execute top level code Lots of annoying metadata bookkeeping 39
+ ZIP Import Hook Stage 2 RPC Import Hook & Mainloop Tasking bytecode Binary Injector / Userland Exec Native task • Self-Bootstrapping • Stage 0 is the only persistent part of the implant. Tiny & generic • Simple event-loop that GETs bytecode over SSL & runs it from memory • This is used to bootstrap the Stage 1 import hook ….
+ ZIP Import Hook Stage 2 RPC Import Hook & Mainloop Tasking bytecode Binary Injector / Userland Exec Native task • Stage 1 Import Hook - In memory import of a zip over SSL • Zip imports supported since Py2.3 • but only from the ﬁlesystem not memory • Re-implement the stdlib zipﬁle module in Python
bytecode bundles to be sent, executed and automatically have dependencies resolved remotely without touching disk Write completely standard Python Much quicker to write than C/ASM Much easier to debug/QA Non-stdlib packages easily usable 46
IP’s are often used but generally a bad choice when managing many targets • Instead we use SYSUUID from SMBIOS Fairly easy to get at from Pure Python on Unixes, Linux & OSX Pain in the a** on Windows but can be done via Ctypes 47
persistent connection At random intervals checks-in to RPC endpoint(s) Pending tasks can be sent as A task ID to import, resolve & execute All tasks can operate in own thread or child • Nothing needs to touch disk • Result objects cached & returned next check-in 48
executes on the target Service: The logic that processes the result of the payload, executes on the server • Payloads are pure Python bytecode • Determination of next task happens at the server If compromise detected we leak minimal MO Allows easy updating of goal oriented logic No need to deﬁne goal at asset creation time 50
+ ZIP Import Hook Stage 2 RPC Import Hook & Mainloop Common Task Bytecode Binary Injector / Userland Exec Native task • A Common Task is one that is pure Python bytecode E.g. Search for ﬁles named ‘pk.pem’ • There is a balance to be struck between stealth & efﬁciency when splitting tasks Task searching for ‘secret.doc’ can leak MO Exﬁltrating every ﬁlename to match to ‘secret.doc’ at the server would use bandwidth
+ ZIP Import Hook Stage 2 RPC Import Hook & Mainloop Tasking bytecode Binary Injector / Userland Exec Native task • A Native Task is one that executes native code Some tasks are too low level/ speciﬁc for Python • A number of options depending on OS Ctypes, PyObjC, Subprocess • Potential issues Forensically noisy Native functions may be hooked • One solution userland execution …….
image with a new one Without calling OS (Execve, loadlibrary etc) Without having to load from disk • Useful in a number of scenarios Antiforensics Non-exec ﬁlesystem mounts Wanting to inject native code from a IL VM! 53
MachO bundle to do webcam capture • isight.bundle hasn’t worked since 64bit Snow Leopard • Relies on Quicktime.framework • 32 bit only • So we wrote a new one for the demo using QTKit (32 & 64 bit supported) 57