为什么 cl.exe 更改了我的代码中使用的 extern 函数名称?

逆向工程 艾达 登录 纳姆
2021-07-04 15:49:31

所以基本上我是我的 nasm 语法 asm 代码,我使用了一些像这样的外部函数:

extern _printf
extern __imp__Sleep@4
....
call _printf
call    [__imp__Sleep@4]

然后我用nasm把它组装成obj:

nasm -f win32 test.asm

然后我用IDA Pro反汇编test.obj,可以看到这样的代码:

在此处输入图片说明

看,像_printf这样的外部函数名被保留了下来。

但是当我链接这个 obj 文件时:

cl /MT z:\\windows\\test.obj /link kernel32.lib libcmt.lib /SUBSYSTEM:CONSOLE

然后我用IDA Pro反汇编test.exe,可以看到这样的代码:

在此处输入图片说明

看,_printf的函数名已经改了。

静态链接后基本知道_printf的代码已经放到test.exe中,在sub_409C9B的子程序中

但基本上我必须使 extern 声明函数的名称不可更改,因为我需要对 test.exe 进行逆向工程并对这些函数进行一些修改/删除,一旦 PE exe 丢失了名称信息,我就无法找到那些目标函数.

所以我的问题是:

为什么 cl.exe 会更改这些函数的名称,有什么办法可以阻止更改(我的意思是在链接期间保持函数名称不可更改)?

2个回答

你有某种XY 问题

事实是:正是 IDA 可以这么说,将函数(她认为是)的名称从绝对无更改为sub_{address}. 为什么会PE-file在其中存储未导出的符号?某种受虐狂?给逆向者一颗糖果?

因此,您至少可以通过三种方式来处理您的问题:

  • 祈祷并希望 IDA 的FLIRT能够启发式地识别printf
  • link您的程序带有调试信息:-debug它告诉链接器生成pdb-file,IDA 将查询为您的应用程序存储的所有符号;
  • 告诉链接器,-export:printf以便它的名称将在导出目录中,您甚至可以通过编程轻松获取它的地址。

printf()作为外部函数调用时,Windows 加载程序需要printf()在运行时按名称查找函数的地址,以便调用者可以找到printf()代码。

printf()作为嵌入式库函数被调用时,编译器在编译时就已经知道printf()函数的地址,因此不需要在可执行文件中嵌入函数的名称。

如果您希望printf()名称在反汇编中自动显示,请导出调试符号或坚持使用外部 DLL。或者,您可以使用 IDA 的 FLIRT 库来识别printf()嵌入库代码中函数。