[调试器的设计]第四章 函数名的解析

4.1 问题的提出与分析
4.1.1 问题的分析
最初对于这个问题处理的想法就是分析被调试程序的导入表,后来和苏玉海讨论,发现这样不能解决问题,因为API里可能还调用了别的API,再跟进API的话,程序就不能正确解析函数名了!
据说Windows有上万个API,如何组织这些数据,如果提高查询的效率、以及最大化的合理使用空间。
4.2 问题的解决
4.2.1 函数名与函数地址的组织
     用一个链表用来存储已经加载的DLL的名字已及当前状态。为了提高查询的效率,同时记录DLL名字的CRC值,当查找时,算出要查找的DLL名 的CRC值,再直接查找通过CRC值查找,当CRC值相同时,再用字符串比较是否完全相等,当加载DLL比较多的时候,或者经常要查询的话,这样可以大大 的提升的效率。
  同时用红黑树记录函数名地址(函数名在被调试进程里面的地址)以及函数的绝对地址(基址加偏移后的真实地址)。
红黑树并不追求“完全平衡”——它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能。红黑树能够以O(log2 n) 的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。
4.2.2 函数名的显示
在我的设计中,使用的是OD的反汇编引擎,结构体中有记录命令的类型,首先判断他是不是call、jmp这类的指令,然后再根据相应的值,找出API的地 址,再判断目标地址是否是API函数的地址,是的话则从本地加载DLL链表中取得DLL名字,然后再通过函数名地址去调试进程中取得函数名(在程序中,并 没有申请空间保存函数名,因为导出函数可能非常之多,不停的申请空间,然后字符串拷备,这个开销是非常之大的,所以在程序中我们只记录函数名在调试进程中 的地址,同时dll名链表中有个状态值,当状态值为真时,表明那个dll当前已经加载,这样可以直接去内存拿函数名)。而对于call ebp之类的指 令,而需要在运行时才解析,因为在没有执行到那条语句的时候,寄存器的值是不确定的。
效果如下:
名称:  1.jpg
查看次数: 517
文件大小:  30.0 KB

 

附件:

第四章节.pdf

posted @ 2015-05-10 11:09  银河彼岸  阅读(213)  评论(0编辑  收藏  举报