如何通过IDA Appcall获取函数返回的自定义类型对象数组
解决IDA中getHumans函数返回数组的遍历问题
已知条件
- 已定义本地结构体:
struct Human { char* name; int age; double height; };
- 目标函数原型:
const Human** __fastcall getHumans(const cusType2 *t, size_t *num);
- 调用后
num值为10,但无法获取完整的10个Human对象,尝试过Appcall.array()、直接调用、重新声明结构体数组均仅能拿到第一个对象,怀疑返回值可能为std::vector。
解决方法
情况1:返回值为const Human**(指针数组)
函数返回的是指针的指针,本质是数组首地址,每个元素是const Human*,需手动遍历内存获取后续元素:
- 调用函数拿到返回地址与元素数量:
size_t num = 0; uint64_t humans_base = (uint64_t)getHumans(t, &num); - 根据程序位数(32位/64位),按指针大小偏移遍历:
- 64位程序(指针占8字节):
for (size_t i = 0; i < num; i++) { uint64_t human_ptr = get_qword(humans_base + i * 8); Human* h = (Human*)human_ptr; // 访问h->name、h->age、h->height } - 32位程序(指针占4字节):
for (size_t i = 0; i < num; i++) { uint32_t human_ptr = get_dword(humans_base + i * 4); Human* h = (Human*)human_ptr; // 访问成员 }
- 64位程序(指针占8字节):
情况2:返回值为std::vector<const Human*>
手动解析std::vector的内存结构(标准实现中,64位是3个指针,32位是3个32位整数):
- 定义vector结构体:
// 64位版本 struct Vector { uint64_t begin; uint64_t end; uint64_t capacity; }; // 32位版本 struct Vector { uint32_t begin; uint32_t end; uint32_t capacity; }; - 解析并遍历:
size_t num = 0; Vector* vec = (Vector*)getHumans(t, &num); size_t count = num; // 直接用函数输出的num值即可 for (size_t i = 0; i < count; i++) { // 64位用get_qword,32位用get_dword uint64_t human_ptr = get_qword(vec->begin + i * 8); Human* h = (Human*)human_ptr; // 访问成员 }
关于Appcall.array()报错的替代方案
若想用数组声明方式,可尝试显式定义数组类型后强制转换:
typedef const Human* HumanPtrArray[10]; HumanPtrArray* arr = (HumanPtrArray*)getHumans(t, &num); // 遍历arr[0]到arr[9]
注意:此方法依赖编译时固定大小,不如手动遍历灵活。
验证要点
- 确保
cusType2结构体定义完全正确,否则函数调用可能因参数错误导致返回值异常。 - 检查程序位数,保证指针偏移的字节数(4/8)与程序匹配。
- 调试时可直接查看返回值地址的内存,确认后续元素是否为有效
Human*指针,排除函数返回无效数据的可能。
内容的提问来源于stack exchange,提问作者noone
相关产品推荐
相关产品推荐

