ARM exploitation for IoT – Episode 3

In the previousepisodes we have seen some basic concepts regarding ARM reversing and shellcode writing.
In this last part will see a brief introduction to exploit writing and we’ll keep it as simple as possible.

The compiler suggest not to use the gets() deprecated function, never overlook the compiler’s warnings ;), for example an alternative could be to use the fgets() function, but our goal is to prove that the above code can actually be dangerous.

Let’s start from here:

echo `python -c 'print "A"*41'` | ./stack1

as we expect, there is a segmentation fault

Let’s analyze the crash, open gdb and set a breakpoint at the instruction:

We can notice that there is a function that contains a small sequence of instructions (rop_func).

The strategy that we will use is not the only way to exploit the program.

The strategy which we will adopt is to use the “write” function to print the address of the “read” function (leak), from here we can calculate the address of the “system” function and run it with the “/bin/sh” argument.

We can summarize:

Get the address of the system function

Execute system(/bin/sh)

Get the address of the system function

Start the program and set a breakpoint at line

-> 12 read(0, message, 256);

the payload to send is

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Go on with the next instruction

gef> next
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

It is a simple server that is listening on the 4444 port, we can insert a note, show all the notes, edit a note, delete the last note, set an address, change the welcome message, it is also possible to print some debugging info.

A few observations:

virtual method show_all_notes()

stack_pivot() function

stack_info() function

delete and set_address() function

Observation 1 – virtual method show_all_notes()

If we look into the edit_obj object

we can see that the first 4 bytes are a pointer to the vtable, and the first address of the vtable is the pointer to the code of the “show_all_notes” virtual function

Observation 2 – stack_pivot() function

With the stack_pivot() function if we have the control of “r4 + #0x0c” we can set the stack with an address that we have under control.

Observation 3 – stack_info() function

A string format vulnerability in the stack_info() function

Observation 4 – delete and set_address() function

In the case4 the edit_obj is deleted, then if this object will be used we will have the UAF vulnerability. The purpose of the set_address function is to try to allocate in the heap an object with the size equal to the size of the deleted object.

I summarize the strategy that we will use in the following steps:

We use case 9 to take the address of the libc and also of the wel_msg and roulette variables

Free the memory and allocate the hole

We use the address of the wel_msg to keep the value of the new stack and the shellcode

Let’s see in details

1- We use case 9 to take the address of the libc and also of the wel_msg and roulette variables

Let’s analyze the stack_info functions

we will use the format string vulnerability only for arbitrary read from the stack, if we send this payload

0x%08x,0x%08x,0x%08x,0x%08x

we get the following output

0x00000000,0x76fb2f0c,0x0002a3f4,0xffffffff

Let’s look at the address 0x76fb2f0c

We could calculate the base address of the libc by offset, in our case the libc base address is 0x76c85000

We can put everything together for a little test, then start the server

gdb ./uaf

For do this test I used

And type 9 and after this payload

0x%08x.0x%08x.0x%08x

Then insert the following 3 notes (case 1)

“AAAA”

wel_msg address

“BBBB”

As mentioned before, we will use the “wel_msg” array to keep the values of the new stack and the shellcode (we will use the reverse shell shellcode), then in order to edit this array we must use the “change the message” case.