(gdb) disass main
Dump of assembler code for function main:
   0x00008d3c <+0>:    push    {r4, r11, lr} ; stack에 r4, r11, lr의 값을 넣는다.
   0x00008d40 <+4>:    add    r11, sp, #8    ; r11에 sp+8의 값을 넣는다.
   0x00008d44 <+8>:    sub    sp, sp, #12 ; sp를 12만큼 감소시킨다.
   0x00008d48 <+12>:    mov    r3, #0 ; r3에 0을 넣는다.
   0x00008d4c <+16>:    str    r3, [r11, #-16] ; r3의 스택값(=0)을 r11-16(=sp-8) 주소에 넣는다.
   0x00008d50 <+20>:    ldr    r0, [pc, #104] ; pc+104<main+132>에 r0의 주소값을 넣는다.
   0x00008d54 <+24>:    bl    0xfb6c <printf> ; call printf
   0x00008d58 <+28>:    sub    r3, r11, #16 ; r3에 r11-16(=sp-8)의 값을 넣는다.
   0x00008d5c <+32>:    ldr    r0, [pc, #96]    ; 0x8dc4 <main+136>에 r0의 주소값을 넣는다.
   0x00008d60 <+36>:    mov    r1, r3 ; r1에 r3의 값(sp-8)을 넣는다.
   0x00008d64 <+40>:    bl    0xfbd8 <__isoc99_scanf> ; call scanf
   0x00008d68 <+44>:    bl    0x8cd4 <key1> ; call key1
   0x00008d6c <+48>:    mov    r4, r0 ; r4에 r0의 값을 넣는다.
   0x00008d70 <+52>:    bl    0x8cf0 <key2> ; call key2
   0x00008d74 <+56>:    mov    r3, r0 ; r3에 r0의 값을 넣는다.
   0x00008d78 <+60>:    add    r4, r4, r3 ; r4에 r4+r3의 값을 넣는다.
   0x00008d7c <+64>:    bl    0x8d20 <key3> ; call key3
   0x00008d80 <+68>:    mov    r3, r0 ; r3에 r0의 값을 넣는다.
   0x00008d84 <+72>:    add    r2, r4, r3 ; r2에 r4+r3의 값을 넣는다.
   0x00008d88 <+76>:    ldr    r3, [r11, #-16] ; r3에 r11-16에 있는 값을 넣는다.
   0x00008d8c <+80>:    cmp    r2, r3 ; r2와 r3가 같냐
   0x00008d90 <+84>:    bne    0x8da8 <main+108>
   0x00008d94 <+88>:    ldr    r0, [pc, #44]    ; 0x8dc8 <main+140>
   0x00008d98 <+92>:    bl    0x1050c <puts>
   0x00008d9c <+96>:    ldr    r0, [pc, #40]    ; 0x8dcc <main+144>
   0x00008da0 <+100>:    bl    0xf89c <system>
   0x00008da4 <+104>:    b    0x8db0 <main+116>
   0x00008da8 <+108>:    ldr    r0, [pc, #32]    ; 0x8dd0 <main+148>
   0x00008dac <+112>:    bl    0x1050c <puts>
   0x00008db0 <+116>:    mov    r3, #0
   0x00008db4 <+120>:    mov    r0, r3
   0x00008db8 <+124>:    sub    sp, r11, #8
   0x00008dbc <+128>:    pop    {r4, r11, pc}
   0x00008dc0 <+132>:    andeq    r10, r6, r12, lsl #9
   0x00008dc4 <+136>:    andeq    r10, r6, r12, lsr #9
   0x00008dc8 <+140>:            ; <UNDEFINED> instruction: 0x0006a4b0
   0x00008dcc <+144>:            ; <UNDEFINED> instruction: 0x0006a4bc
   0x00008dd0 <+148>:    andeq    r10, r6, r4, asr #9
End of assembler dump.

ARM(Advanced Risc Machine)

레지스터

  • R0~R12 : 범용 레지스터, 인자값 및 임시 계산 저장소 등
  • R13(SP) : Stack Pointer
  • R14(LR) : Link Register, 함수 호출 전 LR에 리턴 주소를 저장하고 점프한다. (기존에는 스택에 저장하는 방식)
  • PC : EIP 역할

PC가 가르키고 있는 곳

cpu는 명령어를 실행하는 데에 있어서 fetch -> decode -> execute라는 과정을 거치고 그래서 어떤 명령어를 execute할 때 그 다음 명령어는 deocde되고 또 다음 명령어는 fetch된다. pc는 CPU가 현재 실행하고 있는 명령어의 주소(fetch되고 있는 것)를 가리킨다.

How to Exploit

ARM 코드는 처음이니 직접 한 줄씩 해석해보았다. 중요한 것은 key함수가 call 되고 나서 r0의 값이 key함수의 리턴값이므로 각 r0의 값을 구하자.

(gdb) disass key1
Dump of assembler code for function key1:
   0x00008cd4 <+0>:    push    {r11}        ; (str r11, [sp, #-4]!)
   0x00008cd8 <+4>:    add    r11, sp, #0
   0x00008cdc <+8>:    mov    r3, pc ; 이 때 pc의 값은 0x8ce4이다.
   0x00008ce0 <+12>:    mov    r0, r3
   0x00008ce4 <+16>:    sub    sp, r11, #0
   0x00008ce8 <+20>:    pop    {r11}        ; (ldr r11, [sp], #4)
   0x00008cec <+24>:    bx    lr
End of assembler dump.

r0의 값이 0x8ce4이다.

(gdb) disass key2
Dump of assembler code for function key2:
   0x00008cf0 <+0>:    push    {r11}        ; (str r11, [sp, #-4]!)
   0x00008cf4 <+4>:    add    r11, sp, #0
   0x00008cf8 <+8>:    push    {r6}        ; (str r6, [sp, #-4]!)
   0x00008cfc <+12>:    add    r6, pc, #1
   0x00008d00 <+16>:    bx    r6
   0x00008d04 <+20>:    mov    r3, pc ; r3에 0x8d08 저장
   0x00008d06 <+22>:    adds    r3, #4 ; r3d의 값이 0x8d0c
   0x00008d08 <+24>:    push    {r3}
   0x00008d0a <+26>:    pop    {pc}
   0x00008d0c <+28>:    pop    {r6}        ; (ldr r6, [sp], #4)
   0x00008d10 <+32>:    mov    r0, r3 ; r0의 값이 0x8d0c가 된다.
   0x00008d14 <+36>:    sub    sp, r11, #0
   0x00008d18 <+40>:    pop    {r11}        ; (ldr r11, [sp], #4)
   0x00008d1c <+44>:    bx    lr
End of assembler dump.

r0의 값이 0x8d0c이다.

(gdb) disass key3
Dump of assembler code for function key3:
   0x00008d20 <+0>:    push    {r11}        ; (str r11, [sp, #-4]!)
   0x00008d24 <+4>:    add    r11, sp, #0
   0x00008d28 <+8>:    mov    r3, lr ; r3에 lr의 값 저장
   0x00008d2c <+12>:    mov    r0, r3 ; r0에 r3의 값 저장
   0x00008d30 <+16>:    sub    sp, r11, #0
   0x00008d34 <+20>:    pop    {r11}        ; (ldr r11, [sp], #4)
   0x00008d38 <+24>:    bx    lr
End of assembler dump.

key3 함수가 호출되기 전에 lr의 값을 구하자. key3를 call 하는 다음 instruction의 주소가 0x8d80이며 이것이 lr의 값이다.

0x8ce4+0x8d0c+0x8d80 = 108400

Capture The Flag

image

'Writeup [pwn] > pwnable.kr' 카테고리의 다른 글

memcpy  (0) 2020.03.07
lotto  (0) 2020.03.07
input  (0) 2020.03.07
horcruxes  (0) 2020.03.07
fd  (0) 2020.03.07

+ Recent posts