leg

References

重點摘要

  • ARM組合語言
  • ARM Mode和Thumb Mode
  • 暫存器的用途,例如pc、r0、lr

Problem

Daddy told me I should study arm.
But I prefer to study my leg!

Download : http://pwnable.kr/bin/leg.c
Download : http://pwnable.kr/bin/leg.asm

ssh [email protected] -p2222 (pw:guest)

Source Code

  • C
    #include <stdio.h>
    #include <fcntl.h>
    int key1(){
      asm("mov r3, pc\n");
    }
    int key2(){
      asm(
      "push    {r6}\n"
      "add    r6, pc, $1\n"
      "bx    r6\n"
      ".code   16\n"
      "mov    r3, pc\n"
      "add    r3, $0x4\n"
      "push    {r3}\n"
      "pop    {pc}\n"
      ".code    32\n"
      "pop    {r6}\n"
      );
    }
    int key3(){
      asm("mov r3, lr\n");
    }
    int main(){
      int key=0;
      printf("Daddy has very strong arm! : ");
      scanf("%d", &key);
      if( (key1()+key2()+key3()) == key ){
          printf("Congratz!\n");
          int fd = open("flag", O_RDONLY);
          char buf[100];
          int r = read(fd, buf, 100);
          write(0, buf, r);
      }
      else{
          printf("I have strong leg :P\n");
      }
      return 0;
    }
    
  • Assembly
    (gdb) disass main
    Dump of assembler code for function main:
     0x00008d3c <+0>:    push    {r4, r11, lr}
     0x00008d40 <+4>:    add    r11, sp, #8
     0x00008d44 <+8>:    sub    sp, sp, #12
     0x00008d48 <+12>:    mov    r3, #0
     0x00008d4c <+16>:    str    r3, [r11, #-16]
     0x00008d50 <+20>:    ldr    r0, [pc, #104]    ; 0x8dc0 <main+132>
     0x00008d54 <+24>:    bl    0xfb6c <printf>
     0x00008d58 <+28>:    sub    r3, r11, #16
     0x00008d5c <+32>:    ldr    r0, [pc, #96]    ; 0x8dc4 <main+136>
     0x00008d60 <+36>:    mov    r1, r3
     0x00008d64 <+40>:    bl    0xfbd8 <__isoc99_scanf>
     0x00008d68 <+44>:    bl    0x8cd4 <key1>
     0x00008d6c <+48>:    mov    r4, r0
     0x00008d70 <+52>:    bl    0x8cf0 <key2>
     0x00008d74 <+56>:    mov    r3, r0
     0x00008d78 <+60>:    add    r4, r4, r3
     0x00008d7c <+64>:    bl    0x8d20 <key3>
     0x00008d80 <+68>:    mov    r3, r0
     0x00008d84 <+72>:    add    r2, r4, r3
     0x00008d88 <+76>:    ldr    r3, [r11, #-16]
     0x00008d8c <+80>:    cmp    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.
    (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
     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.
    (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
     0x00008d06 <+22>:    adds    r3, #4
     0x00008d08 <+24>:    push    {r3}
     0x00008d0a <+26>:    pop    {pc}
     0x00008d0c <+28>:    pop    {r6}        ; (ldr r6, [sp], #4)
     0x00008d10 <+32>:    mov    r0, r3
     0x00008d14 <+36>:    sub    sp, r11, #0
     0x00008d18 <+40>:    pop    {r11}        ; (ldr r11, [sp], #4)
     0x00008d1c <+44>:    bx    lr
    End of assembler dump.
    (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
     0x00008d2c <+12>:    mov    r0, r3
     0x00008d30 <+16>:    sub    sp, r11, #0
     0x00008d34 <+20>:    pop    {r11}        ; (ldr r11, [sp], #4)
     0x00008d38 <+24>:    bx    lr
    End of assembler dump.
    (gdb)
    

Writeup

  • 從source code得知輸入的key值要等於key1()+key2()+key3()
    scanf("%d", &key);
      if( (key1()+key2()+key3()) == key ){
    
  • key1():r3等於pc,pc是指向當前位址的下兩個位址,因為兩個位址是8 bytes,所以pc就是指向pc+8的位址,也就是0x00008cdc+8
    int key1(){
      asm("mov r3, pc\n");
    }
    
    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
     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~r3暫存器通常作為函數的返回值

  • key2()
    • 首先注意這邊,會從原本arm mode切換至thumb mode,此時的指令集從原本的32 bits變為16 bits,因此pc指向的位址也從原本的pc+8變為pc+4
      0x00008cfc <+12>:    add    r6, pc, #1
      0x00008d00 <+16>:    bx    r6
      
    • 由於r0=r3,而r3=r3+4,而r3又等於pc,所以最後r0就等於0x00008d04+4+4
      int key2(){
      asm(
      "push    {r6}\n"
      "add    r6, pc, $1\n"
      "bx    r6\n"
      ".code   16\n"
      "mov    r3, pc\n"
      "add    r3, $0x4\n"
      "push    {r3}\n"
      "pop    {pc}\n"
      ".code    32\n"
      "pop    {r6}\n"
      );
      }
      
      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
      0x00008d06 <+22>:    adds    r3, #4
      0x00008d08 <+24>:    push    {r3}
      0x00008d0a <+26>:    pop    {pc}
      0x00008d0c <+28>:    pop    {r6}        ; (ldr r6, [sp], #4)
      0x00008d10 <+32>:    mov    r0, r3
      0x00008d14 <+36>:    sub    sp, r11, #0
      0x00008d18 <+40>:    pop    {r11}        ; (ldr r11, [sp], #4)
      0x00008d1c <+44>:    bx    lr
      End of assembler dump.
      
  • key3():r0=r3,r3=lr,lr是儲存副程式key3()的返回位址,也就是main裡的0x00008d80
    0x00008d7c <+64>:    bl    0x8d20 <key3>
    0x00008d80 <+68>:    mov    r3, r0
    
    int key3(){
      asm("mov r3, lr\n");
    }
    
    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
     0x00008d2c <+12>:    mov    r0, r3
     0x00008d30 <+16>:    sub    sp, r11, #0
     0x00008d34 <+20>:    pop    {r11}        ; (ldr r11, [sp], #4)
     0x00008d38 <+24>:    bx    lr
    End of assembler dump.
    

    :LR(Link Register)會儲存副程式的返回位址

  • 最後將key1()、key2()和key3()做相加:
    • 0x00008cdc+8+0x00008d04+4+4+0x00008d80=108400
  • Result:
    / $ ./leg
    Daddy has very strong arm! : 108400
    Congratz!
    My daddy has a lot of ARMv5te muscle!
    

results matching ""

    No results matching ""