-
-
OllyDBG1.1条件记录断点中传递命令到命令行插件功能的使用探索
-
发表于:
2006-9-11 14:45
10552
-
OllyDBG1.1条件记录断点中传递命令到命令行插件功能的使用探索
OllyDBG1.1条件记录断点中传递命令到命令行插件功能的使用探索
By icow 2006-9-11
附插图版本见所符文档
OD的条件记录断点很好用,在帮助文件中关于OD条件记录断点的说明是:
条件记录断点 [Conditional logging breakpoint] (Shift+F4)是一种条件断点,每当遇到此类断点或者满足条件时,它将记录已知函数表达式或参数的值。例如,您可以在一些窗口过程函数上设置记录断点并列出对该函数的所有调用。或者只对接收到的WM_COMMAND消息标识符设断,或者对创建文件的函数(CreateFile)设断,并且记录以只读方式打开的文件名等,记录断点和条件断点速度相当,并且从记录窗口中浏览上百条消息要比按上百次F9轻松的多,您可以为表达式选择一个预先定义好的解释说明。
您可以设置通过的次数 - 每次符合暂停条件时,计数器就会减一。如果通过计数在减一前,不等于零,OllyDbg就会继续执行。如果一个循环执行100次(十进制),在循环体内设置一个断点,并设置通过次数为99(十进制)。OllyDbg将会在最后一次执行循环体时暂停。
另外,条件记录断点允许您传递一个或多个命令给插件[plugins]。例如,您需要使用命令行插件改变一个寄存器的内容,然后继续执行程序。
搜索论坛及google,关于条件记录断点的使用说得很详细,但对如何传递命命到命令行插件没有介绍(或许是我没找到),在论坛发了求助贴,放了两天也没有人应,只好自己来分析了。
直接在传递命令框里添上命令,中断时并没有执行所添命令。如下图:在命令框里添上d esp,中断时命令行插件并没有执行d esp。
不知如何入手,又再读了一遍OD的帮助文件。其中有一段文字值得注意:
新的插件函数:
- 当被调试程序暂停时,都会调用回调用函数 ODBG_Paused(int reason,t_reg *registers) 或其的扩展版本 ODBG_Pausedex(int reasonex,int extmode,reg *registers,DEBUG_EVENT *debugevent);
- 当应用程序因条件断点暂停,并且断点包含有传递给插件的命令,都会调用回调函数 ODBG_Plugincmd(int reason,t_reg *registers,char *cmd).
- 函数Function Settracecount(ulong count) 用于设置命令执行多少次后Run跟踪暂停;
- 函数 Settracepauseoncommands(char *cmdset) s用于指定暂停的命令集;
- 函数 Getbreakpointtypecount(ulong addr,ulong *passcount) 和 Setbreakpointext(ulong addr,ulong type,char cmd,ulong passcount) 支持传递条件断点中的计数器;
- 函数 Listmemory() 用于实现内存块列表。
其中加下划线的那句话:回调函数ODBG_Plugincmd(int reason,t_reg *registers,char *cmd),呵呵,应该就是它了,动态跟一跟它再说。
复制一份OD,称OD_CP,运行OllyICE,载入OD_CP中的OllyICE(以下称OllyDBG,以示区别),F9运行。用OllyDBG载入一个窗口程式AA己任选一个)并运行。
找到一处(我找的是窗体的ClassPROC)设条件记录断点如下图:
切换到OllyICE即最先运行的OD,ALT-M打开内存窗口,
找到CmdBar模块,在CPU数据窗口查看,CTRL-N,查找_ODBG_Plugincmd并跟随,在入口去设断点。在程式AA中点鼠标左键,首先OllyICE断下:
03463790 > 55 push ebp
03463791 8BEC mov ebp, esp
03463793 81C4 00FFFFFF add esp, -100
03463799 53 push ebx
0346379A 56 push esi
0346379B 8B5D 10 mov ebx, [ebp+10] ;指向传给命令行插件的命令”d esp”
0346379E 85DB test ebx, ebx
034637A0 74 0B je short 034637AD
034637A2 803B 2E cmp byte ptr [ebx], 2E;比较首字符是否是’.’(ACSII码是2E)
034637A5 75 06 jnz short 034637AD;不是则转,置EAX=0并退出
034637A7 807B 01 00 cmp byte ptr [ebx+1], 0;比较第二个字符是否为空
034637AB 75 04 jnz short 034637B1;不为空则跳
034637AD 33C0 xor eax, eax
034637AF EB 48 jmp short 034637F9
034637B1 8D95 00FFFFFF lea edx, [ebp-100]
034637B7 52 push edx
034637B8 8D73 01 lea esi, [ebx+1];将命令串的首字符去掉后压栈
034637BB 56 push esi
034637BC E8 27E8FFFF call 03461FE8;对命令串进行命令分析既表达式逻辑验证等,然后执行,有兴趣的可以跟一跟。
034637C1 83C4 08 add esp, 8
034637C4 85C0 test eax, eax
034637C6 75 07 jnz short 034637CF
034637C8 56 push esi
034637C9 E8 02F1FFFF call 034628D0;执行命令
034637CE 59 pop ecx
034637CF 833D D4EA4603 0>cmp dword ptr [346EAD4], 0
034637D6 74 1C je short 034637F4
034637D8 833D E8EA4603 0>cmp dword ptr [346EAE8], 0
034637DF 74 13 je short 034637F4
034637E1 8D85 00FFFFFF lea eax, [ebp-100]
034637E7 50 push eax
034637E8 8B15 E8EA4603 mov edx, [346EAE8]
034637EE 52 push edx
034637EF E8 E0770000 call <jmp.&USER32.SetWindowTextA>;addline
034637F4 B8 01000000 mov eax, 1
034637F9 5E pop esi
034637FA 5B pop ebx
034637FB 8BE5 mov esp, ebp
034637FD 5D pop ebp
034637FE C3 retn
分析_ODBG_Plugincmd函数可知,在命令框输入命令格式应该为:.加命令。即d esp 应为.d esp。
重新设条件记录断点:
再执行,_ODBG_Plugincmd执行两次,第一次传递命令.d esp,第二次传递命令.a send。
两个命令都能正确执行。
总结:OD的条件记录断点传递命令到命令行插件的正确用法是:
在条件记录断点对话框的命令框中输入.+命令。即按照命令行插件的用法前加一.(ASCII码为2E)。
搞得很复杂,只是我的分析过程,大家不要笑话。
其实直接看命令行插件的源码更省事。搞玩了才想到这一着.
extc int _export cdecl ODBG_Plugincmd(int reason,t_reg *reg,char *cmd)
{
char answer[TEXTLEN];
// Command-line plugin accepts only commands that start with point (.)
if(cmd==NULL || cmd[0]!='.' || cmd[1]=='\0') {
return 0;
}
if(Execute(cmd+1,answer)==0) {
Addline(cmd+1); // Add line only if command valid
}
if(hwmain!=NULL && hwerr!=NULL) {
SetWindowText(hwerr,answer); // Display result or error message
}
return 1;
};
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课