文章总结: 本文介绍了在IDA中处理可变大小结构的技巧。在反编译器中可直接使用C语法,但在反汇编视图中默认仅覆盖固定部分,需按星号键调整实例大小以完整覆盖可变数据。此外,可将结构字段标记为字符串字面量来优化显示,使数据以文本形式呈现,而非十六进制字节。 综合评分: 91 文章分类: 逆向分析,二进制安全,安全工具
IDA技巧(94)可变大小结构
二进制磨剑
2025年1月2日 16:20 四川
可变大小结构是一种用于处理可变大小二进制结构的构造,具有编译时类型检查的优势。
在源代码中
通常,这种结构使用类似以下的布局:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(linestruct varsize_t{ // 开头的一些固定字段 int id; size_t datalen; //[更多字段] unsigned char data[]; // 可变部分};
换句话说,开头是固定布局部分,末尾是未指定大小的数组。
一些编译器不喜欢[]语法,因此也可以使用[0]或甚至[1]。在运行时,结构的空间是使用完整大小分配的,数组可以像具有预期大小一样访问。例如:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(linestruct varsize_t* allocvar(int id, void *data, size_t datalen);{ size_t fullsize = sizeof(varsize_t) + datalen + 1; struct varsize_t *var = (struct varsize_t*) malloc(fullsize); var->id = id; var->datalen = datalen; memcpy(var->data, data, datalen); var->data[datalen] = 0; return var;}
IDA能处理这样的结构吗?可以,但你需要注意一些特殊情况。
在反编译器中
在反编译器中一切都很简单:只需使用C语法将结构添加到本地类型中,并将其用于局部变量和函数参数的类型。反编译器会自动检测对可变部分的访问并相应地表示它们。
在反汇编中
然而,反汇编视图更棘手。你可以从本地类型导入结构到IDB结构,或者通过在末尾显式添加0元素的数组手动创建一个:
ounter(lineounter(lineounter(lineounter(lineounter(line00000000 varsize_t struc ; (sizeof=0x8, align=0x4, copyof_1, variable size)00000000 id dd ?00000004 datalen dd ?00000008 data db 0 dup(?)00000008 varsize_t ends
但当你在数据区有这样的结构实例时,使用这个定义只覆盖固定部分。要扩展结构,使用*(创建/调整数组大小操作)并指定结构的完整大小。
示例
最近的微软编译器向PE可执行文件中添加了所谓的“COFF组”信息。IDA目前尚未完全解析,但在反汇编列表中用注释IMAGE_DEBUG_TYPE_POGO标记:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line.rdata:004199E4 ; 调试信息 (IMAGE_DEBUG_TYPE_POGO).rdata:004199E4 dword_4199E4 dd 0 ; 数据引用: .rdata:004196BC↑o.rdata:004199E8 dd 1000h, 25Fh, 7865742Eh, 74h, 1260h, 0BCh, 7865742Eh, 69642474h, 0.rdata:00419A0C dd 1320h, 11BE2h, 7865742Eh, 6E6D2474h, 0.rdata:00419A20 dd 12F10h, 12Ch, 7865742Eh, 782474h, 13040h, 164h, 7865742Eh, 64792474h.rdata:00419A20 dd 0.rdata:00419A44 dd 14000h, 11Ch, 6164692Eh, 35246174h, 0.rdata:00419A58 dd 1411Ch, 4, 6330302Eh, 6766h, 14120h, 4, 5452432Eh, 41435824h, 0.rdata:00419A7C dd 14124h, 4, 5452432Eh, 41435824h, 41h, 14128h, 1Ch, 5452432Eh, 55435824h
在展开数组或查看十六进制视图时,很明显它存储了可执行文件的原始节名称信息,在链接器合并它们之前。因此,格式化此信息可能很有用。它似乎由以下结构列表组成:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(linestruct section_info{ int start; // RVA int size; char name[]; // 以零结尾};
如果需要,将字符串用零填充以对齐每个结构在4字节边界上。
创建本地类型并将结构导入IDB后,我们可以取消定义IDA创建的数组,并开始在区域中使用编辑 > 结构变量…(Alt–Q)创建结构实例。然而,默认情况下只覆盖固定部分:
要扩展结构,按*并输入完整大小。例如,第一个应该是14(8用于固定部分,6用于“.text”和终止零),尽管你也可以使用建议的16:
现在结构具有正确的大小并覆盖字符串,但它以十六进制字节而不是文本形式打印。为什么以及如何修复?
当IDA将C类型转换为汇编级别(IDB)结构时,它仅依赖于C类型的大小,因为在汇编级别上字节和字符之间没有区别。因此,字符数组与字节数组相同。然而,你仍然可以应用额外的表示标志来影响结构的格式化。例如,你可以转到结构列表中的导入定义,并将name字段标记为字符串字面量,无论是从上下文菜单还是按A:
字段现在相应地被注释,数据实例显示为文本:
事实上,一旦你将字段标记为字符串,新声明的实例将由IDA使用零终止符自动调整大小。
学习资源
立即关注【二进制磨剑】公众号
👉👉👉【IDA 技巧合集】👈👈👈
👉👉👉【Github 安全项目合集】👈👈👈
学习零基础学习 IDA 逆向
【课程完结!内容揭秘!】7 天打造 IDA 9.0 大师:从零基础到逆向精英
🔥🔥🔥 第二期 Android 内核逆向🔥🔥🔥🔥
【课程完结!内容揭秘】第 2 期-Android 逆向内核攻防
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:二进制磨剑 《IDA技巧(94)可变大小结构》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论