| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 7455 人关注过本帖
标题:二进制拆弹
只看楼主 加入收藏
wog
Rank: 2
来 自:南昌
等 级:论坛游民
帖 子:33
专家分:31
注 册:2010-10-2
结帖率:100%
收藏
 问题点数:0 回复次数:11 
二进制拆弹
话说曾几何时,兴冲冲的搞了本UNIX高级编程,看了半天发现竟然看不懂

我了个去,硬着头皮看咯

结果看得我头皮都麻了也硬是没搞懂,

然后又找了本操作系统,悲剧再次上演……

再换

计算机组成原理,这个能看懂,不过更喜欢汇编

闲话少说

上正餐:

之所以会学汇编,跟着个贴子也有关

http://bbs.

当初看不懂,觉得好厉害,最近学完了GAS的语法,自然是拿他先练手咯
ps:初学,接受所有批评和意见
ps2:绝对没有提前看答案
ps3:如果后面的拆不出来,太监了,大家也请见谅
PSP:再次感谢看雪,感谢编程论坛
PSP2000:怎么传不了附件啊
bomb.tar.gz (8.16 KB)


[ 本帖最后由 wog 于 2011-4-13 18:37 编辑 ]
搜索更多相关主题的帖子: 计算机 操作系统 二进制 答案 
2011-04-12 22:59
wog
Rank: 2
来 自:南昌
等 级:论坛游民
帖 子:33
专家分:31
注 册:2010-10-2
收藏
得分:0 
这一楼的内容转自看雪
【背景介绍】:二进制拆弹实验是卡内基-梅隆(CMU)开设的:计算机系统导论(ICS)课程的一道实验题,下面是《深入理解计算机系统》上面对这个实验的文字说明:
二进制炸弹是一个作为目标代码文件提供给学生们的程序。运行时,它提示用户输入6个不同的字符串。如果其中的任何一个不正确,炸弹就会“爆炸”,打印出一条错误信息,并在一个分级(gradin)服务器上记录事件日志。学生们必须通过对程序的反汇编和逆向工程来测定应该是哪6个串,从而解除他们各自炸弹的雷管。该实验教会学生理解汇编语言,并且强制他们学习怎样使用调试器
程序代码:
FILE *infile;
 
int main(int argc, char *argv[])
{
char *input;
 
/* Note to self: remember to port this bomb to Windows and put a 
* fantastic GUI on it. */

 
/* When run with no arguments, the bomb reads its input lines 
* from standard input. */
if (argc == 1) { 
    infile = stdin;
} 

 
/* When run with one argument <file>, the bomb reads from <file> 
* until EOF, and then switches to standard input. Thus, as you 
* defuse each phase, you can add its defusing string to <file> and
* avoid having to retype it. */
else if (argc == 2) {
    if (!(infile = fopen(argv[1], "r"))) {
     printf("%s: Error: Couldn't open %s\n", argv[0], argv[1]);
     exit(8);
    }
}

 
/* You can't call the bomb with more than 1 command line argument. */
else {
    printf("Usage: %s [<input_file>]\n", argv[0]);
    exit(8);
}

 
/* Do all sorts of secret stuff that makes the bomb harder to defuse. */
initialize_bomb();

 
printf("Welcome to my fiendish little bomb. You have 6 phases with\n");
printf("which to blow yourself up. Have a nice day!\n");

 
/* Hmm... Six phases must be more secure than one phase! */
input = read_line(); /* Get input */
phase_1(input); /* Run the phase */
phase_defused(); /* Drat! They figured it out!
                 * Let me know how they did it. */
printf("Phase 1 defused. How about the next one?\n");

 
/* The second phase is harder. No one will ever figure out
* how to defuse this... */
input = read_line();
phase_2(input);
phase_defused();
printf("That's number 2. Keep going!\n");

 
/* I guess this is too easy so far. Some more complex code will
* confuse people. */
input = read_line();
phase_3(input);
phase_defused();
printf("Halfway there!\n");

 
/* Oh yeah? Well, how good is your math? Try on this saucy problem! */
input = read_line();
phase_4(input);
phase_defused();
printf("So you got that one. Try this one.\n");

 
/* Round and 'round in memory we go, where we stop, the bomb blows! */
input = read_line();
phase_5(input);
phase_defused();
printf("Good work! On to the next...\n");

 
/* This phase will never be used, since no one will get past the
* earlier ones. But just in case, make this one extra hard. */
input = read_line();
phase_6(input);
phase_defused();

 
/* Wow, they got it! But isn't something... missing? Perhaps
* something they overlooked? Mua ha ha ha ha! */

 
return 0;
}

