SLAE: linux_x86_exec Shellcode Analysis

Intro

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: SLAE-924

The task is to:

  • Take up at least 3 shellcode samples created using MSFpayload for linux/x86
  • Use gdb_ndisasm_libemu to dissect the functionality of the shellcode
  • present your analysis

The first shellcode we will examine is linux/x86/exec.

msfvenom -p linux/x86/exec --payload-options

Basic option is CMD.

Let’s generate our shellcode:

msfvenom -p linux/x86/exec CMD=whoami -f c

That’s it

msfvenom -p linux/x86/exec CMD=whoami -f c
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 42 bytes
Final size of c file: 201 bytes
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\x07\x00\x00\x00\x77"
"\x68\x6f\x61\x6d\x69\x00\x57\x53\x89\xe1\xcd\x80";

Let’s put it into c template file and compile it:

 gcc shellcode.c -z execstack
./a.out

It works and whoami command executes. Sample image

Analyzing shellcode in gdb

Now let’s see how it works in gdb. I recommend also to install peda which is available here.

pagliacci@pagliacci-ubuntu:~$ gdb -q ./a.out
Reading symbols from /home/pagliacci/a.out...(no debugging symbols found)...done.
gdb-peda$ set disassembly-flavor intel
gdb-peda$
gdb-peda$ print /x &code
$1 = 0x804a040
gdb-peda$  break *0x804a040
Breakpoint 1 at 0x804a040
gdb-peda$ run
Shellcode Length:  15

Sample image

To move to the next instruction you can use stepi.

That’s what we’ve get:

0x804a040 <code>:	push   0xb                
0x804a042 <code+2>:	pop    eax            ;0xb to eax
0x804a043 <code+3>:	cdq                   ;zero out edx
0x804a044 <code+4>:	push   edx            ;push zero byte to the stack
0x804a045 <code+5>:	pushw  0x632d         ;pushing -c to the stack
0x804a049 <code+9>:	mov    edi,esp        ;now edi points to the stack with -c, terminated by the zero
0x804a04b <code+11>:	push   0x68732f     ;pushing ('hs/') to the stack
0x804a050 <code+16>:	push   0x6e69622f   ;pushing ('nib/') to the stack (now it contains /bin/sh)
0x804a055 <code+21>:	mov    ebx,esp      ;now ebx points to /bin/sh
0x804a057 <code+23>:	push   edx          ;push zero to the stack
0x804a058 <code+24>:	call   0x804a064    ;address of "whoami" is pushed to the stack through call
0x804a064 <code+36>:	push   edi          ;push pointer to -c
0x804a065 <code+37>:	push   ebx          ;push pointer to /bin/sh

Now we’ve put all necessary values for the execve system call to the stack. Now stack looks like this:

0000| 0xbffff67e --> 0xbffff68e ("/bin/sh")
0004| 0xbffff682 --> 0xbffff696 --> 0x632d ('-c')
0008| 0xbffff686 --> 0x804a05d ("whoami")

After that we will move the value of the esp register to the ecx. So now:

  • eax is set to 0xb, which is the syscall number for execve
  • ebx points to /bin/sh
  • ecx points to argv[] which is { “_bin_sh”, “-c”, “whoami” } And now we can call interrupt.
0x804a066 <code+38>:	mov    ecx,esp       ;ecx now points to the top of the stack: where:
                                           ;/bin/sh
                                           ;-c
                                           ;"whoami"

0x804a068 <code+40>:	int    0x80          ;call execve

And finally we get it: Sample image

That’s how it works!