Shellcode Encoder

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:


Student ID: SLAE-1517

SLAE Assignment #4 - Encoder
 - Create a custom encoding scheme


For this assignment,  we will be encoding an execve shellcode that spawns a /bins/sh using XOR and then NOT encoding The idea behind encoding is that we can alter opcodes without altering its functionality. For instance, using the shellcode below, it is pretty clear that our shellcode contains \x2f\x2f\x73\x68\x2f\x62\x69\x6e which translates to //bin/sh. Among other things, this is something that could be easily caught by Anti-virus (AV) or Intrusion  Detection System (IDS).

Below is the original execve-stack.nasm file and its corresponding opcodes/shellcode.

Once we get the original shellcode...I used python for encoding which will be a two-step process: XOR encoding first, then NOT encoding the result of the first step.

Here we initialize it with our original shellcode from execve-stack.nasm file:

The first step is the  XOR encoding. For this step, I am going through each byte of the original shellcode and XOR'ng it with 0xaa.

The second step is to encode each byte of the result from XOR encoding, with a NOT encoding.

Below is the output of the encoder python script. I am printing both XOR and NOT encoded shellcodes however, we will only need the NOT encoded shellcode for our decoder.

With the 'XOR then NOT' encoded shellcode, we are now ready to create our decoder to revert or decode it back to the original shellcode.

For this step, I am using the jmp-pop-call method again. We load the encoded shellcode into the stack by using the call instruction. We then pop it and load it into a register (esi for this one). We can then loop through each byte of the encoded shellcode loaded in esi. 

We first do a NOT then followed by XOR 0xaa.

Below shows the encoding and decoding scheme for the first byte

encoding: 0x31---> 0x9b (0x31 XOR 0xaa) -----> 0x64 (NOT 0x9b & 0xff)
decoding: 0x64---> 09xb (NOT 0x64 & 0xff) ---> 0x31 (0x9b XOR 0xaa)

...and here's the complete nasm file with our decoder.

We compile then generate a new shellcode using objdump.

We update our shellcode.c file, compile it and execute.

Note that with this the new shellcode, it shows that we can 'hide' the //bin/sh while maintaining the functionality.