C++逆向学习(一) string
字数 1148 2025-08-05 11:39:26

C++逆向学习:string类的内存布局与扩容机制分析

1. string类的基本内存布局

在Visual Studio环境下,定义一个string类并存储字符串"abcd"时,其内存布局如下:

  • size:当前字符串长度(4字节)
  • capacity:最大容量(通常比size大)
  • allocator:空间配置器
  • 字符数据:以\x00结尾的连续内存

示例内存视图:

[allocator][size][capacity][...][a][b][c][d][\x00]

2. string的扩容机制

通过实验观察string的capacity增长规律:

string str;
for(int i=0; i<100; i++) {
    str += 'a';
    cout << "size: " << str.size() << " capacity: " << str.capacity() << endl;
}

观察到的capacity变化序列:

15 → 31 → 47 → 70 → 105

扩容特点:

  1. 初始容量为15(二进制1111)
  2. 第一次扩容到31(二进制11111)
  3. 后续扩容按约1.5倍增长

3. 逆向工程视角下的string操作

3.1 基本操作分析

测试程序1

string input;
cin >> input;
for(int i=0; i<3; i++) input += 'a';
for(int i=0; i<3; i++) input.append("12345abcde");
cout << input;

IDA逆向观察:

  1. size > capacity时调用Reallocate_xxx函数
  2. 直接追加字符时:*(_WORD*)&str_addr[_size] = 97(同时写入\x00
  3. 追加长字符串时使用memmove_0函数
  4. 末尾总是添加\x00v9[10] = 0

3.2 字符串连接操作

测试程序2

string input1, input2, result;
cin >> input1 >> input2;
result = input1 + input2;
cout << result;

g++编译后的逻辑:

  1. 调用operator+进行连接
  2. 使用operator=赋值
  3. 输出结果

3.3 基于范围的for循环

测试程序3

string input1, input2;
cin >> input1 >> input2;
for(auto c : input2) input1 += c;
cout << input1;

逆向分析要点:

  1. 使用迭代器beginend
  2. 通过operator!=判断循环结束
  3. 使用operator+=追加字符
  4. 使用operator++移动迭代器

4. 逆向分析技巧总结

  1. 动态调试:使用Visual Studio等工具观察内存变化(红色表示刚改变的值)
  2. 静态分析
    • 识别扩容判断逻辑(size vs capacity)
    • 注意内存操作函数(memmove等)
    • 观察字符串终止符的处理
  3. 命名规范:在IDA中重命名变量提高可读性
  4. 编译器差异
    • g++生成的代码通常更简洁
    • Visual Studio生成的代码可能包含更多内部细节

5. 关键点备忘

  1. string内部总是以\x00结尾
  2. capacity的增长策略:
    • 初始15
    • 后续约1.5倍增长
  3. 小字符追加可能使用WORD写入(同时设置\x00
  4. 大字符串追加使用memmove类函数
  5. 基于范围的for循环转换为迭代器操作

6. 进一步研究方向

  1. 不同编译器(g++ vs MSVC)的实现差异
  2. 空间配置器(allocator)的详细工作机制
  3. reallocation函数的具体实现
  4. 异常处理机制在string操作中的表现

通过深入理解string类的内部实现,可以更有效地分析C++逆向工程中的字符串相关操作,提高漏洞分析和CTF解题的效率。

C++逆向学习:string类的内存布局与扩容机制分析 1. string类的基本内存布局 在Visual Studio环境下,定义一个string类并存储字符串"abcd"时,其内存布局如下: size :当前字符串长度(4字节) capacity :最大容量(通常比size大) allocator :空间配置器 字符数据 :以 \x00 结尾的连续内存 示例内存视图: 2. string的扩容机制 通过实验观察string的capacity增长规律: 观察到的capacity变化序列: 扩容特点: 初始容量为15(二进制1111) 第一次扩容到31(二进制11111) 后续扩容按约1.5倍增长 3. 逆向工程视角下的string操作 3.1 基本操作分析 测试程序1 : IDA逆向观察: 当 size > capacity 时调用 Reallocate_xxx 函数 直接追加字符时: *(_WORD*)&str_addr[_size] = 97 (同时写入 \x00 ) 追加长字符串时使用 memmove_0 函数 末尾总是添加 \x00 : v9[10] = 0 3.2 字符串连接操作 测试程序2 : g++编译后的逻辑: 调用 operator+ 进行连接 使用 operator= 赋值 输出结果 3.3 基于范围的for循环 测试程序3 : 逆向分析要点: 使用迭代器 begin 和 end 通过 operator!= 判断循环结束 使用 operator+= 追加字符 使用 operator++ 移动迭代器 4. 逆向分析技巧总结 动态调试 :使用Visual Studio等工具观察内存变化(红色表示刚改变的值) 静态分析 : 识别扩容判断逻辑(size vs capacity) 注意内存操作函数(memmove等) 观察字符串终止符的处理 命名规范 :在IDA中重命名变量提高可读性 编译器差异 : g++生成的代码通常更简洁 Visual Studio生成的代码可能包含更多内部细节 5. 关键点备忘 string内部总是以 \x00 结尾 capacity的增长策略: 初始15 后续约1.5倍增长 小字符追加可能使用WORD写入(同时设置 \x00 ) 大字符串追加使用memmove类函数 基于范围的for循环转换为迭代器操作 6. 进一步研究方向 不同编译器(g++ vs MSVC)的实现差异 空间配置器(allocator)的详细工作机制 reallocation函数的具体实现 异常处理机制在string操作中的表现 通过深入理解string类的内部实现,可以更有效地分析C++逆向工程中的字符串相关操作,提高漏洞分析和CTF解题的效率。