2011-04-12 23:01
wog
Rank: 2
来 自:南昌
等 级:论坛游民
帖 子:33
专家分:31
注 册:2010-10-2
收藏
得分:0 
程序代码:
(gdb) break *_start

Breakpoint 1 at 0x80488f0

(gdb) run

Starting program: /home/wog/bomb 


(gdb) s

Single stepping until exit from function _start,

which has no line number information.

0x00145c00 in __libc_start_main () from /lib/libc.so.6

(gdb) s

Single stepping until exit from function __libc_start_main,

which has no line number information.

Welcome to my fiendish little bomb. You have 6 phases with

which to blow yourself up. Have a nice day!

程序到这里就要密码了
于是先进行反汇编,
因为是用C写的,所以直接反汇编main函数
程序代码:
(gdb) disas main

Dump of assembler code for function main:

   0x080489c4 <+0>:lea    0x4(%esp),%ecx

   0x080489c8 <+4>:and    $0xfffffff0,%esp

   0x080489cb <+7>:pushl  -0x4(%ecx)

   0x080489ce <+10>:push   %ebp

   0x080489cf <+11>:mov    %esp,%ebp

   0x080489d1 <+13>:push   %ebx

   0x080489d2 <+14>:push   %ecx

   0x080489d3 <+15>:sub    $0x10,%esp

   0x080489d6 <+18>:mov    (%ecx),%eax

   0x080489d8 <+20>:mov    0x4(%ecx),%ebx

   0x080489db <+23>:cmp    $0x1,%eax

   0x080489de <+26>:jne    0x80489ec <main+40>

   0x080489e0 <+28>:mov    0x804a800,%eax

   0x080489e5 <+33>:mov    %eax,0x804a814

   0x080489ea <+38>:jmp    0x8048a50 <main+140>

   0x080489ec <+40>:cmp    $0x2,%eax

   0x080489ef <+43>:jne    0x8048a32 <main+110>

   0x080489f1 <+45>:movl   $0x8049972,0x4(%esp)

   0x080489f9 <+53>:mov    0x4(%ebx),%eax

   0x080489fc <+56>:mov    %eax,(%esp)

---Type <return> to continue, or q <return> to quit---

   0x080489ff <+59>:call   0x80487f4 <fopen@plt>

   0x08048a04 <+64>:mov    %eax,0x804a814

   0x08048a09 <+69>:test   %eax,%eax

   0x08048a0b <+71>:jne    0x8048a50 <main+140>

   0x08048a0d <+73>:mov    0x4(%ebx),%eax

   0x08048a10 <+76>:mov    %eax,0x8(%esp)

   0x08048a14 <+80>:mov    (%ebx),%eax

   0x08048a16 <+82>:mov    %eax,0x4(%esp)

   0x08048a1a <+86>:movl   $0x804974c,(%esp)

   0x08048a21 <+93>:call   0x8048814 <printf@plt>

   0x08048a26 <+98>:movl   $0x8,(%esp)

   0x08048a2d <+105>:call   0x80488d4 <exit@plt>

   0x08048a32 <+110>:mov    (%ebx),%eax

   0x08048a34 <+112>:mov    %eax,0x4(%esp)

   0x08048a38 <+116>:movl   $0x8049769,(%esp)

   0x08048a3f <+123>:call   0x8048814 <printf@plt>

   0x08048a44 <+128>:movl   $0x8,(%esp)

   0x08048a4b <+135>:call   0x80488d4 <exit@plt>

   0x08048a50 <+140>:call   0x80495af <initialize_bomb>

   0x08048a55 <+145>:movl   $0x80497d0,(%esp)

   0x08048a5c <+152>:call   0x80488a4 <puts@plt>

---Type <return> to continue, or q <return> to quit---

   0x08048a61 <+157>:movl   $0x804980c,(%esp)

   0x08048a68 <+164>:call   0x80488a4 <puts@plt>

   0x08048a6d <+169>:call   0x8049363 <read_line>

   0x08048a72 <+174>:mov    %eax,(%esp)

   0x08048a75 <+177>:call   0x8048ec1 <phase_1>

   0x08048a7a <+182>:call   0x80491c1 <phase_defused>

   0x08048a7f <+187>:movl   $0x8049838,(%esp)

   0x08048a86 <+194>:call   0x80488a4 <puts@plt>

   0x08048a8b <+199>:call   0x8049363 <read_line>

   0x08048a90 <+204>:mov    %eax,(%esp)

   0x08048a93 <+207>:call   0x8048d1c <phase_2>

   0x08048a98 <+212>:call   0x80491c1 <phase_defused>

   0x08048a9d <+217>:movl   $0x8049783,(%esp)

   0x08048aa4 <+224>:call   0x80488a4 <puts@plt>

   0x08048aa9 <+229>:call   0x8049363 <read_line>

   0x08048aae <+234>:mov    %eax,(%esp)

   0x08048ab1 <+237>:call   0x8048e01 <phase_3>

   0x08048ab6 <+242>:call   0x80491c1 <phase_defused>

   0x08048abb <+247>:movl   $0x80497a1,(%esp)

   0x08048ac2 <+254>:call   0x80488a4 <puts@plt>

   0x08048ac7 <+259>:call   0x8049363 <read_line>

