首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > 其他数据库 >

OllyDBG 入门系列(3)-函数

2012-09-01 
OllyDBG 入门系列(三)-函数在第一篇中已经介绍了领空的概念,如我这里调试这个程序时?OllyDBG?的标题栏显示

OllyDBG 入门系列(三)-函数

在第一篇中已经介绍了领空的概念,如我这里调试这个程序时?OllyDBG?的标题栏显示的就是“[CPU?-?主线程,?模块?-?CrackHea]”,这表明我们当前在被调试程序的领空)。通过上面的操作后会弹出一个对话框,如图:
OllyDBG 入门系列(3)-函数
对于这样的编辑框中输注册码的程序我们要设断点首选的?API?函数就是?GetDlgItemText?及?GetWindowText。每个函数都有两个版本,一个是?ASCII?版,在函数后添加一个?A?表示,如?GetDlgItemTextA,另一个是?UNICODE?版,在函数后添加一个?W?表示。如?GetDlgItemTextW。对于编译为?UNCODE?版的程序可能在?Win98?下不能运行,因为?Win98?并非是完全支持?UNICODE?的系统。而?NT?系统则从底层支持?UNICODE,它可以在操作系统内对字串进行转换,同时支持?ASCII?和?UNICODE?版本函数的调用。一般我们打开的程序看到的调用都是?ASCII?类型的函数,以“A”结尾。又跑题了,呵呵。现在回到我们调试的程序上来,我们现在就是要找一下我们调试的程序有没有调用?GetDlgItemTextA?或?GetWindowTextA?函数。还好,找到一个?GetWindowTextA。在这个函数上右击,在弹出菜单上选择“在每个参考上设置断点”,我们会在?OllyDBG?窗口最下面的那个状态栏里看到“已设置?2?个断点”。另一种方法就是那个?GetWindowTextA?函数上右击,在弹出菜单上选择“查找输入函数参考”(或者按回车键),将会出现下面的对话框:
OllyDBG 入门系列(3)-函数?
看上图,我们可以把两条都设上断点。这个程序只需在第一条指令设断点就可以了。好,我们现在按前面提到的第一条方法,就是“在每个参考上设置断点”,这样上图中的两条指令都会设上断点。断点设好后我们转到我们调试的程序上来,现在我们在被我们调试的程序上点击那个“Check?It”按钮,被?OllyDBG?断下:

00401323?|.?E8?4C010000?????????CALL?<JMP.&USER32.GetWindowTextA>???????????;?GetWindowTextA
00401328?|.?E8?A5000000?????????CALL?CrackHea.004013D2??????????????????????;?关键,要按F7键跟进去
0040132D?|.?3BC6????????????????CMP?EAX,ESI?????????????????????????????????;?比较
0040132F?|.?75?42???????????????JNZ?SHORT?CrackHea.00401373?????????????????;?不等则完蛋
00401331?|.?EB?2C???????????????JMP?SHORT?CrackHea.0040135F
00401333?|.?4E?6F?77?20?7>??????ASCII?"Now?write?a?keyg"
00401343?|.?65?6E?20?61?6>??????ASCII?"en?and?tut?and?y"
00401353?|.?6F?75?27?72?6>??????ASCII?"ou're?done.",0
0040135F?|>?6A?00???????????????PUSH?0??????????????????????????????????????;?Style?=?MB_OK|MB_APPLMODAL
00401361?|.?68?0F304000?????????PUSH?CrackHea.0040300F??????????????????????;?Title?=?"Crudd's?Crack?Head"
00401366?|.?68?33134000?????????PUSH?CrackHea.00401333??????????????????????;?Text?=?"Now?write?a?keygen?and?tut?and?you're?done."
0040136B?|.?FF75?08?????????????PUSH?DWORD?PTR?SS:[EBP+8]???????????????????;?hOwner
0040136E?|.?E8?19010000?????????CALL?<JMP.&USER32.MessageBoxA>??????????????;?MessageBoxA

