死或生phase4技巧_4拆炸弹

[原创][原创]经典的二进制拆弹逆向分析
【文章标题】:&经典的二进制拆弹逆向分析
【文章作者】:&loongzyd
【操作平台】:&linux
【逆向声明】:&处于对逆向工程的爱好,虽然这是一个linux下的可执行文件,用IDA也能逆,
但是为了熟悉一下linux环境下的逆向,就没有用IDA。&感谢范晨鹏大哥在嵌入式板块发表的关于gdb的汇编级调试的文章:
【背景介绍】:二进制拆弹实验是卡内基-梅隆(CMU)开设的:计算机系统导论(ICS)课程的一道实验题,下面是《深入理解计算机系统》上面对这个实验的文字说明:
二进制炸弹是一个作为目标代码文件提供给学生们的程序。运行时,它提示用户输入6个不同的字符串。如果其中的任何一个不正确,炸弹就会“爆炸”,打印出一条错误信息,并在一个分级(gradin)服务器上记录事件日志。学生们必须通过对程序的反汇编和逆向工程来测定应该是哪6个串,从而解除他们各自炸弹的雷管。该实验教会学生理解汇编语言,并且强制他们学习怎样使用调试器。
【详细过程】:
首先bomb.rar里面给了我们一个C程序,主要的部分如下:
int&main(int&argc,&char&*argv[])
/*&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&=&
/*&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.&*/
&&&&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!&*/
这相当于给我们了一个很大的提示,我们能够得到如下的信息:
1.我们可以手动输入字符串进行拆弹或者将这些字符串放在一个文件里面。
2.一共有6个小关,其中函数read_line()应该是负责读入每一关的字符串phase_x(input)应该
是每一关的验证算法,phase_defused()目前还不清楚是干什么的.initialize_bomb()应该是进行
初始化之类的工作.
之后我们阅读那个pdf文档,根据大意我们得知,这是某个国外大学的题目,此程序与某服务器连接
,每个做题的人的解题过程的情况会返回到那个服务器,然后根据题目的描述我们应该知道可能是要
废除与那个服务器有关的功能。
好了,我们进入linux环境具体的分析吧。
打开一个终端,输入命令:gbd&./bomb
然后输入:disas&main(对main函数进行反汇编),得到的情况如下:
Dump&of&assembler&code&for&function&main:
0x&&main+0&:&lea&0x4(%esp),%ecx
0x&&main+4&:&and&$0xfffffff0,%esp
0x080489cb&&main+7&:&pushl&-0x4(%ecx)
0x080489ce&&main+10&:&push&%ebp
0x080489cf&&main+11&:&mov&%esp,%ebp
0x&&main+13&:&push&%ebx
0x&&main+14&:&push&%ecx
0x&&main+15&:&sub&$0x10,%esp
0x&&main+18&:&mov&(%ecx),%eax
0x&&main+20&:&mov&0x4(%ecx),%ebx
0x080489db&&main+23&:&cmp&$0x1,%eax
0x080489de&&main+26&:&jne&0x80489ec&&main+40&
0x&&main+28&:&mov&0x804a800,%eax
0x&&main+33&:&mov&%eax,0x804a814
0x080489ea&&main+38&:&jmp&0x8048a50&&main+140&
0x080489ec&&main+40&:&cmp&$0x2,%eax
0x080489ef&&main+43&:&jne&0x8048a32&&main+110&
0x&&main+45&:&movl&$0xx4(%esp)
0x&&main+53&:&mov&0x4(%ebx),%eax
0x080489fc&&main+56&:&mov&%eax,(%esp)
0x080489ff&&main+59&:&call&0x80487f4&&fopen@plt&
0x08048a04&&main+64&:&mov&%eax,0x804a814
0x08048a09&&main+69&:&test&%eax,%eax
0x08048a0b&&main+71&:&jne&0x8048a50&&main+140&
0x08048a0d&&main+73&:&mov&0x4(%ebx),%eax
0x08048a10&&main+76&:&mov&%eax,0x8(%esp)
0x08048a14&&main+80&:&mov&(%ebx),%eax
0x08048a16&&main+82&:&mov&%eax,0x4(%esp)
0x08048a1a&&main+86&:&movl&$0x804974c,(%esp)
0x08048a21&&main+93&:&call&0x8048814&&printf@plt&
0x08048a26&&main+98&:&movl&$0x8,(%esp)
0x08048a2d&&main+105&:&call&0x80488d4&&exit@plt&
0x08048a32&&main+110&:&mov&(%ebx),%eax
0x08048a34&&main+112&:&mov&%eax,0x4(%esp)
0x08048a38&&main+116&:&movl&$0x8049769,(%esp)
0x08048a3f&&main+123&:&call&0x8048814&&printf@plt&
0x08048a44&&main+128&:&movl&$0x8,(%esp)
0x08048a4b&&main+135&:&call&0x80488d4&&exit@plt&
0x08048a50&&main+140&:&call&0x80495af&&initialize_bomb&
0x08048a55&&main+145&:&movl&$0x80497d0,(%esp)
0x08048a5c&&main+152&:&call&0x80488a4&&puts@plt&
0x08048a61&&main+157&:&movl&$0x804980c,(%esp)
0x08048a68&&main+164&:&call&0x80488a4&&puts@plt&
0x08048a6d&&main+169&:&call&0x8049363&&read_line&
0x08048a72&&main+174&:&mov&%eax,(%esp)
0x08048a75&&main+177&:&call&0x8048ec1&&phase_1&
0x08048a7a&&main+182&:&call&0x80491c1&&phase_defused&
0x08048a7f&&main+187&:&movl&$0x8049838,(%esp)
0x08048a86&&main+194&:&call&0x80488a4&&puts@plt&
0x08048a8b&&main+199&:&call&0x8049363&&read_line&
0x08048a90&&main+204&:&mov&%eax,(%esp)
0x08048a93&&main+207&:&call&0x8048d1c&&phase_2&
0x08048a98&&main+212&:&call&0x80491c1&&phase_defused&
0x08048a9d&&main+217&:&movl&$0x8049783,(%esp)
0x08048aa4&&main+224&:&call&0x80488a4&&puts@plt&
0x08048aa9&&main+229&:&call&0x8049363&&read_line&
0x08048aae&&main+234&:&mov&%eax,(%esp)
0x08048ab1&&main+237&:&call&0x8048e01&&phase_3&
0x08048ab6&&main+242&:&call&0x80491c1&&phase_defused&
0x08048abb&&main+247&:&movl&$0x80497a1,(%esp)
0x08048ac2&&main+254&:&call&0x80488a4&&puts@plt&
0x08048ac7&&main+259&:&call&0x8049363&&read_line&
0x08048acc&&main+264&:&mov&%eax,(%esp)
0x08048acf&&main+267&:&call&0x8048db6&&phase_4&
0x08048ad4&&main+272&:&call&0x80491c1&&phase_defused&
0x08048ad9&&main+277&:&movl&$0x8049864,(%esp)
0x08048ae0&&main+284&:&call&0x80488a4&&puts@plt&
0x08048ae5&&main+289&:&call&0x8049363&&read_line&
0x08048aea&&main+294&:&mov&%eax,(%esp)
0x08048aed&&main+297&:&call&0x8048d6a&&phase_5&
0x08048af2&&main+302&:&call&0x80491c1&&phase_defused&
0x08048af7&&main+307&:&movl&$0x80497b0,(%esp)
0x08048afe&&main+314&:&call&0x80488a4&&puts@plt&
0x08048b03&&main+319&:&call&0x8049363&&read_line&
0x08048b08&&main+324&:&mov&%eax,(%esp)
0x08048b0b&&main+327&:&call&0x8048c2c&&phase_6&
0x08048b10&&main+332&:&call&0x80491c1&&phase_defused&
0x08048b15&&main+337&:&mov&$0x0,%eax
0x08048b1a&&main+342&:&add&$0x10,%esp
0x08048b1d&&main+345&:&pop&%ecx
0x08048b1e&&main+346&:&pop&%ebx
0x08048b1f&&main+347&:&pop&%ebp
0x08048b20&&main+348&:&lea&-0x4(%ecx),%esp
0x08048b23&&main+351&:&ret
得到的结果显然与题目给我们那个提示的C程序是一样的,下面我们先来看看initialize_bomb函数:
同样:disas&initialize_bomb:列出关键的地方:
0x0804963c&&initialize_bomb+141&:&call&0x80494b1&&open_clientfd&
根据这个函数名称的意思(打开连接),应该与我们之前的猜想吻合,所以:
Disas&open_clientfd:
0x080494da&&open_clientfd+41&:&call&0x80487a4&&socket@plt&,
Socket出现了,这个是用于网络编程的,我们大致就可以确定initialize_bomb函数应该
就是负责与服务器的连接,所以可以大胆的将其nop掉,既然要修改次可执行文件,所以我们先:quit,退出gdb,然后:gdb&–write&./bomb(gdb默认的是只读权限打开),我们用之前的方法定位到0x080495af(initialize_bomb函数的第一行)和0x08048f72(send_msg函数的第一行),然后分别输入下面的命令:
set&*(unsigned&char&*)0xxc3和set&*(unsigned&char&*)0x080495af=0xc3,其中0xc3是指令ret的16进制值,也就是说对于那两个函数一旦调用就马上结束,它们的功能都没有实现。现在程序在本地就可以顺利的执行了=&=
下面似乎就到了用gdb进行跟踪的时候,无奈本人太懒了,受不了那种,所以在无奈之下找到了另一个工具insight,号称是图形化的gdb,用了一下感觉真的不错,有了一点点OD的影子,当然解密太粗糙鸟=&=给一个界面展示吧:
是不是比黑乎乎的界面人性化多鸟,而且为了保持向下兼容有个这个东东:
在Console&Window这个窗口中就可以输入gdb的命令达到同样的效果,按r将程序运行起来,然后我们一路ni(单步跟踪,不进入调用函数内部,类似于OD的F7),当我们在终端看到输入提示之后输入一串字符串:hello&word&/*本来是想输入hello&world的&习惯吧world打成word了=&=*/然后si进入phash_1函数内部:
这段代码应该简单,关键是call&0x8048f10,下面的test&%eax,%eax,再下面是je&XXX
这个函数名是strings_not_equal,如果作者真的是很人性化的话,那么那个函数就应该是对字符串进行明文匹配,函数调用时堆栈的情况,我们可以看出,0x80498b0应该是内存中早已初始化了的一串字符串,我们输入的字符串应该和它一样,我们查看一下那个地址的内容:
我们可以发现字符串是:I&am&not&part&of&the&problem.I&am&a&Republican.
我们输入的字符串的首地址应在0x8(%ebp)[ebp+8]里面,在运行到0x8048ed2的时候查看eax里面的值为:0x804a820,此时内存中该地址里面的内容是:
正是我们输入的内容,所以判断是正确的,所以我们我们第一关输入:I&am&not&part&of&the&problem.&I&am&a&Republican.
看来作者也是比较人性话的。嘿嘿,我们继续往下走吧:
-&&&&0x8048d1c&&&&&phase_2&:&&&&&&&&push&%ebp
-&&&&0x8048d1d&&&&&phase_2+1&:&&&&&&&&mov&%esp,%ebp
-&&&&0x8048d1f&&&&&phase_2+3&:&&&&&&&&push&%esi
-&&&&0x8048d20&&&&&phase_2+4&:&&&&&&&&push&%ebx
-&&&&0x8048d21&&&&&phase_2+5&:&&&&&&&&sub&$0x30,%esp
-&&&&0x8048d24&&&&&phase_2+8&:&&&&&&&&lea&-0x20(%ebp),%eax
-&&&&0x8048d27&&&&&phase_2+11&:&&&&&&&&mov&%eax,0x4(%esp)&//[esp+4]=0xbfae7798
-&&&&0x8048d2b&&&&&phase_2+15&:&&&&&&&&mov&0x8(%ebp),%eax
-&&&&0x8048d2e&&&&&phase_2+18&:&&&&&&&&mov&%eax,(%esp)&//[esp]=0x804a870
-&&&&0x8048d31&&&&&phase_2+21&:&&&&&&&&call&0x8049295&&read_six_numbers&
-&&&&0x8048d36&&&&&phase_2+26&:&&&&&&&&cmpl&$0x1,-0x20(%ebp)
-&&&&0x8048d3a&&&&&phase_2+30&:&&&&&&&&je&0x8048d41&&phase_2+37&
-&&&&0x8048d3c&&&&&phase_2+32&:&&&&&&&&call&0x8049253&&explode_bomb&
-&&&&0x8048d41&&&&&phase_2+37&:&&&&&&&&mov&$0x2,%ebx
-&&&&0x8048d46&&&&&phase_2+42&:&&&&&&&&lea&-0x20(%ebp),%esi
-&&&&0x8048d49&&&&&phase_2+45&:&&&&&&&&mov&%ebx,%eax
-&&&&0x8048d4b&&&&&phase_2+47&:&&&&&&&&imul&-0x8(%esi,%ebx,4),%eax
-&&&&0x8048d50&&&&&phase_2+52&:&&&&&&&&cmp&%eax,-0x4(%esi,%ebx,4)
-&&&&0x8048d54&&&&&phase_2+56&:&&&&&&&&je&0x8048d5b&&phase_2+63&
-&&&&0x8048d56&&&&&phase_2+58&:&&&&&&&&call&0x8049253&&explode_bomb&
-&&&&0x8048d5b&&&&&phase_2+63&:&&&&&&&&add&$0x1,%ebx
-&&&&0x8048d5e&&&&&phase_2+66&:&&&&&&&&cmp&$0x7,%ebx
-&&&&0x8048d61&&&&&phase_2+69&:&&&&&&&&jne&0x8048d49&&phase_2+45&
-&&&&0x8048d63&&&&&phase_2+71&:&&&&&&&&add&$0x30,%esp
-&&&&0x8048d66&&&&&phase_2+74&:&&&&&&&&pop&%ebx
-&&&&0x8048d67&&&&&phase_2+75&:&&&&&&&&pop&%esi
-&&&&0x8048d68&&&&&phase_2+76&:&&&&&&&&pop&%ebp
-&&&&0x8048d69&&&&&phase_2+77&:&&&&&&&&ret
0x804a870里面的内容是我们第二关输入的字符串,我们来看看call&0x8049253,这个函数的名称是read_six_numbers,应该是要我们输入六个数字吧,看看函数的具体内容:
0x&&read_six_numbers+0&:&push&%ebp
0x&&read_six_numbers+1&:&mov&%esp,%ebp
0x&&read_six_numbers+3&:&sub&$0x28,%esp
0x0804929b&&read_six_numbers+6&:&mov&0xc(%ebp),%edx
0x0804929e&&read_six_numbers+9&:&lea&0x14(%edx),%eax
0x&&read_six_numbers+12&:&mov&%eax,0x1c(%esp)
0x&&read_six_numbers+16&:&lea&0x10(%edx),%eax
0x&&read_six_numbers+19&:&mov&%eax,0x18(%esp)
0x080492ac&&read_six_numbers+23&:&lea&0xc(%edx),%eax
0x080492af&&read_six_numbers+26&:&mov&%eax,0x14(%esp)
0x&&read_six_numbers+30&:&lea&0x8(%edx),%eax
0x&&read_six_numbers+33&:&mov&%eax,0x10(%esp)
0x080492ba&&read_six_numbers+37&:&lea&0x4(%edx),%eax
0x080492bd&&read_six_numbers+40&:&mov&%eax,0xc(%esp)
0x&&read_six_numbers+44&:&mov&%edx,0x8(%esp)
0x&&read_six_numbers+48&:&movl&$0x8049aca,0x4(%esp)
0x080492cd&&read_six_numbers+56&:&mov&0x8(%ebp),%eax
0x&&read_six_numbers+59&:&mov&%eax,(%esp)
0x&&read_six_numbers+62&:&call&0x80488b4&&sscanf@plt&
0x&&read_six_numbers+67&:&cmp&$0x5,%eax//读入的数据至少6个
0x080492db&&read_six_numbers+70&:&jg&0x80492e2&&read_six_numbers+77&
0x080492dd&&read_six_numbers+72&:&call&0x8049253&&explode_bomb&
0x&&read_six_numbers+77&:&leave
0x&&read_six_numbers+78&:&ret
我们可以看到cmp&$0x5,%eax,下一行是jg,则读入的数据至少六个,看来出题人真的很厚道,
而前面那应该是对我们输入的数据进行复制处理,我们在看这部分:
0x8048d36&&&&&phase_2+26&:&&&&&&&&cmpl&$0x1,-0x20(%ebp)
[ebp-0x20]=&0xbfae7798,[0xbfae7798]里面的内容就是我们输入的数据的第一个值,发现它必须为1,否则就失败了,我们先关注下面这一段代码:
-&&&&0x8048d36&&&&&phase_2+26&:&&&&&&&&cmpl&$0x1,-0x20(%ebp)
-&&&&0x8048d3a&&&&&phase_2+30&:&&&&&&&&je&0x8048d41&&phase_2+37&
-&&&&0x8048d3c&&&&&phase_2+32&:&&&&&&&&call&0x8049253&&explode_bomb&
-&&&&0x8048d41&&&&&phase_2+37&:&&&&&&&&mov&$0x2,%ebx&//ebx作为计数之用
-&&&&0x8048d46&&&&&phase_2+42&:&&&&&&&&lea&-0x20(%ebp),%esi&//esi指向我们输入数据
-&&&&0x8048d49&&&&&phase_2+45&:&&&&&&&&mov&%ebx,%eax&//eax复制为此时ebx的值
-&&&&0x8048d4b&&&&&phase_2+47&:&&&&&&&&imul&-0x8(%esi,%ebx,4),%eax&
//eax&=&eax&*[esi+4*ebx-8]&,&[esi+4*ebx-8]为第(ebx-2)个我们输入的数据
-&&&&0x8048d50&&&&&phase_2+52&:&&&&&&&&cmp&%eax,-0x4(%esi,%ebx,4)
//此时eax的值必须要等于我们输入的第(ebx-1)个数据的值,不相等就失败
-&&&&0x8048d54&&&&&phase_2+56&:&&&&&&&&je&0x8048d5b&&phase_2+63&
-&&&&0x8048d56&&&&&phase_2+58&:&&&&&&&&call&0x8049253&&explode_bomb&
-&&&&0x8048d5b&&&&&phase_2+63&:&&&&&&&&add&$0x1,%ebx&//计数加1
-&&&&0x8048d5e&&&&&phase_2+66&:&&&&&&&&cmp&$0x7,%ebx&循环(7-2)=5次
-&&&&0x8048d61&&&&&phase_2+69&:&&&&&&&&jne&0x8048d49&&phase_2+45&
看这段的架势应该是个循环语句;
翻译成C‘伪’代码大致如下:
int&arr[6]//里面是我们输入的6个数据
if&(arr[0]&!=&1)&失败&退出
&&&&ebx&=&2;
&&&&&&&&eax&=&
&&&&&&&&eax&=&eax&*&arr[ebx-2];
&&&&&&&&if&(eax&!=&arr[ebx&–&1])&失败&退出
&&&&&&&&ebx++;
&&&&}while(ebx&!=&7);
这段代码应该比较好理解,转化成语言描述就是指着6个数据的值分别是1,1*2,1*2*3,1*2*3*4,1*2*3*4*5,1*2*3*4*5*6.即第n个数据为n!.
下面继续战斗
0x8048e01&&&&&phase_3&:&&&&&&&&push&%ebp
-&&&&0x8048e02&&&&&phase_3+1&:&&&&&&&&mov&%esp,%ebp
-&&&&0x8048e04&&&&&phase_3+3&:&&&&&&&&sub&$0x28,%esp
-&&&&0x8048e07&&&&&phase_3+6&:&&&&&&&&lea&-0x8(%ebp),%eax&
-&&&&0x8048e0a&&&&&phase_3+9&:&&&&&&&&mov&%eax,0xc(%esp)
-&&&&0x8048e0e&&&&&phase_3+13&:&&&&&&&&lea&-0x4(%ebp),%eax
-&&&&0x8048e11&&&&&phase_3+16&:&&&&&&&&mov&%eax,0x8(%esp)
-&&&&0x8048e15&&&&&phase_3+20&:&&&&&&&&movl&$0xx4(%esp)
-&&&&0x8048e1d&&&&&phase_3+28&:&&&&&&&&mov&0x8(%ebp),%eax
-&&&&0x8048e20&&&&&phase_3+31&:&&&&&&&&mov&%eax,(%esp)
在调用sscanf函数之前:
[esp+0x4]=0x8049ad6(%d&%d)读入数据的格式,我们知道读入的数据是两个int型(%d)
[esp+0x8]=0xbfae77b4:第一个数据存放的地址
[esp+0xc]=0xbfae77b0:第二个数据存放的地址
-&&&&0x8048e23&&&&&phase_3+34&:&&&&&&&&call&0x80488b4&&sscanf@plt&
-&&&&0x8048e28&&&&&phase_3+39&:&&&&&&&&cmp&$0x1,%eax&//输入的数据个数要大于1
-&&&&0x8048e2b&&&&&phase_3+42&:&&&&&&&&jg&0x8048e32&&phase_3+49&
-&&&&0x8048e2d&&&&&phase_3+44&:&&&&&&&&call&0x8049253&&explode_bomb&
-&&&&0x8048e32&&&&&phase_3+49&:&&&&&&&&cmpl&$0x7,-0x4(%ebp)
-&&&&0x8048e36&&&&&phase_3+53&:&&&&&&&&ja&0x8048ea1&&phase_3+160&
           //第一个数据与7比较,大于7就game&over