---Type <return> to continue, or q <return> to quit---

   0x08048acc <+264>:mov    %eax,(%esp)

   0x08048acf <+267>:call   0x8048db6 <phase_4>

   0x08048ad4 <+272>:call   0x80491c1 <phase_defused>

   0x08048ad9 <+277>:movl   $0x8049864,(%esp)

   0x08048ae0 <+284>:call   0x80488a4 <puts@plt>

   0x08048ae5 <+289>:call   0x8049363 <read_line>

   0x08048aea <+294>:mov    %eax,(%esp)

   0x08048aed <+297>:call   0x8048d6a <phase_5>

   0x08048af2 <+302>:call   0x80491c1 <phase_defused>

   0x08048af7 <+307>:movl   $0x80497b0,(%esp)

   0x08048afe <+314>:call   0x80488a4 <puts@plt>

   0x08048b03 <+319>:call   0x8049363 <read_line>

   0x08048b08 <+324>:mov    %eax,(%esp)

   0x08048b0b <+327>:call   0x8048c2c <phase_6>

   0x08048b10 <+332>:call   0x80491c1 <phase_defused>

   0x08048b15 <+337>:mov    $0x0,%eax

   0x08048b1a <+342>:add    $0x10,%esp

   0x08048b1d <+345>:pop    %ecx

   0x08048b1e <+346>:pop    %ebx

   0x08048b1f <+347>:pop    %ebp

   0x08048b20 <+348>:lea    -0x4(%ecx),%esp

---Type <return> to continue, or q <return> to quit---

   0x08048b23 <+351>:ret    

不得不说,这教授的c代码还真规范,让人一眼就看到了一个硕大的
0x08048a75 <+177>:call   0x8048ec1 <phase_1>
猜测这个就是第一个炸弹
于是,尾行之
程序代码:
(gdb) disas phase_1
Dump of assembler code for function phase_1:
   0x08048ec1 <+0>:push   %ebp
   0x08048ec2 <+1>:mov    %esp,%ebp
   0x08048ec4 <+3>:sub    $0x8,%esp
   0x08048ec7 <+6>:movl   $0x80498b0,0x4(%esp)
   0x08048ecf <+14>:mov    0x8(%ebp),%eax
   0x08048ed2 <+17>:mov    %eax,(%esp)
   0x08048ed5 <+20>:call   0x8048f10 <strings_not_equal>
   0x08048eda <+25>:test   %eax,%eax
   0x08048edc <+27>:je     0x8048ee3 <phase_1+34>
   0x08048ede <+29>:call   0x8049253 <explode_bomb>
   0x08048ee3 <+34>:leave  
   0x08048ee4 <+35>:ret    
End of assembler dump.

在这里,注意到0x08048ed5 <+20>:call   0x8048f10 <strings_not_equal>
我英语不好,但我认得这个<strings_not_equal>
所以,往上看
0x08048ec7 <+6>:movl   $0x80498b0,0x4(%esp)
   0x08048ecf <+14>:mov    0x8(%ebp),%eax
   0x08048ed2 <+17>:mov    %eax,(%esp)

吆西,密码就在这里
$0x80498b0
窥之
(gdb) x/4sb 0x80498b0
0x80498b0 <__dso_handle+360>: "I am not part of the problem. I am a Republican."

答案出来了
运行得
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
I am not part of the problem. I am a Republican.
Phase 1 defused. How about the next one?


[ 本帖最后由 wog 于 2011-4-12 23:07 编辑 ]
2011-04-12 23:02
zaixuexi
Rank: 12Rank: 12Rank: 12
来 自:上海
等 级:火箭侠
威 望:8
帖 子:858
专家分:3233
注 册:2010-12-1
收藏
得分:0 
哇塞,AT&T的语法,学习学习

技术问题,请不要以短消息方式提问
2011-04-12 23:09
wog
Rank: 2
来 自:南昌
等 级:论坛游民
帖 子:33
专家分:31
注 册:2010-10-2
收藏
得分:0 
话说,这第二颗确实比第一颗难度大很多,我按照上面的思路,被炸得体无完肤~~!
后来发现这个并不是像上面一样的固定的密码
这里是main函数反汇编得到的
   
