OllyDBG 入门系统(六) - 消息断点及RUN跟踪补充

看完了《OllyDBG入门系统(五)-消息断点及RUN跟踪》之后感觉如何?会否有如下问题:
1、是否觉得不知道在哪下断?
2、为什么要这样子下断?
3、如何确定断下来后的位置就是正确的?

好,就本着这几个问题来分析一遍。

首先,先回顾下Windows的消息机制。要点:所有要处理的消息必然会由程序自己处理,不处理的消息都交由Windows处理。Windows的消息处理函数的格式,如下:
LRESULTCALLBACKWindowProc(
HWNDhwnd,//handleofwindow
UINTuMsg,//messageidentifier
WPARAMwParam,//firstmessageparameter
LPARAMlParam//secondmessageparameter
);
其中uMsg就是关键,它代表消息的类型,如:WM_COMMAND,WM_GETTEXT等。记好哦。

下面,我们来用实例讲解。
http://images18.51.com/1001/c/dc/7a/tjszl1/140_102_7ca75025ac63e372.jpg
这个CrackMe是用对话框做的(你是怎么知道的?)。
1、用OllyDbg加载,Crtl N,找到函数:USER32.DialogBoxParamA,右击->“在每个参考上设置断点”。
2、F9,运行。看,被拦了下来,如图:

3、其中DlgProc的内容,就是我们需要找的东东。这个地址是消息处理函数的入口点。现在来解释为什么要在窗口那才有消息断点,看图,

要下消息断点,首先得找到具有Windows消息处理函数格式的函数,然后,再根据栈的数据来判断消息,如果符合下断的消息,那么,OllyDbg就会拦下来(还会觉得不知道在哪下消息断点了吗?知道该如何下消息断点了吧?)。很明显有一点,这个消息断点的功能是有限的,比如,要拦主窗口中的菜单消息呢?所以,消息断点的功能还是有限的。如何扩展?扯远了,下面再讲。

4、Ctrl G来到cyle.0041029,我们来到了消息处理函数了,但是,OllyDbg并未识别出这个函数是消息处理函数。所以,在cyle.0041029处,右击->“分析”->“假定参数”,如图:
http://images18.51.com/1001/b/dc/7a/tjszl1/486_176_bd2ca39da4b5347d.jpg
弹出一个对话框,选择“WinProc(hWnd,msg,wParam,lParam)”。
http://images18.51.com/1001/c/dc/7a/tjszl1/350_160_8dcc020b417cc80e.jpg
点击“应用”后,如图。
http://images18.51.com/1003/b/dc/7a/tjszl1/591_79_d6b8fe6166efd8bf.jpg
5、在cyle.0041029处,右击->“断点”->“在WinProc上的消息断点”(平时是不是没见过这个菜单呀?呵呵)。
http://images18.51.com/1002/a/dc/7a/tjszl1/474_57_d5f8e27449a91836.jpg
5、在“消息”表框中,选择你要下断的消息(Alt B,删除以前的断点,以免影响心情)。
http://images18.51.com/1003/a/dc/7a/tjszl1/381_262_aa6581414ca2a924.jpg
6、F9,运行,程序运行起来了。这时没什么事情发生,当你在里面点了一个文本框之后(点它,是想让它获得Focus(焦点),以便能够输入数据),事情就发生了。现在没办法在文本框里输入注册码,也没办法点击按钮。这是怎么回事呢?仔细看一下Stack(栈)的那个窗口,噢!原来被文本框的通知EN_SETFOUCE搞坏了!停留在EN_SETFOCUS和EN_KILLFOCUS两个消息之间了。
7、好,现在来扩展消息断点(消息断点是否是条件断点的特殊例子?),即使用条件断点(卖弄了一下,呵呵)。
http://images18.51.com/1001/a/dc/7a/tjszl1/480_171_cf268cdc89f147c5.jpg
看你需求,条件和条件记录,在这里是没什么区别的,因为不需要记录的内容。
8、按Shitf F2,输入MSG==WM_COMMAND&&[ESP C]==66(这个66是怎么来的?这个就是那个Check按钮的ID,意思就是“当收到WM_COMMAND,且是由ID为0x66发出的时候中断”),确定,F9,运行。
9、现在,输入Name和Serial之后,点”Check”按钮。
10、这次中断,位置上似乎没有变化,但是,明白了消息处理机制,应该知道这次中断的不同吧?(这次会流程会流到注册算法那哦)
00401029>/.>enter0,0;解码为<WinProc>
0040102D|.>pushebx
0040102E|.>pushedi
0040102F|.>pushesi
00401030|.>cmp[arg.2],110
00401037|.>jeshortcycle.0040105E
00401039|.>cmp[arg.2],111//111=WM_COMMAND
00401040|.>jeshortcycle.00401082//肯定在这里跳(为什么?)
00401042|.>cmp[arg.2],10
00401046|.>jeshortcycle.00401057
00401048|.>cmp[arg.2],2
0040104C|.>jeshortcycle.00401057
0040104E|.>xoreax,eax

11、来到cycle.00401082,
00401082|>/>cmp[arg.3],67
00401086|.>jnzshortcycle.0040108D//这里肯定会跳
00401088|.>callcycle.00401151
0040108D|>>cmp[arg.3],66
00401091|.>jnzshortcycle.00401098//这里肯定不会跳(又是为什么呢?)
00401093|.>callcycle.0040109C//关键,
00401098|>>xoreax,eax

