1. ホーム

2値化爆弾解除の記録

2022-02-08 01:57:12

学校からバイナリーボムの宿題が出され、自分で解体する作戦を確認しながら、合計2~3日かけて完成したものを解体していく。解体するときは、先に行った人の経験談を見ると上達が早い気がするので、まだ初心者の私でも、参考までに載せておきたいと思います。

の前に書いてください。
<ブロッククオート

https://www.cnblogs.com/liqiuhao/p/7624880.html和https://blog.csdn.net/the_v_/article/details/46842337/这两位大佬的无私奉献 のおかげで、私の爆弾発言は、この2つの解体の参考になりました。

0.gdbのブレークポイント

特に心配だったのは、爆弾を解除する前に爆発してしまうことです。gdbデバッグでブレークポイントを設定できることは知っていても、その方法がまだ理解できていませんでした。そこで、ブレークポイントの設定と結果をトップで実演し、爆発を恐れず安心して爆弾を爆発させることができるようにしますhh

どのように私はスキップした爆弾のファイルに入るには、爆弾が話すか、ステップバイステップのドキュメントか何かを参照する必要があります前に解体する必要があります。

では、爆弾のある場所までcdして、gdbデバッグだとします。

(@の前に学校番号があるので、表示されない) gdb bombと直接入力(または爆弾の名前)

すると、このようになり、gdbコマンドを直接入力できるようになります。


break *0x401751(爆弾があるアドレス、watch callq xxxxxx<explode_bomb> )と入力してEnterすると、ブレークポイントが設定されたことが表示されます。

その後、run と入力すれば爆弾の実行が開始され、もし間違った結果を入力して爆弾が爆発した場合は、次のように表示されます。


これでブレークポイントが有効になりました。この時点で、gdbのデバッグを続けるか(データを見るにはrunかx/s 0xxxxxxx)、qをタイプして終了してください。終了した後、再びgdb bombをするときには、ブレークポイントをリセットすることを忘れないでください。ブレークポイントが爆弾の前に設定されている場合、c(continue)を入力しない、または実行を継続することは爆発です。

さて、いよいよ正式に爆弾の信管を外す作業を開始します


*csapp 3rd P120: %r(e)di 第1引数; %r(e)si 第2引数; %r(e)dx 第3引数; %r(e)cx 第4引数、%eax 関数の戻り値です。後で使うかもしれません。

1. Phase1 文字列比較

00000000000000400f90 <phase_1>:
  400f90: 48 83 ec 08 sub $0x8,%rsp //current input
  400f94: be 50 27 40 00 mov    
$0x402750
,%esi // take the contents of 0x402750, as the second argument
  400f99: e8 da 04 00 00 callq 401478 <strings_not_equal>// found a call to a function that compares two strings
  400f9e: 85 c0 test %eax,%eax
  400fa0: 74 05 je 400fa7 <phase_1+0x17>//return value is not 0, googled: test themselves, plus je, is to compare is not 0
  400fa2: e8 aa 07 00 00 callq 401751 <explode_bomb>//or blow up
  400fa7: 48 83 c4 08 add $0x8,%rsp
  400fab: c3 retq   

strings_not_equal (文字列が同じ場合に返されるものだけを調べました)

00000000000000401478 <strings_not_equal>:
  401478: 41 54 push %r12
  40147a: 55 push %rbp
  40147b: 53 push %rbx
  40147c: 48 89 fb mov %rdi,%rbx //rbx=first parameter address: input
  40147f: 48 89 f5 mov %rsi,%rbp// rbp=second parameter address: address
  401482: e8 d4 ff ff ff callq 40145b <string_length>
  401487: 41 89 c4 mov %eax,%r12d // r12d input string length
  40148a: 48 89 ef mov %rbp,%rdi
  40148d: e8 c9 ff ff ff callq 40145b <string_length>
  401492: ba 01 00 00 00 mov $0x1,%edx
  401497: 41 39 c4 cmp %eax,%r12d //compare length of two strings
  40149a: 75 3f jne 4014db <strings_not_equal+0x63>
  40149c: 0f b6 03 movzbl (%rbx),%eax//equal, extract first character of input
  40149f: 84 c0 test %al,%al
  4014a1: 74 25 je 4014c8 <strings_not_equal+0x50>//compare if input is 0 (end of string), end jump
  4014a3: 3a 45 00 cmp 0x0(%rbp),%al//Didn't end, compare the first character of the two strings
  4014a6: 74 0a je 4014b2 <strings_not_equal+0x3a>//same jump... .4b2
  4014a8: eb 25 jmp 4014cf <strings_not_equal+0x57>
  4014aa: 3a 45 00 cmp 0x0(%rbp),%al///From . ...4bf jump here, look out for this loop block Start loop to compare one by one
  4014ad: 0f 1f 00 nopl (%rax)
  4014b0: 75 24 jne 4014d6 <strings_not_equal+0x5e>
  4014b2: 48 83 c3 01 add $0x1,%rbx///First character same to here
  4014b6: 48 83 c5 01 add $0x1,%rbp//Second character
  4014ba: 0f b6 03 movzbl (%rbx),%eax
  4014bd: 84 c0 test %al,%al
  4014bf: 75 e9 jne 4014aa <strings_not_equal+0x32>//again, is it the end
  4014c1: ba 00 00 00 00 mov $0x0,%edx//Compare to the end of the string, edx=0
  4014c6: eb 13 jmp 4014db <strings_not_equal+0x63>//jump... .4db
  4014c8: ba 00 00 00 00 mov $0x0,%edx
  4014cd: eb 0c jmp 4014db <strings_not_equal+0x63>
  4014cf: ba 01 00 00 00 mov $0x1,%edx
  4014d4: eb 05 jmp 4014db <strings_not_equal+0x63>
  4014d6: ba 01 00 00 00 mov $0x1,%edx
  4014db: 89 d0 mov %edx,%eax//If all are equal, return value is 0
  4014dd: 5b pop %rbx
  4014de: 5d pop %rbp
  4014df: 41 5c pop %r12
  4014e1: c3 retq   