程序代码:
0x08048a8b <+199>:    call   0x8049363 <read_line>
   0x08048a90 <+204>:    mov    %eax,(%esp)
   0x08048a93 <+207>:    call   0x8048d1c <phase_2>
   0x08048a98 <+212>:    call   0x80491c1 <phase_defused>
   0x08048a9d <+217>:    movl   $0x8049783,(%esp)

即将断点设在phase_2上
重新运行
发现要先输入才能运行到断点处
随便输入什么比如1 2 3 4 5 6吧
所以这个  0x08048a8b <+199>:call   0x8049363 <read_line>
一定是得到密码的函数,并且  他这么急着保存,很有可能刚输入的就在eax里
程序代码:
(gdb) info reg
eax            0x804a870
……
(gdb) x/1sb 0x804a870
0x804a870 <input_strings+80>:     "1 2 3 4 5 6"

果然就在这里,所以,就先不看read_line了

然后disas phase_2
程序代码:
(gdb) disas phase_2
Dump of assembler code for function phase_2:
   0x08048d1c <+0>:    push   %ebp
   0x08048d1d <+1>:    mov    %esp,%ebp
   0x08048d1f <+3>:    push   %esi
   0x08048d20 <+4>:    push   %ebx
   0x08048d21 <+5>:    sub    $0x30,%esp
   0x08048d24 <+8>:    lea    -0x20(%ebp),%eax
   0x08048d27 <+11>:    mov    %eax,0x4(%esp)
   0x08048d2b <+15>:    mov    0x8(%ebp),%eax
   0x08048d2e <+18>:    mov    %eax,(%esp)
   0x08048d31 <+21>:    call   0x8049295 <read_six_numbers>
   0x08048d36 <+26>:    cmpl   $0x1,-0x20(%ebp)
   0x08048d3a <+30>:    je     0x8048d41 <phase_2+37>
   0x08048d3c <+32>:    call   0x8049253 <explode_bomb>
   0x08048d41 <+37>:    mov    $0x2,%ebx
   0x08048d46 <+42>:    lea    -0x20(%ebp),%esi
   0x08048d49 <+45>:    mov    %ebx,%eax
   0x08048d4b <+47>:    imul   -0x8(%esi,%ebx,4),%eax
   0x08048d50 <+52>:    cmp    %eax,-0x4(%esi,%ebx,4)
   0x08048d54 <+56>:    je     0x8048d5b <phase_2+63>
   0x08048d56 <+58>:    call   0x8049253 <explode_bomb>
   0x08048d5b <+63>:    add    $0x1,%ebx
   0x08048d5e <+66>:    cmp    $0x7,%ebx
   0x08048d61 <+69>:    jne    0x8048d49 <phase_2+45>
   0x08048d63 <+71>:    add    $0x30,%esp
   0x08048d66 <+74>:    pop    %ebx
   0x08048d67 <+75>:    pop    %esi
   0x08048d68 <+76>:    pop    %ebp
   0x08048d69 <+77>:    ret   

这段代码
eax给了esp后就调用函数read_six_numbers
所以再disas  read_six_numbers

程序代码:
gdb) disas read_six_numbers
Dump of assembler code for function read_six_numbers:
   0x08049295 <+0>:    push   %ebp
   0x08049296 <+1>:    mov    %esp,%ebp
   0x08049298 <+3>:    sub    $0x28,%esp
   0x0804929b <+6>:    mov    0xc(%ebp),%edx
   0x0804929e <+9>:    lea    0x14(%edx),%eax
   0x080492a1 <+12>:    mov    %eax,0x1c(%esp)
   0x080492a5 <+16>:    lea    0x10(%edx),%eax
   0x080492a8 <+19>:    mov    %eax,0x18(%esp)
   0x080492ac <+23>:    lea    0xc(%edx),%eax
   0x080492af <+26>:    mov    %eax,0x14(%esp)
   0x080492b3 <+30>:    lea    0x8(%edx),%eax
   0x080492b6 <+33>:    mov    %eax,0x10(%esp)
   0x080492ba <+37>:    lea    0x4(%edx),%eax
   0x080492bd <+40>:    mov    %eax,0xc(%esp)
   0x080492c1 <+44>:    mov    %edx,0x8(%esp)
   0x080492c5 <+48>:    movl   $0x8049aca,0x4(%esp)
   0x080492cd <+56>:    mov    0x8(%ebp),%eax
   0x080492d0 <+59>:    mov    %eax,(%esp)
   0x080492d3 <+62>:    call   0x80488b4 <sscanf@plt>
   0x080492d8 <+67>:    cmp    $0x5,%eax
   0x080492db <+70>:    jg     0x80492e2 <read_six_numbers+77>
   0x080492dd <+72>:    call   0x8049253 <explode_bomb>
   0x080492e2 <+77>:    leave  
   0x080492e3 <+78>:    ret    
