Summary
When reversing C++ binaries, recognizing STL types like std::string
, std::vector
, and std::shared_ptr
can make your analysis significantly more readable. However, IDA Pro does not natively understand STL layouts due to their complexity and compiler-specific ABI implementations.
This section walks through how to import STL structure definitions into IDA and use them to label memory regions, class members, or function arguments.
A Ready-to-Import STL Struct Header
I created a multi-compiler STL header file that includes simplified type definitions for:
- MSVC (Visual Studio)
- libstdc++ (used by GCC)
- libc++ (used by Clang/LLVM)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#ifndef STL_STRUCTS_H
#define STL_STRUCTS_H
// Choose your compiler ABI
// #define COMPILER_MSVC
// #define COMPILER_LIBSTDCXX
// #define COMPILER_LIBCXX
// =====================
// MSVC STL Layouts
// =====================
#ifdef COMPILER_MSVC
struct std_string {
void* _ptr;
int _length;
int _capacity;
char _buffer[1];
};
struct std_vector_int {
int* _start;
int* _end;
int* _capacity_end;
};
struct std_shared_ptr_int {
int* _ptr;
void* _ref_count;
};
struct std_unique_ptr_int {
int* _ptr;
};
struct std_optional_int {
char _has_value;
int _value;
};
// Simplified red-black tree node (std::map/set internal)
struct std_rb_node {
struct std_rb_node* _parent;
struct std_rb_node* _left;
struct std_rb_node* _right;
bool _is_red;
char _padding[7]; // alignment
};
struct std_map_int_int {
struct std_rb_node* _root;
size_t _size;
};
#endif // COMPILER_MSVC
// =====================
// libstdc++ Layouts (GCC / Itanium ABI)
// =====================
#ifdef COMPILER_LIBSTDCXX
struct std_string {
char* _data;
size_t _length;
size_t _capacity;
};
struct std_vector_int {
int* _start;
int* _finish;
int* _end_of_storage;
};
struct std_shared_ptr_int {
int* _ptr;
void* _ctrl; // control block with ref count
};
struct std_unique_ptr_int {
int* _ptr;
};
struct std_optional_int {
char _has_value;
char _storage[sizeof(int)];
};
// Simplified tree layout for std::map/set
struct std_map_node_base {
struct std_map_node_base* _parent;
struct std_map_node_base* _left;
struct std_map_node_base* _right;
bool _color; // true = red, false = black
};
struct std_map_int_int {
struct std_map_node_base* _root;
size_t _size;
};
#endif // COMPILER_LIBSTDCXX
// =====================
// libc++ Layouts (Clang)
// =====================
#ifdef COMPILER_LIBCXX
struct std_string {
char* _data;
size_t _size;
union {
size_t _cap;
char _small[16];
};
};
struct std_vector_int {
int* _begin;
int* _end;
struct {
int* _begin;
size_t _cap;
} _storage;
};
struct std_shared_ptr_int {
int* _ptr;
void* _ctrl_block;
};
struct std_unique_ptr_int {
int* _ptr;
};
struct std_optional_int {
char _engaged;
char _value[sizeof(int)];
};
// libc++ uses red-black tree for std::map/set
struct std_map_node {
struct std_map_node* _parent;
struct std_map_node* _left;
struct std_map_node* _right;
bool _red;
};
struct std_map_int_int {
struct std_map_node* _root;
size_t _size;
};
#endif // COMPILER_LIBCXX
#endif // STL_STRUCTS_H
What’s Inside the header?
Each compiler layout includes common STL types:
Type | MSVC | libstdc++ (GCC) | libc++ (Clang) |
---|---|---|---|
std::string | _ptr, len, cap | data, len, cap | SSO/heap union |
std::vector | start/cap-end | start/finish/end | begin/end/cap |
std::shared_ptr | ptr/ref-count | ptr/control blk | ptr/ctrl blk |
std::unique_ptr | _ptr | _ptr | _ptr |
std::optional | _has_value, _value | _has_value, _storage[] | _engaged, _value[] |
std::map<int, int> | _root (rb_node*), _size | _root (map_node_base*), _size | _root (map_node*), _size |
How to Use It in IDA
Choose the Right Compiler
Before using the header, identify which compiler was used to build the binary:
- MSVC: Look for ??-prefixed symbols or msvcrt.dll imports.
- GCC: Look for Itanium name mangling (_Z), glibc calls.
- Clang: Similar to GCC but may use libc++ layouts.
Define the Compiler Macro
At the top of the file, uncomment the matching line:
1
2
3
// #define COMPILER_MSVC
// #define COMPILER_LIBSTDCXX
// #define COMPILER_LIBCXX
Example for GCC:
1
#define COMPILER_LIBSTDCXX
Import the Header into IDA
- Go to:
File → Load
File → C Header File...
- Select the
stl_structs_multi_compiler.h
file - IDA will parse the matching struct definitions
Apply Structs in Disassembly or Decompiler Views
Highlight a variable or memory region and press T to assign a struct type (e.g., std_string
, std_vector_int
, std_shared_ptr_int
).