01
OD篇
1.1使用工具:
OD(OllyDbg)
功能:用于动态调试
1.2该调试过程中常用快捷键
F8 单步步过
F7 单步步入(查看函数)
F9 直接运行程序,遇到断点则暂停
1.3步骤:
首先,运行一遍IgniteMe.exe软件,记录下关键语句Give me your flag。
在OD里面载入待调试的程序IgniteMe.exe 。
单击鼠标右键,选择中文引擎搜索——智能搜索,进入智能搜索界面后,单击鼠标右键选择Find,输入“Give me your flag”,单击确认按钮,双击出现该关键语句处,程序自动跳转到反汇编窗口的对应行,在此处我们设置断点。
在弹出的DOS界面中,随便输入一个flag,回车。继续查看代码。
继续单步步过浏览代码,遇到函数不暂停,但是要注意步过函数之后,寄存器里面值的改变(返回值的改变),从而猜测到函数的作用(如步过函数IgniteMe. 0041F2D0,eax里的内容改变,经过输入字符串对比,可知道该函数的作用是将输入字符串的长度返回到eax里)。函数后面常常跟着cmp,用于比较返回值和给定值的关系。通过观察我们可以发现,上面所述函数下方的cmp的具体作用是用来比较字符串的长度是否为小于4或大于等于30。是则输出Sorry,keep trying! ,flag输入错误。其实在此我们就应该知道输入字符串长度应为29。
(相关代码如下:)
00401050 . E8 7BE20100 call IgniteMe.0041F2D0 ; 字符串长度
00401055 . 83C4 04 add esp,0x4
00401058 . 83F8 1E cmp eax,0x1E
0040105B 73 11 jnb short IgniteMe.0040106E ; 长度大于等于30跳转
0040105D . 8D55 80 lea edx,[local.32] ; 为输入的字符串
00401060 . 52 push edx
00401061 . E8 6AE20100 call IgniteMe.0041F2D0
00401066 . 83C4 04 add esp,0x4
00401069 . 83F8 04 cmp eax,0x4
0040106C 77 25 ja short IgniteMe.00401093 ;
长度大于4则跳转
在第二个Sorry,keep trying!之前发现寄存器里面出现EIS{,容易知道这是大赛flag的输入格式要求,这个地方就是来判断输入字符串的是否以EIS”
相等则跳转
接下来继续步过,这一次我们通过单步步过的方式很难判断出进行了什么变换和判断,于是我们选择单步步入到IgniteMe.004011C0这个函数中去。
此时进入了一个循环,可看出该循环的作用是把输入的字符串去掉EIS{}格式之后存入到ss堆栈中。
字符串完全存入到ss中之后,又进入一个循环,通过寄存器内容的改变可以简单判断这个循环进行了一个大小写交换的修改。修改后将值存入edx中。但是该循环并不只是仅仅做了这个简单的改变。
观察 push edx之后的语句,着重观察和edx有关的语句。
通过单步步过,发现mov edx,[local.45] 和xor edx,ecx语句,下次调试时,认真观察[local.45]和ecx的值,可以发现如下关系:
以上步骤很关键,总结起来即为对字符串EIS{ }括号中的内容逐个进行大小写交换,对[arg.1]的内容逐个赋给eax,进行一个异或并相加的操作,结果与关键字符串进行异或(关键字符串为ds:[eax+0x4420B0]中的内容,可通过数据窗口跟随查看其中的内容)。最终的结果存入ss堆栈中。(相关部分代码)
0040134C . E8 6F000000 call IgniteMe.004013C0 ;
关键函数,eax异或相加
00401351 . 83C4 04 add esp,0x4 ;
00401354 . 8985 4CFFFFFF mov [local.45],eax
0040135A . 8B85 7CFFFFFF mov eax,[local.33]
00401360 . 0FBE88 B02044>movsx ecx,byte ptr ds:[eax+0x4420B0] ; 关键字符串
00401367 . 8B95 4CFFFFFF mov edx,[local.45]
0040136D . 33D1 xor edx,ecx
0040136F . 8B85 7CFFFFFF mov eax,[local.33]
00401375 . 889405 54FFFF>mov byte ptr ss:[ebp+eax-0xAC],dl ;
存入修改之后的
0040137C . C785 50FFFFFF>mov [local.44],0x0
00401386 .^\E9 0BFFFFFF \jmp IgniteMe.00401296
0040138B > \8D8D 54FFFFFF lea ecx,[local.43]
继续单步步过,遇到函数IgniteMe.0041F390,单步步入可发现改变后的字符串与IgniteMe.0x43B188(内容为GONDPHyGjPEKruv{
2
IDA篇
我们如果用IDA对IgniteMe.exe进行分析,选择Generate pseudocode 将伪代码调出,会发现这比在OD中进行分析容易得多。但是,值得一提的是,在OD中进行调试,更有益于我们对汇编程序及过程的进一步了解。
2.1以下为在IDA中进行分析的过程:
选择Generate pseudocode调出伪代码后,我们首先对主函数进行分析,它的思路非常清晰,就是通过四个主要判断对输入的flag进行验证,如果判断均正确,则flag正确。
这四个判断分别是:
(1)if ( strlen(v8) < 0x1E && strlen(v8) > 4 ) //v8为输入字符串
判断输入字符串长度是否在大于4且小于30
(2)
strcpy(v7, "EIS{");
for ( i = 0; ; ++i )
{
v4 = strlen(v7);
if ( i >= v4 )
break;
if ( v8[i] != v7[i] )
{
sub_402B30((int)&unk_446360, "Sorry, keep trying! ");
sub_4013F0(sub_403670);
return 0;
}
这里运用了一个循环函数,即将输入字符串前四位与“EIS{”进行一个比较,全部相等则通过验证,不相同则flag错误。
(3)if ( v9 == 125 ) //v9为输入字符串最后一位
判断输入字符串最后一位是否为“}”
(4)
if ( sub_4011C0(v8) )
{
sub_402B30((int)&unk_446360, "Congratulations! ");
sub_4013F0(sub_403670);
result = 0;
}
else
{
sub_402B30((int)&unk_446360, "Sorry, keep trying! ");
sub_4013F0(sub_403670);
result = 0;
}
我们点击sub_4011C0这个函数进行查看,看看它对v8进行了什么样的变换。
由于该函数的返回值是result,我们先来看看result的值是怎么得来的。我们发现这样一个语句:
意思就是v7和GONDPHyGjPEKruv{”。1处的循环意在于将括号中的内容传入v11中。
对v11中的字母进行大小写交换。
函数sub_4013C0的内容为:
int __cdecl sub_4013C0(int a1)
{
return (a1 ^ 0x55) + 72;
}
可知3处的代码意在于将v11中的字符数组内容逐个与0x55异或后加上72再与j(0~24)进行异或。最终得到的内容就是v7的全部内容。
结合上面的分析,当v7与GONDPHyGjPEKruv{;
领取专属 10元无门槛券
私享最新 技术干货