在 Ollydbg 或 IDA 中识别 CLib 函数

逆向工程 艾达 ollydbg C
2021-07-09 00:17:48

我只是在学习 Olly/IDA 并用 C 编写简单的程序,并查看 Ollydbg 和 IDA 中的 .EXE 代码。下面我有一个简单的 printf Hello World 程序,我在 Visual Studio 6 中编译了它。我可以看到事件链以 kernel32.dll 调用开始,以获取 Windows 版本号、设置堆、获取命令行等. 我认出了 main() 函数并看到字符串变量被放在堆栈上,可以推断出 00401010 处的函数是 printf(),如果我查看该地址的“名称窗口”,IDA 会确认,但 Olly 没有明确告诉我。

#include <stdio.h>

void main(void)
{
printf("blah blah\n");

return;
}

在 Olly 中,这是我的 main() 函数的程序集:

CPU Disasm
Address   Hex dump          Command                                  Comments
00401000  /$  68 30604000   PUSH OFFSET 00406030  ; ASCII "blah blah"
00401005  |.  E8 06000000   CALL 00401010
0040100A  |.  59            POP ECX
0040100B  \.  C3            RETN

所以上面的那些汇编指令都是对应我写的C代码的。.EXE 的其余部分充满了许多其他代码,我希望它们能够识别应用程序并将其与 printf() 等 LIBC 函数区分开来。我知道编译器会生成依赖于操作系统的设置和拆卸内容(如 windows 版本号、堆等),但我认为在几个程序和学习 PE 程序标准之后我应该能够认识到这一点(加上 Olly 需要无论如何,您将其传递给应用程序代码)。

例如,这里是我认为是 LIBC printf() 函数的顶级函数,由 CALL 00401010 调用:

CPU Disasm
Address   Hex dump          Command                                  Comments
00401010  /$  53            PUSH EBX
00401011  |.  56            PUSH ESI
00401012  |.  BE 70604000   MOV ESI,OFFSET 00406070
00401017  |.  57            PUSH EDI
00401018  |.  56            PUSH ESI
00401019  |.  E8 4B010000   CALL 00401169
0040101E  |.  8BF8          MOV EDI,EAX
00401020  |.  8D4424 18     LEA EAX,[ARG.2]
00401024  |.  50            PUSH EAX
00401025  |.  FF7424 18     PUSH DWORD PTR SS:[ARG.1]
00401029  |.  56            PUSH ESI
0040102A  |.  E8 04020000   CALL 00401233
0040102F  |.  56            PUSH ESI
00401030  |.  57            PUSH EDI
00401031  |.  8BD8          MOV EBX,EAX
00401033  |.  E8 BE010000   CALL 004011F6
00401038  |.  83C4 18       ADD ESP,18
0040103B  |.  8BC3          MOV EAX,EBX
0040103D  |.  5F            POP EDI
0040103E  |.  5E            POP ESI
0040103F  |.  5B            POP EBX
00401040  \.  C3            RETN

如果我在 IDA 中打开我的 EXE 并查看“名称窗口”,我会看到此代码从 00401010 开始为“_printf”,如果我双击它,我会看到以下内容:

_printf 第一级的 IDA 视图

这只是顶层,如果我向下跟踪几个级别(遵循 CALL 指令到更深层次的函数),我会发现像 KERNEL32.WriteFile() 这样的操作系统函数实际上使字符串出现在 CMD 窗口中。

我的问题是:如何识别 printf() 等库函数并将它们与应用程序代码区分开来?如果它们能出现标记就好了。我知道 Olly 有脚本和插件,但到目前为止(在我的早期学习中)我还没有找到如何做到这一点。

目前我只知道把同一个EXE带入IDA,在“Names Window”中查看地址,看是不是CLIB函数的一级函数。但是,将这个函数调用的函数标记为标准 C 库的一部分,而不是用户代码的一部分需要一些工作。

在 IDA 中查找地址并不是什么大问题,但是仍然有大量代码属于较低级别的函数,如果我能快速知道它们是 CLIB 的一部分而不是应用程序代码,那就太好了。

