Obfuscating python

Who knew making code difficult to read could be fun?

Thu, 03 Mar 2016

Intro

I got to thinking, you can obfuscate js and vbs when serving up code to people, why not Python? Well to there is that whole whitespace thing and lack of semi-colons, but lets see what we can do.


Obfuscation: “To make so confused or opaque as to be difficult to perceive or understand”

In terms of programming one usually doesnt purposefully obfuscate their code as they may wish for others to read it. However within the realm of Cyber Security the opposite often holds true. Many of those who are crafting the code behind malware (or for fun in puzzles/competitions like IOCCC) purposefully make their code as difficult to read as possible using obfuscation. Therefore it is relatively important to understand obfuscation when it comes to code analysis.

Here we will be going through the process of applying basic obfuscation to python code in the below examples.


Our initial code

Scanner.py is a simple scapy implementation of an arp scan for a local area network. An attacker may find it useful to find all live hosts on a network so they may find potential pivots. However most attackers would probably use something a little more sophisticated in order to remain undetected but for our purposes this will work.

#!/usr/bin/env python
 
from scapy.all import *
 
try:
    alive,dead=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst='192.168.1.0/24'), timeout=2, verbose=0)
    print "MAC - IP"
    for i in range(0,len(alive)):
            print alive[i][1].hwsrc + " - " + alive[i][1].psrc
except:
    pass

Here is sample output from Scanner.py.

user@ubuntu:~$ sudo python scanner.py 
[sudo] password for user: 
WARNING: No route found for IPv6 destination :: (no default route?)
MAC - IP
00:00:11:11:11:11 - 192.168.1.10
cc:bb:44:33:22:11 - 192.168.1.1
dd:ee:ae:45:67:34 - 192.168.1.14
ff:dd:78:ad:6d:23 - 192.168.1.4
00:00:00:70:07:e2 - 192.168.1.30
00:00:11:22:22:22 - 192.168.1.27

Base64 is a common type of encoding that is easy to encode and decode using the python Base64 module. It adds a layer of obfuscation between prying eyes and our code. So the first step we will take will be to encode Scanner.py in Base64. The below code snippet will call the base64 library and encode Scanner.py, then dump it as a single string into output.o

import base64 
#Its all pretty self explanatory
def main():

    target=open("scanner.py", "r")
    todo = target.read()
    target.close()
    s=base64.b64encode(todo)
    target = open("output.o", "w")
    target.write(s)
    target.close()

if __name__ == '__main__':
    main()

Afterwards we can open up both files side by side to see the difference.

Obfuscation

Loading...
Anthony Laiuppa

If you have any feedback feel free to @ me on twitter, Im always looking to learn. -AL