C++ name demangling

发布于 2019-05-20  57 次阅读


D:\android-ndk-r19c-windows-x86_64\android-ndk-r19c\toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\bin\aarch64-linux-android-c++filt.exe有一个c++filt的程序。Linux中也有。
使用方法

c++filt TheManglingName

例如c++filt _ZNKSt9type_info4nameEv就能还原符号

RTTI

RTTI的实现依赖于编译时使用的STL,libc++,liggnustllibstlport的RTTI实现可能是不同的。
我们使用默认选项编译(此处使用的应该是llvm-libc++)

clang++ app9.cpp -o app9 -fPIE -pie -std=c++11 

然后我们使用nm查看与c++类型相关的__cxxabiv1命名空间,(也可以type_info

nm app9 | grep cxxabiv1

得到结果

U _ZTVN10__cxxabiv117__class_type_infoE@@CXXABI_1.3
U _ZTVN10__cxxabiv119__pointer_type_infoE@@CXXABI_1.3
U _ZTVN10__cxxabiv120__si_class_type_infoE@@CXXABI_1.3
U _ZTVN10__cxxabiv121__vmi_class_type_infoE@@CXXABI_1.3

我们使用c++filt还原四个导出符号

ubuntu# c++filt _ZTVN10__cxxabiv117__class_type_infoE
vtable for __cxxabiv1::__class_type_info
ubuntu# c++filt _ZTVN10__cxxabiv119__pointer_type_infoE
vtable for __cxxabiv1::__pointer_type_info
ubuntu# c++filt _ZTVN10__cxxabiv120__si_class_type_infoE
vtable for __cxxabiv1::__si_class_type_info
ubuntu# c++filt _ZTVN10__cxxabiv121__vmi_class_type_infoE
vtable for __cxxabiv1::__vmi_class_type_info

从名称上可以看出,这是四个类的vtable虚表信息。对于启用了RTTI的类来说,所有的基础类(没有父类的类)都继承于_class_type_info,所有的基础类指针都继承自__pointer_type_info,所有的单一继承类都继承自__si_class_type_info,所有的多继承类都继承自__vmi_class_type_info
正因为所有启用了RTTI的类都继承自它们,静态分析工具只要检索对它们的交叉引用,就可以定位所有的类。

一个类的typeinfo结构体,起始地址保存的是类的虚表的地址,第二个成员中存放的是当前类的类名的指针。如果当前类是单一继承的,在第三个成员存放的是父类的typeinfo指针;如果当前类是双重继承或多重继承,在接下来的成员中会分别存放一些用于标志成员和父类的typeinfo指针。

配合frida进行demangle

# Extract exports & demangle it

import frida
import cxxfilt


session = frida.attach("PwnAdventure3-Linux-Shipping")
script = session.create_script("""
    var exports = Module.enumerateExportsSync("libGameLogic.so");
    for (i = 0; i < exports.length; i++) {
        send(exports[i].name);
    }
        """);

def on_message(message, data):
    print message["payload"] + " - " + cxxfilt.demangle(message["payload"])

script.on('message', on_message)
script.load()