End of assembler dump.

在这里
  
程序代码:
 0x0804929b <+6>:    mov    0xc(%ebp),%edx
   0x0804929e <+9>:    lea    0x14(%edx),%eax
   0x080492a1 <+12>:    mov    %eax,0x1c(%esp)
   0x080492a5 <+16>:    lea    0x10(%edx),%eax
   0x080492a8 <+19>:    mov    %eax,0x18(%esp)
   0x080492ac <+23>:    lea    0xc(%edx),%eax
   0x080492af <+26>:    mov    %eax,0x14(%esp)
   0x080492b3 <+30>:    lea    0x8(%edx),%eax
   0x080492b6 <+33>:    mov    %eax,0x10(%esp)
   0x080492ba <+37>:    lea    0x4(%edx),%eax
   0x080492bd <+40>:    mov    %eax,0xc(%esp)
   0x080492c1 <+44>:    mov    %edx,0x8(%esp)

这一段,我觉得不光是复制,还有一个作用就是把字符串转换成了数字恩,
然后对齐了数据以便后面使用,
ps:光着一段数据的对齐,我算了1个小时~~!
这第二颗炸弹的关键就是后面了
    0x08048d36 <+26>:    cmpl   $0x1,-0x20(%ebp)
   0x08048d3a <+30>:    je     0x8048d41 <phase_2+37>[\code]
说明第一个密码是1,不解释
程序代码:
0x08048d41 <+37>:    mov    $0x2,%ebx
   0x08048d46 <+42>:    lea    -0x20(%ebp),%esi
   0x08048d49 <+45>:    mov    %ebx,%eax
   0x08048d4b <+47>:    imul   -0x8(%esi,%ebx,4),%eax
   0x08048d50 <+52>:    cmp    %eax,-0x4(%esi,%ebx,4)
   0x08048d54 <+56>:    je     0x8048d5b <phase_2+63>

伪代码表示:
(ebx)=2
esi=ebp-20
(eax)=(ebx)
(eax)=(eax)*((ebx)*4+esi-8)=2
if(-0x4(%esi,%ebx,4)!=2)
exit
计算-0x4(%esi,%ebx,4)实际是esi+4
也就是ebp-0x1c
就是刚对齐的第二个数据
所以第二个密码是2
再往下ebx当计数器,在exb<7时循环
自己算咯
所以第二个炸弹的密码分别是
1     2      2*3      6*4   24*5    120*6     也就是
1     2      6          24     120     720
---------------------------------
程序代码:
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
I am not part of the problem. I am a Republican.
Phase 1 defused. How about the next one?
1 2 6 24 120 720
That's number 2.  Keep going!


[ 本帖最后由 wog 于 2011-4-12 23:13 编辑 ]
2011-04-12 23:12
wog
Rank: 2
来 自:南昌
等 级:论坛游民
帖 子:33
专家分:31
注 册:2010-10-2
收藏
得分:0 
回复 4楼 zaixuexi
我才刚刚接触汇编
还要向大家学习的,
今天实在弄这个弄得头痛了,明晚继续弄咯
2011-04-12 23:16
zaixuexi
Rank: 12Rank: 12Rank: 12
来 自:上海
等 级:火箭侠
威 望:8
帖 子:858
专家分:3233
注 册:2010-12-1
收藏
得分:0 
回复 6楼 wog
加油

技术问题,请不要以短消息方式提问
2011-04-12 23:34
wog
Rank: 2
来 自:南昌
等 级:论坛游民
帖 子:33
专家分:31
注 册:2010-10-2
收藏
得分:0 
程序代码:
(gdb) disas phase_3
Dump of assembler code for function phase_3:
   0x08048e01 <+0>:push   %ebp
   0x08048e02 <+1>:mov    %esp,%ebp
   0x08048e04 <+3>:sub    $0x28,%esp
   0x08048e07 <+6>:lea    -0x8(%ebp),%eax
   0x08048e0a <+9>:mov    %eax,0xc(%esp)
   0x08048e0e <+13>:lea    -0x4(%ebp),%eax
   0x08048e11 <+16>:mov    %eax,0x8(%esp)
   0x08048e15 <+20>:movl   $0x8049ad6,0x4(%esp)
   0x08048e1d <+28>:mov    0x8(%ebp),%eax
   0x08048e20 <+31>:mov    %eax,(%esp)
   0x08048e23 <+34>:call   0x80488b4 <sscanf@plt>
   0x08048e28 <+39>:cmp    $0x1,%eax
   0x08048e2b <+42>:jg     0x8048e32 <phase_3+49>
   0x08048e2d <+44>:call   0x8049253 <explode_bomb>
   0x08048e32 <+49>:cmpl   $0x7,-0x4(%ebp)
   0x08048e36 <+53>:ja     0x8048ea1 <phase_3+160>
   0x08048e38 <+55>:mov    -0x4(%ebp),%eax
   0x08048e3b <+58>:jmp    *0x8049900(,%eax,4)
   0x08048e42 <+65>:mov    $0x0,%eax
   0x08048e47 <+70>:jmp    0x8048e9a <phase_3+153>
