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/exec 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
- Obtain as much information about the payload as possible through documentation. How does it work, expected parameters, end result once detonated
- Analyze payload using Libemu
- Test shellcode
Payload Information
We can obtain a summary on the payload by passing the S for summary switch to msfpayload
$ msfpayload linux/x86/exec 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 Execute Command Module: payload/linux/x86/exec Platform: Linux Arch: x86 Needs Admin: No Total size: 158 Rank: Normal Provided by: vlad902 <vlad902@gmail.com> Basic options: Name Current Setting Required Description ---- --------------- -------- ----------- CMD yes The command string to execute Description: Execute an arbitrary command
We can see the payload target platform and architecture is Linux x86.
The size is 158 bytes.
The payload accepts one parameter, CMD, which is required. We can assume that the CMD parameter is used to specify the program to be executed.
We can confirm from the description that the payload will exec a user specified program.
Analyze using libemu
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 a program called sctest from the libemu testsuite. sctest will emulate a computer and actually run the shellcode in a sand boxed environment.
Note: “libemu is a small library written in C offering basic x86 emulation and shellcode detection using GetPC heuristics. It is designed to be used within network intrusion/prevention detections and honeypots.” http://libemu.carnivore.it/
So let’s generate the payload using msfpayload and specify ‘/sbin/ifconfig’ as the executable the shellcode should spawn. The output format of msfpayload will be ‘R’, raw, which will be fed into (-S stdin) sctest and an image file name (-G libemu-exec.dot) is specified for a flow diagram of the execution pattern.
$ msfpayload linux/x86/exec CMD=/sbin/ifconfig R| /opt/libemu/bin/sctest -vvv -Ss 1000 -G libemu-exec.dot graph file libemu-exec.dot verbose = 3 [!] ************************************************************************ [!] * 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 * [!] ************************************************************************ [emu 0x0x8056090 debug ] cpu state eip=0x00417000 [emu 0x0x8056090 debug ] eax=0x00000000 ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x8056090 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] cpu state eip=0x00417000 [emu 0x0x8056090 debug ] eax=0x00000000 ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x8056090 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 6A0B push byte 0xb [emu 0x0x8056090 debug ] cpu state eip=0x00417002 [emu 0x0x8056090 debug ] eax=0x00000000 ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x8056090 debug ] esp=0x00416fca ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 58 pop eax [emu 0x0x8056090 debug ] cpu state eip=0x00417003 [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x8056090 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 99 cwd [emu 0x0x8056090 debug ] cpu state eip=0x00417004 [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x8056090 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 52 push edx [emu 0x0x8056090 debug ] cpu state eip=0x00417005 [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x8056090 debug ] esp=0x00416fca ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 66682D63 push word 0x632d [emu 0x0x8056090 debug ] cpu state eip=0x00417009 [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x8056090 debug ] esp=0x00416fc8 ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 89E7 mov edi,esp [emu 0x0x8056090 debug ] cpu state eip=0x0041700b [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x8056090 debug ] esp=0x00416fc8 ebp=0x00000000 esi=0x00000000 edi=0x00416fc8 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 682F736800 push dword 0x68732f [emu 0x0x8056090 debug ] cpu state eip=0x00417010 [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x8056090 debug ] esp=0x00416fc4 ebp=0x00000000 esi=0x00000000 edi=0x00416fc8 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 682F62696E push dword 0x6e69622f [emu 0x0x8056090 debug ] cpu state eip=0x00417015 [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x8056090 debug ] esp=0x00416fc0 ebp=0x00000000 esi=0x00000000 edi=0x00416fc8 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 89E3 mov ebx,esp [emu 0x0x8056090 debug ] cpu state eip=0x00417017 [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00000000 edx=0x00000000 ebx=0x00416fc0 [emu 0x0x8056090 debug ] esp=0x00416fc0 ebp=0x00000000 esi=0x00000000 edi=0x00416fc8 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 52 push edx [emu 0x0x8056090 debug ] cpu state eip=0x00417018 [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00000000 edx=0x00000000 ebx=0x00416fc0 [emu 0x0x8056090 debug ] esp=0x00416fbc ebp=0x00000000 esi=0x00000000 edi=0x00416fc8 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] E8 call 0x1 [emu 0x0x8056090 debug ] cpu state eip=0x0041702c [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00000000 edx=0x00000000 ebx=0x00416fc0 [emu 0x0x8056090 debug ] esp=0x00416fb8 ebp=0x00000000 esi=0x00000000 edi=0x00416fc8 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 57 push edi [emu 0x0x8056090 debug ] cpu state eip=0x0041702d [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00000000 edx=0x00000000 ebx=0x00416fc0 [emu 0x0x8056090 debug ] esp=0x00416fb4 ebp=0x00000000 esi=0x00000000 edi=0x00416fc8 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 53 push ebx [emu 0x0x8056090 debug ] cpu state eip=0x0041702e [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00000000 edx=0x00000000 ebx=0x00416fc0 [emu 0x0x8056090 debug ] esp=0x00416fb0 ebp=0x00000000 esi=0x00000000 edi=0x00416fc8 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 89E1 mov ecx,esp [emu 0x0x8056090 debug ] cpu state eip=0x00417030 [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00416fb0 edx=0x00000000 ebx=0x00416fc0 [emu 0x0x8056090 debug ] esp=0x00416fb0 ebp=0x00000000 esi=0x00000000 edi=0x00416fc8 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] CD80 int 0x80 execve int execve (const char *dateiname=00416fc0={/bin/sh}, const char * argv[], const char *envp[]); [emu 0x0x8056090 debug ] cpu state eip=0x00417032 [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00416fb0 edx=0x00000000 ebx=0x00416fc0 [emu 0x0x8056090 debug ] esp=0x00416fb0 ebp=0x00000000 esi=0x00000000 edi=0x00416fc8 [emu 0x0x8056090 debug ] Flags: [emu 0x0x8056090 debug ] 0000 add [eax],al cpu error error accessing 0x00000004 not mapped stepcount 15 copying vertexes optimizing graph vertex 0x80ad3d8 going forwards from 0x80ad3d8 -> vertex 0x80af578 -> vertex 0x80af788 -> vertex 0x80af968 -> vertex 0x80afa48 -> vertex 0x80afd00 -> vertex 0x80afdd0 -> vertex 0x80aff38 -> vertex 0x80b0130 -> vertex 0x80b0318 -> vertex 0x80b0490 -> vertex 0x80b0608 -> vertex 0x80b0780 -> vertex 0x80b08f8 copying edges for 0x80b08f8 -> 0x80b3c40 vertex 0x80b0a70 going forwards from 0x80b0a70 copying edges for 0x80b0a70 vertex 0x80b0ef8 going forwards from 0x80b0ef8 copying edges for 0x80b0ef8 [emu 0x0x8056090 debug ] cpu state eip=0x00417034 [emu 0x0x8056090 debug ] eax=0x0000000b ecx=0x00416fb0 edx=0x00000000 ebx=0x00416fc0 [emu 0x0x8056090 debug ] esp=0x00416fb0 ebp=0x00000000 esi=0x00000000 edi=0x00416fc8 [emu 0x0x8056090 debug ] Flags: int execve ( const char * dateiname = 0x00416fc0 => = "/bin/sh"; const char * argv[] = [ = 0x00416fb0 => = 0x00416fc0 => = "/bin/sh"; = 0x00416fb4 => = 0x00416fc8 => = "-c"; = 0x00416fb8 => = 0x0041701d => = "/sbin/ifconfig"; = 0x00000000 => none; ]; const char * envp[] = 0x00000000 => none; ) = 0;
As we can see from the above sctest output, we have the program instructions and CPU register statuses listed. What is perhaps one of the most powerful outputs though is the de-compiled representation of the program that stands out and clearly indicates the intent of the program.
I have highlighted execve() function and we can clearly see the contents of each of the parameters. By the way, the parameters shown are the memory locations of where the actual parameters are stored. This can further be confirmed from the previous assignments where execve() is documented.
Let’s confirm how execve works.
$ man execve ... NAME execve - execute program SYNOPSIS #include int execve(const char *filename, char *const argv[], char *const envp[]); DESCRIPTION execve() executes the program pointed to by filename. filename must be either a binary executable, or a script starting with a line of the form: ... argv is an array of argument strings passed to the new program. By convention, the first of these strings should contain the filename associated with the file being executed. envp is an array of strings, conventionally of the form key=value, which are passed as environment to the new pro‐ gram. Both argv and envp must be terminated by a NULL pointer. The argument vector and environment can be accessed by the called program's main function, when it is defined as:
1st parameter points to the string /bin/sh representing the file name to run.
2nd parameter points to the string “/bin/sh” “-c” “/sbin/ifconfig”
3rd parameter is not required and is null.
So there we have it, our CMD payload parameter /sbin/ifconfig is actually spawned from the /bin/sh shell using the -c option.
$ man sh ... -c Read commands from the command_string operand instead of from the standard input.
Just for good measure, I’ve included the image flow diagram generated from sctest.
We need to convert from dot to jpg format
$ dot libemu-exec.dot -Tjpeg > libemu-exec.jpg $ file libemu-exec.jpg libemu-exec.jpg: JPEG image data, JFIF standard 1.01, comment: "CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), default quality"
Not the very best example to use this feature for but hey, it confirms what we observed.
Testing
We’ll change the msfpayload output to c for easy input into our c shellcode template for testing.
$ msfpayload linux/x86/exec CMD=/sbin/ifconfig 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/exec - 50 bytes * http://www.metasploit.com * VERBOSE=false, PrependFork=false, PrependSetresuid=false, * PrependSetreuid=false, PrependSetuid=false, * PrependSetresgid=false, PrependSetregid=false, * PrependSetgid=false, PrependChrootBreak=false, * AppendExit=false, CMD=/sbin/ifconfig */ unsigned char buf[] = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68" "\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x0f\x00\x00\x00\x2f" "\x73\x62\x69\x6e\x2f\x69\x66\x63\x6f\x6e\x66\x69\x67\x00\x57" "\x53\x89\xe1\xcd\x80";
Final shellcode test file.
#include<stdio.h> #include<string.h> /* * linux/x86/exec - 50 bytes * http://www.metasploit.com * VERBOSE=false, PrependFork=false, PrependSetresuid=false, * PrependSetreuid=false, PrependSetuid=false, * PrependSetresgid=false, PrependSetregid=false, * PrependSetgid=false, PrependChrootBreak=false, * AppendExit=false, CMD=/sbin/ifconfig */ unsigned char code[] = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68" "\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x0f\x00\x00\x00\x2f" "\x73\x62\x69\x6e\x2f\x69\x66\x63\x6f\x6e\x66\x69\x67\x00\x57" "\x53\x89\xe1\xcd\x80"; main() { printf("Shellcode Length: %d\n", sizeof(code)-1); int (*ret)() = (int(*)())code; ret(); }
Compile shellcode
$ gcc -o ./execve_shellcode_skeleton shellcode_skeleton.c -fno-stack-protector -z execstack
Run shellcode
$ ./execve_shellcode_skeleton Shellcode Length: 50 eth0 Link encap:Ethernet HWaddr 00:0c:29:77:e6:0b inet addr:192.168.244.130 Bcast:192.168.244.255 Mask:255.255.255.0 inet6 addr: fe80::20c:29ff:fe77:e60b/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:136005 errors:0 dropped:0 overruns:0 frame:0 TX packets:94907 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:79219580 (75.5 MiB) TX bytes:16993657 (16.2 MiB) Interrupt:19 Base address:0x2000 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:4388 errors:0 dropped:0 overruns:0 frame:0 TX packets:4388 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:280380 (273.8 KiB) TX bytes:280380 (273.8 KiB)
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
Reblogged this on youremindmeofmymother.