12、蓝色部分,已经在CCDebuger那篇文章分析过了,这里就不分析了,我用红色字体来标明重点。
0040109C/$>movdwordptrds:[402182],FEDCBA98
004010A6|.>push11;/Count=11(17.)
004010A8|.>pushcycle.00402171;|Buffer=cycle.00402171
004010AD|.>push3E9;|ControlID=3E9(1001.)
004010B2|.>push[arg.1];|hWnd
004010B5|.>call<jmp.&USER32.GetDlgItemTextA>;/GetDlgItemTextA(Serial)
004010BA|.>oreax,eax
004010BC|.>jeshortcycle.0040111F
004010BE|.>push11;/Count=11(17.)
004010C0|.>pushcycle.00402160;|Buffer=cycle.00402160
004010C5|.>push3E8;|ControlID=3E8(1000.)
004010CA|.>push[arg.1];|hWnd
004010CD|.>call<jmp.&USER32.GetDlgItemTextA>;/GetDlgItemTextA(name)
004010D2|.>oreax,eax
004010D4|.>jeshortcycle.0040111F
004010D6|.>movecx,10
004010DB|.>subecx,eax
004010DD|.>movesi,cycle.00402160
004010E2|.>movedi,esi
004010E4|.>addedi,eax
004010E6|.>cld
004010E7|.>repmovsbyteptres:[edi],byteptr>
004010E9|.>xorecx,ecx
004010EB|.>movesi,cycle.00402171
004010F0|>>/incecx
004010F1|.>|lodsbyteptrds:[esi]
004010F2|.>|oral,al
004010F4|.>|jeshortcycle.00401100
004010F6|.>|cmpal,7E
004010F8|.>|jgshortcycle.00401100
004010FA|.>|cmpal,30
004010FC|.>|jbshortcycle.00401100
004010FE|.^>/jmpshortcycle.004010F0
00401100|>>cmpecx,11
00401103|.>jnzshortcycle.0040111F//判断长度是否为16个有效字符,即16个字节,不是则跳
00401105|.>callcycle.004011F1//算法
0040110A|.>movecx,0FF01
0040110F|.>pushecx
00401110|.>callcycle.00401190//算法
00401115|.>cmpecx,1
00401118|.>jeshortcycle.00401120//需要跳
0040111A|>>callcycle.00401166
0040111F|>>retn
00401120|>>moveax,dwordptrds:[402168]
00401125|.>movebx,dwordptrds:[40216C]
0040112B|.>xoreax,ebx
0040112D|.>xoreax,dwordptrds:[402182]
00401133|.>oreax,40404040
00401138|.>andeax,77777777
0040113D|.>xoreax,dwordptrds:[402179]
00401143|.>xoreax,dwordptrds:[40217D]
00401149|.^>jnzshortcycle.0040111A//不可以跳
0040114B|.>callcycle.0040117B//提示注册成功!
00401150/.>retn

终于写完了,现在来回顾下刚开始的问题:
1、是否觉得不知道在哪下断?
答:在Windows消息处理函数的入口处下消息断点。
2、为什么要这样子下断?
答:可能OllyDbg是根据栈的数据和函数原型来匹配,所以,一般来说,匹配条件都会是[Esp XX]==XXXXX
3、如何确定断下来后的位置就是正确的?
答:这里是根据编程的思路以及Windows的消息处理机制来定位的,理论与实战相结合。

最后,总结下,由于windows是消息驱动的,很大一部分都是通过消息来完成的,所以,有很大一部分可以通过对消息下断来达到目的,但是,如何下消息断点?从大体上讲,是这样子的:1、找出消息循环处理的函数2、在消息循环处理函数的入口处设断

写到这里,废话一下。赞扬CCDebuger的太多了,但是,在赞扬的同时,不知道大家有没仔细消化人家的成果?呵呵,其实,我也没有,因为我看不太懂,所以,还是照着自己的思路走。写这篇文章的目的是为了帮一位朋友,他想下消息断点,但是,不知道如何下,我就把CCDebuger的这那篇消息断点给他,可是,还是没解决,后来,自己也动了一下手,确实,对于WM_COMMAND消息来说,OD肯定会不停的拦下来的,所以,单纯的消息断点就行不通了,所以,再结合Run跟踪来记录下,刚好能解决问题,也就产生了CCDebuger的那篇文章(猜的,呵呵)。
最后,帮忙纠正下错误:
引用:
写到这准备跟踪算法时,才发现这个crackme还是挺复杂的,具体算法我就不写了,实在没那么多时间详细跟踪。有兴趣的可以跟一下,注册码是17位,用户名采用复制的方式扩展到16位,如我输入“CCDebuger”,扩展后就是“CCDebugerCCDebug”。大致是先取扩展后用户名的前8位和注册码的前8位,把用户名的前四位和后四位分别与注册码的前四位和后四位进行运算,算完后再把扩展后用户名的后8位和注册码的后8位分两部分,再与前面用户名和注册码的前8位计算后的值进行异或计算,最后结果等于0就成功。注册码的第17位我尚未发现有何用处。对于新手来说,可能这个crackme的难度大了一点。没关系,我们主要是学习OllyDBG的使用,方法掌握就可以了。

关于“位”的概念,“位”,是指二进制位,在这里,一个字节等于8位,一个字符等于一个字节。“注册码是17位”,应改成“注册码是17个字节”,如果你跟踪分析过,你可以发现,这样子还是不对的,最后应该是“注册码是16个字节”,
cmpecx,11,这里的11是16进制,即十进制数:17。从代码中可以看出这个十进制数17,还得减1才是字符串的真实长度,所以,应该改成“注册码是16个字节”,后面的“位”,需要改成“字节”。第一次看的时候,没注意看,都给蒙了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值