Reversing Challenges List の問題。
ARMアーキテクチャのバイナリ。
ARMアーキテクチャについては、以下の2つの記事を見ればだいたい理解できた。
実行環境がないので、アセンブリ言語だけ見て解析する。
解析には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として扱われることに注意 (ももテク の記事に記載)。
結果としては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}