type
status
date
slug
summary
tags
category
icon
password
STL 逆向方法论
- 识别 STL 容器类型
- 识别 STL 容器操作
- 提取STL 容器中的数据
逆向STL 主要的问题:
- 缺少符号,无法判断STL 容器类型 (主要困难)
- STL 内部数据结构复杂,难以提取数据
- 03 优化使大量 stl 函数被 inline
- 方法: 解析 STL 容器内存数据,从内存数据角度判断容器类型,提取容器内判断函数操作
常见 STL容器
- 序列容器
- vector
- Deque
- List
- String
- 关联容器
- Pair
- Map
- Set
- MultiMap / MultiSet
- 无序关联容器
- unordered_map
常见 STL 容器适配器
容器适配器是一个封装了序列容器的类模板,它在一般序列容器的基础上提供了一些不同的功能。之所以称作适配器类,是因为它可以通过适配容器现有的接口来提供不同的功能。
- stack :deque
- queue :deque
- priority_queue :vector
逆向时处理容器适配器只需要用底层容器来处理即可。
std::string
- 固定长度 32 字节,4 个 dq
- 第一个指针字段指向数据地址
- 第二个 size_t 字段存储字符串长度
std::string内存布局
IDA dump脚本
std::stringsteam
- 字符串流(理解成文件流,有读写指针)
- 输入流 / 输出流
std::stringsteam 内存布局
解决办法
构建一个结构体
std::vector
- 固定长度 24 字节,3 个 dq
- 第一个指针字段指向数组起始地址
- 第二个指针字段指向数组最后元素地址
- 第三个指针字段指向最大内存地址
std::vector内存布局
IDA dump脚本
std::list
- 双向循环链表存储
- 头结构 + 节点结构
- 遍历长度可以用 size 字段确定
std::list内存布局
IDA dump脚本
std::deque
- 头结构 + 迭代器结构
- 适用 std::deque / std::stack
- stl_deque.start.node 确定first map 项位置
- stl_deque.start.last - stl_deque.start.first 确定缓冲区大小
- stl_deque.finish.node 确定last map 项位置
- 对于每一个 map 项:
- start 项,解析 cur, last 区间
- finish 项,解析 start, cur 区间
- 其余项,解析 start, last 区间
std::deque内存布局
IDA dump脚本
std::map
- 底层采用 Rb-Tree 实现(红黑二叉树)
- 头结构 + 节点结构
- 用二叉树遍历可提取数据
- 适用 std::map / std::set / std::multimap / std::multiset
std::map内存布局
IDA dump脚本
std::unsorted_map
- 底层采用 HashTable 实现
- 头结构 + Bucket 数组 + 节点结构
- 所有节点结构用单链表串联(*dump** 只需要遍历单链表)
- 头结构的第三个字段为单链表头
- 适用 std::*unsorted_map** / std::*unsorted_set** / …
std::unsorted_map内存布局
IDA dump脚本
std::shared_ptr
- 第一个指针就是数据指针
std::shared_ptr内存布局
- Author:5m10v3
- URL:https://5m10v3.top/article/96be792d-4850-4f7a-a458-22671cbde98d
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts