x86上的二進制炸彈對於反彙編的練習來說還是比較經典的,由於網上有很多該程序的講解,所以在此我打算寫一下arm平臺上的二進制拆炸彈這個遊戲。
環境的搭建
由於是arm平臺的環境,所以需要在linux環境下安裝一個模擬器,在此我選擇了qemu該模擬器,具體操作如下(該操作對Ubuntu環境有效,其他linux版本可自行查找方法)
sudo apt-get install qemu-user
運行ARM指令集模擬器並運行開啓gdbserver和運行bomb_1程序
qemu-arm -g 8009 bomb_1
其中,-g參數是爲了添加調試信息,爲了使遠程gdb調試能夠起作用,8009爲自定義的端口號。
另外啓動一個終端,通過命令遠程開啓gdb調試器並加載待調試程序。
arm-linux-gdb bomb_1
輸命令來連接模擬器中的gdbserver
target remote localhost:8009
輔助工具IDA pro。IDA pro是一款靜態分析的反彙編工具,利用它可以查看數據段的具體數據,用起來十分方便。
具體分析
Phase 1
- Arm指令
0000844c <phase_1>:
844c: e92d4800 push {fp, lr}
8450: e28db004 add fp, sp, #4
8454: e24dd008 sub sp, sp, #8
8458: e50b0008 str r0, [fp, #-8]
845c: e51b0008 ldr r0, [fp, #-8]
8460: e59f101c ldr r1, [pc, #28] ; 8484 <phase_1+0x38>
8464: eb000241 bl 8d70 <strings_not_equal>
8468: e1a03000 mov r3, r0
846c: e3530000 cmp r3, #0
8470: 0a000000 beq 8478 <phase_1+0x2c>
8474: eb000321 bl 9100 <explode_bomb>
8478: e24bd004 sub sp, fp, #4
847c: e8bd4800 pop {fp, lr}
8480: e12fff1e bx lr
8484: 0006483c .word 0x0006483c
- 反彙編分析
從標重點的三行彙編可以看出,該代碼從把輸入的字符串爲參數1,把8484裏存的字符串作爲參數2,然後再調用函數strings_not_equal,判斷兩個函數是否相等。所以關鍵是找8484處的地址存的字符串。有IDA pro可以看出8484處存的是數據段6483c處存的字符串,所以用ida可以找出該處的字符串。 - 密碼
密碼爲Let’s begin now!
利用gdb及arm服務器驗證該答案正確。
Phase 2
- Arm指令
00008488 <phase_2>:
8488: e92d4800 push {fp, lr}
848c: e28db004 add fp, sp, #4
8490: e24dd028 sub sp, sp, #40 ; 0x28
8494: e50b0028 str r0, [fp, #-40] ; 0xffffffd8
8498: e24b3020 sub r3, fp, #32
849c: e51b0028 ldr r0, [fp, #-40] ; 0xffffffd8
84a0: e1a01003 mov r1, r3
84a4: eb0001f4 bl 8c7c <read_six_numbers> ○1
////////////////////////////////////////////////
84a8: e51b3020 ldr r3, [fp, #-32] ; 0xffffffe0
84ac: e3530001 cmp r3, #1
84b0: 0a000000 beq 84b8 <phase_2+0x30> ○2
84b4: eb000311 bl 9100 <explode_bomb>
84b8: e3a03001 mov r3, #1
84bc: e50b3008 str r3, [fp, #-8]
84c0: e51b3008 ldr r3, [fp, #-8]
84c4: e2432001 sub r2, r3, #1
84c8: e3e0301b mvn r3, #27
84cc: e1a02102 lsl r2, r2, #2
84d0: e24b0004 sub r0, fp, #4
84d4: e0802002 add r2, r0, r2
84d8: e0823003 add r3, r2, r3
84dc: e5933000 ldr r3, [r3]
84e0: e51b2008 ldr r2, [fp, #-8]
84e4: e2421001 sub r1, r2, #1 ○3
84e8: e0020391 mul r2, r1, r3
84ec: e51b1008 ldr r1, [fp, #-8]
84f0: e3e0301b mvn r3, #27
84f4: e1a01101 lsl r1, r1, #2
84f8: e24b0004 sub r0, fp, #4
84fc: e0801001 add r1, r0, r1
8500: e0813003 add r3, r1, r3 ○4
8504: e5933000 ldr r3, [r3]
//////////////////////////////////////////////
8508: e1520003 cmp r2, r3
850c: 0a000000 beq 8514 <phase_2+0x8c> ○5
8510: eb0002fa bl 9100 <explode_bomb>
//////////////////////////////////////////////
8514: e51b3008 ldr r3, [fp, #-8]
8518: e2833001 add r3, r3, #1
851c: e50b3008 str r3, [fp, #-8]
8520: e51b3008 ldr r3, [fp, #-8]
8524: e3530005 cmp r3, #5
8528: daffffe4 ble 84c0 <phase_2+0x38>
852c: e24bd004 sub sp, fp, #4
8530: e8bd4800 pop {fp, lr}
8534: e12fff1e bx lr
- 反彙編分析
該炸彈的邏輯是for循環。
○1處那兩行由函數名可以看出爲從終端讀取六個數,並將其存入一個數組中,且地址從fp-32開始。○2處那四行是讀取數組第一個數判斷是否爲1,如果是1繼續判斷,如果不是就會explode_bomb。如果是1 的話就會使i = 1到5,然後判斷每一個數值。○3那四行及以上幾行的邏輯是取出a[i-1]的值,並將a[i-1]*(i-1),然後存入r2中。○4那兩行及以上幾行的邏輯是取出a[i]的數據,並將其存入r3中。○5處的邏輯是判斷r2和r3的值,如果相等則i+1,繼續判斷,如果不行等則explode_bomb。
其大致的c語言邏輯如下:
if(a[0] != 1)
explode_bomb();
for(i = 1;i <= 5;i++)
{
if(a[i] != a[i-1]*(i-1))
explode_bomb();
}
所以a[0] = 1;a[1] = a[2] = a[3] = a[4] = a[5] = 0;
- 密碼
1 0 0 0 0 0
Phase 3
- arm指令
00008538 <phase_3>:
8538: e92d4800 push {fp, lr}
853c: e28db004 add fp, sp, #4
8540: e24dd020 sub sp, sp, #32
8544: e50b0018 str r0, [fp, #-24] ; 0xffffffe8
8548: e51b0018 ldr r0, [fp, #-24] ; 0xffffffe8
854c: e59f119c ldr r1, [pc, #412] ; 86f0 <phase_3+0x1b8>○1
8550: e24b2014 sub r2, fp, #20
8554: e24b300d sub r3, fp, #13
8558: e24bc00c sub ip, fp, #12
855c: e58dc000 str ip, [sp]
8560: eb000976 bl ab40 <_IO_sscanf>
8564: e1a03000 mov r3, r0
8568: e3530002 cmp r3, #2
856c: ca000000 bgt 8574 <phase_3+0x3c> ○2
8570: eb0002e2 bl 9100 <explode_bomb>
///////////////////////////////////////////////////
8574: e51b3014 ldr r3, [fp, #-20] ; 0xffffffec
8578: e3530007 cmp r3, #7
857c: 979ff103 ldrls pc, [pc, r3, lsl #2]
8580: ea000041 b 868c <phase_3+0x154>
8584: 000085a4 .word 0x000085a4
8588: 000085c4 .word 0x000085c4
858c: 000085e0 .word 0x000085e0 ○3
8590: 00008600 .word 0x00008600
8594: 0000861c .word 0x0000861c
8598: 00008638 .word 0x00008638
859c: 00008658 .word 0x00008658
85a0: 00008670 .word 0x00008670
/////////////////////////////////////////////////
85a4: e3a03071 mov r3, #113 ; 0x71 ○4
85a8: e54b3005 strb r3, [fp, #-5]
85ac: e51b200c ldr r2, [fp, #-12]
85b0: e59f313c ldr r3, [pc, #316] ; 86f4 <phase_3+0x1bc>
85b4: e1520003 cmp r2, r3
85b8: 0a000037 beq 869c <phase_3+0x164>
85bc: eb0002cf bl 9100 <explode_bomb>
85c0: ea000042 b 86d0 <phase_3+0x198>
85c4: e3a03062 mov r3, #98 ; 0x62○5
85c8: e54b3005 strb r3, [fp, #-5]
85cc: e51b300c ldr r3, [fp, #-12]
85d0: e35300d6 cmp r3, #214 ; 0xd6
85d4: 0a000032 beq 86a4 <phase_3+0x16c>
85d8: eb0002c8 bl 9100 <explode_bomb>
85dc: ea00003b b 86d0 <phase_3+0x198>
85e0: e3a03062 mov r3, #98 ; 0x62○6
85e4: e54b3005 strb r3, [fp, #-5]
85e8: e51b200c ldr r2, [fp, #-12]
85ec: e59f3104 ldr r3, [pc, #260] ; 86f8 <phase_3+0x1c0>
85f0: e1520003 cmp r2, r3
85f4: 0a00002c beq 86ac <phase_3+0x174>
85f8: eb0002c0 bl 9100 <explode_bomb>
85fc: ea000033 b 86d0 <phase_3+0x198>
8600: e3a0306b mov r3, #107 ; 0x6b ○7
8604: e54b3005 strb r3, [fp, #-5]
8608: e51b300c ldr r3, [fp, #-12]
860c: e35300fb cmp r3, #251 ; 0xfb
8610: 0a000027 beq 86b4 <phase_3+0x17c>
8614: eb0002b9 bl 9100 <explode_bomb>
8618: ea00002c b 86d0 <phase_3+0x198>
861c: e3a0306f mov r3, #111 ; 0x6f○8
8620: e54b3005 strb r3, [fp, #-5]
8624: e51b300c ldr r3, [fp, #-12]
8628: e35300a0 cmp r3, #160 ; 0xa0
862c: 0a000022 beq 86bc <phase_3+0x184>
8630: eb0002b2 bl 9100 <explode_bomb>
8634: ea000025 b 86d0 <phase_3+0x198>
8638: e3a03074 mov r3, #116 ; 0x74○9
863c: e54b3005 strb r3, [fp, #-5]
8640: e51b200c ldr r2, [fp, #-12]
8644: e59f30b0 ldr r3, [pc, #176] ; 86fc <phase_3+0x1c4>
8648: e1520003 cmp r2, r3
864c: 0a00001c beq 86c4 <phase_3+0x18c>
8650: eb0002aa bl 9100 <explode_bomb>
8654: ea00001d b 86d0 <phase_3+0x198>
8658: e3a03076 mov r3, #118 ; 0x76○10
865c: e54b3005 strb r3, [fp, #-5]
8660: e51b300c ldr r3, [fp, #-12]
8664: e3530fc3 cmp r3, #780 ; 0x30c
8668: 0a000000 beq 8670 <phase_3+0x138>
866c: eb0002a3 bl 9100 <explode_bomb>
8670: e3a03062 mov r3, #98 ; 0x62○11
8674: e54b3005 strb r3, [fp, #-5]
8678: e51b300c ldr r3, [fp, #-12]
867c: e3530f83 cmp r3, #524 ; 0x20c
8680: 0a000011 beq 86cc <phase_3+0x194>
8684: eb00029d bl 9100 <explode_bomb>
8688: ea000010 b 86d0 <phase_3+0x198>
868c: e3a03078 mov r3, #120 ;0x78 ○12
8690: e54b3005 strb r3, [fp, #-5]
8694: eb000299 bl 9100 <explode_bomb>
8698: ea00000c b 86d0 <phase_3+0x198>
869c: e1a00000 nop ; (mov r0, r0)
86a0: ea00000a b 86d0 <phase_3+0x198>
86a4: e1a00000 nop ; (mov r0, r0)
86a8: ea000008 b 86d0 <phase_3+0x198>
86ac: e1a00000 nop ; (mov r0, r0)
86b0: ea000006 b 86d0 <phase_3+0x198>
86b4: e1a00000 nop ; (mov r0, r0)
86b8: ea000004 b 86d0 <phase_3+0x198>
86bc: e1a00000 nop ; (mov r0, r0)
86c0: ea000002 b 86d0 <phase_3+0x198>
86c4: e1a00000 nop ; (mov r0, r0)
86c8: ea000000 b 86d0 <phase_3+0x198>
86cc: e1a00000 nop ; (mov r0, r0)
86d0: e55b300d ldrb r3, [fp, #-13]
86d4: e55b2005 ldrb r2, [fp, #-5]
86d8: e1520003 cmp r2,r3○13
86dc: 0a000000 beq 86e4 <phase_3+0x1ac>
86e0: eb000286 bl 9100 <explode_bomb>
86e4: e24bd004 sub sp, fp, #4
86e8: e8bd4800 pop {fp, lr}
86ec: e12fff1e bx lr
86f0: 00064850 .word 0x00064850
86f4: 00000309 .word 0x00000309
86f8: 000002f3 .word 0x000002f3
86fc: 000001ca .word 0x000001ca
- 反彙編分析
○1處將pc+412的數據傳入r1,藉助IDA pro可以查看pc+412引用的是
00064850處的數據,如圖:
所以該處的數據爲”%d %c %d”,由此可知輸入的數據的形式爲int,char,int。
○2處判斷第一個參數int是否大於2,如果大於2則進行switch操作,如果不是則explode_bomb。○3處是對輸入的第一個int進行switch判斷,其僞代碼如下:
switch(int c)
{
case 0:
jmp 85a4;
break;
case 1:
jmp 85c4;
break;
case 2:
jmp 85e0;
break;
case 3:
jmp 8600;
break;
case 4:
jmp 861c;
break;
case 5:
jmp 8638;
break;
case 6:
jmp 8658;
break;
case 7:
jmp 8670;
break;
default:
jmp 868c;
break;
}
○4-○11是對case 0 –case 7這八種情況的具體判斷,其邏輯都是一樣的,所以在此只分析一種情況(由於必須要求第一個int大於2,所以分析爲3,4,5,6,7這五種情況)。現分析○7,首先將0x6b放入fp-5,然後將fp-12的值(即第三個傳入的int的值)與0xfb(十進制爲251)進行比較,如果相等則跳轉86b4,如果不是的話就會explode_bomb;然後相等的話跳轉86b4,我們發現從869c到86cc的邏輯都是先nop,什麼都不做,然後再b 86d0
00008760 <phase_4>:
8760: e92d4800 push {fp, lr}
8764: e28db004 add fp, sp, #4
8768: e24dd010 sub sp, sp, #16
876c: e50b0010 str r0, [fp, #-16]
8770: e51b1010 ldr r1, [fp, #-16]
8774: e59f2054 ldr r2, [pc, #84] ; 87d0 <phase_4+0x70> ○1
8778: e24b3008 sub r3, fp, #8
877c: e1a00001 mov r0, r1
8780: e1a01002 mov r1, r2
8784: e1a02003 mov r2, r3
8788: eb0008ec bl ab40 <_IO_sscanf>
878c: e1a03000 mov r3, r0
8790: e3530001 cmp r3, #1
8794: 1a000002 bne 87a4 <phase_4+0x44>
8798: e51b3008 ldr r3, [fp, #-8]
879c: e3530000 cmp r3, #0
87a0: ca000000 bgt 87a8 <phase_4+0x48> ○2
87a4: eb000255 bl 9100 <explode_bomb>
////////////////////////////////////
87a8: e51b3008 ldr r3, [fp, #-8]
87ac: e1a00003 mov r0, r3 ○3
87b0: ebffffd2 bl 8700 <func4>
///////////////////////////////////
87b4: e1a03000 mov r3, r0
87b8: e3530008 cmp r3, #8
87bc: 0a000000 beq 87c4 <phase_4+0x64> ○8
87c0: eb00024e bl 9100 <explode_bomb>
87c4: e24bd004 sub sp, fp, #4
87c8: e8bd4800 pop {fp, lr}
87cc: e12fff1e bx lr
87d0: 0006485c .word 0x0006485c
00008700 <func4>:
8700: e92d4810 push {r4, fp, lr}
8704: e28db008 add fp, sp, #8
8708: e24dd00c sub sp, sp, #12
870c: e50b0010 str r0, [fp, #-16]
8710: e51b3010 ldr r3, [fp, #-16]
8714: e3530001 cmp r3, #1 ○4
8718: da00000b ble 874c <func4+0x4c>
////////////////////////////////////////////
871c: e51b3010 ldr r3, [fp, #-16]
8720: e2433001 sub r3, r3, #1
8724: e1a00003 mov r0, r3 ○5
8728: ebfffff4 bl 8700 <func4>
/////////////////////////////////////////////
872c: e1a04000 mov r4, r0
8730: e51b3010 ldr r3, [fp, #-16]
8734: e2433002 sub r3, r3, #2 ○6
8738: e1a00003 mov r0, r3
873c: ebffffef bl 8700 <func4>
8740: e1a03000 mov r3, r0
8744: e0843003 add r3, r4, r3
8748: ea000000 b 8750 <func4+0x50>
874c: e3a03001 mov r3, #1
8750: e1a00003 mov r0, r3
8754: e24bd008 sub sp, fp, #8 ○7
8758: e8bd4810 pop {r4, fp, lr}
875c: e12fff1e bx lr
- 反彙編分析
○1處是輸入的參數的形式,位於87d0處,利用IDA pro找到了87d0引用了0006485C數據段的數據,爲
即要求輸入一個數字。○2處判斷是否是輸入的參數是否大於0,如果大於0則繼續判斷,如果不是則explode_bomb。○3處將輸入的數傳入r0中作爲參數然後調用func4()。○4首先將傳入的參數存入fp-16中,然後判斷參數是否小於等於1,如果小於等於1的話就跳到○7處,○7處將返回值賦值爲1,然後pop返回值和參數;如果大於1的話就到○5,○5和○6的邏輯就是分別讓參數-1和-2,然後再分別調用func4,由此可以看出該bomb的邏輯是一個遞歸的調用。其c語言的僞代碼如下:
func4(int i)
{
if(i < = 1)
return 1;
else
return func4(i-1) + func4(i-2);
}
然後看代碼塊○8,其將func4函數的返回值與8進行比較,如果等於8就通過,否則explode_bomb。所以通過計算可以得出輸入的值爲5。
- 密碼
5
Phase 5
- Arm指令
000087d4 <phase_5>:
87d4: e92d4800 push {fp, lr}
87d8: e28db004 add fp, sp, #4
87dc: e24dd018 sub sp, sp, #24
87e0: e50b0018 str r0, [fp, #-24] ; 0xffffffe8
87e4: e51b0018 ldr r0, [fp, #-24] ; 0xffffffe8
87e8: eb000144 bl 8d00 <string_length>
87ec: e1a03000 mov r3, r0
87f0: e3530006 cmp r3, #6 ○1
87f4: 0a000000 beq 87fc <phase_5+0x28>
87f8: eb000240 bl 9100 <explode_bomb>
////////////////////////////////////////
87fc: e3a03000 mov r3, #0
8800: e50b3008 str r3, [fp, #-8]○2
8804: ea00000f b 8848 <phase_5+0x74>
////////////////////////////////////////
8808: e51b1008 ldr r1, [fp, #-8]
880c: e51b3008 ldr r3, [fp, #-8]
8810: e51b2018 ldr r2, [fp, #-24] ; 0xffffffe8
8814: e0823003 add r3, r2, r3○4
8818: e5d33000 ldrb r3, [r3]
881c: e203300f and r3, r3, #15
///////////////////////////////////////
8820: e59f2060 ldr r2, [pc, #96] ; 8888 <phase_5+0xb4>
8824: e7d22003 ldrb r2, [r2, r3] ○5
///////////////////////////////////////
8828: e3e0300b mvn r3, #11
882c: e24b0004 sub r0, fp, #4
8830: e0801001 add r1, r0, r1 ○6
8834: e0813003 add r3, r1, r3
8838: e5c32000 strb r2, [r3]
////////////////////////////////////
883c: e51b3008 ldr r3, [fp, #-8]
8840: e2833001 add r3, r3, #1 ○7
8844: e50b3008 str r3, [fp, #-8]
////////////////////////////////////
8848: e51b3008 ldr r3, [fp, #-8]
884c: e3530005 cmp r3, #5 ○3
8850: daffffec ble 8808 <phase_5+0x34>
///////////////////////////////////
8854: e3a03000 mov r3, #0
8858: e54b300a strb r3, [fp, #-10]
885c: e24b3010 sub r3, fp, #16
8860: e1a00003 mov r0, r3 ○8
8864: e59f1020 ldr r1, [pc, #32] ; 888c <phase_5+0xb8>
8868: eb000140 bl 8d70 <strings_not_equal>
886c: e1a03000 mov r3, r0
8870: e3530000 cmp r3, #0
8874: 0a000000 beq 887c <phase_5+0xa8>
8878: eb000220 bl 9100 <explode_bomb>
887c: e24bd004 sub sp, fp, #4
8880: e8bd4800 pop {fp, lr}
8884: e12fff1e bx lr
8888: 0008216c .word 0x0008216c
888c: 00064860 .word 0x00064860
- 反彙編分析
○1中代碼首先判斷讀入的字符串的長度,如果長度等於6則跳到代碼塊○2中去,如果不等於6則explode_bomb。在代碼塊○2中,首先將計數變量i置爲0,然後跳到代碼塊○3中去,在代碼塊○3中先判斷i是否小於等於5,如果小於等於5的話就跳入○4中,其中○4○5○6○7爲for循環的主體,我將其化成了這4部分。其中在○4的邏輯如下:取出字符串的第i個字符s[i],
然後將s[i]與0xF相與,其中一個char爲一個字節,由兩個16進制數組成,做相與運算後就只取出char的後4個b,將數值存入r3中。然後到代碼塊○5中,找到數據pc+96(8888)處的數據,根據IDA pro得出其引用的是0008216C處的數據,數據如圖:
,然後根據r3中的數值作爲索引取得相應的字符,將得到的字符存入r2中,然後到代碼塊○6中,其將r2的數據存入(fp-4-11)+i的地址處。代碼○7是將i++。所以該段代碼的僞代碼如下:
for(i = 0;i <= 5;i++)
{
int a = (int)(s[i]&0xF);
s1[i] = 0x0008216c+a;
}
其中s爲輸入的字符串,s1爲找到的字符串。
for循環結束了之後,得到長度爲6的s1字符串,到了代碼塊○8中,該邏輯是將s1與(pc-32)即888c處的字符串進行比較,根據IDA pro得到引用了數據段00064860處的數據爲:
所以只有當s1爲”giants”時,才能通過,即索引順序爲0xF,0x0,0x5,0xB,0xD,0x1,查ascii表得到後4個b分別爲這些的十六進制的數的字符分別爲opeka(可能有多重情況,只要後4個b分別對應那五個十六進制數的字符即可)。
- 密碼
opeka
Phase 6
指令及邏輯分析:
由於該炸彈的指令及邏輯較長,所以指令分開了幾份分別進行分析。
00008890 :
1:讀入六個數
8890: e92d4800 push {fp, lr}
8894: e28db004 add fp, sp, #4
8898: e24dd048 sub sp, sp, #72 ; 0x48
889c: e50b0048 str r0, [fp, #-72] ; 0xffffffb8
88a0: e59f3234 ldr r3, [pc, #564] ; 8adc <phase_6+0x24c>
88a4: e50b3010 str r3, [fp, #-16]
88a8: e24b3028 sub r3, fp, #40 ; 0x28
88ac: e51b0048 ldr r0, [fp, #-72] ; 0xffffffb8
88b0: e1a01003 mov r1, r3
88b4: eb0000f0 bl 8c7c <read_six_numbers>
以上的指令的邏輯比較簡單,是首先讀入六個數字,並將其放入數組中,假設數組爲a。
2:對這六個數的值進行判定
88b8: e3a03000 mov r3, #0
88bc: e50b300c str r3, [fp, #-12]
88c0: e51b200c ldr r2, [fp, #-12] ○1
////////////////////////////////////
88c4: e3e03023 mvn r3, #35 ; 0x23
88c8: e1a02102 lsl r2, r2, #2
88cc: e24b0004 sub r0, fp, #4
88d0: e0802002 add r2, r0, r2 ○2
88d4: e0823003 add r3, r2, r3
88d8: e5933000 ldr r3, [r3]
///////////////////////////////////
88dc: e2433001 sub r3, r3, #1
88e0: e3530005 cmp r3, #5 ○3
88e4: 9a000000 bls 88ec <phase_6+0x5c>
88e8: eb000204 bl 9100 <explode_bomb>
//////////////////////////////////
88ec: e51b300c ldr r3, [fp, #-12]
88f0: e2833001 add r3, r3, #1 ○4
88f4: e50b3008 str r3, [fp, #-8]
88f8: ea000013 b 894c <phase_6+0xbc>
//////////////////////////////////
88fc: e51b200c ldr r2, [fp, #-12]
8900: e3e03023 mvn r3, #35 ; 0x23
8904: e1a02102 lsl r2, r2, #2
8908: e24b1004 sub r1, fp, #4 ○6
890c: e0812002 add r2, r1, r2
8910: e0823003 add r3, r2, r3
8914: e5932000 ldr r2, [r3]
//////////////////////////////////
8918: e51b1008 ldr r1, [fp, #-8]
891c: e3e03023 mvn r3, #35 ; 0x23
8920: e1a01101 lsl r1, r1, #2
8924: e24b0004 sub r0, fp, #4 ○7
8928: e0801001 add r1, r0, r1
892c: e0813003 add r3, r1, r3
8930: e5933000 ldr r3, [r3]
/////////////////////////////////
8934: e1520003 cmp r2, r3
8938: 1a000000 bne 8940 <phase_6+0xb0>
893c: eb0001ef bl 9100 <explode_bomb>
8940: e51b3008 ldr r3, [fp, #-8]○8
8944: e2833001 add r3, r3, #1
8948: e50b3008 str r3, [fp, #-8]
///////////////////////////////////
894c: e51b3008 ldr r3, [fp, #-8]
8950: e3530005 cmp r3, #5 ○5
8954: daffffe8 ble 88fc <phase_6+0x6c>
//////////////////////////////////
8958: e51b300c ldr r3, [fp, #-12]
895c: e2833001 add r3, r3, #1
8960: e50b300c str r3, [fp, #-12] ○9
8964: e51b300c ldr r3, [fp, #-12]
8968: e3530005 cmp r3, #5
896c: daffffd3 ble 88c0 <phase_6+0x30>
8970: e3a03000 mov r3, #0
8974: e50b300c str r3, [fp, #-12]
以上的指令爲兩個for循環的嵌套。
其中○1爲(fp-12)處存的變量假設爲i,把變量i的值存入r2,然後代碼段○2處爲取出a[i]的值並將其存入r3中,緊接着代碼段○3處判斷r3的值是否大於6,如果大於6就explode_bomb。然後進入代碼塊○4中,在此就進入了第二個for循環,首先初始化(fp-8)處的變量,設爲j,j = i+1;然後進入代碼段○5處對j的值進行判斷,如果大於5就進入代碼段○9,其中代碼○9是將i增1並進行判斷,如果i大於5就跳出for循環,如果小於5則跳至○1再進行一次for循環,對於代碼○5處的判斷如果j小於等於5的話,則跳入代碼○6處,其中邏輯爲取出a[i]的值將其放入r2中,然後進入○7中,取出a[j]的值將其放入r3中,然後進入○8,將r2和r3進行比較,如果相等的話就explode_bomb,不行等就進入○5,又進行了一次循環。其僞代碼如下:
for(int i = 0;i <= 5;i++)
{if(a[i]>6)
explode_bomb();
for(int j = i+1;j<=5;j++)
{if(a[j] == a[i])
explode_bomb();
}
}
3:根據輸入的6個數把鏈表的6個node進行索引排序
8978: e59f315c ldr r3, [pc, #348] ; 8adc <phase_6+0x24c>
897c: e50b3010 str r3, [fp, #-16]
8980: e3a03001 mov r3, #1 ○1
8984: e50b3008 str r3, [fp, #-8]
8988: ea000005 b 89a4 <phase_6+0x114>
/////////////////////////////////////////////
898c: e51b3010 ldr r3, [fp, #-16]
8990: e5933008 ldr r3, [r3, #8]
8994: e50b3010 str r3, [fp, #-16] ○3
8998: e51b3008 ldr r3, [fp, #-8]
899c: e2833001 add r3, r3, #1
89a0: e50b3008 str r3, [fp, #-8]
////////////////////////////////////////
89a4: e51b200c ldr r2, [fp, #-12]
89a8: e3e03023 mvn r3, #35 ; 0x23
89ac: e1a02102 lsl r2, r2, #2
89b0: e24b1004 sub r1, fp, #4
89b4: e0812002 add r2, r1, r2 ○2
89b8: e0823003 add r3, r2, r3
89bc: e5932000 ldr r2, [r3]
89c0: e51b3008 ldr r3, [fp, #-8]
89c4: e1520003 cmp r2, r3
89c8: caffffef bgt 898c <phase_6+0xfc>
////////////////////////////////////////////
89cc: e51b200c ldr r2, [fp, #-12]
89d0: e3e0303b mvn r3, #59 ; 0x3b
89d4: e1a02102 lsl r2, r2, #2
89d8: e24b0004 sub r0, fp, #4 ○4
89dc: e0802002 add r2, r0, r2
89e0: e0823003 add r3, r2, r3
89e4: e51b2010 ldr r2, [fp, #-16]
89e8: e5832000 str r2, [r3]
///////////////////////////////////////////
89ec: e51b300c ldr r3, [fp, #-12]
89f0: e2833001 add r3, r3, #1
89f4: e50b300c str r3, [fp, #-12] ○5
89f8: e51b300c ldr r3, [fp, #-12]
89fc: e3530005 cmp r3, #5
8a00: daffffdc ble 8978 <phase_6+0xe8>
///////////////////////////////////////////
8a04: e51b3040 ldr r3, [fp, #-64] ; 0xffffffc0
8a08: e50b3010 str r3, [fp, #-16]○9
8a0c: e3a03001 mov r3, #1
8a10: e50b300c str r3, [fp, #-12]
/////////////////////////////////////////
8a14: e51b200c ldr r2, [fp, #-12]
8a18: e3e0303b mvn r3, #59 ; 0x3b
8a1c: e1a02102 lsl r2, r2, #2
8a20: e24b1004 sub r1, fp, #4
8a24: e0812002 add r2, r1, r2○6
8a28: e0823003 add r3, r2, r3
8a2c: e5932000 ldr r2, [r3]
8a30: e51b3010 ldr r3, [fp, #-16]
8a34: e5832008 str r2, [r3, #8]
///////////////////////////////////////
8a38: e51b200c ldr r2, [fp, #-12]
8a3c: e3e0303b mvn r3, #59 ; 0x3b
8a40: e1a02102 lsl r2, r2, #2○7
8a44: e24b0004 sub r0, fp, #4
8a48: e0802002 add r2, r0, r2
8a4c: e0823003 add r3, r2, r3
8a50: e5933000 ldr r3, [r3]
8a54: e50b3010 str r3, [fp, #-16]
////////////////////////////////////
8a58: e51b300c ldr r3, [fp, #-12]
8a5c: e2833001 add r3, r3, #1
8a60: e50b300c str r3, [fp, #-12] ○8
8a64: e51b300c ldr r3, [fp, #-12]
8a68: e3530005 cmp r3, #5
8a6c: daffffe8 ble 8a14 <phase_6+0x184>
該段代碼也有一個for循環的嵌套。
首先初始化,將(PC+348)的索引的數存入r3中,由ida pro得出具體數據爲
所以將node1的索引傳入r3,然後跳入到代碼塊○2,其邏輯是先取出a[i]的數據至r2,然後取出j至r3,比較這兩個數據的大小,如果r2 >r3,就跳到代碼段○3,該邏輯是將r3+0x8的數據存入fp-16中,有以上的數據可知該數據爲0x20A0,用IDA pro查找到爲:
以此類推,根據每個節點的第8個字節處的數據作爲下一個節點的地址,直到找到鏈表的a[i]個元素,就會跳出該內層的for循環,然後進入代碼塊○4,該邏輯是將該node的地址存入-0x3c+[R11] + 4 * i中,然後進入代碼塊○5,其邏輯是使變量i增1,然後判斷是否大於5,如果小於5再跳入○1中繼續循環。
其for循環的僞代碼如下:
for(int i = 0;i <=5;i++)
{
node = 0x000820AC;
for(int j = 1;j<a[i];j++)
node = *(node+0x8);
-0x3c+[R11] + 4 * i = node;
}
所以經過上一個for循環的嵌套,從-0x3c+[R11]開始就有了這些節點的地址的索引,然後進入代碼段○9,其邏輯是先將fp-12處的變量i初始化爲1,目的是進入for循環。進入代碼段○6,其目的是將*((-0x3c+[R11]+i-1)+0x8) = (-0x3c+[R11]+i);然後進入代碼段○7,其目的是將當前節點設爲-0x3c+[R11]+i處的地址所指向的節點,進入代碼塊○8,使i增1並判斷和5的大小關係。
4:判斷鏈表的節點的數值是否是按從大到小的順序排列的
8a70: e51b3010 ldr r3, [fp, #-16]
8a74: e3a02000 mov r2, #0
8a78: e5832008 str r2, [r3, #8]
8a7c: e3a03000 mov r3, #0 ○1
8a80: e50b300c str r3, [fp, #-12]
8a84: e51b3040 ldr r3, [fp, #-64] ; 0xffffffc0
8a88: e50b3010 str r3, [fp, #-16]
//////////////////////////////////////
8a8c: e51b3010 ldr r3, [fp, #-16]
8a90: e5932000 ldr r2, [r3]
8a94: e51b3010 ldr r3, [fp, #-16]
8a98: e5933008 ldr r3, [r3, #8] ○2
8a9c: e5933000 ldr r3, [r3]
8aa0: e1520003 cmp r2, r3
8aa4: aa000000 bge 8aac <phase_6+0x21c>
8aa8: eb000194 bl 9100 <explode_bomb>
//////////////////////////////////////////
8aac: e51b3010 ldr r3, [fp, #-16]
8ab0: e5933008 ldr r3, [r3, #8] ○3
8ab4: e50b3010 str r3, [fp, #-16]
///////////////////////////////////////
8ab8: e51b300c ldr r3, [fp, #-12]
8abc: e2833001 add r3, r3, #1
8ac0: e50b300c str r3, [fp, #-12] ○4
8ac4: e51b300c ldr r3, [fp, #-12]
8ac8: e3530004 cmp r3, #4
8acc: daffffee ble 8a8c <phase_6+0x1fc>
首先進入○1進行初始化,將(fp-16)處的地址換爲鏈表的第一個node,並對(fp-12)的變量i初始化爲0。然後進入代碼塊○2,首先獲得當前node的地址,並將該node的數據存入r2中,地址存入r3中,然後通過[r3+8]獲得下一個node的地址,並將下一個node的地址存入r3中,然後比較r2和r3的值,如果r2小於r3,就explode_bomb,
如果不小於就進入代碼塊○3,該邏輯是將當前節點(fp-16)的地址改爲[r3+8]處的數值,即爲下一個節點的地址,然後進入代碼○4,對變量i進行增1操作,並判斷和4的大小。其僞代碼如下:
其中node的數據結構如下:
struct node
{
int x, y;
node *next; };
//進行判斷:
node a = firstNode;
for(int i = 0; i < 5; i++)
{
node b = a->next;
if (a->x >= b->x)
a = b;
else
explode_bomb();
}
所以根據邏輯,先找出每個節點的數據,然後再根據輸入的數進行排序,保證其是從大到小的順序排列的。根據IDA pro找到每個node所在的地址爲:
地址 數據 下個節點地址
0x820AC 0xFD 0x820A0
0x820A0 0x2D5 0x82094
0x82094 0x12D 0x82088
0x82088 0x3E5 0x8207C
0x8207C 0xD4 0x82070
0x82070 0x1B0
所以由大到小排列的話就爲4 2 6 3 1 5
密碼
4 2 6 3 1 5