Why Perl is better than Python for Exploit Development

This is a bold claim considering how much Python is used for writing exploits, however as we compare the output of some shellcode produced from both Perl and Python, you will see why Perl can be the better choice in most scenarios, or at least more straightforward.

Two potential solutions in Python3

$ uname -sp
Linux x86_64
#!/usr/bin/env python3

# Equivalent to running: execve /bin/sh
shellcode =  "\x31\xc0\x50\x68\x2f\x2f\x73"
shellcode += "\x68\x68\x2f\x62\x69\x6e\x89"
shellcode += "\xe3\x89\xc1\x89\xc2\xb0\x0b"
shellcode += "\xcd\x80\x31\xc0\x40\xcd\x80"

print(shellcode)
execve_binsh_shellcode1.py

Piping the Python shellcode output to a file works most of the time; however, when we attempt to write the shellcode straight to a file or binary, we run into some more issues (examples below).

#!/usr/bin/env python3

# Equivalent to running: execve /bin/sh
shellcode =  b"\x31\xc0\x50\x68\x2f\x2f\x73"
shellcode += b"\x68\x68\x2f\x62\x69\x6e\x89"
shellcode += b"\xe3\x89\xc1\x89\xc2\xb0\x0b"
shellcode += b"\xcd\x80\x31\xc0\x40\xcd\x80"

with open('python_shellcode2.bin', 'wb') as f:
	f.write(shellcode)
execve_binsh_shellcode2.py

Let's compare the two

$ python3 execve_binsh_shellcode.py > python_shellcode1.bin
$ python3 execve_binsh_shellcode2.py
$ cat python_shellcode1.bin
1ÀPh//shh/bin‰ã‰Á‰Â°♂Í€1À@Í€
$
$ cat python_shellcode2.bin
1└Ph//shh/binëπë┴ë┬░♂═Ç1└@═Ç
execve_binsh_shellcode.py terminal output
Comparing the outputs, it's obvious that something is a little bit off...

However, it isn't immediately clear what went wrong until we compare the differences between the two using xxd.

$ xxd python_shellcode1.bin
00000000: 31c3 8050 682f 2f73 6868 2f62 696e c289  1..Ph//shh/bin..
00000010: c3a3 c289 c381 c289 c382 c2b0 0bc3 8dc2  ................
00000020: 8031 c380 40c3 8dc2 800a                 .1..@.....

$ xxd python_shellcode2.bin
00000000: 31c0 5068 2f2f 7368 682f 6269 6e89 e389  1.Ph//shh/bin...
00000010: c189 c2b0 0bcd 8031 c040 cd80            .......1.@..
It seems like Python is replacing \x80 and possibly some other bytes it doesn't like.

\x31\xc0\x50\x68\x2f\x2f\x73
\x68\x68\x2f\x62\x69\x6e\x89
\xe3\x89\xc1\x89\xc2\xb0\x0b
\xcd\x80\x31\xc0\x40\xcd\x80

Looking at the original shellcode we want, it is clear that we are getting some extra and undesired bytes in our output.

Okay...Well, how does Perl perform then?


A safer and more straightforward approach

perl -e 'print("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80")' | xxd
00000000: 31c0 5068 2f2f 7368 682f 6269 6e89 e389  1.Ph//shh/bin...
00000010: c189 c2b0 0bcd 8031 c040 cd80            .......1.@..
Piping our output to xxd instead of a file

Awesome!!! Now we're ready to start writing some exploits. I will continue where we left off and demonstrate how we can drop some shells using Perl and a little bit of disassembly in a future post, subscribe to my blog so you don't miss it!

Happy hacking! -Kal