我将用实践的方式来展示如何将理论运用到实际~
找类名
我以对话框为例(大家可以使用VC新建一个对话框程序,然后拖入一个按钮,然后添加处理函数比如弹窗,或者直接使用我提供的附件)。我们自己的创建的对话框类是继承自CDialog的,而且我们自定义的对话框类默认是没有实现RTTI的,所以我们要先找到父类即CDialog的RTTI结构,然后找到父类的消息映射表,然后通过数据交叉引用找到我们自定义对话框类的消息映射表。
首先将程序载入IDA,等待程序分析完成,打开字符串子窗口,如下所示:
找到CDialog字符串,如下所示
双击跟踪字符串到数据段,然后查看字符串的交叉引用,如下所示:
向下翻动很快就能找到我们的消息映射表结构了,消息映射表结构非常特殊,消息条目数组就紧跟着消息映射表结构
我们还可以使用IDA的自定义数据结构功能来提高代码的可读性,首先打开本地类型子窗口
然后右键插入AFX_MSGMAP_ENTRY和AFX_MSGMAP数据结构体,直接插入MFC源码里面的这两个结构是有问题的,需要修改成如下格式(注意插入顺序):
struct AFX_MSGMAP_ENTRY
{
UINT nMessage;
UINT nCode;
UINT nID;
UINT nLastID;
UINT_PTR nSig;
void (*pfn)(void);
};
struct AFX_MSGMAP
{
const AFX_MSGMAP *(__stdcall *pfnGetBaseMap)();
const AFX_MSGMAP_ENTRY *lpEntries;
};
插入完成后同步到idb中
然后我们回到刚才找到的结构体,将鼠标移到off_5B4A78处,按下ALT+Q,然后选择我们添加的第二个结构体AFX_MSGMAP
效果如下:
同理转换unk_5B4A80为第一个结构体,效果如下:
但是我们stru_584A80其实是一个结构体数组,所以我们还要将其转成数组,在结构体上右键选择Array
额,这个时候看脸了,有些时候IDA能正确识别数组大小,但是有些时候不行,需要我们自己计算,不过这个数组的结尾有个特征,就是全部都是0,只要依次将后面的结构全都转换成AFX_MSGMAP_ENTRY,当出现全0的AFX_MSGMAP_ENTRY结构说明数组到末尾了,这次演示的时候脸不好,所以自己转换了下,效果如下,然后我们再转数组(当然这个时候不转也没关系了)
然后重命名下,效果更佳
这边我们已经找到了父类的消息映射表,那么我们怎么找到我们自定义的对话框类的消息映射表呢?这又要用到交叉引用了,在我们的MsgMap右边的数据交叉引用上右键,选择跳转到交叉引用,如下图所示:
弹出的对话框中所有.rdata部分都是子类的消息映射表结构,依次双击跟进,然后按照上面的方法转换成对应数据结构后显示如下
然后在这些子类的消息条目数组中寻找消息号为0x111并且控件ID为1000即0x3E8的消息条目,很快就能定位到如下位置(资源ID使用Resource Hacker查看):
双击跟踪sub_401019函数试试,是不是发觉这就是我们要找的代码?
为了避免篇幅过长,另外两种方法我将放在下一篇介绍~