CS:APP 二進(jìn)制炸彈拆解全解析

花了一段時(shí)間做完了暑假作業(yè), 二進(jìn)制炸彈破解的過程可謂苦盡甘來

現(xiàn)在把自己寫的解析報(bào)告放上來, 純?cè)瓌?chuàng), 沒有參考任何關(guān)于此炸彈的解析

可能會(huì)與你拿到的炸彈有所不同, 本文只提供思路


第一關(guān) 字符串比較

1.??? 通過read_line從標(biāo)準(zhǔn)輸入流輸入測(cè)試字符串例如: 1234567

2.??? 進(jìn)入phase_1 函數(shù)

3.??? 進(jìn)入strings_not_equal 函數(shù)

4.??? 進(jìn)入第一個(gè)string_length函數(shù)

5.??? 根據(jù)string_length函數(shù)返回值 %eax = 7 推斷第二個(gè)string_length函數(shù)計(jì)算的是標(biāo)準(zhǔn)字符串(密碼)的長(zhǎng)度

6.??? 進(jìn)入第二個(gè)stirng_length函數(shù), 根據(jù)add 與 jne 指令判斷該函數(shù)通過遍歷字符數(shù)組到’\0’來計(jì)算長(zhǎng)度, 易知 %ebx 存儲(chǔ)該數(shù)組的首地址

7.??? 遍歷完成后得到 %eax 值為 41, 表明密碼字符串長(zhǎng)度為41,

8.??? restart 程序并執(zhí)行到第6步

9.??? 運(yùn)用 print $ebx 得到起始地址 134521080

10.??? 通過 x/41cb (x查看內(nèi)存值 41表明單位個(gè)數(shù)c以字符形式顯示b表明每次取一個(gè)字節(jié)長(zhǎng)度) 指令 得到密碼字符串的內(nèi)容

第一關(guān)密鑰的內(nèi)容

第一關(guān)密鑰:

For NASA, space is still a high priority.


第二關(guān) 循環(huán)

1.??? 進(jìn)入read_line函數(shù), 隨便輸入幾個(gè)字符 "asdasfa"

2.??? 進(jìn)入, read_six_numbers函數(shù)

3.??? 按s繼續(xù)執(zhí)行,進(jìn)入sscanf函數(shù)

4.??? 繼續(xù)按s可以看到sscanf函數(shù)的定義, 如下

第二關(guān)sscanf函數(shù)的定義

5.??? 可知應(yīng)該輸入6個(gè)數(shù)字, 每個(gè)數(shù)字用空格隔開

6.??? 重新進(jìn)入read_line, 按n后輸入數(shù)字1 2 3 4 5 6

7.??? 繼續(xù)執(zhí)行到sscanf后, 易知0x4(%esp)取輸入的第一個(gè)數(shù)字, 即1, 并與1比較,相等即繼續(xù)執(zhí)行

8.??? 通過觀察寄存器值的變化, 可以判斷出phase_2 + 54 到 phase_2 + 73為循環(huán)過程, 遍歷我們剛剛輸入的6個(gè)數(shù), 整理循環(huán)的運(yùn)行邏輯如下, 以a1 – a6 表示他們.

start = a1;

x = a2;

if (start == 1)

??????? do {

??????????????? start += start;

??????????????? if ( start != x );

??????????????? BOOM!!!;

??????????????? x = a.next;

??????? } while ( x != a6 )

else??????? BOOM!!!!;

9.??? 根據(jù)上述算法依次類推, 即可得到應(yīng)該輸入的密碼為 1 2 4 8 16 32.

第二關(guān)密鑰執(zhí)行結(jié)果

第二關(guān)密鑰:

1 2 4 8 16 32


第三關(guān) 條件/分支