从上面的代码,我们很容易看出?00401328?地址处的?CALL?CrackHea.004013D2?是关键,必须仔细跟踪。而注册成功则会显示一个对话框,标题是“Crudd's?Crack?Head”,对话框显示的内容是“Now?write?a?keygen?and?tut?and?you're?done.”现在我按一下?F8,准备步进到?00401328?地址处的那条?CALL?CrackHea.004013D2?指令后再按?F7?键跟进去。等等,怎么回事?怎么按一下?F8?键跑到这来了:

00401474?$-?FF25?2C204000??????JMP?DWORD?PTR?DS:[<&USER32.GetWindowText>????;?USER32.GetWindowTextA
0040147A?$-?FF25?30204000??????JMP?DWORD?PTR?DS:[<&USER32.LoadCursorA>]?????;?USER32.LoadCursorA
00401480?$-?FF25?1C204000??????JMP?DWORD?PTR?DS:[<&USER32.LoadIconA>]???????;?USER32.LoadIconA
00401486?$-?FF25?20204000??????JMP?DWORD?PTR?DS:[<&USER32.LoadMenuA>]???????;?USER32.LoadMenuA
0040148C?$-?FF25?24204000??????JMP?DWORD?PTR?DS:[<&USER32.MessageBoxA>]?????;?USER32.MessageBoxA

原来是跳到另一个断点了。这个断点我们不需要,按一下?F2?键删掉它吧。删掉?00401474?地址处的断点后,我再按?F8?键,呵,完了,跑到?User32.dll?的领空了。看一下?OllyDBG?的标题栏:“[CPU?-?主线程,?模块?-?USER32],跑到系统领空了,OllyDBG?反汇编窗口中显示代码是这样:

77D3213C?6A?0C?????????????????PUSH?0C
77D3213E?68?A021D377???????????PUSH?USER32.77D321A0
77D32143?E8?7864FEFF???????????CALL?USER32.77D185C0

怎么办?别急,我们按一下?ALT+F9?组合键,呵,回来了:

00401328?|.?E8?A5000000????????CALL?CrackHea.004013D2?????????????????????;?关键,要按F7键跟进去
0040132D?|.?3BC6???????????????CMP?EAX,ESI????????????????????????????????;?比较
0040132F?|.?75?42??????????????JNZ?SHORT?CrackHea.00401373????????????????;?不等则完蛋

光标停在?00401328?地址处的那条指令上。现在我们按?F7?键跟进:

004013D2?/$?56????????????????PUSH?ESI????????????????????????????????????;?ESI入栈
004013D3?|.?33C0??????????????XOR?EAX,EAX?????????????????????????????????;?EAX清零
004013D5?|.?8D35?C4334000?????LEA?ESI,DWORD?PTR?DS:[4033C4]???????????????;?把注册码框中的数值送到ESI
004013DB?|.?33C9??????????????XOR?ECX,ECX?????????????????????????????????;?ECX清零
004013DD?|.?33D2??????????????XOR?EDX,EDX?????????????????????????????????;?EDX清零
004013DF?|.?8A06??????????????MOV?AL,BYTE?PTR?DS:[ESI]????????????????????;?把注册码中的每个字符送到AL
004013E1?|.?46????????????????INC?ESI?????????????????????????????????????;?指针加1,指向下一个字符
004013E2?|.?3C?2D?????????????CMP?AL,2D???????????????????????????????????;?把取得的字符与16进制值为2D的字符(即“-”)比较,这里主要用于判断输入的是不是负数
004013E4?|.?75?08?????????????JNZ?SHORT?CrackHea.004013EE?????????????????;?不等则跳
004013E6?|.?BA?FFFFFFFF???????MOV?EDX,-1??????????????????????????????????;?如果输入的是负数,则把-1送到EDX,即16进制FFFFFFFF
004013EB?|.?8A06??????????????MOV?AL,BYTE?PTR?DS:[ESI]????????????????????;?取“-”号后的第一个字符
004013ED?|.?46????????????????INC?ESI?????????????????????????????????????;?指针加1,指向再下一个字符
004013EE?|>?EB?0B?????????????JMP?SHORT?CrackHea.004013FB
004013F0?|>?2C?30?????????????SUB?AL,30???????????????????????????????????;?每位字符减16进制的30,因为这里都是数字,如1的ASCII码是“31H”,减30H后为1,即我们平时看到的数值
004013F2?|.?8D0C89????????????LEA?ECX,DWORD?PTR?DS:[ECX+ECX*4]????????????;?把前面运算后保存在ECX中的结果乘5再送到ECX
004013F5?|.?8D0C48????????????LEA?ECX,DWORD?PTR?DS:[EAX+ECX*2]????????????;?每位字符运算后的值与2倍上一位字符运算后值相加后送ECX
004013F8?|.?8A06??????????????MOV?AL,BYTE?PTR?DS:[ESI]????????????????????;?取下一个字符
004013FA?|.?46????????????????INC?ESI?????????????????????????????????????;?指针加1,指向再下一个字符
004013FB?|>?0AC0??????????????OR?AL,AL
004013FD?|.^?75?F1????????????JNZ?SHORT?CrackHea.004013F0?????????????????;?上面一条和这一条指令主要是用来判断是否已把用户输入的注册码计算完
004013FF?|.?8D040A????????????LEA?EAX,DWORD?PTR?DS:[EDX+ECX]??????????????;?把EDX中的值与经过上面运算后的ECX中值相加送到EAX
00401402?|.?33C2??????????????XOR?EAX,EDX?????????????????????????????????;?把EAX与EDX异或。如果我们输入的是负数,则此处功能就是把EAX中的值取反
00401404?|.?5E????????????????POP?ESI?????????????????????????????????????;?ESI出栈。看到这条和下一条指令,我们要考虑一下这个ESI的值是哪里运算得出的呢?
00401405?|.?81F6?53757A79?????XOR?ESI,797A7553????????????????????????????;?把ESI中的值与797A7553H异或
0040140B?\.?C3????????????????RETN


这里留下了一个问题:那个?ESI?寄存器中的值是从哪运算出来的?先不管这里,我们接着按?F8?键往下走,来到?0040140B?地址处的那条?RETN?指令(这里可以通过在调试选项的“命令”标签中勾选“使用?RET?代替?RETN”来更改返回指令的显示方式),再按一下?F8,我们就走出?00401328?地址处的那个?CALL?了。现在我们回到了这里:

0040132D?|.?3BC6?????????????CMP?EAX,ESI??????????????????????????????????;?比较
0040132F?|.?75?42????????????JNZ?SHORT?CrackHea.00401373??????????????????;?不等则完蛋

光标停在了?0040132D?地址处的那条指令上。根据前面的分析,我们知道?EAX?中存放的是我们输入的注册码经过计算后的值。我们来看一下信息窗口:

ESI=E6B5F2F9
EAX=FF439EBE

左键选择信息窗口中的?ESI=E6B5F2F9,再按右键,在弹出菜单上选“修改寄存器”,我们会看到这样一个窗口:
OllyDBG 入门系列(3)-函数?
可能你的显示跟我不一样,因为这个?crackme?中已经说了每个机器的序列号不一样。关掉上面的窗口,再对信息窗口中的?EAX=FF439EBE?做同样操作:
OllyDBG 入门系列(3)-函数?
由上图我们知道了原来前面分析的对我们输入的注册码进行处理后的结果就是把字符格式转为数字格式。我们原来输入的是字串“12345666”,现在转换为了数字?12345666。这下就很清楚了,随便在上面那个修改?ESI?图中显示的有符号或无符号编辑框中复制一个,粘贴到我们调试的程序中的编辑框中试一下:
OllyDBG 入门系列(3)-函数?
呵呵,成功了。且慢高兴,这个?crackme?是要求写出注册机的。我们先不要求写注册机,但注册的算法我们要搞清楚。还记得我在前面说到的那个?ESI?寄存器值的问题吗?现在看看我们上面的分析,其实对做注册机来说是没有多少帮助的。要搞清注册算法,必须知道上面那个?ESI?寄存器值是如何产生的,这弄清楚后才能真正清楚这个?crackme?算法。今天就先说到这里,关于如何追出?ESI?寄存器的值我就留到下一篇?OllyDBG?入门系列(四)-内存断点?中再讲吧。

热点排行