Msfvenom generated Exec shellcode analysis - exec shellcode

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert Certification. The task for 5.1/7 assignment is to analyse at least 3 shellcode examples created using Msfpayload for linux/x86_64. Since msfpayload is outdated, I used msfvenom instead. The analysis of the shellcodes is carried out using the gdb debugger and 1/3 shellcode analysed in this article is the linux/x64/exec payload.

Student ID: SLAE64 - 1594

MSFvenom generated linux/x64/exec payload

The first payload I chose is the linux/x64/exec payload, which is used to execute an arbitrary command which I have specified in the CMD commandline argument. In order to generate the payload I used the following command:

root@kali:~# msfvenom -p linux/x64/exec -f c CMD=whoami
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 46 bytes
Final size of c file: 220 bytes
unsigned char buf[] =
"\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00\x53"
"\x48\x89\xe7\x68\x2d\x63\x00\x00\x48\x89\xe6\x52\xe8\x07\x00"
"\x00\x00\x77\x68\x6f\x61\x6d\x69\x00\x56\x57\x48\x89\xe6\x0f"
"\x05";

Shellcode test program

In order to analyse the generated payload I am placing it into the C program where we will be executing the shellcode:

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

unsigned char code[] = \
"\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00\x53"
"\x48\x89\xe7\x68\x2d\x63\x00\x00\x48\x89\xe6\x52\xe8\x07\x00"
"\x00\x00\x77\x68\x6f\x61\x6d\x69\x00\x56\x57\x48\x89\xe6\x0f"
"\x05";

int main()
{

  printf("Shellcode Length:  %d\n", (int)strlen(code));
        int (*ret)() = (int(*)())code;
        ret();
}

and then compile it as follows:

gcc -m64 -fno-stack-protector -z execstack testshellcode.c -o testshellcode -no-pie

Analysis

I started the debugger gdb ./testshellcode and looked at the state of all the important registers just before taking the syscall - rax, rdi, rsi and rdx. From that we can construct that the syscall to be executed:

  • is execve as rax is 0x3b (59 in decimal)
  • the program which will be executed is /bin/sh as we can find it from register rdi
  • rsi points to an array at 0x7fffffffdc28 with 3 array elements [“/bin/sh”, “-c”, “whoami”] as array elements are layed out into memory from lower addresses to higher addresses
  • we pass no environment variables to the syscall.

So the final syscall, which this shellcode will execute is in following format:
execve("/bin/sh", ["/bin/sh", "-c", "whoami", 0])



© 2019. All rights reserved.

Powered by Hydejack v8.1.1