這一關(guān)通得很快, 因?yàn)橛卸嘟? 碰巧湊了一個(gè), 感覺運(yùn)氣成分比較大 (逃

1.??? 同上, 進(jìn)入read_line函數(shù)后隨便輸入一串字符? "hahaha"

2.??? si 進(jìn)入sscanf函數(shù), 再按一次s可以調(diào)出sscanf函數(shù)原型, 如下

第三關(guān)sscanf函數(shù)原型

3.??? 可知這關(guān)密碼的格式是 整數(shù)空格字符空格整數(shù)

4.??? 退出重新進(jìn)入, 輸入測(cè)試字符串1<空格>a<空格>2

( 體現(xiàn)運(yùn)氣的時(shí)刻到了)

5.??? 通過 cmpl $0x7, 0x4(%esp) <換行> ja blabla 語句可知, 第一個(gè)數(shù)字需要小于7

6.??? 通過 jmp *0x804a160 (, %eax, 4) 語句可知跳轉(zhuǎn)目的語句與第一個(gè)數(shù)字的值有關(guān)

7.??? 猜測(cè)一共有7種破解密碼, 我這里遇到的是第2種(第一個(gè)數(shù)字為1)

8.??? 跳轉(zhuǎn)到phase_3+113, 將第二個(gè)整數(shù)與0xbe (即190 ) 作比較, 相等即可繼續(xù)進(jìn)行, 由此推斷 第二個(gè)整數(shù)是0xbe, 即190

9.??? 觀察跳轉(zhuǎn)到phase_3+323后需要將%al中的值與字符參數(shù)做比較相等才可以完成密碼匹配

10.? 通過 print $al 查看寄存器中的值, 發(fā)現(xiàn)為113, 查ASCII碼表, 發(fā)現(xiàn)為字符’q’

那么, 1 q 190即為解之一

第三關(guān)密鑰執(zhí)行結(jié)果

第三關(guān)密鑰 ( 之一)

1 q 190


第四關(guān) 遞歸調(diào)用和棧

1.??? 同樣, 輸入測(cè)試字符進(jìn)入sscanf函數(shù), 輸入s指令觀察到sscanf函數(shù)的原型

第四關(guān)sscanf函數(shù)原型

2.??? 重新進(jìn)入, 輸入測(cè)試字符1 2

3.??? 根據(jù)phase_4+78的 cmp $0x5, %eax 語句以及 cmpl $0x5, 0x8(%esp) 語句, 可以推斷出以第一個(gè)數(shù)字為參數(shù)的fun4函數(shù)返回值應(yīng)該為5, 第二個(gè)數(shù)字的值應(yīng)該為5

4.??? 進(jìn)入fun函數(shù),觀察%eax, %ebx, %esi, %ecx的變化

5.??? 經(jīng)過初步推斷, %ecx存儲(chǔ)函數(shù)參數(shù)值, %eax為返回值, %ebx與%esi分別存儲(chǔ)函數(shù)中間值, 并賦初始值分別為0和14, %edx作為函數(shù)比較的中間值, 其作為中轉(zhuǎn)站與%eax性質(zhì)相同

6.??? 通過分析比較代碼, 可以大致推斷出原函數(shù)的算法如下, 其中以origin作為%esi存儲(chǔ)的值, 以sub作為%ebx的值, 以center作為%eax和%edx所存儲(chǔ)的值, x為函數(shù)參數(shù), 也就是我們輸入的第一個(gè)數(shù)字

origin = 14;

center = origin;

sub = 0;

fun4 ( int x ) {

??????? center = ( origin – sub ) / 2 + sub;??? //函數(shù)的開頭計(jì)算用于比較的center值( %eax )

??????? if ( x == center ) return 0;?????????//對(duì)應(yīng)匯編代碼fun4 + 0 ---- fun4 + 33

??????? else if ( x < center ) {?????????????????? ??

??????????????? center -= 1;???????????????? //匯編代碼fun4+ 40

??????????????? origin = center;????????????? //匯編代碼push%edx

??????????????? return 2 * fun ( x ) ;?????????? //匯編代碼 fun4 +54 add指令

??????? }??????????????????????????????

??????? else if ( x > center ) {?????????????

?????????????? center += 1;???????????????? //匯編代碼fun4+ 71

?????????????? sub = center;??????????????? //匯編代碼push %edx

?????????????? return 2 * fun ( x ) + 1;??????? //匯編代碼fun4 + 84

??????? }

}

7.??? 根據(jù)上述代碼, 反向遞推, 令最后返回的%eax值為5

5 = 2 * 2 * ( 2 * 0 + 1 ) + 1, 只有10可以滿足左側(cè)遞推式

第四關(guān)密鑰執(zhí)行結(jié)果

第四關(guān)密鑰

10 5


第五關(guān) 指針

1.??? 進(jìn)入read_line函數(shù)后進(jìn)入phase5中的sscanf函數(shù), 按下s得到sscanf的函數(shù)原型

第五關(guān)sscanf函數(shù)原型

2.??? 可知本關(guān)依然需要兩個(gè)整數(shù)作為密鑰

3.??? 重新進(jìn)入, 輸入測(cè)試數(shù)據(jù)1和2并觀察函數(shù)執(zhí)行情況

4.??? 根據(jù)下方的 mov <地址>(, %eax, 4 ) 可以推斷出輸入的第一個(gè)整數(shù)作為地址的偏移量

即整形數(shù)組中的下標(biāo)

5.??? 利用 gdb x/70cb <地址> 指令查看程序內(nèi)部提供整形數(shù)組的所有值, 并記錄為表格如下

查看內(nèi)存中數(shù)組的存儲(chǔ)情況
數(shù)組下標(biāo)與元素對(duì)應(yīng)情況

6.??? 根據(jù)后續(xù)的 jne $0xf 以及對(duì)起計(jì)數(shù)作用的%edx中的值可知, 該程序進(jìn)行15次循環(huán)后使得%eax的值為15, 即通過15次對(duì)地址的重新計(jì)算得到最終值15, 下標(biāo)為5, 按此邏輯寫出該程序段的大致算法如下:

result = input ( 第一個(gè)參數(shù));

counter = 0;

sum = 0;

do{

?????? counter ++;

?????? result= array [ result ];

?????? sum+= result;

while?( result != 15 && counter != 15 );

7.??? 按照上述算法, 從15開始遞推 15次, 得到第一次result的值, 也就是我們需要輸入的一個(gè)整數(shù)值為5.

15 6 14 2 1 10 0 8 4 9 13 11 7 3 12 ? array [ 5 ] = 12

8.??? 又根據(jù) cmp 0x8 ( %esp ), %ecx 可知, 第二個(gè)參數(shù)需要與sum值相同, 即所有遍歷過的值的和, 15 + 6 + ……+ 12 = 115

第五關(guān)密鑰執(zhí)行情況

第五關(guān)密鑰

5 115


第六關(guān) 鏈表/指針/結(jié)構(gòu)

1.??? 進(jìn)入read_line函數(shù), 根據(jù)phase_6 + 26的read_six_numbers函數(shù), 根據(jù)第二關(guān)已知, 需要輸入6個(gè)數(shù)字.

2.??? 重新進(jìn)入函數(shù), 并輸入測(cè)試數(shù)字組1 2 3 4 5 6

3.??? 進(jìn)入phase函數(shù)并跳過read_six_numbers函數(shù), 就來到了本關(guān)的第一個(gè)循環(huán)判斷, 如下

第六關(guān)第一個(gè)坎

以array數(shù)組表示用戶輸入的六個(gè)數(shù)字,該部分代碼可用以下算法來描述

for ( int I = 0; I < = 5 ; I ++ ) {

?????? if ( array [ I ] <= 6 ) {

????????????? for ( int m = I + 1; m <=5; m ++ )

???????????????????? if( array [ I ] == array [ m ] )

??????????????????????????? BOOM!!!;

?????? }

?????? else??? BOOM!!!;

}

根據(jù)該段代碼可知用戶輸入的每個(gè)數(shù)字都應(yīng)該小于6并且各數(shù)字互不相等

4.??? phase_6+104 ~ phase_6+115是7減去原來每個(gè)數(shù)后重新存入源地址中, 算法不贅述, 即phase[x] = 7 – phase [7]

5.??? phase_6+124 ~ phase_6+167是通過計(jì)算好的新數(shù)組, 將一個(gè)六結(jié)點(diǎn)鏈表初始地址每次移動(dòng)(array[x] – 1) 個(gè)8字節(jié)后得到值依次保存于棧幀中. 原理可用下述公式表示, 在這里觀察到 0x8(%edx) 直接就是移動(dòng)到下一個(gè)結(jié)點(diǎn)的首地址了, 而每個(gè)結(jié)點(diǎn)所占空間是12個(gè)字節(jié), 推翻上述分析, 移動(dòng)8個(gè)地址后即是下一個(gè)結(jié)點(diǎn)首地址,從而構(gòu)成單向鏈表.

即此部分是取第array [? x ] 個(gè)結(jié)點(diǎn)值并依次保存

第六關(guān)第二個(gè)坎

6.??? 通過 x/18dw 指令觀察鏈表六個(gè)結(jié)點(diǎn)首元素的值:

鏈表node1 - 6

從上圖可以看出:

鏈表node1 - 6

7.??? 下述代碼作為此關(guān)的終極武器, 經(jīng)過寄存器值的查看即跳轉(zhuǎn)條件分析, 只有滿足存入棧幀的結(jié)點(diǎn)降序排列才可躲避phase_6+219的爆炸函數(shù)

第六關(guān)第三個(gè)坎

8.??? 手動(dòng)排序, node6 > node4 > node1> node5 > node2 > node3

????? 整理得最終結(jié)果與輸入值的對(duì)應(yīng)關(guān)系如下

輸入值的變化過程
第六關(guān)密鑰執(zhí)行結(jié)果

第六關(guān)密鑰:

1 3 6 2 5 4


隱藏關(guān)卡

1.??? 進(jìn)入phase4的defused函數(shù), 觀察到一條指令?

cmpl $0x6, 0x804c3cc

使用x指令查看地址0x804c3cc中的值, 發(fā)現(xiàn)這個(gè)值記錄的是輸入字符串的個(gè)數(shù)

也就是在輸入6個(gè)字符串, 即通過6個(gè)關(guān)卡后才可以跳轉(zhuǎn)到下方的sscanf函數(shù)附近

2.??? 猜測(cè)defused函數(shù)中的sscanf函數(shù)記錄著有關(guān)隱藏關(guān)的密碼

3.??? 繼續(xù)進(jìn)行到第六關(guān), 重新進(jìn)入phase_defused函數(shù), 進(jìn)入sscanf函數(shù)使用 s 指令查看到

有關(guān)隱藏關(guān)密鑰的格式, 即我們需要在第四關(guān)密鑰后加一個(gè)字符串.

隱藏關(guān)sscanf函數(shù)原型

4.??? 重新開始, 第四關(guān)密鑰處輸入測(cè)試字符串 "10 5 haha" , 進(jìn)入到第六關(guān)后的pahse_defused函數(shù), 進(jìn)入其中的strings_not_equal函數(shù).

5.??? 按照第一關(guān)流程, 直接進(jìn)入第二個(gè)string_length函數(shù), 使用

x/8cb $edx

指令查看%s, 即第四關(guān)密鑰后需要輸入什么字符串

進(jìn)入隱藏關(guān)的密鑰

據(jù)此寫出%s的內(nèi)容: DrEvil.

看起來像一個(gè)人名, 猜測(cè)這個(gè)彩蛋密鑰應(yīng)該算類似“炸彈制作者名單”

6.??? 重新進(jìn)入該phase_defused函數(shù), 進(jìn)行到puts函數(shù), 發(fā)現(xiàn)了進(jìn)入隱藏關(guān)的提示語

已進(jìn)入隱藏關(guān)

不慌, 繼續(xù)執(zhí)行進(jìn)入secret_phase函數(shù)

7.??? read_line函數(shù), 輸入一行字符串, "lstnb"

8.??? 進(jìn)入到strtol函數(shù), 該函數(shù)是將字符串轉(zhuǎn)化為數(shù)字, base參數(shù)表明進(jìn)制, 查看原型:

隱藏關(guān)strtol函數(shù)原型

base = 10, 由此可知將輸入數(shù)字轉(zhuǎn)化為十進(jìn)制整數(shù)

9.??? 根據(jù)?? cmp $0x3e8, %eax / jbe ~~

可知輸入一個(gè)小于等于1000的數(shù)字可以避免爆炸

10.??? 重新開始, 輸入1000, 進(jìn)入fun7函數(shù), 發(fā)現(xiàn)fun7又是一個(gè)遞歸函數(shù)……$%!&^%!*#&^%

fun7函數(shù)

11.??? 經(jīng)過一定觀察, 發(fā)現(xiàn)fun7函數(shù)比第四關(guān)的fun4函數(shù)簡(jiǎn)單了不少, 長(zhǎng)舒一口氣

整理得到fun7函數(shù)所描述的算法如下

middle = array [ 0 ];?? //array首地址存儲(chǔ)在%edx中, middle存儲(chǔ)在middle中

fun7 ( input ) {??? ? ? ? //input存儲(chǔ)在%ecx中

? ? ?? if( input == middle ) return 0;

?????? else if ( input < middle) middle = *( array + 1 ) return 2 * fun ( input ) ;

?????? else middle = *(array + 2)return 2 * fun ( input ) + 1;

? ?}

12.??? 根據(jù)secretphase函數(shù)中的 cmp 0x2 %eax 指令, 可知fun7返回值應(yīng)為2

2 = 2 * ( 2 * 0 + 1) 進(jìn)行兩次遞歸調(diào)用, 利用x指令查看array中的部分值

數(shù)組array

根據(jù)遞推關(guān)系36→ 8 →22 可知需要用戶輸入的值為22

隱藏關(guān)密鑰:

22


[完結(jié)]

破解二進(jìn)制炸彈
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谭羔,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子界斜,更是在濱河造成了極大的恐慌服猪,老刑警劉巖宰译,帶你破解...
    沈念sama閱讀 211,496評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件迎变,死亡現(xiàn)場(chǎng)離奇詭異宁仔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)锤悄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,187評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門韧骗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人零聚,你說我怎么就攤上這事袍暴。” “怎么了隶症?”我有些...
    開封第一講書人閱讀 157,091評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵政模,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我沿腰,道長(zhǎng)览徒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,458評(píng)論 1 283
  • 正文 為了忘掉前任颂龙,我火速辦了婚禮习蓬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘措嵌。我一直安慰自己躲叼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,542評(píng)論 6 385
  • 文/花漫 我一把揭開白布企巢。 她就那樣靜靜地躺著枫慷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浪规。 梳的紋絲不亂的頭發(fā)上或听,一...
    開封第一講書人閱讀 49,802評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音笋婿,去河邊找鬼誉裆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛缸濒,可吹牛的內(nèi)容都是我干的足丢。 我是一名探鬼主播,決...
    沈念sama閱讀 38,945評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼庇配,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼斩跌!你這毒婦竟也來了朴摊?” 一聲冷哼從身側(cè)響起一屋,我...
    開封第一講書人閱讀 37,709評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤耽梅,失蹤者是張志新(化名)和其女友劉穎同仆,沒想到半個(gè)月后荆隘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吝镣,經(jīng)...
    沈念sama閱讀 44,158評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柱蟀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,502評(píng)論 2 327
  • 正文 我和宋清朗相戀三年屎即,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片著角。...
    茶點(diǎn)故事閱讀 38,637評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡揪漩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吏口,到底是詐尸還是另有隱情奄容,我是刑警寧澤,帶...
    沈念sama閱讀 34,300評(píng)論 4 329
  • 正文 年R本政府宣布产徊,位于F島的核電站昂勒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏舟铜。R本人自食惡果不足惜戈盈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,911評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谆刨。 院中可真熱鬧塘娶,春花似錦、人聲如沸痊夭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,744評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽她我。三九已至虹曙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間番舆,已是汗流浹背酝碳。 一陣腳步聲響...
    開封第一講書人閱讀 31,982評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恨狈,地道東北人疏哗。 一個(gè)月前我還...
    沈念sama閱讀 46,344評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像拴事,于是被迫代替她去往敵國(guó)和親沃斤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子圣蝎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,500評(píng)論 2 348