c++编译后会给函数签名加上很多特有的修饰,比如bool ReqGetGuildUserList(long)将会被编译成:

1
?ReqGetGuildUserList@@YA_NJ@Z

Dependency Walker这个工具可以看的很清楚的。

     Dependency Walker工具一般是用来查看dll或者exe的依赖项的,这样就可以在软件发布的时候避免漏掉某些dll,当然对于动态加载的dll是没有办法的。但其中的Undecorate C++ Functions功能也甚是好用。

编译后的dll导出签名格式

功能强大的Undecorate C++ Functions

Undecorate后的C++签名,这样就看的很清楚了

    如果要在代码中做这样的转换也是可以的。Windows提供了一个UnDecorateSymbolName函数,用来Undecorates the specified decorated C++ symbol name。

第一个参数为输出地址,第二个参数为未修饰的名字,第三个参数为长度,第四个参数为0表示完全修饰。

作为例子,一个未修饰的函数名:

1
private: char * __thiscall R0Pxx::My_Aut0_PWN(unsigned char *)

修饰规则如下:

c++函数名的修饰更为复杂,提供的信息也更为丰富。
无论 __cdecl,__fastcall还是__stdcall调用方式,函数修饰都是以一个“?”开始,后面紧跟函数的名字。再后面是参数表的开始标识和依照参数类型代号拼出的参数表。

v2 = ?My_Aut0_PWN

对于C++的类成员函数(其调用方式是thiscall),函数的名字修饰与非成员的C++函数稍有不同,首先就是在函数名字和参数表之间插入以“@”字 符引导的类名。

v2 = ?My_Aut0_PWN@R0Pxx

其次是参数表的开始标识不同,公有(public)成员函数的标识是“@@QAE”,保护(protected)成员函数的标识是 “@@IAE”,私有(private)成员函数的标识是“@@AAE”,假设函数声明使用了constkeyword,则对应的标识应分别为“@@QBE”,“@@IBE”和“@@ABE”。

因为函数为private,私有成员
所以v2 =?My_Aut0_PWN@R0Pxx@@AAE
后面就是添加参数了,先加入函数返回值参数,函数的返回值类型为char *

参数表的拼写代号如下:
X–void
D–char
E–unsigned char
F–short
H–int
I–unsigned int
J–long
K–unsigned long(DWORD)
M–float
N–double
_N–bool
U–struct

指针的方式有些特别。用PA表示指针,用PB表示const类型的指针。

char *也就是PAD
所以v2 = ?My_Aut0_PWN@R0Pxx@@AAEPAD
然后是参数的类型unsigned char *,也就是PAE
所以v2 = ?My_Aut0_PWN@R0Pxx@@AAEPADPAE

参数表后以“@Z”标识整个名字的结束。假设该函数无参数,则以“Z”标识结束。

所以最终修饰为了:

1
?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z

re学习笔记(24)BUUCTF-re-[2019红帽杯]childRE

C++修饰名的转换

2022-04-03
Contents

⬆︎TOP