-&&&&0x8048e38&&&&&phase_3+55&:&&&&&&&&mov&-0x4(%ebp),%eax//第一个数据赋值给eax
-&&&&0x8048e3b&&&&&phase_3+58&:&&&&&&&&jmp&*0x8049900(,%eax,4)
//jmp&[0x*eax]&这是gcc中switch结构的跳转表!
从上面的图可以得知
eax=0&jmp&0x8048e72;&eax=1&jmp&0x8048e79;eax=2&jmp&0x8048e69;eax=3&jmp&0x8048e62
eax=4&jmp&0x8048e59;&eax=5&jmp&0x8048e52;eax=6&jmp&0x8048e49;eax=7&jmp&0x8048e42
我们设输入的两个整数为int1和int2
-&&&&0x8048e42&&&&&phase_3+65&:&&&&&&&&mov&$0x0,%eax
-&&&&0x8048e47&&&&&phase_3+70&:&&&&&&&&jmp&0x8048e9a&&phase_3+153&&int1=7
-&&&&0x8048e49&&&&&phase_3+72&:&&&&&&&&mov&$0x0,%eax
-&&&&0x8048e4e&&&&&phase_3+77&:&&&&&&&&xchg&%ax,%ax
-&&&&0x8048e50&&&&&phase_3+79&:&&&&&&&&jmp&0x8048e95&&phase_3+148&int1=6
-&&&&0x8048e52&&&&&phase_3+81&:&&&&&&&&mov&$0x0,%eax
-&&&&0x8048e57&&&&&phase_3+86&:&&&&&&&&jmp&0x8048e90&&phase_3+143&int1=5
-&&&&0x8048e59&&&&&phase_3+88&:&&&&&&&&mov&$0x0,%eax
-&&&&0x8048e5e&&&&&phase_3+93&:&&&&&&&&xchg&%ax,%ax
-&&&&0x8048e60&&&&&phase_3+95&:&&&&&&&&jmp&0x8048e8b&&phase_3+138&&&&&int1=4
-&&&&0x8048e62&&&&&phase_3+97&:&&&&&&&&mov&$0x0,%eax
-&&&&0x8048e67&&&&&phase_3+102&:&&&&&&&&jmp&0x8048e86&&phase_3+133&int1=3
-&&&&0x8048e69&&&&&phase_3+104&:&&&&&&&&mov&$0x0,%eax
-&&&&0x8048e6e&&&&&phase_3+109&:&&&&&&&&xchg&%ax,%ax
-&&&&0x8048e70&&&&&phase_3+111&:&&&&&&&&jmp&0x8048e81&&phase_3+128&int1=2
-&&&&0x8048e72&&&&&phase_3+113&:&&&&&&&&mov&$0x396,%eax
-&&&&0x8048e77&&&&&phase_3+118&:&&&&&&&&jmp&0x8048e7e&&phase_3+125&int1=0
-&&&&0x8048e79&&&&&phase_3+120&:&&&&&&&&mov&$0x0,%eax&//int1=1
-&&&&0x8048e7e&&&&&phase_3+125&:&&&&&&&&sub&$0x53,%eax
-&&&&0x8048e81&&&&&phase_3+128&:&&&&&&&&add&$0x139,%eax
-&&&&0x8048e86&&&&&phase_3+133&:&&&&&&&&sub&$0x1e5,%eax
-&&&&0x8048e8b&&&&&phase_3+138&:&&&&&&&&add&$0x279,%eax
-&&&&0x8048e90&&&&&phase_3+143&:&&&&&&&&sub&$0x3da,%eax
-&&&&0x8048e95&&&&&phase_3+148&:&&&&&&&&add&$0x3da,%eax
-&&&&0x8048e9a&&&&&phase_3+153&:&&&&&&&&sub&$0x30e,%eax
-&&&&0x8048e9f&&&&&phase_3+158&:&&&&&&&&jmp&0x8048eab&&phase_3+170&
-&&&&0x8048ea1&&&&&phase_3+160&:&&&&&&&&call&0x8049253&&explode_bomb&
-&&&&0x8048ea6&&&&&phase_3+165&:&&&&&&&&mov&$0x0,%eax
-&&&&0x8048eab&&&&&phase_3+170&:&&&&&&&&cmpl&$0x5,-0x4(%ebp)
-&&&&0x8048eaf&&&&&phase_3+174&:&&&&&&&&jg&0x8048eb6&&phase_3+181&
-&&&&0x8048eb1&&&&&phase_3+176&:&&&&&&&&cmp&-0x8(%ebp),%eax
-&&&&0x8048eb4&&&&&phase_3+179&:&&&&&&&&je&0x8048ebb&&phase_3+186&
-&&&&0x8048eb6&&&&&phase_3+181&:&&&&&&&&call&0x8049253&&explode_bomb&
-&&&&0x8048ebb&&&&&phase_3+186&:&&&&&&&&leave&
-&&&&0x8048ebc&&&&&phase_3+187&:&&&&&&&&lea&0x0(%esi),%esi
-&&&&0x8048ec0&&&&&phase_3+191&:&&&&&&&&ret
这个貌似很头大=。=&其实仔细看一下倒是很有规律的:
我们用伪代码进行描述:
int&temp=0;
switch(int1)
temp=0x396;
&&&&jmp&_125;
&&&&jmp&_128;
&&&&jmp&_133;
&&&&jmp&_138;
&&&&jmp&_143;
&&&&jmp&_148;
&&&&jmp&_153;
_125:&temp&-=&0x53;
_128:&temp&+=&0x139;
_133:&temp&-=&0x1e5;
_138:&temp&+=&0x279;
_143:&temp&-=&0x3
_148:&temp&+=&0x3
_153:&temp&-=&0x30e;
if&(int1&&&5&||&temp&!=&int2)&失败
则int1只有:0,1,2,3,4,5这六种情况:
int1=0;&则int2=0x398-0x53+0x139-0x1e5+0x279-0x3da+0x3da-0x30e=514
int1=1;&则int2=0-0x53+0x139-0x1e5+0x279-0x3da+0x3da-0x30e=-404
int1=2;&则int2=0+0x139-0x1e5+0x279-0x3da+0x3da-0x30e=-321
int1=3;&则int2=0-0x1e5+0x279-0x3da+0x3da-0x30e=-634
int1=4;&则int2=0+0x279-0x3da+0x3da-0x30e=-149
int1=5;&则int2=0-0x3da+0x3da-0x30e=-782
即第三关有6组答案(0,514),(1,-404),(2,-321),(3,-634),(4,-149),(5,-782)
进过测试,key取的是第一组的结果.
-&0x8048db6&&&&&phase_4&:&&&&&&&&push&%ebp
-&&&&0x8048db7&&&&&phase_4+1&:&&&&&&&&mov&%esp,%ebp
-&&&&0x8048db9&&&&&phase_4+3&:&&&&&&&&sub&$0x28,%esp
-&&&&0x8048dbc&&&&&phase_4+6&:&&&&&&&&lea&-0x4(%ebp),%eax
-&&&&0x8048dbf&&&&&phase_4+9&:&&&&&&&&mov&%eax,0x8(%esp)
-&&&&0x8048dc3&&&&&phase_4+13&:&&&&&&&&movl&$0xx4(%esp)&//%d
-&&&&0x8048dcb&&&&&phase_4+21&:&&&&&&&&mov&0x8(%ebp),%eax
-&&&&0x8048dce&&&&&phase_4+24&:&&&&&&&&mov&%eax,(%esp)
-&&&&0x8048dd1&&&&&phase_4+27&:&&&&&&&&call&0x80488b4&&sscanf@plt&
-&&&&0x8048dd6&&&&&phase_4+32&:&&&&&&&&cmp&$0x1,%eax&//只能输入一个整数
-&&&&0x8048dd9&&&&&phase_4+35&:&&&&&&&&jne&0x8048de1&&phase_4+43&
-&&&&0x8048ddb&&&&&phase_4+37&:&&&&&&&&cmpl&$0x0,-0x4(%ebp)&//输入的整数必须大于0
-&&&&0x8048ddf&&&&&phase_4+41&:&&&&&&&&jg&0x8048de6&&phase_4+48&
-&&&&0x8048de1&&&&&phase_4+43&:&&&&&&&&call&0x8049253&&explode_bomb&
-&&&&0x8048de6&&&&&phase_4+48&:&&&&&&&&mov&-0x4(%ebp),%eax
-&&&&0x8048de9&&&&&phase_4+51&:&&&&&&&&mov&%eax,(%esp)
-&&&&0x8048dec&&&&&phase_4+54&:&&&&&&&&call&0x8048b30&&func4&&//这个是关键的算法,跟进去
-&&&&0x8048df1&&&&&phase_4+59&:&&&&&&&&cmp&$0x2ac2,%eax
-&&&&0x8048df6&&&&&phase_4+64&:&&&&&&&&je&0x8048dfd&&phase_4+71&
-&&&&0x8048df8&&&&&phase_4+66&:&&&&&&&&call&0x8049253&&explode_bomb&
-&&&&0x8048dfd&&&&&phase_4+71&:&&&&&&&&leave&
-&&&&0x8048dfe&&&&&phase_4+72&:&&&&&&&&xchg&%ax,%ax
-&&&&0x8048e00&&&&&phase_4+74&:&&&&&&&&ret
我们发现0x8049ad9的内容为%d,则说明要求输入一个整数,跟踪进func4:
-&&&&0x8048b30&&&&&func4&:&&&&&&&&push&%ebp
-&&&&0x8048b31&&&&&func4+1&:&&&&&&&&mov&%esp,%ebp
-&&&&0x8048b33&&&&&func4+3&:&&&&&&&&sub&$0xc,%esp
-&&&&0x8048b36&&&&&func4+6&:&&&&&&&&mov&%ebx,-0x8(%ebp)
-&&&&0x8048b39&&&&&func4+9&:&&&&&&&&mov&%esi,-0x4(%ebp)
-&&&&0x8048b3c&&&&&func4+12&:&&&&&&&&mov&0x8(%ebp),%esi
-&&&&0x8048b3f&&&&&func4+15&:&&&&&&&&mov&$0x1,%eax&//eax初值为输入的整数
-&&&&0x8048b44&&&&&func4+20&:&&&&&&&&cmp&$0x1,%esi&//esi初值为输入的整数
-&&&&0x8048b47&&&&&func4+23&:&&&&&&&&jle&0x8048b63&&func4+51&&//eis&=1就结束
-&&&&0x8048b49&&&&&func4+25&:&&&&&&&&lea&-0x1(%esi),%eax&
-&&&&0x8048b4c&&&&&func4+28&:&&&&&&&&mov&%eax,(%esp)
-&&&&0x8048b4f&&&&&func4+31&:&&&&&&&&call&0x8048b30&&func4&
-&&&&0x8048b54&&&&&func4+36&:&&&&&&&&mov&%eax,%ebx
-&&&&0x8048b56&&&&&func4+38&:&&&&&&&&lea&-0x2(%esi),%eax
-&&&&0x8048b59&&&&&func4+41&:&&&&&&&&mov&%eax,(%esp)
-&&&&0x8048b5c&&&&&func4+44&:&&&&&&&&call&0x8048b30&&func4&
-&&&&0x8048b61&&&&&func4+49&:&&&&&&&&add&%ebx,%eax
-&&&&0x8048b63&&&&&func4+51&:&&&&&&&&mov&-0x8(%ebp),%ebx
-&&&&0x8048b66&&&&&func4+54&:&&&&&&&&mov&-0x4(%ebp),%esi
-&&&&0x8048b69&&&&&func4+57&:&&&&&&&&mov&%ebp,%esp
-&&&&0x8048b6b&&&&&func4+59&:&&&&&&&&pop&%ebp
-&&&&0x8048b6c&&&&&func4+60&:&&&&&&&&ret
定眼一看里面又有调用fun4,则应该是一个递归调用了!
我们先来弄一个“伪代码”:
fun(int&x)&
while(esi&1)
ebx=&fun(esi-1);
&&&&&&&&&&&&Eax=&fun(esi-2)+
&&&&&&&&Return&
学过奥赛的童鞋应该并不陌生,这是有名的费波那契数列:
f(1)=1,f(2)=1,n&2;f(n)=f(n-1)+f(n-2);
我们相当于是要求f(N)=&0x2ac2,我们输入的就是N,这个编程也可,手算也行,N=20
-&&&&0x8048d6a&&&&&phase_5&:&&&&&&&&push&%ebp
-&&&&0x8048d6b&&&&&phase_5+1&:&&&&&&&&mov&%esp,%ebp
-&&&&0x8048d6d&&&&&phase_5+3&:&&&&&&&&push&%ebx
-&&&&0x8048d6e&&&&&phase_5+4&:&&&&&&&&sub&$0x4,%esp
-&&&&0x8048d71&&&&&phase_5+7&:&&&&&&&&mov&0x8(%ebp),%ebx
-&&&&0x8048d74&&&&&phase_5+10&:&&&&&&&&mov&%ebx,(%esp)
-&&&&0x8048d77&&&&&phase_5+13&:&&&&&&&&call&0x8048ef0&&string_length&
-&&&&0x8048d7c&&&&&phase_5+18&:&&&&&&&&cmp&$0x6,%eax&//输入字符串的长度必须为6
-&&&&0x8048d7f&&&&&phase_5+21&:&&&&&&&&je&0x8048d86&&phase_5+28&
-&&&&0x8048d81&&&&&phase_5+23&:&&&&&&&&call&0x8049253&&explode_bomb&
-&&&&0x8048d86&&&&&phase_5+28&:&&&&&&&&mov&$0x0,%edx
-&&&&0x8048d8b&&&&&phase_5+33&:&&&&&&&&mov&$0x0,%ecx
-&&&&0x8048d90&&&&&phase_5+38&:&&&&&&&&movsbl&(%edx,%ebx,1),%eax&//ebx存放的是我们输入的字符串的首地址:0x804a960
-&&&&0x8048d94&&&&&phase_5+42&:&&&&&&&&and&$0xf,%eax&//每个字符串与0xf异或
-&&&&0x8048d97&&&&&phase_5+45&:&&&&&&&&add&0x8049920(,%eax,4),%ecx//内存中存在的一个数组,ecx记录其中某几个字符的ASC码之和
-&&&&0x8048d9e&&&&&phase_5+52&:&&&&&&&&add&$0x1,%edx&//edx起计数器的作用
-&&&&0x8048da1&&&&&phase_5+55&:&&&&&&&&cmp&$0x6,%edx&//6个字符
-&&&&0x8048da4&&&&&phase_5+58&:&&&&&&&&jne&0x8048d90&&phase_5+38&
-&&&&0x8048da6&&&&&phase_5+60&:&&&&&&&&cmp&$0x32,%ecx//几个字符之和为0x32
-&&&&0x8048da9&&&&&phase_5+63&:&&&&&&&&je&0x8048db0&&phase_5+70&
-&&&&0x8048dab&&&&&phase_5+65&:&&&&&&&&call&0x8049253&&explode_bomb&
-&&&&0x8048db0&&&&&phase_5+70&:&&&&&&&&add&$0x4,%esp
-&&&&0x8048db3&&&&&phase_5+73&:&&&&&&&&pop&%ebx
-&&&&0x8048db4&&&&&phase_5+74&:&&&&&&&&pop&%ebp
-&&&&0x8048db5&&&&&phase_5+75&:&&&&&&&&ret
进过简单的分析我们可以知道这个算法的大致思路:
首先在内存0x8049920开始有一串字符串,然后按照我们输入的字符串的每个字符的ASC码与0xf异或得到的数字作为索引,在之前的那个字符串按照索引得到的字符的ASC码之和要为0x32(50),那么显然我们的关键点是要放在0x8049920的那一串字符串里面,截图如下:
我们可以看到字符串各字符的10进制为:
2,10,6,1,12,16,10,9,3,4,7,14,5,11,8,15,13
我表示这很疼=&=不过还好这些数字里面没有重复滴&囧&刚好是1-16
从里面选六个数字加起来等于50,情况很多种=&=,不想去弄了=&=,
大家找六个数,找到其在字符串当中对应的索引,然后分别与0xf异或吧…
这里给出一组最后的结果:pqrwzn
终于要最后一关鸟=&=
我们看到这个算法函数非常长,估计循环都有几个,只静态分析的话有点难度=&=,还是动态跟踪加静态分析吧。
-&&&&0x8048c2c&&&&&phase_6&:&&&&&&&&push&%ebp
-&&&&0x8048c2d&&&&&phase_6+1&:&&&&&&&&mov&%esp,%ebp
-&&&&0x8048c2f&&&&&phase_6+3&:&&&&&&&&push&%edi
-&&&&0x8048c30&&&&&phase_6+4&:&&&&&&&&push&%esi
-&&&&0x8048c31&&&&&phase_6+5&:&&&&&&&&push&%ebx
-&&&&0x8048c32&&&&&phase_6+6&:&&&&&&&&sub&$0x3c,%esp
-&&&&0x8048c35&&&&&phase_6+9&:&&&&&&&&lea&-0x24(%ebp),%eax
-&&&&0x8048c38&&&&&phase_6+12&:&&&&&&&&mov&%eax,0x4(%esp)
-&&&&0x8048c3c&&&&&phase_6+16&:&&&&&&&&mov&0x8(%ebp),%eax
-&&&&0x8048c3f&&&&&phase_6+19&:&&&&&&&&mov&%eax,(%esp)
-&&&&0x8048c42&&&&&phase_6+22&:&&&&&&&&call&0x8049295&&read_six_numbers&
//之前已经遇到过这个函数,输入六个数字
-&&&&0x8048c47&&&&&phase_6+27&:&&&&&&&&mov&$0x0,%ebx
-&&&&0x8048c4c&&&&&phase_6+32&:&&&&&&&&mov&-0x24(%ebp,%ebx,4),%eax
//[ebp-0x24]=0xbfc1994,就是我们输入的6个数字的起始位置
//根据后面的判断,这里使用了一个双重循环:判断我们输入的6个数字是不是两两不相等的!
-&&&&0x8048c50&&&&&phase_6+36&:&&&&&&&&sub&$0x1,%eax
-&&&&0x8048c53&&&&&phase_6+39&:&&&&&&&&cmp&$0x5,%eax
-&&&&0x8048c56&&&&&phase_6+42&:&&&&&&&&jbe&0x8048c5d&&phase_6+49&
//我们输入的整数不能大于6,否则就失败
-&&&&0x8048c58&&&&&phase_6+44&:&&&&&&&&call&0x8049253&&explode_bomb&
-&&&&0x8048c5d&&&&&phase_6+49&:&&&&&&&&lea&0x1(%ebx),%edi
//ebx应该起计数器的作用,这应该是一个循环
-&&&&0x8048c60&&&&&phase_6+52&:&&&&&&&&cmp&$0x6,%edi
-&&&&0x8048c63&&&&&phase_6+55&:&&&&&&&&je&0x8048d03&&phase_6+215&
//当判断完毕的时候,就从这里跳出去
-&&&&0x8048c69&&&&&phase_6+61&:&&&&&&&&lea&-0x24(%ebp,%ebx,4),%esi
//esi存放的是我们输入数字
-&&&&0x8048c6d&&&&&phase_6+65&:&&&&&&&&mov&%edi,%ebx
-&&&&0x8048c6f&&&&&phase_6+67&:&&&&&&&&lea&-0x24(%ebp),%eax
-&&&&0x8048c72&&&&&phase_6+70&:&&&&&&&&mov&%eax,-0x40(%ebp)
-&&&&0x8048c75&&&&&phase_6+73&:&&&&&&&&mov&-0x40(%ebp),%edx
-&&&&0x8048c78&&&&&phase_6+76&:&&&&&&&&mov&-0x4(%edx,%edi,4),%eax
//eax里面依次存放的也是我们输入的数字
-&&&&0x8048c7c&&&&&phase_6+80&:&&&&&&&&cmp&0x4(%esi),%eax
//[esi+4]存放的正好是eax里面的数字的下一个数字:
比如:我们输入的是1,2,3,4,5,6。&eax为2,则[esi+4]=3
-&&&&0x8048c7f&&&&&phase_6+83&:&&&&&&&&jne&0x8048c86&&phase_6+90&
//看来估计是要求我们输入的这6个数字不能有重复的
-&&&&0x8048c81&&&&&phase_6+85&:&&&&&&&&call&0x8049253&&explode_bomb&
-&&&&0x8048c86&&&&&phase_6+90&:&&&&&&&&add&$0x1,%ebx
-&&&&0x8048c89&&&&&phase_6+93&:&&&&&&&&add&$0x4,%esi
-&&&&0x8048c8c&&&&&phase_6+96&:&&&&&&&&cmp&$0x5,%ebx
//上面几行验证了我们的推断
-&&&&0x8048c8f&&&&&phase_6+99&:&&&&&&&&jle&0x8048c75&&phase_6+73&//跳回去第一个循环处
-&&&&0x8048c91&&&&&phase_6+101&:&&&&&&&&mov&%edi,%ebx
-&&&&0x8048c93&&&&&phase_6+103&:&&&&&&&&jmp&0x8048c4c&&phase_6+32&
-&&&&0x8048c95&&&&&phase_6+105&:&&&&&&&&mov&0x8(%ecx),%ecx&//地址加0x8
-&&&&0x8048c98&&&&&phase_6+108&:&&&&&&&&add&$0x1,%edx&//edx增加1
-&&&&0x8048c9b&&&&&phase_6+111&:&&&&&&&&cmp&-0x24(%ebp,%eax,4),%edx
//一个循环:输入的数字的值与edx作比较
-&&&&0x8048c9f&&&&&phase_6+115&:&&&&&&&&jl&0x8048c95&&phase_6+105&
-&&&&0x8048ca1&&&&&phase_6+117&:&&&&&&&&mov&%ecx,-0x3c(%ebp,%eax,4)
//发现程序将地址放到了[ebp-0x3]开始的地址中,
-&&&&0x8048ca5&&&&&phase_6+121&:&&&&&&&&add&$0x1,%eax//将上面的地址增加
-&&&&0x8048ca8&&&&&phase_6+124&:&&&&&&&&cmp&$0x5,%eax
//看来这是一个外层循环,将所有的六个数依次遍历。
整个循环结束之后,我们得到了一个排列好了的六个地址,
这几个地址是0x804a5fc,&0x804a5f0,0x804a5e4,0x804a5d8,0x804a5cc,0x804a5c0,
-&&&&0x8048cab&&&&&phase_6+127&:&&&&&&&&jg&0x8048cb9&&phase_6+141&
-&&&&0x8048cad&&&&&phase_6+129&:&&&&&&&&mov&$0x1,%edx
-&&&&0x8048cb2&&&&&phase_6+134&:&&&&&&&&mov&$0x804a5fc,%ecx
-&&&&0x8048cb7&&&&&phase_6+139&:&&&&&&&&jmp&0x8048c9b&&phase_6+111&
最开始:[ebp-0x3c]=[0xbf9d5d9c]的值为上面六个地址排在最前面的值,其余值依次排在后面,我们不妨设这6个地址为add1-add6
-&&&&0x8048cb9&&&&&phase_6+141&:&&&&&&&&mov&-0x3c(%ebp),%ecx//ecx=add1
-&&&&0x8048cbc&&&&&phase_6+144&:&&&&&&&&mov&-0x38(%ebp),%eax//eax=add2
-&&&&0x8048cbf&&&&&phase_6+147&:&&&&&&&&mov&%eax,0x8(%ecx)//[add1+8]=add2
-&&&&0x8048cc2&&&&&phase_6+150&:&&&&&&&&mov&-0x34(%ebp),%edx//edx=add3
-&&&&0x8048cc5&&&&&phase_6+153&:&&&&&&&&mov&%edx,0x8(%eax)//[add2+8]=add3
-&&&&0x8048cc8&&&&&phase_6+156&:&&&&&&&&mov&-0x30(%ebp),%eax//eax=add4
-&&&&0x8048ccb&&&&&phase_6+159&:&&&&&&&&mov&%eax,0x8(%edx)//[add3+8]=add4
-&&&&0x8048cce&&&&&phase_6+162&:&&&&&&&&mov&-0x2c(%ebp),%edx//edx=add5
-&&&&0x8048cd1&&&&&phase_6+165&:&&&&&&&&mov&%edx,0x8(%eax)//[add4+8]=add5
-&&&&0x8048cd4&&&&&phase_6+168&:&&&&&&&&mov&-0x28(%ebp),%eax//eax=add6
-&&&&0x8048cd7&&&&&phase_6+171&:&&&&&&&&mov&%eax,0x8(%edx)//[add5+8]=add6
-&&&&0x8048cda&&&&&phase_6+174&:&&&&&&&&movl&$0x0,0x8(%eax)//[add6+8]=0
-&&&&0x8048ce1&&&&&phase_6+181&:&&&&&&&&mov&%ecx,%ebx//ebx=add1
-&&&&0x8048ce3&&&&&phase_6+183&:&&&&&&&&mov&$0x0,%esi
-&&&&0x8048ce8&&&&&phase_6+188&:&&&&&&&&mov&0x8(%ebx),%edx//edx=[add1+8]=add2
-&&&&0x8048ceb&&&&&phase_6+191&:&&&&&&&&mov&(%ebx),%eax//eax=[add1]
-&&&&0x8048ced&&&&&phase_6+193&:&&&&&&&&cmp&(%edx),%eax
//必须满足[add1]&[add2]
-&&&&0x8048cef&&&&&phase_6+195&:&&&&&&&&jge&0x8048cf6&&phase_6+202&
-&&&&0x8048cf1&&&&&phase_6+197&:&&&&&&&&call&0x8049253&&explode_bomb&
相信到了这里应该就比较明朗了=&=:之后的条件就是:
[add2]&[add3]&[add4]&[add5]&add[6],又
*0x804a5fc=0x1a2,*0x804a5f0=0x248,*0x804a5e4=0x39f,
*0x804a5d8=0xec,*0x804a5cc=0x32b,*0x804a5c0=0x1d0,因为这6个值从大到小的排列为:0x39f&0x32b&0x248&0x160&0x1a2&0xec对应的地址的正确排列为:
0x804a5e4,0x804a5cc,0x804a5f0,0x804a5c0,0x804a5fc,0x804a5d8.
而地址的排序与我们输入的1-6的顺序刚好是对应关系,所以我们输入的6个数字调整为:3&5&2&6&1&4即可
-&&&&0x8048cf6&&&&&phase_6+202&:&&&&&&&&mov&0x8(%ebx),%ebx
-&&&&0x8048cf9&&&&&phase_6+205&:&&&&&&&&add&$0x1,%esi
-&&&&0x8048cfc&&&&&phase_6+208&:&&&&&&&&cmp&$0x5,%esi//
一个外层循环,当esi能够达到0x5时候,这关就算过了=&=
-&&&&0x8048cff&&&&&phase_6+211&:&&&&&&&&je&0x8048d14&&phase_6+232&
-&&&&0x8048d01&&&&&phase_6+213&:&&&&&&&&jmp&0x8048ce8&&phase_6+188&
-&&&&0x8048d03&&&&&phase_6+215&:&&&&&&&&mov&$0x1,%edx//edx的初始值为1
-&&&&0x8048d08&&&&&phase_6+220&:&&&&&&&&mov&$0x804a5fc,%ecx//[ecx]=0x1a2
-&&&&0x8048d0d&&&&&phase_6+225&:&&&&&&&&mov&$0x0,%eax
-&&&&0x8048d12&&&&&phase_6+230&:&&&&&&&&jmp&0x8048c9b&&phase_6+111&
-&&&&0x8048d14&&&&&phase_6+232&:&&&&&&&&add&$0x3c,%esp
-&&&&0x8048d17&&&&&phase_6+235&:&&&&&&&&pop&%ebx
-&&&&0x8048d18&&&&&phase_6+236&:&&&&&&&&pop&%esi
-&&&&0x8048d19&&&&&phase_6+237&:&&&&&&&&pop&%edi
-&&&&0x8048d1a&&&&&phase_6+238&:&&&&&&&&pop&%ebp
-&&&&0x8048d1b&&&&&phase_6+239&:&&&&&&&&ret
好了,到这里,6个关都分析完毕了,感觉头早都被弄晕了
上传的附件:
(25.87kb,45次下载)
(7.56kb,33次下载)
支付方式:
最新回复 (7)
额...由于不知道怎么上传本地图片所以,文中有几张图片没有上传成功= =
顶。。。。。。章鱼哥。。。。。大牛淫
我记得还有一个隐藏的,不知道是不是这个。
其实在phase_defused()函数里面还有一个“隐藏”关,但是貌似由于对initialize_bomb()的废除导致了一系列的问题:
我们必须要将在某个时刻将0x804a810里面的内容设置成0x6,在一个字符串对比之后手动将返回值eax调整为0,然后才能进入到算法函数,
那也是一个递归算法,其实这个算法不难,第一个参数的值固定放在0x804a6b0里面为0x24,第二个参数我们要输入的(之前减了1),根据逻辑
最后很容易得出另一个参数为0x2c,因为之前减去了1,所以应该输入的值为0x2d,又由于之前调用了一个函数:将我们输入的字符串转化为10进制
的整数,所以我们输入的内容应为0x2d对应的10进制数。这里就不在给出具体的位置了,大家可以自己去试试,希望大牛们能够将之前两个修改
的问题解决掉,不甚感激。
其实在phase_defused()函数里面还有一个“隐藏”关,但是貌似由于对initialize_bomb()的废除导致了一系列的问题:
我们必须要将在某个时刻将0x804a810里面的内容设置成0x6,在一个字符串对比之后手动将返回值eax调整为0,然后才能进入到算法函数,
那也是一个递归算法,其实这个算法不难,第一个参数的值固定放在0x804a6b0里面为0x24,第二个参数我们要输入的(之前减了1),根据逻辑
最后很容易得出另一个参数为0x2c,因为之前减去了1,所以应该输入的值为0x2d,又由于之前调用了一个函数:将我们输入的字符串转化为10进制
的整数,所以我们输入的内容应为0x2d对应的10进制数。这里就不在给出具体的位置了,大家可以自己去试试,希望大牛们能够将之前两个修改
的问题解决掉,不甚感激。
世界计算机专业排名第一的学府CMU的牛叉课程啊,看CSAPP的时候也看到这段了。。。不过书里面没有这个bomb啊,你的bomb那里搞到的?
1.请先关注公众号。
2.点击菜单"更多"。
3.选择获取下载码。}

我要回帖

更多关于 4phase pa 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信