名称修饰(Name mangling,也称为名称装饰)是编译器用来实现语言所需的一些功能的技术。
例如,在 C++ 中,它用于区分具有相同名称但不同参数的函数(函数重载),以及支持命名空间、模板和其他用途。
修饰的名称通常会出现在最终的二进制文件中,并且根据编译器的不同,对于人类来说可能很难理解(一个简单的例子:“operator new” 可以修饰为 ??2@YAPAXI@Z
或 _Znwm
)。
虽然这些神秘的字符串可以通过编译器提供的实用程序(例如 undname (MSVC) 或 c++filt (GCC/Clang))进行解码,但如果反汇编程序为您完成此操作会更好(特别是如果您没有编译器)安装)。
这种解码回人类可读形式的过程称为“demangling”。
IDA 对以下编译器和语言的名称解析提供开箱即用的支持:
-
Microsoft (Visual C++) -
Borland (C++, Pascal, C++ Builder, Delphi) -
Watcom (C++) -
Visual Age (C++) -
DMD (D language) -
GNU mangling (GCC, Clang, some commercial compilers) -
Swift
您不需要手动选择编译器;IDA 会从名称格式中检测它并自动应用相应的解析器。
Demangled name 选项
默认情况下,IDA 使用注释来显示分解结果,这意味着每次使用分解名称时,IDA 都会打印一条包含分解结果的注释。
例如, ?FromHandle@CGdiObject@@SGPAV1@PAX@Z
还原为 CGdiObject::FromHandle(void *)
,它作为注释打印:
如果您愿意,可以显示还原结果来代替修饰名称,而不仅仅是注释。
这可以在 Options > Demangled names… 中完成。
短名称和长名称
“Setup short names” 和 “Setup long names” 按钮允许您在两种常见情况下修改内置名称还原器的行为。
“短”名称用在空间非常宝贵的上下文中:反汇编中的引用、函数列表等。
“长”名称在其他情况下使用,例如在函数开头打印注释时。
通过使用附加选项对话框,您可以选择显示、隐藏或缩短已还原名称的哪些部分,以使其更紧凑或更详细。
名称化简
一些看似简单的名称在编译后可能会变得非常复杂,尤其是涉及模板时。
例如,STL 中的一个简单的 std::string 实际上扩展为 std::basic_string<char,std::char_traits<char>,std::allocator<char>>
为了确保互操作性,编译器必须在名称修饰中保留这些详细信息,以便它们在重新还原时重新出现;
然而,对于那些更愿意再次看到简单的 std::string
的人类读者来说,这样的实现细节通常并不有趣。
这就是 IDA 将名称简化作为后处理步骤的原因。
IDA 使用文件 cfg/goodname.cfg 中的规则应用它们来转换名称,例如
std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > & __thiscall std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >::erase(unsigned int,unsigned int)
转换成
std::string & std::string::erase(unsigned int,unsigned int)
这更容易阅读和理解。
IDA 附带了大多数标准 STL 类的规则,但您也可以添加自定义规则。
请阅读 goodname.cfg 中的注释,了解如何执行此操作的说明。
原文始发于微信公众号(二进制磨剑):IDA 技巧(35) Demangled names
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论