解析の結果、0x402750が目的の文字列であることがわかったので、(gdb) x/s 0x402750 で文字列をチェックします。私の家からロシアが見える!" ロシアと中国の友好は長く続くだろう hhhh

2.第2期シリーズ

00000000000000400fac <phase_2>:0 1 1 2 3 5
  400fac: 55 push %rbp
  400fad: 53 push %rbx
  400fae: 48 83 ec 28 sub $0x28,%rsp
  400fb2: 48 89 e6 mov %rsp,%rsi
  400fb5: e8 cd 07 00 00 callq 401787 <read_six_numbers>// look at the name anyway to know read in six numbers ... Look closely at the function is too big head ...
  400fba: 83 3c 24 00 cmpl $0x0,(%rsp)//rsp point to the first number, you can just lose a string of numbers gdb take a look, anyway, not afraid to blow hahaha
  400fbe: 75 07 jne 400fc7 <phase_2+0x1b> // and 0 than, not equal to blow up (ac+1b=c7)
  400fc0: 83 7c 24 04 01 cmpl $0x1,0x4(%rsp)//rsp+4 //second number, compare with 1
  400fc5: 74 21 je 400fe8 <phase_2+0x3c> //not equal explosion, equal jump e8
  400fc7: e8 85 07 00 00 callq 401751 <explode_bomb>
  400fcc: eb 1a jmp 400fe8 <phase_2+0x3c>  
  400fce: 8b 43 f8 mov -0x8(%rbx),%eax//eax=rbx first two digits
  400fd1: 03 43 fc add -0x4(%rbx),%eax//eax=eax+eax previous number
  400fd4: 39 03 cmp %eax,(%rbx)//compare whether rbx is equal to the sum of the first two numbers
  400fd6: 74 05 je 400fdd <phase_2+0x31>equal jump dd otherwise blow
  400fd8: e8 74 07 00 00 callq 401751 <explode_bomb>
  400fdd: 48 83 c3 04 add $0x4,%rbx//rbx shift back one
  400fe1: 48 39 eb cmp %rbp,%rbx // whether rbx is out of range by 6
  400fe4: 75 e8 jne 400fce <phase_2+0x22> //rbx not out of range, loop ce
  400fe6: eb 0c jmp 400ff4 <phase_2+0x48> //exceeded, jump f4 , end
  400fe8: 48 8d 5c 24 08 lea 0x8(%rsp),%rbx //rbx points to third number 
  400fed: 48 8d 6c 24 18 lea 0x18(%rsp),%rbp//rbp points to rsp+24, i.e. the data after the sixth digit
  400ff2: eb da jmp 400fce <phase_2+0x22> skip ce
  400ff4: 48 83 c4 28 add $0x28,%rsp
  400ff8: 5b pop %rbx
  400ff9: 5d pop %rbp
  400ffa: c3 retq   

ループ本体の外側で比較すると、最初の数=0、2番目の数=1であることがわかる。ループは配列 a[i+2] == a[i+1]+a[i] を判断するために使用されるので、解答配列が導かれることになります。0 1 1 2 3 5

3. フェーズ3スイッチ

