-
-
[原创]第二题 数据结构 的分析
-
发表于:
2018-6-20 02:41
3793
-
本题目是一个字典树的数据结构,关键是对字典树的理解,程序在一开始就初始化了静态的字典树结构。在程序里面,已经能看到字典树结构,当然,最开始并不知道是字典树...
先拖到IDA里面,进入到main,略去无关紧要的代码,直接到 sub_12F1C40
在sub_12F1C40里面,可以明显地看到程序将输入的22个字符截成了8段,长度依次是2, 2, 3, 2, 4, 3, 3, 3,截取出的字符串通过 sub_12F3AB0 函数做过第一步变换,再将变换的结果通过sub_12F2B40函数做第二次变换。跳转到sub_12F3AB0函数,查看代码后可定义出第一个结构体:
// 保存字符串的结构
struct _st_dataobj
{
char szBufs[0x80];
unsigned int buflen;
};
// 保存字符串的结构
struct _st_dataobj
{
char szBufs[0x80];
unsigned int buflen;
};
然后进入 sub_12F2B40 函数,该函数的实现较复杂,也没有打算完全去理解它,只需要知道它把保存字符串的结构体存到了一个数据结构中就可以了。经过8次调用,数据结构已经生成成功,然后调用到sub_12F30E0函数,该函数返回成功调用到sub_12F1B80,失败就直接打印出错误信息。可基本确定这至少是主要的对比函数之一
sub_12F1B80函数就两个输入,一个是根据输入生成的结构,一个是全局的dword_12F7E48,查找该变量的交叉引用,发现到一个关键的虚函数表
程序告诉了我们这是一个字典树,估且当做字典树来分析一下。既然dword_12F7E48是对比的关键之一,首先查看一下该变量的初始化。直接交叉引用,找到关键的初始化代码 sub_12F1900, 在这个函数里面发现对sub_E43AB0和sub_E43620的几次调用,生成了几个标识明显的数据结构,把sub_E43AB0的第一个参数转换成前面定义好的
struct _st_dataobj, 同时通过sub_E43620函数的第一个参数,可以猜测出字典树节点的结构体长度为272字节,其中,第4字节开始为一个_st_dataobj的结构体。根据字典树的定义,每一个节点包括有字符串(根节点为空)、子节点数组、个数等,再结合sub_E43940,sub_E43650,以及节点结构的长度,定义出节点结构体:
// 字典树节点定义
struct _st_trie_tree_node
{
void *pvftables;
_st_dataobj pdataobj;
struct _st_trie_tree_node * arChilds[32];
unsigned int counts; // 描述子节点的个数
unsigned int repeats;
};
// 字典树节点定义
struct _st_trie_tree_node
{
void *pvftables;
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)