---Type <return> to continue, or q <return> to quit---
   0x08048e49 <+72>:mov    $0x0,%eax
   0x08048e4e <+77>:xchg   %ax,%ax
   0x08048e50 <+79>:jmp    0x8048e95 <phase_3+148>
   0x08048e52 <+81>:mov    $0x0,%eax
   0x08048e57 <+86>:jmp    0x8048e90 <phase_3+143>
   0x08048e59 <+88>:mov    $0x0,%eax
   0x08048e5e <+93>:xchg   %ax,%ax
   0x08048e60 <+95>:jmp    0x8048e8b <phase_3+138>
   0x08048e62 <+97>:mov    $0x0,%eax
   0x08048e67 <+102>:jmp    0x8048e86 <phase_3+133>
   0x08048e69 <+104>:mov    $0x0,%eax
   0x08048e6e <+109>:xchg   %ax,%ax
   0x08048e70 <+111>:jmp    0x8048e81 <phase_3+128>
   0x08048e72 <+113>:mov    $0x396,%eax
   0x08048e77 <+118>:jmp    0x8048e7e <phase_3+125>
   0x08048e79 <+120>:mov    $0x0,%eax
   0x08048e7e <+125>:sub    $0x53,%eax
   0x08048e81 <+128>:add    $0x139,%eax
   0x08048e86 <+133>:sub    $0x1e5,%eax
   0x08048e8b <+138>:add    $0x279,%eax
   0x08048e90 <+143>:sub    $0x3da,%eax
---Type <return> to continue, or q <return> to quit---
   0x08048e95 <+148>:add    $0x3da,%eax
   0x08048e9a <+153>:sub    $0x30e,%eax
   0x08048e9f <+158>:jmp    0x8048eab <phase_3+170>
   0x08048ea1 <+160>:call   0x8049253 <explode_bomb>
   0x08048ea6 <+165>:mov    $0x0,%eax
   0x08048eab <+170>:cmpl   $0x5,-0x4(%ebp)
   0x08048eaf <+174>:jg     0x8048eb6 <phase_3+181>
   0x08048eb1 <+176>:cmp    -0x8(%ebp),%eax
   0x08048eb4 <+179>:je     0x8048ebb <phase_3+186>
   0x08048eb6 <+181>:call   0x8049253 <explode_bomb>
   0x08048ebb <+186>:leave  
   0x08048ebc <+187>:lea    0x0(%esi,%eiz,1),%esi
   0x08048ec0 <+191>:ret    
End of assembler dump.

前面没什么好说的
只是这次的断点设置是关键
程序代码:
(gdb) break *phase_3
Breakpoint 1 at 0x8048e01
(gdb) run
Starting program: /home/wog/bomb 
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
I am not part of the problem. I am a Republican.
Phase 1 defused. How about the next one?
1 2 6 24 120 720
That's number 2.  Keep going!
1 2 

Breakpoint 1, 0x08048e01 in phase_3 ()

运行到这里
我们查看一下寄存器
程序代码:
(gdb) info reg
eax            0x804a8c0134523072
ecx            0x77
edx            0x33
ebx            0xbffff414-1073744876
esp            0xbffff33c0xbffff33c
ebp            0xbffff3580xbffff358
esi            0x00
edi            0x00
eip            0x8048e010x8048e01 <phase_3>

有了第二颗炸弹的经验,我们知道eax里是刚才输入的字符串的地址
eip指向0x8048e01,ebp已经进栈,所以4(%esp)里是字符串地址   
   
0x08048e07 <+6>:lea    -0x8(%ebp),%eax
   0x08048e0a <+9>:mov    %eax,0xc(%esp)
   0x08048e0e <+13>:lea    -0x4(%ebp),%eax
   0x08048e11 <+16>:mov    %eax,0x8(%esp)

这个和前一次差不多,预留空位
  
 0x08048dc3 <+13>:movl   $0x8049ad6,0x4(%esp)
   0x08048dcb <+21>:mov    0x8(%ebp),%eax

