Arm pwn – Stack overflow

Stack overflow

Arm's program is very alike x86_x64's, but that use register lr(x30) to record the return address of function. It use the intruction bl to call child funciotn.


In short, it behaves like the assembly instructions below in x86_x64.

mov lr, next_instrtion_address
jmp target

In general, it is hard to hijack lr with stack overflow, but we can find other ways to achieve it through analyzing program which was compiled by gcc.

Compiling the following programs by gcc, you'll find out how the stack store function's environment.

void f2()


void f()



Disassembly of section .text:

0000000000000000 <f2>:
   0:   d503201f    nop
   4:   d65f03c0    ret

0000000000000008 <f>:
   8:   a9bf7bfd    stp x29, x30, [sp, #-16]!
   c:   910003fd    mov x29, sp
  10:   94000000    bl  0 <f2>
  14:   d503201f    nop
  18:   a8c17bfd    ldp x29, x30, [sp], #16
  1c:   d65f03c0    ret


00000000 <f2>:
   0:   b480        push    {r7}
   2:   af00        add r7, sp, #0
   4:   bf00        nop
   6:   46bd        mov sp, r7
   8:   f85d 7b04   ldr.w   r7, [sp], #4
   c:   4770        bx  lr

0000000e <f>:
   e:   b580        push    {r7, lr}
  10:   af00        add r7, sp, #0
  12:   f7ff fffe   bl  0 <f2>
  16:   bf00        nop
  18:   bd80        pop {r7, pc}

It is wired for x86_x64 regulation to save ip ans sp in top of the fucntion's stack, but we also can control the value by stack overflow with second-called.

For example, if we can overflow the stack in f2, the programs will be controled when f is finishing.


In arm, we can use pop and push directly, but the instruction set of aarch64 has removed them. It could be reason that aarch64 architecture has too many registers. We also can use ldr and str to replace it.