00000000000000400ffb <phase_3>:
  400ffb: 48 83 ec 18 sub $0x18,%rsp
  400fff: 4c 8d 44 24 0c lea 0xc(%rsp),%r8///3rd input
  401004: 48 8d 4c 24 07 lea 0x7(%rsp),%rcx//2nd input
  401009: 48 8d 54 24 08 lea 0x8(%rsp),%rdx///First input
  40100e: be 96 27 40 00 mov $0x402796,%esi//move the input here
  401013: b8 00 00 00 00 mov $0x0,%eax
  401018: e8 93 fc ff ff callq 400cb0 <__isoc99_sscanf@plt>
  40101d: 83 f8 02 cmp $0x2,%eax //eax returns the number of inputs
  401020: 7f 05 jg 401027 <phase_3+0x2c> //greater than 2 jump 1027, otherwise blow. So greater than two inputs
  401022: e8 2a 07 00 00 callq 401751 <explode_bomb>
  401027: 83 7c 24 08 07 cmpl $0x7,0x8(%rsp) //rdx and 7
  40102c: 0f 87 fc 00 00 00 ja 40112e <phase_3+0x133>//greater than 7, jump 112e bomb , so rdx is less than 7
  401032: 8b 44 24 08 mov 0x8(%rsp),%eax
  401036: ff 24 c5 a0 27 40 00 jmpq 
 *0x4027a0
(,%rax,8)//with switch jump Base address 40103d

前のアドレスを見てみると、オフセットを加えた後にジャンプするアドレスで、0を入力することにしたので、40103dにジャンプしています

  40103d: b8 71 00 00 00 mov $0x71,%eax //eax=71H
  401042: 81 7c 24 0c 6e 03 00 cmpl $0x36e,0xc(%rsp) //third digit=878
  401049: 00 
  40104a: 0f 84 e8 00 00 00 je 401138 <phase_3+0x13d>   
  401050: e8 fc 06 00 00 callq 401751 <explode_bomb>
  401055: b8 71 00 00 00 mov $0x71,%eax
  40105a: e9 d9 00 00 00 jmpq 401138 <phase_3+0x13d>//jump . .1138
  40105f: b8 64 00 00 00 mov $0x64,%eax
  401064: 81 7c 24 0c fd 02 00 cmpl $0x2fd,0xc(%rsp)
  40106b: 00 
  40106c: 0f 84 c6 00 00 00 je 401138 <phase_3+0x13d>
  401072: e8 da 06 00 00 callq 401751 <explode_bomb>
  401077: b8 64 00 00 00 mov $0x64,%eax
  40107c: e9 b7 00 00 00 jmpq 401138 <phase_3+0x13d>
  401081: b8 61 00 00 00 mov $0x61,%eax
  401086: 81 7c 24 0c c8 00 00 cmpl $0xc8,0xc(%rsp)
  40108d: 00 
  40108e: 0f 84 a4 00 00 00 je 401138 <phase_3+0x13d>
  401094: e8 b8 06 00 00 callq 401751 <explode_bomb>
  401099: b8 61 00 00 00 mov $0x61,%eax
  40109e: e9 95 00 00 00 jmpq 401138 <phase_3+0x13d>
  4010a3: b8 63 00 00 00 mov $0x63,%eax
  4010a8: 81 7c 24 0c 76 02 00 cmpl $0x276,0xc(%rsp)
  4010af: 00 
  4010b0: 0f 84 82 00 00 00 je 401138 <phase_3+0x13d>
  4010b6: e8 96 06 00 00 callq 401751 <explode_bomb>
  4010bb: b8 63 00 00 00 mov $0x63,%eax
  4010c0: eb 76 jmp 401138 <phase_3+0x13d>
  4010c2: b8 78 00 00 00 mov $0x78,%eax
  4010c7: 81 7c 24 0c df 00 00 cmpl $0xdf,0xc(%rsp)
  4010ce: 00 
  4010cf: 74 67 je 401138 <phase_3+0x13d>
  4010d1: e8 7b 06 00 00 callq 401751 <explode_bomb>
  4010d6: b8 78 00 00 00 mov $0x78,%eax
  4010db: eb 5b jmp 401138 <phase_3+0x13d>
  4010dd: b8 72 00 00 00 mov $0x72,%eax
  4010e2: 81 7c 24 0c f9 02 00 cmpl $0x2f9,0xc(%rsp)
  4010e9: 00 
  4010ea: 74 4c je 401138 <phase_3+0x13d>
  4010ec: e8 60 06 00 00 callq 401751 <explode_bomb>
  4010f1: b8 72 00 00 00 mov $0x72,%eax
  4010f6: eb 40 jmp 401138 <phase_3+0x13d>
  4010f8: b8 69 00 00 00 mov $0x69,%eax
  4010fd: 81 7c 24 0c 73 03 00 cmpl $0x373,0xc(%rsp)
  401104: 00 
  401105: 74 31 je 401138 <phase_3+0x13d>
  401107: e8 45 06 00 00 callq 401751 <explode_bomb>
  40110c: b8 69 00 00 00 mov $0x69,%eax
  401111: eb 25 jmp 401138 <phase_3+0x13d>
  401113: b8 75 00 00 00 mov $0x75,%eax
  401118: 81 7c 24 0c a0 02 00 cmpl $0x2a0,0xc(%rsp)
  40111f: 00 
  401120: 74 16 je 401138 <phase_3+0x13d>
  401122: e8 2a 06 00 00 callq 401751 <explode_bomb>
  401127: b8 75 00 00 00 mov $0x75,%eax
  40112c: eb 0a jmp 401138 <phase_3+0x13d>
  40112e: e8 1e 06 00 00 callq 401751 <explode_bomb>
  401133: b8 63 00 00 00 mov $0x63,%eax
  401138: 3a 44 24 07 cmp 0x7(%rsp),%al // go here and compare the second number with al (eax lower 8 bits) which is 0x71: 113--ASCII(q)
  40113c: 74 05 je 401143 <phase_3+0x148>
  40113e: e8 0e 06 00 00 callq 401751 <explode_bomb>
  401143: 48 83 c4 18 add $0x18,%rsp
  401147: c3 retq   


