好友
阅读权限30
听众
最后登录1970-1-1
|
在学习反调试时,我惊叹他们的OllyDbg反调试为何能绕过反附加,反调试。于是开始了简易调试器的编写,可是我并不能满足止步于此。我好奇经典的OllyDbg界面是如何去实现的,还有其他功能又是如何实现的,我们知道他不仅界面友好,而且支持插件丰富。想自己通过逆向去发现实现原理,并最终实现自己的调试器。从今年大三下学期疫情在家上网课,陆陆续续,零零散散耗时二月份到今年九月份,对OllyDbg 1.10的逆向还原终于有了进展,特此记录一下。
现在开始正题。
一、窗口绘制的实现
OD的自绘窗口分为主要分为4种 dump窗口,table窗口,寄存器窗口,对话框窗口。
所有自绘窗口的绘制函数都由Painttable函数来完成。Paint会根据t_table指定的各种属性来进行来绘制,调用时需要传入数据解析函数(后面会提到)
大量的数据结构如t_table、t_dll、t_sorted数据结构可以在OllyDbg的插件编写帮助文档与提供的插件开发代码例子中找到。
在创建table窗口时,都会初始化上面的结构体
工具条的实现,是一开始遇到的难点。后来逆向出来了结构体,也不难发现只不过也是通过MoveToEx(hdcDst, rct.left + 2, rct.bottom - 2, NULL); LineTo(hdcDst, rct.right - 2, rct.bottom - 2);
画出来一个小方框,然后再通过LoadBitmap加载位图进去。如果是发生了点击则把方框线的颜色使用其他颜色,模拟产生了点击了效果。
二、数据的解析
数据的解析是由Painttable的getline参数来指定的,该函数的原型是
typedef int DRAWFUNC(char *s, char *mask, int *select, t_sortheader *ps, int column);
几乎每个自绘窗口都有自己的数据解析函数,除开反汇编窗口、栈窗口、数据窗口共用一个解析函数。
每个窗口基本都有自己的数据结构,如t_thread、t_module、t_memory等。解析时对应结构体解析就可以了。
三、逆向还原的难点
逆向还原时最复杂莫过于Win32消息循环的处理。OD的作者定义了众多的自定义消息来处理系统默认窗口消息,大部分的窗体事件都是由
Tablefunction来完成的。
一个窗口过程函数复杂的话基本就是千行代码,其中内容最多的还是菜单消息的处理,OllyDbg会根据当前窗口的句柄进行动态创建右键菜单,然后直接在里面处理菜单的单击事件,看到的就是函数体巨大。
cpu的窗口使用了两套数据来维护窗口大小,一个是还原模式,一个是最大化模式。如果使用一份数据,那么会遇到5个子窗口大小十分难以处理。当然逆向这里时花费了我很多时间,没体验过窗口大小的bug就不知道有多痛苦。
其次就是5个窗口的resize的窗口大小伸缩时会有一定的鼠标光标的切换,起初是以为MFC中的分割条原理相似,cpu窗口是通过分割条割出来的,其实不然其确实创建了5个子窗口,并不是分割条控件分出来的。鼠标的切换在于响应了WM_SETCURSOR消息,然后加载相应的光标,再设置光标。
还有就是OD的大量可配置性导致全局变量很多,比如说字体颜色、分割线颜色、是否显示滚动条等, 这也是其界面美观的主要原因了。
四、复现的效果
主界面
cpu窗口
内存块窗口
线程窗口
其他窗口的实现是大同小异的。
五、总结
逆向的乐趣在于发现其内部原理,类似ctf解出来了flag,而我则是发现了od查找数据时使用了二分查找、位图双缓存技术防止窗口闪烁。现在基本界面实现已不是难题,接下来继续完善调试器的功能!
|
免费评分
-
查看全部评分
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|