首页
社区
课程
招聘
[原创]FlatBuffers小记
发表于: 2023-8-16 00:01 10806

[原创]FlatBuffers小记

2023-8-16 00:01
10806

首先运行程序,直接挑明了它用的是flatbuffer:

静态分析,读取函数为sub_1100,读取之后由sub_18B0和sub_1970进行解析:

解析出来的对象(?)为v33,结构暂时未知,之后有很多函数从v33中解析数据:

猜测应该和protobuf差不多,先根据flatbuf的语法定义一个数据结构,并在某个语言中通过这个数据结构生成对象,再把对象进行序列化,输入到这个程序中进行反序列化得到原来的对象,然后再通过这些函数来取出原来的对象中的数据。所以只需要还原出来数据结构即可。

函数sub_1BE0明显就是取出了一个字符串,程序根据这个字符串进行相应的操作,可以将其重命名为get_operation。

在create操作中,首先sub_1C00从v33中取出了v32,暂时看不出来有什么作用。然后sub_1C30从v33中取出了size,用于后面的malloc操作,所以可以确定sub_1C30为get_size。

v5和v6是一个东西,都是sub_1C60函数从v33中取出来的,为了搞清楚他是个什么东西,需要先看一下函数sub_1C80和函数sub_1CA0,函数sub_1C80直接对v5进行了解引用,得到了一个__int64,并与v32进行比较;sub_1CA0就比较明显了,直接告诉了我们它是干什么用的:

现在搞清楚了,v5和v6是一个flatbuffers中的vector,v32是vector的索引。通过简单的分析得出flatbuffers中的vector前四个字节为长度,后面为数据。现在可以确定sub_1C60为Get_vec,sub_1C00为Get_vecidx,sub_1C80为vec_size,sub_1CA0为Get_value_from_vec。

接下来函数sub_1D10又从value_from_vec中取出了v30,由此可以推断出value_from_vec也是个对象。v30被用作了idx往heaplist里存储申请的堆块和堆块的size,所以sub_1D10为Get_idx。至此create中所有从对象中取值的操作分析完毕。点开每个Get函数会看到里面还套了一层函数,里面的那一层函数第二个参数都是数字,而且对同一个对象操作的不同函数,这个数字都不相同,Get_opeartion里为4、Get_vecidx里为6、get_size里为8、Get_vec里为10:

推测数字和每个成员在对象中的偏移有关。整合现有信息即可得出大概的数据结构:

接下来要先搞清楚flatbuffer中的vector代表什么,查阅文档可知,在flatbuffer中定义的数组结构,在c++中实现的时候会变成vector,并且string是由byte数组实现的(也就是flatbuffer中定义的string在c++中实现的时候也是vector):

并且根据文档可以找到flatbuffer中的数据类型,原来的数据结构可以写成:

之所以还有省略号是因为还没分析完(Edit操作中还有新的函数)

分析edit操作,edit中使用Get_value_from_vec从vec中取出对象后除了使用了Get_idx函数获得对象中的idx,又使用了sub_1D40函数获取了对象中的未知数据v26:

要想知道v26的身份就得先分析函数sub_1D60和sub_1D80,查看sub_1D60发现是对v26进行了解引用得到一个int,和vec_size一样的操作,所以v26不出意外也是个vector。sub_1D80函数返回了v26+4位置的指针,下面memcpy直接用这个指针的数据对堆块进行了编辑,前面我们分析得到flatbuffers中的vector前四个字节为长度,后面为数据,所以v26确实是vector而且是byte数组,那byte数组不就是string吗

所以可以得到完整的数据结构:

github搞一份源码编译得到flatc,新建文件heap.fbs写入上面得到的数据结构,使用如下命令生成头文件:

tips:应该先根据猜测的数据结构在C++中生成对象,然后将对象序列化再反序列化之后,根据题目的操作分别对对象中的成员进行取值,编译为二进制文件之后拉下来放到ida里验证那些取值操作和题目里的操作是不是一致。(原来写的代码被我删了,懒得演示了.jpg)

写test.cpp:

使用如下命令编译:

编写脚本用来中转序列化数据:

交互成功:

对于flatbuffer没找到像protobuf一样的现成的逆向工具,头铁硬猜

字符串 operation
整数 vecidx
整数 size
Vector vec
字符串 operation
整数 vecidx
整数 size
Vector vec
table Heapinfo{
  idx:ulong;
  ......
}
table Player {
  operation:string;
  vectoridx:ulong;
  create_size:ulong;
  vec:[Heapinfo];
}
table Heapinfo{
  idx:ulong;
  ......
}
table Player {
  operation:string;
  vectoridx:ulong;
  create_size:ulong;
  vec:[Heapinfo];
}
table Heapinfo{
  idx:ulong;
  heap:string;
}
table Player {
  operation:string;
  vectoridx:ulong;
  create_size:ulong;
  vec:[Heapinfo];
}
root_type Player;
table Heapinfo{
  idx:ulong;

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2023-8-16 00:15 被/x01编辑 ,原因: 添加附件
上传的附件:
收藏
免费 1
支持
分享
最新回复 (2)
雪    币: 2277
活跃值: (6653)
能力值: ( LV7,RANK:102 )
在线值:
发帖
回帖
粉丝
2
flatbuffer写逆向工具可能会比较难,貌似是因为不知道索引到的地址对应的是什么类型的数据
2023-8-16 07:59
0
雪    币: 3070
活跃值: (30876)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2023-8-16 09:13
0
游客
登录 | 注册 方可回帖
返回
//