ノックレベルが長く感じられる?長いのはいいんだけど...。ああの理解を参照してください... 第四再帰は、私が吐いた...

2回目の入力でぐずぐず・・・。なんで間違うんだろうと思いながら113を入力し続けたら、どんどん吹っ飛んでいって、ついに格納されているアドレスのデータ型を見に行ったら...。

なんと、2つ目は実は文字なんです(実は冒頭でヒントが出ていて、0x7(%rsp)と0x8(%rsp)、1バイトはもちろんcharなんですが・・・。しかし、私はバカだ...) そして、ASCIIコードを調べて思い出したのが、3つ目の答えです。0 q 878

4. Phase4 再帰

0000000000000040117b <phase_4>:
  40117b: 48 83 ec 18 sub $0x18,%rsp
  40117f: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx //second input
  401184: 48 8d 54 24 08 lea 0x8(%rsp),%rdx //first input
  401189: be 6d 2a 40 00 mov $0x402a6d,%esi
  40118e: b8 00 00 00 00 mov $0x0,%eax
  401193: e8 18 fb ff ff callq 400cb0 <__isoc99_sscanf@plt>
  401198: 83 f8 02 cmp $0x2,%eax
  40119b: 75 07 jne 4011a4 <phase_4+0x29>//not equal, bomb so enter two numbers
  40119d: 83 7c 24 08 0e cmpl $0xe,0x8(%rsp)
  4011a2: 76 05 jbe 4011a9 <phase_4+0x2e> //the first number is less than or equal to 14, jump a9 
  4011a4: e8 a8 05 00 00 callq 401751 <explode_bomb> 
  4011a9: ba 0e 00 00 00 mov $0xe,%edx //edx=14
  4011ae: be 00 00 00 00 mov $0x0,%esi //esi=0
  4011b3: 8b 7c 24 08 mov 0x8(%rsp),%edi //edi=first input
  4011b7: e8 8c ff ff ff callq 401148 <func4>
  4011bc: 83 f8 25 cmp $0x25,%eax
  4011bf: 75 07 jne 4011c8 <phase_4+0x4d> // return must be 0x25=37
  4011c1: 83 7c 24 0c 25 cmpl $0x25,0xc(%rsp) //second number is 37
  4011c6: 74 05 je 4011cd <phase_4+0x52>   
  4011c8: e8 84 05 00 00 callq 401751 <explode_bomb>   
  4011cd: 48 83 c4 18 add $0x18,%rsp
  4011d1: c3 retq   
0000000000401148 <func4>:// three arguments, (edi=input, rsi,rdx)
  401148: 53 push %rbx
  401149: 89 d0 mov %edx,%eax //eax=14
  40114b: 29 f0 sub %esi,%eax //eax=eax-0=14
  40114d: 89 c3 mov %eax,%ebx //ebx=14
  40114f: c1 eb 1f shr $0x1f,%ebx //logical right shift 31 bits 14>>31=0
  401152: 01 d8 add %ebx,%eax //eax=eax+0=14
  401154: d1 f8 sar %eax //eax arithmetic shift right eax=7		
  401156: 8d 1c 30 lea (%rax,%rsi,1),%ebx //ebx=rsi+rax=0+14=14		
  401159: 39 fb cmp %edi,%ebx  
  40115b: 7e 0c jle 401169 <func4+0x21> //14<=Enter first number Skip 69
  40115d: 8d 53 ff lea -0x1(%rbx),%edx //Input first number<14 edx=rbx-1=13
  401160: e8 e3 ff ff ff callq 401148 <func4> //recursive
  401165: 01 d8 add %ebx,%eax //eax=eax+ebx=14+recursive return
  401167: eb 10 jmp 401179 <func4+0x31>//end
  401169: 89 d8 mov %ebx,%eax //eax=14
  40116b: 39 fb cmp %edi,%ebx     
  40116d: 7d 0a jge 401179 <func4+0x31> //14>=Enter first number Skip 79,end. If 14 is entered, then return 14 
  40116f: 8d 73 01 lea 0x1(%rbx),%esi //enter first number>14 esi=rbx+1=14+1
  401172: e8 d1 ff ff ff callq 401148 <func4>//recursive
  401177: 01 d8 add %ebx,%eax//eax=eax+ebx return
  401179: 5b pop %rbx
  40117a: c3 retq