我猜这类似于构建 Ollydbg .UDD 文件或下载插件或脚本。对不起,如果它在某些文档中很明显,但到目前为止我还没有找到它。

综上所述,我可以想象链接器可能会改变一些事情,以至于如果进行了一些优化,则每次内存中都可能不存在确切的模式。

2个回答

除非另有说明,否则说明适用于 ollydbg 1.10 和 ollydbg 2.01

选择感兴趣的模块,即 helloworld.exe 使用 alt + E 右键单击所选模块和 enter (在 cpu 中查看代码),然后让 ollydbg 使用 ctrl + A

然后使用ctrl+g转到

type [modname].main without the SQ brackets在编辑框/列表框中
ollydbg 2.01从下拉列表中选择并按照表达式
ollydbg 1.10点击确定

您将进入主函数
,ollydbg 将显示正确注释的主函数
在此处输入图片说明

还可以做进一步的微调

comments pane can be cycled通过comments and source
right click->appearance->show bar 如果您在 ollydbg 中使用调试信息构建了可执行
文件,
单击该栏可循环查看源代码、注释、配置文件,将显示有关反汇编的正确源代码行。

您还可以使用
ctrl+o
并选中与
Show Symbolic names 、 Show Module Names 等相对应的适当框来设置 disasm 的显示
(自行探索并决定适合您的内容)

要了解导致您的实际代码的 crt 函数,请安装某些版本的 Visual Studio 并查看 crt 文件夹中的实际源代码,并为 ollydbg 设置 src 文件夹目录结构以将它们拉出并在注释窗格中并排显示

我不确定你的意思 ollydbg 不识别像 ida 这样的函数,尽管 Ida 有天赋(以标准代码的签名形式预先整理信息)ollydbg 在注释函数方面做得不错

既然你说你编译了它,你是否启用了在编译时生成的调试信息(/Zi 开关,如果你编译它来自微软的可视化 c++ 编译器)如果你从其他编译器编译它,寻找类似的开关

如果你用visual studio编译它,那么你应该在文件夹(c:\progxxx\mic vis \xxx\crt)中有一个crt函数的副本

Visual Studio 2010 express 的这些 src 文件的原始位置是 f:\dd (如果您没有名为 f 的分区,请使用 mount ,如果您的驱动器路径 f 被其他设备(如 cdrom)占用,请使用 diskmgmt.msc 更改驱动器号放置一个可移动磁盘 使用 dismgmt.msc 将驱动器号更改为 F:对于该可移动磁盘并将源复制粘贴到该驱动器 ollydbg 将自动拉它

udl 功能不适用于导入库。
导入库不包含对象数据

头文件是文本文件,它们在进行二进制分析时同样没有用

lat 但并非最不重要的是,有几个插件可以将 ida 签名导入 ollydbg,例如 idasig / 或 godup 插件查看 tuts4you.com 您可能会在 ida 中找到数百个 ollydbg 插件生产 -> 映射文件并使用导入映射文件这些插件

你有设置选项-> 代码-。与显示本地、显示符号地址等有关的复选标记

ollydbg 的屏幕截图,显示了 printf 函数的源代码 在此处输入图片说明

与我想要的(在 Olly 中识别 LIBC/CRT)略有不同的是查看 IDA 中的图表。起初,显示的所有函数似乎令人生畏(请参见下面令人恐惧的图片,我的 main() 是标有“_main”的黑框)。注意我的程序是对 printf() 的一次调用。

在此处输入图片说明

然后在阅读 IDA 的教程链接后,我看到我可以使用在此处输入图片说明按钮“显示用户指定的外部参照图”并打开“忽略”下的“来自库函数”复选框,然后它绘制了一个更简单的树:

在此处输入图片说明

所以我现在可以看到如何轻松地将应用程序代码与 C 库和启动函数区分开来,至少在 IDA 中是这样。

对于 Ollydbg,Blabb 的回答显示了如何使用 PDB 文件进行操作,现在我想尝试在没有调试或 .PDB 文件的情况下进行操作。