这个$0x8049ad6就有点奇怪了
所以,现在关键是搞清楚这个是什么
多试几次,最后用
(gdb) x/sb 0x8049ad6
0x8049ad6: "%d %d"

额……学过c语言就毫无压力了
(密码是两个数字?)
然后再运行一个GDB,设置另一个断点
(gdb) break sscanf
Breakpoint 2 at 0x17d1e4

单步走到这里
程序代码:
(gdb) s
Single stepping until exit from function sscanf,
which has no line number information.
0x08048e28 in phase_3 ()
(gdb) info reg
eax            0x22
ecx            0x3220313285041
edx            0x00
ebx            0xbffff414-1073744876
esp            0xbffff3100xbffff310
ebp            0xbffff3380xbffff338
esi            0x00
edi            0x00
eip            0x8048e280x8048e28 <phase_3+39>

因为下面就已经开始判断了
所以先查看查看内存(再也不纯手工算了)
程序代码:
(gdb) x/20xw 0xbffff310
0xbffff310:0x0804a8c0    0x08049ad6    0xbffff334    0xbffff330
0xbffff320:0x0000001d    0xbffff414    0xbffff338    0x0804936f
0xbffff330:0x00000002    0x00000001    0xbffff358    0x08048ab6
0xbffff340:0x0804a8c0    0x00287ff4    0x08049680    0xbffff368
0xbffff350:0xbffff370    0x00287ff4    0xbffff3e8    0x00145ce7

看到%d%d已经与数字对齐
(这里是怎么对的,中间又为什么多了个0xbffff358,求高手指教……)
再往下看
  
 0x08048e32 <+49>:cmpl   $0x7,-0x4(%ebp)
   0x08048e36 <+53>:ja     0x8048ea1 <phase_3+160>

第一个数字大于7就gameover了
  0x08048e38 <+55>:mov    -0x4(%ebp),%eax
   0x08048e3b <+58>:jmp    *0x8049900(,%eax,4)

还好这个以前在书上见过,先弄清这个*0x8049900是什么
(gdb) x/xw 0x8049900
0x8049900 <__dso_handle+440>:0x08048e72

所以就是0x08048e72(,%eax,4)
这个就相当与c语言中的switch语句了
eax的值不同jmp的位置不同
从0到7一个一个试,(在试过程中就发现其实只用试到5,而且最后的结果就是第二个数)
程序代码:
case ‘0’:
eax=0x398-0x53+0x139-0x1e5+0x279-0x3da+0x3da-0x30e=514
case ‘1’:
eax=0-0x53+0x139-0x1e5+0x279-0x3da+0x3da-0x30e=-404
……

最后发现只有case‘0’最后是正数
所以密码是0 514
程序代码:
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
I am not part of the problem. I am a Republican.
Phase 1 defused. How about the next one?
1 2 6 24 120 720
That's number 2.  Keep going!
0 514
Halfway there!

[code]

[ 本帖最后由 wog 于 2011-4-13 18:36 编辑 ]
2011-04-13 18:34
wog
Rank: 2
来 自:南昌
等 级:论坛游民
帖 子:33
专家分:31
注 册:2010-10-2
收藏
得分:0 
第四颗……
程序代码:
gdb) disas phase_4

Dump of assembler code for function phase_4:

   0x08048db6 <+0>:    push   %ebp

   0x08048db7 <+1>:    mov    %esp,%ebp

   0x08048db9 <+3>:    sub    $0x28,%esp

   0x08048dbc <+6>:    lea    -0x4(%ebp),%eax

   0x08048dbf <+9>:    mov    %eax,0x8(%esp)

   0x08048dc3 <+13>:    movl   $0x8049ad9,0x4(%esp)

   0x08048dcb <+21>:    mov    0x8(%ebp),%eax

   0x08048dce <+24>:    mov    %eax,(%esp)

   0x08048dd1 <+27>:    call   0x80488b4 <sscanf@plt>

   0x08048dd6 <+32>:    cmp    $0x1,%eax

   0x08048dd9 <+35>:    jne    0x8048de1 <phase_4+43>

   0x08048ddb <+37>:    cmpl   $0x0,-0x4(%ebp)

   0x08048ddf <+41>:    jg     0x8048de6 <phase_4+48>

   0x08048de1 <+43>:    call   0x8049253 <explode_bomb>

   0x08048de6 <+48>:    mov    -0x4(%ebp),%eax

   0x08048de9 <+51>:    mov    %eax,(%esp)

   0x08048dec <+54>:    call   0x8048b30 <func4>

   0x08048df1 <+59>:    cmp    $0x2ac2,%eax

   0x08048df6 <+64>:    je     0x8048dfd <phase_4+71>

   0x08048df8 <+66>:    call   0x8049253 <explode_bomb>

   0x08048dfd <+71>:    leave  

   0x08048dfe <+72>:    xchg   %ax,%ax

   0x08048e00 <+74>:    ret    