int digui(int edi, int rsi, int rdx)
{
	int eax = rdx;
	int ebx = eax;
	eax = eax - rsi;
	ebx = ebx >> 31;
	eax = ebx + eax;
	eax = eax / 2;
	ebx = rsi + eax;
	if (ebx <= edi)
	{
		eax = ebx;
		if (ebx >= edi)
			return eax;
		else
		{
			rsi = ebx + 1;
			return digui(edi, rsi, rdx) + ebx;
		}
	}
	else
	{
		rdx = ebx - 1;
		return digui(edi, rsi, rdx) + ebx;
	}
}


みんな、ごめんね・・・。私はこの質問で死亡した... 何からこの再帰を理解していない夜を見た...

最初の数字に範囲があり、2番目の数字が決まっているので、暴力的に爆弾を解除しています...。これからも研究を続けて、新しいものを作ってみようと思います...。

網羅的なリストの答えは、10 37

wow it worked it worked, reread func4 and wrote it in C as follows.

000000000000004011d2 <phase_5>:
  4011d2: 48 83 ec 18 sub $0x18,%rsp
  4011d6: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx// Second number
  4011db: 48 8d 54 24 08 lea 0x8(%rsp),%rdx///First number
  4011e0: be 6d 2a 40 00 mov $0x402a6d,%esi //input put here
  4011e5: b8 00 00 00 00 mov $0x0,%eax
  4011ea: e8 c1 fa ff ff callq 400cb0 <__isoc99_sscanf@plt>
  4011ef: 83 f8 01 cmp $0x1,%eax
  4011f2: 7f 05 jg 4011f9 <phase_5+0x27> //input parameters greater than 1
  4011f4: e8 58 05 00 00 callq 401751 <explode_bomb>
  4011f9: 8b 44 24 08 mov 0x8(%rsp),%eax //eax=first number
  4011fd: 83 e0 0f and $0xf,%eax //eax=fourth digit after the first number
  401200: 89 44 24 08 mov %eax,0x8(%rsp) //0x8(rsp)=last four bits   
  401204: 83 f8 0f cmp $0xf,%eax
  401207: 74 2c je 401235 <phase_5+0x63> //if the last four bits of the first number are all 1s blow up
  401209: b9 00 00 00 00 mov $0x0,%ecx //ecx=0
  40120e: ba 00 00 00 00 mov $0x0,%edx //edx=0
  401213: 83 c2 01 add $0x1,%edx //edx=1 Addition times
  401216: 48 98 cltq      
  401218: 8b 04 85 e0 27 40 00 mov    

0x4027e0
(,%rax,4),%eax //gdb look at 0x4027e0 eax=base address plus 4*lower four bits of the first number

<イグ

0から14まで入力した結果は上記のようになり、10を入力した場合は37が返されます

5. Phase5 配列

  40121f: 01 c1 add %eax,%ecx //ecx=ecx+eax which means the result of the read is cumulative
  401221: 83 f8 0f cmp $0xf,%eax //eax!=f read out not f, keep looping
  401224: 75 ed jne 401213 <phase_5+0x41> //not f, skip 213
  401226: 89 44 24 08 mov %eax,0x8(%rsp)//read out as offset for next jump
  40122a: 83 fa 0f cmp $0xf,%edx //edx=15 must be added 15 times, i.e., ensure that f is read on the fifteenth
  40122d: 75 06 jne 401235 <phase_5+0x63>
  40122f: 3b 4c 24 0c cmp 0xc(%rsp),%ecx //rsp+12=ecx The second number entered is equal to the accumulation of fifteen numbers
  401233: 74 05 je 40123a <phase_5+0x68>
  401235: e8 17 05 00 00 callq 401751 <explode_bomb>
  40123a: 48 83 c4 18 add $0x18,%rsp
  40123e: c3 retq   

このアドレスの後に、以下のように0~fの16個の数字がナンバリングされ、内容が表示されます。

