In this blog post, we will analyze shellcodes created from msfvenom. We will focus on Linux – x86 as the target OS and architecture.
Let’s begin by listing all the available shellcodes for Linux x86 architecture.

Shellcodes to be analyzed:
# | Name | Description |
1 | Linux/x86/exec | Execute an arbitrary command |
2 | linux/x86/adduser | Create a new user with UID 0 |
3 | linux/x86/shell_find_tag | Spawn a shell on an established connection (Proxy/nat safe) |
Tools used:
- GDB-peda
- ndisasm
1. linux/x86/exec
Let us generate our payload to examine it.

Here, I have used the “pwd” command as an argument to the payload. Hence, when the payload will be executed, the “pwd” command will be executed on the victim’s machine. Below is the output:

Running strings on the generated payload shows us that “/bin/sh” is being used in the payload somewhere.

Now let’s get into the real thing and start analyzing the actual shellcode we generated as seen in Fig. 1.
We will pass the generated raw bytes to a c harness and compile the file for analysis.

And compile it using:
gcc -z execstack -fno-stack-protector payload.c -o payload
Let’s load the generated “payload” file in gdb and trace through the instructions.

After hitting our breakpoint at “buf” as seen above, we will disassemble the program by using the disass command in gdb and analyse the instructions. The analysis is shown in the below section wherein a comment has been mentioned describing each instruction being executed.
push 0xb ; Pushing "11" as hex on the stack
pop eax ; Popping the top of the stack (11) inside EAX
cdq
push edx ; Pushing EDX (Null) on the stack which is empty
pushw 0x632d ; Pushing "c-" on the stack (Little Endian)
mov edi,esp ; Moving stack pointer in EDI. (-c)
push 0x68732f ; Pushing "hs/" on the stack. (/sh)
push 0x6e69622f ; Pushing "nib/" on the stack. (/bin). Now the stack contains (/bin/sh)
mov ebx,esp ; Moving stack pointer in EBX
push edx ; Pushing EDX (Null) on the stack which is empty
call 0x804a061 <buf+33>
jo 0x804a0d6
add BYTE PTR fs:[edi+0x53],dl
mov ecx,esp
int 0x80
add BYTE PTR [eax],al
As observed, an execve syscall is being made as EBX contains the value 11.
The registers hold the following contents as of now:
EAX = 11
EBX = Pointer to “/bin/sh“
EDI = Pointer to “-c“
ESP = NULL
As per execve’s man reference, the synopsis is described as –
int execve(const char *filename, char *const argv[], char *constenvp[]);
As of now, EAX holds the expected value. EBX must contain the name of the binary which as of now is pointing to /bin/sh which is also correct. ECX must contain the arguments to the binary terminated by a NULL character and by convention the first string has to be the name of the binary to be executed (/bin/sh) and EDX must contain the environment variables which in our case can be NULL.
So as per our analysis so far, we have satisfied EAX (Syscall number) and EBX (Binary to execute – /bin/sh). We are yet to fully pass the arguments in ECX register which in our case should be “-c pwd”. However, we have already stored -c in EDI. Now let’s place a breakpoint at the next call instruction and furhter analyse from there.

Once we break at 0x804a058 (call to address 0x804a061) and step by one, the address to the next instruction gets populated on the stack, which is 0x804a05d. If we analyze the address on the stack by character bytes, we notice the address points to the bytes 0x70, 0x77 and 0x64 which if converted to ASCII leads to – pwd.

So now the stack (ESP) contains an address which points to pwd. Let’s reiterate over our contents of our registers before moving forward:
EAX = 0xb (11)
EBX = Pointer to “/bin/sh”
EDI = Pointer to “-c”
ESP = Pointer to “pwd”, Pointer to NULL
Now let’s analyse the call to 0x804a061.

As we can see, the address points to 0xe1895357. Let’s try to analyse the address as instruction.

As expected, the instruction is – push EDI, which is nothing but a push “-c” as EDI contains a pointer to “-c”.
Now, from top to bottom the contents of the stack are – “-c pwd NULL”
Moving further, stepping by one, the next instruction pointed by address 0x804a062 contains a PUSH EBX as seen below.

As we already know, EBX contains a pointer to “/bin/sh” which now simply gets pushed on top of the stack. Now if you see, the contents of the stack look something like this:
/bin/sh/ |
-c |
pwd |
NULL |
And the next instruction at 0x804a063 as seen in the above screenshot is simply moving the stack pointer into ECX.
Now if we take a look at the contents of the registers, we get:
EAX = 11
EBX = Pointer to “/bin/sh“
ECX = Pointer to “/bin/sh”, “-c”, “pwd”, NULL
EDX = 0x0 (Never utilised)
The above registers satisfy the requirements of execve syscall requirements as seen in the man reference. The next instruction as seen in the above screenshot is an interrupt 80 which executes the syscall and our payload gets executed.

That’s all for the first shellcode, the remaining two shellcodes will be discussed in the next part.
Links:
Part 2 – linux/x86/adduser
Part 3 – linux/x86/shell_find_tag