This blog post has been created for completing the requirements for the SecurityTube Linux Assembly Expert certification: http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert
Student ID: SLAE-824
- Choose at least 3 shellcode samples created using Msfvenom for linux/x86
- Use GDB/Ndisasm/Libemu to dissect the functionality of the shellcode
- Present your analysis
Source code for this assignment can be found here
For this analysis I have chosen to analyze
linux/x86/exec. My initial
instinct is that this payload essentially just runs
the supplied arguments. Let’s see if thats how it plays out!
First we need to see what options this payload supports:
It looks as though the only basic option is the command we want to run. Seems logical, lets generate some assembly.
Lets break down the code and see what it is doing:
We know from previous exercises that syscall 11 is execve. We can verify that this code actually calls execve by running it through libemu:
Sure enough we can see that it does in fact call execve as hypothesized. Let’s keep going:
Since the call instruction is executing code at an offset in the
shellcode our disassembler has failed us making the instructions
after the call seem random and non-sensical. libemu seems to
have gotten them right but we can also drop the bytes
57 53 89 e1 cd 80 into our favorite online disassembler
Another trick is to use a bit of perl like so:
Looking at the results we get:
These look a little more logical. Before we talk about
these instructions though, what about the bytes
69 64 00
that lie between the call instruction and these bytes
that we just disassembled and that the call instruction
00 is often used to null terminate
a string. We also know that
69 64 falls within the range
of ascii values. Consulting the ascii table we determine that
69 is lowercase
i and 64 is lowercase
d. Right! this is the
command that we configured to run on the machine…
We also know that a call instruction places the next instruction
onto the stack. This means that
69 64 00 57 would be placed
on the stack. The 57 will never be reached because the null
terminator will terminate the string.
Next, the values of edi (the pointer to the -c argument) and ebx (the
pointer to /bin/sh) are pushed onto the stack. Since a pointer to
id was already pushed onto the stack via the invocation
call instruction, the stack will contain
/bin/sh -c id.
A pointer to those arguments are placed into ecx.
We can confirm this by loading our code in the usual sample program and using GDB to step through the program and look at the state of the stack.
Reminding ourselves of the signature of
execve we see:
We then call our
int 0x80 interupt and execute our command.