<テーブル 0 1 2 3 4 5 6 7 8 9 a b c d e f a 2 e 7 8 c f b 0 4 1 d 3 9 6 5
0000000000000040123f <phase_6>:
  40123f: 41 56 push %r14
  401241: 41 55 push %r13
  401243: 41 54 push %r12
  401245: 55 push %rbp
  401246: 53 push %rbx
  401247: 48 83 ec 50 sub $0x50,%rsp
  40124b: 49 89 e5 mov %rsp,%r13
  40124e: 48 89 e6 mov %rsp,%rsi
  401251: e8 31 05 00 00 callq 401787 <read_six_numbers>//read six numbers
  401256: 49 89 e6 mov %rsp,%r14
  401259: 41 bc 00 00 00 00 mov $0x0,%r12d
  40125f: 4c 89 ed mov %r13,%rbp///loop body
  401262: 41 8b 45 00 mov 0x0(%r13),%eax
  401266: 83 e8 01 sub $0x1,%eax
  401269: 83 f8 05 cmp $0x5,%eax
  40126c: 76 05 jbe 401273 <phase_6+0x34>// determine if input is less than or equal to six (eax-1 is less than or equal to 5)
  40126e: e8 de 04 00 00 callq 401751 <explode_bomb>
  401273: 41 83 c4 01 add $0x1,%r12d//r12 add one and six compare
  401277: 41 83 fc 06 cmp $0x6,%r12d
  40127b: 74 21 je 40129e <phase_6+0x5f>//equal Jump 9e
  40127d: 44 89 e3 mov %r12d,%ebx//r12 1~5
  401280: 48 63 c3 movslq %ebx,%rax//loop body
  401283: 8b 04 84 mov (%rsp,%rax,4),%eax//eax=base address plus 4*r12
  401286: 39 45 00 cmp %eax,0x0(%rbp)
  401289: 75 05 jne 401290 <phase_6+0x51>//Current input (base address) and eax (offset) compare to be different
  40128b: e8 c1 04 00 00 callq 401751 <explode_bomb>
  401290: 83 c3 01 add $0x1,%ebx//ebx+1 see ebx as number after current input
  401293: 83 fb 05 cmp $0x5,%ebx
  401296: 7e e8 jle 401280 <phase_6+0x41>//ebx is less than or equal to 5, jump 80, inner loop, compare current number and all numbers after it are not the same
  401298: 49 83 c5 04 add $0x4,%r13//base address add 4, move current number back one
  40129c: eb c1 jmp 40125f <phase_6+0x20>//jump 5f, outer loop, traverse six numbers
  40129e: 48 8d 74 24 18 lea 0x18(%rsp),%rsi///compared the input six numbers are not the same rsi as the input six numbers after the boundary address
  4012a3: 4c 89 f0 mov %r14,%rax //rax the address of the first digit
  4012a6: b9 07 00 00 00 mov $0x7,%ecx
  4012ab: 89 ca mov %ecx,%edx//loop body
  4012ad: 2b 10 sub (%rax),%edx
  4012af: 89 10 mov %edx,(%rax)//


正直なところ、この爆弾を長時間読んでいても、ちょっとめまいがします...。下4桁しか考慮しないのだから、入力はすべて0-fに限定しよう、その方が楽だ。

このループは、私にはかなり複雑に見えますが...。説明しますと... 例えば、最初に入力した数字が0なので、表に従って、table[0]=aを読み出すと、累積0+aがaになり、次の入力がa、2回目のループでは、table[a]=1を読み出すと、累積a+1=bとなり、次の入力が1、3回目ではtable[1]=2と読み出し、累積b+2、次の 次入力が2 ...... と、なっているのですが、このように、ループが複雑になります。

要件を見てください。15番目に読み出されるのはfで、次に後ろに:

fを読むと、前のものは6、6を読むと、前のものはe、eを読むと、...となります。

f-6-e-2-1-a-0-8-4-9-d-b-7-3-c-5-f... という順序を導き出す。ループを開始する。

fから前方へ15を数えると、最初の読みはcなので、最初の入力は5となるはずです。

つまり、上記のfからcまでのシーケンスを追加するか、0から16までのシーケンスから5を引いたものを計算します(fのシーケンスは数字を読む時間がなくスキップされます)。

結果:5 115

6. フェーズ6 

 401325: bd 05 00 00 00 mov $0x5,%ebp
  40132a: 48 8b 43 08 mov 0x8(%rbx),%rax//loop body
  40132e: 8b 00 mov (%rax),%eax
  401330: 39 03 cmp %eax,(%rbx)
  401332: 7d 05 jge 401339 <phase_6+0xfa>//(rbx) is greater than or equal to ((rbx+8))
  401334: e8 18 04 00 00 callq 401751 <explode_bomb>
  401339: 48 8b 5b 08 mov 0x8(%rbx),%rbx//rbx=(rbx+8)
  40133d: 83 ed 01 sub $0x1,%ebp//ebp-1
  401340: 75 e8 jne 40132a <phase_6+0xeb>//non-zero, jump 2a
  401342: 48 83 c4 50 add $0x50,%rsp
  401346: 5b pop %rbx
  401347: 5d pop %rbp
  401348: 41 5c pop %r12
  40134a: 41 5d pop %r13
  40134c: 41 5e pop %r14
  40134e: c3 retq      


