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内存布局

notion image

IDA dump脚本

std::stringsteam

  • 字符串流(理解成文件流,有读写指针)
  • 输入流 / 输出流

std::stringsteam 内存布局

notion image

解决办法

构建一个结构体
notion image

std::vector

  • 固定长度 24 字节,3 个 dq
  • 第一个指针字段指向数组起始地址
  • 第二个指针字段指向数组最后元素地址
  • 第三个指针字段指向最大内存地址

std::vector内存布局

notion image

IDA dump脚本

std::list

  • 双向循环链表存储
  • 头结构 + 节点结构
  • 遍历长度可以用 size 字段确定
    • notion image

std::list内存布局

notion image

IDA dump脚本

std::deque

  • 头结构 + 迭代器结构
  • 适用 std::deque / std::stack
    • notion image
  • 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内存布局

notion image

IDA dump脚本

std::map

  • 底层采用 Rb-Tree 实现(红黑二叉树)
  • 头结构 + 节点结构
  • 用二叉树遍历可提取数据
  • 适用 std::map / std::set / std::multimap / std::multiset

std::map内存布局

notion image

IDA dump脚本

std::unsorted_map

  • 底层采用 HashTable 实现
  • 头结构 + Bucket 数组 + 节点结构
  • 所有节点结构用单链表串联(*dump** 只需要遍历单链表)
  • 头结构的第三个字段为单链表头
  • 适用 std::*unsorted_map** / std::*unsorted_set** / …
notion image

std::unsorted_map内存布局

notion image
IDA dump脚本

std::shared_ptr

  • 第一个指针就是数据指针

std::shared_ptr内存布局

notion image
 
2024长城杯-ez_driver复现与思考IDA学习之类型修复
Loading...