Shellcode Analysis

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:


Student ID: SLAE-1517

SLAE Assignment #5 - Analysis of Linux/x86 msfpayload shellcodes

          - Use GDB/ndisasm/libemu to dissect the functionality of the shellcode


For this assignment, I will be using the first three Linux/x86 payloads generated by msfvenom (formerly msfpayload)

0x1 - linux/x86/adduser

A quick ndisasm gives us the following:

msfvenom -p linux/x86/adduser -f raw | ndisasm-u -

The first obvious ones are the 4-dwords:

           push dword 0x64777373
           push dword 0x61702f2f
           push dword 0x6374652f

The following dwords (in little-endian) are the hex representation of /etc//passwd as shown below:

However, it is still unclear as to what is being done to the /etc//passwd file. I think this is where we can use gdb to see what system calls are being invoked.

I generated the shellcode from msfvenom, loaded it in shellcode.c, compiled and loaded in gdb.

Once loaded in gdb...we first set a breakpoint for shellcode: break *&code 

We can see again the /etc//passwd in lines +15, +20, +25. We can also see several int 0x80 (lines +7, +35, +86, +91) for the system calls. We can add breakpoints on these lines to see what system calls are loaded into eax. 

Note: Here is a list of all the system calls with their corresponding call numbers found in /usr/include/i86-linux-gnu/asm/unistd_32.h

Syscall #1:  eax has 46 or setgid() loaded to it.

setgid() call is pretty straight forward. This call sets a user's group id. In this case, the group id is set to 0 as seen in the first two lines. The function calls only require one argument, in this case 0 is loaded into ebx (mov ebx, ecx) as the argument. 

                                                  root@kali:~/SLAE# id
uid=0(root) gid=0(root) groups=0(root)

Syscall #2: eax has 5 or open() loaded to it.

open() here opens /etc/passwd file for the pathname and sets the flags to O_RDWR (Read/Write). This step will require root access hence why setgid()  was called first and set the user's group id to 0.

                             push   0x64777373
                             push   0x61702f2f
                             push   0x6374652f

Syscall #3: eax has 4 or write() loaded to it.

write() has 3 arguments (fd, *buf, count). count writes up to count bytes from the buffer pointed buf to the file referred to by the file descriptor fd.

The following is what gets written in to /etc/passwd file.
PASS=password (in this case it is hashed)

syscall #4: eax has 1 or exit() loaded to it....enough said.

0x2 - linux/x86/chmod

We again generate a shellcode with the following options:


Compile and we load the file in gdb.

We put a breakpoint at the system  call @ +37 (0x804a065)

Syscall: eax has 15 or chmod() loaded to it.

chmod() requires two arguments: pathname and mode

pathname: /home/slae/test.txt (ebx)

mode: 0777 (ecx) 

Here we can see 0x1ff (0777) pushed to the stack and popped into ecx

0x3 - linux/x86/exec

We generate a shellcode with the following option:


Compile and load it in gdb

We put a breakpoint at the system call @ +42 (0x0804a06a)

syscall: eax has 11 or execve() loaded to it.

Here we see the first part of the string for the command /bin/sh -c loaded into ebx.

The next string should be ifconfig, however, I couldn't find it using gdb. I ended up using ndisasm for this next step.

Call dword 0x26 is what we are looking for. Looking at 1D to 24, we can see that these are the opcodes for ifconfig. 

Furthermore, plugging the next opcodes (26 through 29) shows how the entire command string (/bin/sh -c ifconfig) is pushed into the stack (esp), and loaded into ecx

Thank you for reading.