上の段落は大きなループで、おそらく1〜6が6つのアドレスに対応する関係が確立されており、あまり気にせずgdbで直接見ることができます(この段落はあまりじっくり見ていません...)。

000000000000004018ef <phase_defused>:
  4018ef: 48 83 ec 78 sub $0x78,%rsp
  4018f3: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
  4018fa: 00 00 
  4018fc: 48 89 44 24 68 mov %rax,0x68(%rsp)
  401901: 31 c0 xor %eax,%eax
  401903: bf 01 00 00 00 mov $0x1,%edi
  401908: e8 38 fd ff ff callq 401645 <send_msg>
  40190d: 83 3d a8 2e 20 00 06 cmpl $0x6,0x202ea8(%rip) # 6047bc <num_input_strings>
  401914: 75 6d jne 401983 <phase_defused+0x94>
  401916: 4c 8d 44 24 10 lea 0x10(%rsp),%r8
  40191b: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx
  401920: 48 8d 54 24 08 lea 0x8(%rsp),%rdx
  401925: be b7 2a 40 00 mov $0x402ab7,%esi
  40192a: bf d0 48 60 00 mov $0x6048d0,%edi
  40192f: b8 00 00 00 00 mov $0x0,%eax
  401934: e8 77 f3 ff ff callq 400cb0 <__isoc99_sscanf@plt>
  401939: 83 f8 03 cmp $0x3,%eax//Must enter three quantities
  40193c: 75 31 jne 40196f <phase_defused+0x80>//jump 6f,find jump out secret_phase call, so the above conditions must be met, and the next program is the hidden bomb entrance
  40193e: be c0 2a 40 00 mov $0x402ac0,%esi //hide
  401943: 48 8d 7c 24 10 lea 0x10(%rsp),%rdi
  401948: e8 2b fb ff ff callq 401478 <strings_not_equal>// and a fixed address to compare strings, then the address is likely to be the password
  40194d: 85 c0 test %eax,%eax
  40194f: 75 1e jne 40196f <phase_defused+0x80>
  401951: bf 18 29 40 00 mov $0x402918,%edi
  401956: e8 65 f2 ff ff callq 400bc0 <puts@plt>
  40195b: bf 40 29 40 00 mov $0x402940,%edi
  401960: e8 5b f2 ff ff callq 400bc0 <puts@plt>
  401965: b8 00 00 00 00 mov $0x0,%eax
  40196a: e8 1e fa ff ff callq 40138d <secret_phase>
  40196f: bf 78 29 40 00 mov $0x402978,%edi
  401974: e8 47 f2 ff ff callq 400bc0 <puts@plt>
  401979: bf a8 29 40 00 mov $0x4029a8,%edi
  40197e: e8 3d f2 ff ff callq 400bc0 <pts@plt>
  401983: 48 8b 44 24 68 mov 0x68(%rsp),%rax
  401988: 64 48 33 04 25 28 00 xor %fs:0x28,%rax
  40198f: 00 00 
  401991: 74 05 je 401998 <phase_defused+0xa9>
  401993: e8 48 f2 ff ff callq 400be0 <__stack_chk_fail@plt>
  401998: 48 83 c4 78 add $0x78,%rsp
  40199c: c3 retq   
  40199d: 0f 1f 00 nopl (%rax)


ノックロングノックロングノックロング... 必死で長く...

最後の段落で、見つけるために。7 - 番号の結果の番号を入力してください - 対応するアドレス - 対応する番号 - サイズの配置 - 逆入力

大きなループの中で定数アドレスが何度も登場し、その後gdbが混乱することに注意してください


1 2 3 4 5 6 と直接入力したら結果がおかしかったので、breakpoint1 と表示されて爆弾が爆発し、その後自動的に gdb に移動したので、直接デバッグすることが出来ました。

rspの中は処理した数値とアドレスの関係、rdxの中はアドレスメモリからのデータです。

対応関係を導き出すための整理

6 ---604360 ---1bf
5--604350 ---0e1
4 ---604340 ---05f
3 ---604330 ---2e1
2 ---604320 ---35c

1--604310 ---231

sort 35c(2)>2e1(3)>231(1)>1bf(6)>0e1(5)>05f(4)

収量入力 5 4 6 1 2 3

7. 秘密の爆弾 再帰的