End of assembler dump.


程序代码:
(gdb) disas func4

Dump of assembler code for function func4:

   0x08048b30 <+0>:    push   %ebp

   0x08048b31 <+1>:    mov    %esp,%ebp

   0x08048b33 <+3>:    sub    $0xc,%esp

   0x08048b36 <+6>:    mov    %ebx,-0x8(%ebp)

   0x08048b39 <+9>:    mov    %esi,-0x4(%ebp)

   0x08048b3c <+12>:    mov    0x8(%ebp),%esi

   0x08048b3f <+15>:    mov    $0x1,%eax

   0x08048b44 <+20>:    cmp    $0x1,%esi

   0x08048b47 <+23>:    jle    0x8048b63 <func4+51>

   0x08048b49 <+25>:    lea    -0x1(%esi),%eax

   0x08048b4c <+28>:    mov    %eax,(%esp)

   0x08048b4f <+31>:    call   0x8048b30 <func4>

   0x08048b54 <+36>:    mov    %eax,%ebx

   0x08048b56 <+38>:    lea    -0x2(%esi),%eax

   0x08048b59 <+41>:    mov    %eax,(%esp)

   0x08048b5c <+44>:    call   0x8048b30 <func4>

   0x08048b61 <+49>:    add    %ebx,%eax

   0x08048b63 <+51>:    mov    -0x8(%ebp),%ebx

   0x08048b66 <+54>:    mov    -0x4(%ebp),%esi

   0x08048b69 <+57>:    mov    %ebp,%esp

   0x08048b6b <+59>:    pop    %ebp

   0x08048b6c <+60>:    ret    

End of assembler dump.


-----------------------------------------------------------------------------------------------------
程序代码:
(gdb) break *func4
Breakpoint 1 at 0x8048b30
(gdb) run
Starting program: /home/wog/bomb 
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
I am not part of the problem. I am a Republican.
Phase 1 defused. How about the next one?
1 2 6 24 120 720
That's number 2.  Keep going!
0 514
Halfway there!
1 2

上面随便输入两个数字
跟进函数
查看寄存器
程序代码:
(gdb) info reg
eax            0xbffff334    -1073745100
ecx            0x3    3
edx            0x4    4
ebx            0xbffff414    -1073744876
esp            0xbffff310    0xbffff310
ebp            0xbffff338    0xbffff338
esi            0x0    0
edi            0x0    0
eip            0x8048dbf    0x8048dbf <phase_4+9>

ebp指向0xbffff338,可以判断出字符串地址在0xbffff340里
  
 0x08048dbc <+6>:    lea    -0x4(%ebp),%eax
   0x08048dbf <+9>:    mov    %eax,0x8(%esp)
   0x08048dc3 <+13>:    movl   $0x8049ad9,0x4(%esp)

$0x8049ad9是%d
对应0x8(%esp),
所以估计只有一位密码
再往下没什么一直到
   
程序代码:
 0x08048de9 <+51>:    mov    %eax,(%esp)

   0x08048dec <+54>:    call   0x8048b30 <func4>

   0x08048df1 <+59>:    cmp    $0x2ac2,%eax

   0x08048df6 <+64>:    je     0x8048dfd <phase_4+71>


这段很好理解将输入的密码传入func4处理之后要等于0x2ac2

进入func4

通过反汇编可以看出这是一个递归函数

结束条件是

   
 cmp    $0x1,%esi

   0x08048b47 <+23>:    jle    0x8048b63 <func4+51>


也就是

%esi<=1时结束

整个的函数要多看就能理解(前提是有高级语言的基础)
整个函数用伪代码表示
程序代码:
fun(eax) 
{
    esi=eax;
    eax=1;
    while(esi>1)
    {
        ebx= fun(esi-1);
        Eax= fun(esi-2)+ebx;
    }
        Return eax;
}

很明了了,讲递归必讲的费波那契数列
然后
要让最后的返回值为0x2ac2
呃,我是直接用笔算的可以得出,密码是20
试一下
程序代码:
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
I am not part of the problem. I am a Republican.
Phase 1 defused. How about the next one?
1 2 6 24 120 720
That's number 2.  Keep going!
0 514
Halfway there!
20       
So you got that one.  Try this one.
2011-04-13 23:52
Alar30
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:10
帖 子:988
专家分:1627
注 册:2009-9-8
收藏
得分:0 
相当漂亮
谢谢了
2011-04-16 16:27
快速回复:二进制拆弹
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.037508 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved