Take each shellcode and analyze it to understand what it does
Place it in a sample stub c program to try it out to make sure it
works before modification
Modify the shellcode with garbage instructions and equivalent
Place the modified shellcode into the stub c program and verify that
it continues to work properly
The source code for this exercise can be found here
Shellcode 1: Reboot
The shellcode for rebooting a system looks like the following. I have
converted the AT&T syntax to Intel but other than that the commands
are the same. Lets analyze it and try to understand what it does.
This looks pretty familiar. The shellcode simply populates the registers
with the arguments that execve requires:
And then executes it. Lets go ahead and throw it in a stub c program and
make sure it works but before we do, lets write a little bash function to
place in our .bashrc as I’ve grown tired having to derive the proper
command line incantation to dump the shellcode of a binary. Here we go:
Note: if placing shellcode in cstub doesn’t work it may be because
the cut -f needs to be adjusted to account for the columns of opcodes
in the objdump -d output.
There is our shellcode. Lets throw it in our stub C program. Actually, I’ve
grown tired of doing that too. Lets write a function to do that for us:
Excellent. That should speed up productivity. We can see from the
output that when we execute the shellcode c program that it does
in fact try to run (although you need to be root to reboot the system).
Since we know that it works, lets start making it polymorphic.
Ploymorphic Reboot Shellcode
Returning to our original shellcode, replace some instructions
with equivalent instructions and add some NOP garbage as well:
Lets compile our new polymorphic reboot version and see if it still works:
After our obfuscation our shellcode still works. Perfect. The size of the
shellcode has grown from 36 to 52 bytes. We have kept it under the 150% size
increase limitation. Next up…
Shellcode 2: ASLR Deactivation
The next shellcode disables ASLR on Linux x86 systems. It can be found
again, lets do some analysis before we go and try to run it.
Everything seems to look safe to run. Looking at the permissions
of /proc/sys/kernel/randomize_va_space we see that it is owned by
root and can only be written to by root:
This indicates that our shelllcode will need to be run as root to be
effective. If we compile and run the shellcode with sudo we see that
it in fact does change the randomization value from 2 to 0. Let’s
add in some polymorphism and see if we can keep it under 124 bytes
as we neet to stay under 150% of the original 83 byte size.
Polymorphic ASLR Deactivation Shellcode
After compiling and running we see:
It still works after the polymorphic adjustments. And the byte
Cool. Our byte length is under the 124 byte limit and works as expected!
Interesting… So this shellcode will delete the /etcpasswd file. This
would probably cause a little havoc on a system. Luckily we are using
a vm! Even though we know it is probably going to break our vm, lets
analyze the code just to see exactly how it works.
Lets first take the shellcode provided in it’s C form, compile,
throw it in gdb and extract the assembly code:
So the first thing that jumps out about this shellcode is that it
appears to be utilizing the jmp call pop technique.
Ok. So what is this code acquiring the address of? Well, the code
after the call seems to be a bit cryptic which could mean that this is
actually a string. Lets have a look…
If we put a breakpoint right after the pop call and use x/s $esi we
can investigate if a string is pointed to by esi.
Sure enough it appears that esi points to the string
/etc/passwd. That makes sense as that is the file this code is
supposed to unlink.
Ok, continuing with our analysis:
So everything is accounted for. This shellcode appears to do exactly
what the title says it should do. Lets test it out and see if it in
fact deletes the /etc/passwd file…
LOL! So kids, don’t try this at home unless you can reset your vm!
Lets get our polymorphism on.
Polymorphic Unlink /etc/passwd and Exit Shellcode
First we need to replicate the jump, call, pop setup of the original
Next we move some things around to make our code unique:
Lets see if our polymorphed instructions still accomplish their goal:
Beautiful! It deletes our /etc/passwd file as we hoped :) We end up
with a 39 byte shellcode, the original being only 35 bytes so we are
within our 150% increase.