0000000000000040138d <secret_phase>:
  40138d: 53 push %rbx
  40138e: e8 36 04 00 00 callq 4017c9 <read_line>
  401393: ba 0a 00 00 00 mov $0xa,%edx
  401398: be 00 00 00 00 mov $0x0,%esi
  40139d: 48 89 c7 mov %rax,%rdi
  4013a0: e8 eb f8 ff ff callq 400c90 <strtol@plt>
  4013a5: 48 89 c3 mov %rax,%rbx
  4013a8: 8d 40 ff lea -0x1(%rax),%eax
  4013ab: 3d e8 03 00 00 cmp $0x3e8,%eax
  4013b0: 76 05 jbe 4013b7 <secret_phase+0x2a>//read -1 less than or equal to 3e8
  4013b2: e8 9a 03 00 00 callq 401751 <explode_bomb>
  4013b7: 89 de mov %ebx,%esi //parameter two
  4013b9: bf 30 41 60 00 mov    
$0x604130
,%edi // parameter one
  4013be: e8 8c ff ff ff callq 40134f <fun7>
  4013c3: 85 c0 test %eax,%eax 
  4013c5: 74 05 je 4013cc <secret_phase+0x3f>// return must be zero, so my main concern in fun7 is how to return 0
  4013c7: e8 85 03 00 00 callq 401751 <explode_bomb>
  4013cc: bf 70 27 40 00 mov $0x402770,%edi
  4013d1: e8 ea f7 ff ff callq 400bc0 <puts@plt>
  4013d6: e8 14 05 00 00 callq 4018ef <phase_defused>
  4013db: 5b pop %rbx
  4013dc: c3 retq   
  4013dd: 0f 1f 00 nopl (%rax)


secret_phaseの呼び出し先を探したところ、phase_defusedにあることがわかりました。出現するアドレスに着目。


きっとパスワードがある


実行開始前のデバッグなので、入力は何もなかったのですが、入力比較の基準値が、2つの整数+文字列でした。2つの整数+DrEvil.という文字列の答えで、何かの爆弾を解除するときだとわかる。私のは4番目の爆弾で入力された。

0000000000000040134f <fun7>:
  40134f: 48 83 ec 08 sub $0x8,%rsp
  401353: 48 85 ff test %rdi,%rdi
  401356: 74 2b je 401383 <fun7+0x34>//edi is not 0
  401358: 8b 17 mov (%rdi),%edx
  40135a: 39 f2 cmp %esi,%edx
  40135c: 7e 0d jle 40136b <fun7+0x1c>//24H is less than or equal to input, jump 6b
  40135e: 48 8b 7f 08 mov 0x8(%rdi),%rdi
  401362: e8 e8 ff ff ff ff callq 40134f <fun7>
  401367: 01 c0 add %eax,%eax
  401369: eb 1d jmp 401388 <fun7+0x39>
  40136b: b8 00 00 00 00 mov $0x0,%eax//eax=0, target appears!
  401370: 39 f2 cmp %esi,%edx
  401372: 74 14 je 401388 <fun7+0x39>//end of jump, then the condition must be met, i.e. input=24H=36
  401374: 48 8b 7f 10 mov 0x10(%rdi),%rdi
  401378: e8 d2 ff ff ff callq 40134f <fun7>
  40137d: 8d 44 00 01 lea 0x1(%rax,%rax,1),%eax
  401381: eb 05 jmp 401388 <fun7+0x39>
  401383: b8 ff ff ff ff mov $0xffffffff,%eax
  401388: 48 83 c4 08 add $0x8,%rsp
  40138c: c3 retq   


edi=24H。

func7 懸念事項:0を返す

0000000000000040134f <fun7>:
  40134f: 48 83 ec 08 sub $0x8,%rsp
  401353: 48 85 ff test %rdi,%rdi
  401356: 74 2b je 401383 <fun7+0x34>//edi is not 0
  401358: 8b 17 mov (%rdi),%edx
  40135a: 39 f2 cmp %esi,%edx
  40135c: 7e 0d jle 40136b <fun7+0x1c>//24H is less than or equal to input, jump 6b
  40135e: 48 8b 7f 08 mov 0x8(%rdi),%rdi
  401362: e8 e8 ff ff ff ff callq 40134f <fun7>
  401367: 01 c0 add %eax,%eax
  401369: eb 1d jmp 401388 <fun7+0x39>
  40136b: b8 00 00 00 00 mov $0x0,%eax//eax=0, target appears!
  401370: 39 f2 cmp %esi,%edx
  401372: 74 14 je 401388 <fun7+0x39>//end of jump, then the condition must be met, i.e. input=24H=36
  401374: 48 8b 7f 10 mov 0x10(%rdi),%rdi
  401378: e8 d2 ff ff ff callq 40134f <fun7>
  40137d: 8d 44 00 01 lea 0x1(%rax,%rax,1),%eax
  401381: eb 05 jmp 401388 <fun7+0x39>
  401383: b8 ff ff ff ff mov $0xffffffff,%eax
  401388: 48 83 c4 08 add $0x8,%rsp
  40138c: c3 retq   

そして、24H=36という答えを入力します。

8. 最終結果

最後はふりかけ!