Tuesday, May 2, 2017

8 - Shell exploitation on ARM architecture emulated with QEMU by debugging with GDB


- Layout for this exercise:

- This is an exercise based on the previous one, running the executable confidential in an ARM architecture emulated with Qemu.

- Before starting the exercise let's ensure that ASLR is disabled:

- Launching the debugger GDB for the program confidential:

- Setting up a breakpoint for the vulnerable function vfunction():

- Starting the debugging for the binary, for instance with just a simple parameter like A:

- The function erand48() is part of the general set of commands for Linux:

- Disassembling erand48():

- What actually makes erand48() interesting in this exercise is the section starting at 0x40057148. Let's examine the instructions of that section one by one:

a) ldm sp,{r0,r1} ->  loads 4 Bytes pointed by r0 and another 4 Bytes by r1 into the SP
b) add sp,sp,#12 -> prepares the Stack for making room for next instructions
c) pop {lr} -> pops the content of the top of the Stack to LR
d) bx lr -> jumps to LR

- Actually, any other alternative function to erand48() could be used, having similar functionality to the quoted section.

- On the other hand, it is also very useful the function system(), what executes a shell command, in this case "/bin/sh":

- system() is located at address 0x4005ed34:

- Now, let's pass the crafted parameter to the program:

- Let's examine all parts of the parameter:

a) AAAABBBBCCCCDDDD allows to reach LR (see previous exercise)

b) \x48\x71\x05\x40 is the Little Endian format for the address of the instruction ldm sp,{r0,r1} (0x40057148). 

c) XXXX would be the "/bin/sh" address, which location we don't know at this moment, that will be pass as the r0 argument.

d) YYYY would be padding for r1 and ZZZZ for the next instruction.

e) \x34\xed\x05\x40 is the address location where the function system() starts (0x4005ed34)

f) finally, the command "/bin/sh" itself that will be passed to system(), like system(/bin/sh)

- Entering the whole parameter, the program debugging is restarted from the beginning and the breakpoint for vfunction() is hit:

- Stepping one instruction:

- At this moment the sections of the parameter are located in these memory addresses of the Stack:

- Actually, the address for "/bin/bash" is 0xbefffc18:

- Now, we can replace XXXX with 0xbefffc18 in Little Endian format (\x18\xfc\xff\xbe):

- Passing the whole parameter, and restarting the debugging from the beginning:

- Stepping on instruction:

- Stepping another instruction the program enters the function erand48():

- Stepping another instruction the program enters the function system():

- At this moment, the registers hold these values:

 - It is interesting to notice that the register SP points to 0xbefffc18 ("/bin/sh") and LR points to 0x4005ed34 (system())

- Stepping another instruction, system() calls to "/bin/bash" and eventually a shell with root privileges is achieved::

- Also, the successful of the exploitation can be checked passing the parameter directly, not debugging with GDB: