[Internetwache CTF 2016] ServerfARM write up

[Reversing Challenges List] (https://pastebin.com/q7LGi8w5) の問題。

ARMアーキテクチャのバイナリ。

ARMアーキテクチャについては、以下の2つの記事を見ればだいたい理解できた。

- [Qiitaのまとめ](https://qiita.com/edo_m18/items/a7c747c5bed600dca977 )
- [ももテク](http://inaz2.hatenablog.com/entry/2015/03/06/020239 )



実行環境がないので、アセンブリ言語だけ見て解析する。

解析にはradare2を用いた。

radare2はまだ全然使い方が分かっていないので探り探り。



# main

radare2 で `aaaa` -> `afl` で`main` があったのでそこから解析。

```
pdf @ main
```

関数のコールだけ追っていくと、`malloc` -> `printf` -> `scanf` -> `handle_task` 関数->`free` という感じ。



printf の出力を見てみる。

```
[0x00010580]> pv @ loc._d_15
0x00010e30
[0x00010580]> pvz @ 0x00010e30
Enter Solution for task %d:
```

`%d`  で表示されるのは`[fp-0x8]` なので、これがtaskのIDを表しているらしい。

`handle_task` 関数を`[fp-0x8]` と`scanf` の入力値を引数として呼び出している。



# handle_task

```
[0x00010580]> pdf @ sym.handle_task
|           ;-- $a:
/ (fcn) sym.handle_task 40
|   sym.handle_task ();
|           ; var int local_1ch @ fp-0x1c
|           ; var int local_18h @ fp-0x18
|           ; var int local_10h @ fp-0x10
|           ; CALL XREF from main (0x106f8)
|           0x0001073c      10482de9       push {r4, fp, lr}
|           0x00010740      08b08de2       add fp, sp, 8
|           0x00010744      14d04de2       sub sp, sp, 0x14
|           0x00010748      18000be5       str r0, [local_18h]         ; 0x18 ; 24
|           0x0001074c      1c100be5       str r1, [local_1ch]         ; 0x1c ; 28
|           0x00010750      0030a0e3       mov r3, 0
|           0x00010754      10300be5       str r3, [local_10h]         ; 0x10 ; 16
|           0x00010758      18301be5       ldr r3, [local_18h]         ; 0x18 ; 24
|           0x0001075c      030053e3       cmp r3, 3                   ; 3
\           0x00010760      03f19f97       ldrls pc, [pc, r3, lsl 2]   ; loc._d_16 ; [0x10768:4]=0x10778 loc._a_12 ; "x\a\x01"
```



taskID が `[local_18h]` に`scanf` 入力が`[local_1ch]` に格納され、taskIDが3以下の場合にtaskIDに合わせてpcを変動させている。

ここで、pcが評価させるときにpc + 8として扱われることに注意 ([ももテク](http://inaz2.hatenablog.com/entry/2015/03/06/020239 ) の記事に記載)。

結果としては` pc = [0x00010760 + 8 + 4 * taskID] ` となるので、そこらへんのアドレスを見てみる。

```
[0x00010580]> pd 6 @ 0x00010760
\           0x00010760      03f19f97       ldrls pc, [pc, r3, lsl 2] ; loc._d_16 ; [0x10768:4]=0x10778 loc._a_12 ; "x\a\x01"
        ,=< 0x00010764      6d0000ea       b 0x10920
        |   ;-- $d:
        |   ; CODE XREF from sym.handle_task (0x10760)
        |   0x00010768      .dword 0x00010778 ; loc._a_12
        |   0x0001076c      .dword 0x00010838 ; aav.0x00010838
        |   0x00010770      .dword 0x000108a8 ; aav.0x000108a8
        |   0x00010774      .dword 0x000108f0 ; aav.0x000108f0
```

それぞれ `0x00010778`,  `0x00010838`, `0x000108a8`, `0x000108f0` である。



# task 1

```
[0x00010580]> pd 48 @ 0x00010778
            ;-- $a:
            ; UNKNOWN XREF from loc._d_16 ()
            0x00010778      0030a0e3       mov r3, 0
            0x0001077c      14300be5       str r3, [fp, -0x14]         ; 20
        ,=< 0x00010780      0a0000ea       b 0x107b0
        |   ; CODE XREF from loc._a_12 (+0x4c)
       .--> 0x00010784      14301be5       ldr r3, [fp, -0x14]         ; 20
       :|   0x00010788      1c201be5       ldr r2, [fp, -0x1c]         ; 28
       :|   0x0001078c      033082e0       add r3, r2, r3
       :|   0x00010790      0030d3e5       ldrb r3, [r3]
       :|   0x00010794      0320a0e1       mov r2, r3
       :|   0x00010798      10301be5       ldr r3, [fp, -0x10]         ; 16
       :|   0x0001079c      023083e0       add r3, r3, r2
       :|   0x000107a0      10300be5       str r3, [fp, -0x10]         ; 16
       :|   0x000107a4      14301be5       ldr r3, [fp, -0x14]         ; 20
       :|   0x000107a8      013083e2       add r3, r3, 1
       :|   0x000107ac      14300be5       str r3, [fp, -0x14]         ; 20
       :|   ; CODE XREF from loc._a_12 (+0x8)
       :`-> 0x000107b0      1c001be5       ldr r0, [fp, -0x1c]         ; 28
       :    0x000107b4      65ffffeb       bl sym.imp.strlen           ; size_t strlen(const char *s)
       :    0x000107b8      0020a0e1       mov r2, r0
       :    0x000107bc      14301be5       ldr r3, [fp, -0x14]         ; 20
       :    0x000107c0      030052e1       cmp r2, r3
       `==< 0x000107c4      eeffff8a       bhi 0x10784
            0x000107c8      10401be5       ldr r4, [fp, -0x10]         ; 16
            0x000107cc      1c001be5       ldr r0, [fp, -0x1c]         ; 28
            0x000107d0      5effffeb       bl sym.imp.strlen           ; size_t strlen(const char *s)
            0x000107d4      0030a0e1       mov r3, r0
            0x000107d8      0310a0e1       mov r1, r3
            0x000107dc      0400a0e1       mov r0, r4
            0x000107e0      5f0000eb       bl sym.__aeabi_uidiv
            0x000107e4      0030a0e1       mov r3, r0
            0x000107e8      10300be5       str r3, [fp, -0x10]         ; 16
            0x000107ec      38119fe5       ldr r1, loc._d_17           ; [0x1092c:4]=0x10e50 str.Here_s_your_1._block: ; "P\x0e\x01"
            0x000107f0      38019fe5       ldr r0, aav.0x00010e4c      ; [0x10930:4]=0x10e4c aav.0x00010e4c
            0x000107f4      43ffffeb       bl sym.imp.printf           ; int printf(const char *format)
            0x000107f8      10301be5       ldr r3, [fp, -0x10]         ; 16
            0x000107fc      230053e3       cmp r3, 0x23                ; '#' ; 35
        ,=< 0x00010800      020000da       ble 0x10810
        |   0x00010804      28019fe5       ldr r0, str.I_WAQ3          ; [0x10934:4]=0x10e68 str.I_WAQ3
        |   0x00010808      44ffffeb       bl sym.imp.puts             ; int puts(const char *s)
       ,==< 0x0001080c      440000ea       b 0x10924
       ||   ; CODE XREF from loc._a_12 (+0x88)
       |`-> 0x00010810      20119fe5       ldr r1, aav.0x00010e70      ; [0x10938:4]=0x10e70 aav.0x00010e70
       |    0x00010814      14019fe5       ldr r0, aav.0x00010e4c      ; [0x10930:4]=0x10e4c aav.0x00010e4c
       |    0x00010818      3affffeb       bl sym.imp.printf           ; int printf(const char *format)
       |    0x0001081c      5300a0e3       mov r0, 0x53                ; 'S'
       |    0x00010820      4dffffeb       bl sym.imp.putchar          ; int putchar(int c)
       |    0x00010824      4520a0e3       mov r2, 0x45                ; 'E'
       |    0x00010828      2e10a0e3       mov r1, 0x2e                ; '.'
       |    0x0001082c      08019fe5       ldr r0, str.c_c             ; [0x1093c:4]=0x10e74 str.c_c
       |    0x00010830      34ffffeb       bl sym.imp.printf           ; int printf(const char *format)
       |,=< 0x00010834      370000ea       b 0x10918
```



色々やっているが、`Here's your 1. block:` と出力し、

条件分岐で `IW{S.E` と出力ているのみ。

# task 2

```
[0x00010580]> pd 28 @ 0x00010838
            ;-- aav.0x00010838:
            ; UNKNOWN XREF from loc._d_16 (+0x4)
            0x00010838      00119fe5       ldr r1, str.Here_s_your_2._block: ; [0x10940:4]=0x10e7c str.Here_s_your_2._block:
            0x0001083c      ec009fe5       ldr r0, aav.0x00010e4c      ; [0x10930:4]=0x10e4c aav.0x00010e4c
            0x00010840      30ffffeb       bl sym.imp.printf           ; int printf(const char *format)
            0x00010844      1c301be5       ldr r3, [fp, -0x1c]         ; 28
            0x00010848      0030d3e5       ldrb r3, [r3]
            0x0001084c      0320a0e1       mov r2, r3
            0x00010850      1c301be5       ldr r3, [fp, -0x1c]         ; 28
            0x00010854      013083e2       add r3, r3, 1
            0x00010858      0030d3e5       ldrb r3, [r3]
            0x0001085c      0310a0e1       mov r1, r3
            0x00010860      0200a0e1       mov r0, r2
            0x00010864      490100eb       bl sym.__aeabi_idivmod
            0x00010868      0130a0e1       mov r3, r1
            0x0001086c      410053e3       cmp r3, 0x41                ; 'A' ; 65
        ,=< 0x00010870      0900001a       bne 0x1089c
        |   0x00010874      c8109fe5       ldr r1, aav.0x00010e94      ; [0x10944:4]=0x10e94 aav.0x00010e94
        |   0x00010878      b0009fe5       ldr r0, aav.0x00010e4c      ; [0x10930:4]=0x10e4c aav.0x00010e4c
        |   0x0001087c      21ffffeb       bl sym.imp.printf           ; int printf(const char *format)
        |   0x00010880      5600a0e3       mov r0, 0x56                ; 'V'
        |   0x00010884      34ffffeb       bl sym.imp.putchar          ; int putchar(int c)
        |   0x00010888      4520a0e3       mov r2, 0x45                ; 'E'
        |   0x0001088c      2e10a0e3       mov r1, 0x2e                ; '.'
        |   0x00010890      a4009fe5       ldr r0, str.c_c             ; [0x1093c:4]=0x10e74 str.c_c
        |   0x00010894      1bffffeb       bl sym.imp.printf           ; int printf(const char *format)
       ,==< 0x00010898      1e0000ea       b 0x10918
       ||   ; CODE XREF from aav.0x00010838 (+0x38)
       |`-> 0x0001089c      a4009fe5       ldr r0, str.WI_QA3          ; [0x10948:4]=0x10e98 str.WI_QA3
       |    0x000108a0      1effffeb       bl sym.imp.puts             ; int puts(const char *s)
       |,=< 0x000108a4      1b0000ea       b 0x10918
```



`Here's your 2. block:` と`printf`

-> 先の`scanf` の入力と何かを比較

-> 一致していれば `.R.V.E` と出力



# task 3

```
[0x00010580]> pd 18 @ 0x000108a8
            ;-- aav.0x000108a8:
            ; UNKNOWN XREF from loc._d_16 (+0x8)
            0x000108a8      9c109fe5       ldr r1, str.Here_s_your_3._block: ; [0x1094c:4]=0x10ea0 str.Here_s_your_3._block:
            0x000108ac      7c009fe5       ldr r0, aav.0x00010e4c      ; [0x10930:4]=0x10e4c aav.0x00010e4c
            0x000108b0      14ffffeb       bl sym.imp.printf           ; int printf(const char *format)
            0x000108b4      94109fe5       ldr r1, str.1337            ; [0x10950:4]=0x10eb8 str.1337
            0x000108b8      1c001be5       ldr r0, [fp, -0x1c]         ; 28
            0x000108bc      0effffeb       bl sym.imp.strcmp           ; int strcmp(const char *s1, const char *s2)
            0x000108c0      0030a0e1       mov r3, r0
            0x000108c4      000053e3       cmp r3, 0
        ,=< 0x000108c8      0200001a       bne 0x108d8
        |   0x000108cc      80009fe5       ldr r0, str..R__F:          ; [0x10954:4]=0x10ec0 str..R__F:
        |   0x000108d0      12ffffeb       bl sym.imp.puts             ; int puts(const char *s)
       ,==< 0x000108d4      0f0000ea       b 0x10918
       ||   ; CODE XREF from aav.0x000108a8 (+0x20)
       |`-> 0x000108d8      2130a0e3       mov r3, 0x21                ; '!'
       |    0x000108dc      74209fe5       ldr r2, str.Q.D.Q           ; [0x10958:4]=0x10ec8 str.Q.D.Q
       |    0x000108e0      2e10a0e3       mov r1, 0x2e                ; '.'
       |    0x000108e4      70009fe5       ldr r0, str.c_s_c           ; [0x1095c:4]=0x10ed0 str.c_s_c
       |    0x000108e8      06ffffeb       bl sym.imp.printf           ; int printf(const char *format)
       |,=< 0x000108ec      090000ea       b 0x10918
```



`Here's your 3. block:` と出力

-> `scanf` の入力値と`1337` を比較

-> 一致していれば `.R>=F:` と出力



# task 4

```
[0x00010580]> pd 15 @ 0x000108f0
            ;-- aav.0x000108f0:
            ; UNKNOWN XREF from loc._d_16 (+0xc)
            0x000108f0      1c301be5       ldr r3, [fp, -0x1c]         ; 28
            0x000108f4      0030d3e5       ldrb r3, [r3]
            0x000108f8      000053e3       cmp r3, 0
        ,=< 0x000108fc      0400000a       beq 0x10914
        |   0x00010900      7d30a0e3       mov r3, 0x7d                ; '}'
        |   0x00010904      54209fe5       ldr r2, str.:R:M            ; [0x10960:4]=0x10ed8 str.:R:M
        |   0x00010908      4110a0e3       mov r1, 0x41                ; 'A'
        |   0x0001090c      48009fe5       ldr r0, str.c_s_c           ; [0x1095c:4]=0x10ed0 str.c_s_c
        |   0x00010910      fcfeffeb       bl sym.imp.printf           ; int printf(const char *format)
        |   ; CODE XREF from aav.0x000108f0 (+0xc)
        `-> 0x00010914      0000a0e1       mov r0, r0
            ; CODE XREF from loc._a_12 (+0xbc)
            ; CODE XREFS from aav.0x00010838 (+0x60, +0x6c)
            ; CODE XREFS from aav.0x000108a8 (+0x2c, +0x44)
            0x00010918      0000a0e1       mov r0, r0
        ,=< 0x0001091c      000000ea       b 0x10924
        |   ; CODE XREF from loc._a_11 (+0x28)
        |   0x00010920      0000a0e1       mov r0, r0
        |   ; CODE XREF from loc._a_12 (+0x94)
        |   ; CODE XREF from aav.0x000108f0 (+0x2c)
        `-> 0x00010924      08d04be2       sub sp, fp, 8
            0x00010928      1088bde8       pop {r4, fp, pc}
```



条件分岐の後、 `A:R:M}` を出力している。



全て繋げて、`IW{S.E.R.V.E.R>=F:A:R:M}`