Windows 测试构建
Linux 测试构建
Drltrace 是适用于 Windows 和 Linux 应用程序的动态 API 调用跟踪器。 Drltrace 构建在 DynamoRIO 动态二进制仪器框架之上。 Drltrace 最初由 Derek Bruening 实现,并与 DynamoRIO 和 DrMemory 框架一起分发。该存储库包含 drltrace 的独立版本,以及有关如何使用它进行恶意软件分析的附加脚本和材料。发布版本可以在此处下载。
drltrace的使用非常简单。用户需要通过以下方式指定日志目录和目标进程的名称:
drltrace -logdir . -- calc.exe
就这样,该工具将在目标进程中注入所需的 DLL,启动检测,并并行记录有关在目标进程中执行的所有库调用的信息:
~~43600~~ msvcrt.dll!__wgetmainargs
arg 0: 0x010d2364
arg 1: 0x010d2368
and return to module id:0, offset:0x193a
~~43600~~ ntdll.dll!EtwEventRegister
arg 0: 0x002ff994
arg 1: 0x010d1490
and return to module id:0, offset:0x157e
~~43600~~ ntdll.dll!EtwEventSetInformation
arg 0: 0x007b4b40
arg 1: 0x00000033
and return to module id:0, offset:0x15a1
~~43600~~ SHELL32.dll!ShellExecuteW
arg 0: <null> (type=<unknown>, size=0x0)
arg 1: <null> (type=wchar_t*, size=0x0)
arg 2: calculator:// (type=wchar_t*, size=0x0)
arg 3: <null> (type=wchar_t*, size=0x0)
arg 4: <null> (type=wchar_t*, size=0x0)
arg 5: 0x1 (type=int, size=0x4)
and return to module id:0, offset:0x167d
输出的格式很简单,可以通过外部脚本轻松解析:
~~[thread id]~~ [dll name]![api call name]
arg [arg #]: [value] (type=[Windows type name], size=[size of arg])
and return to module id:[module unique id], offset:[offset in memory]
当使用-grepable
参数时,可以使用grep
进行解析;这将函数名称和参数全部打印在一行上:
~~4824~~ KERNELBASE.dll!CreateFileW {0: C:WindowsFontsstaticcache.dat (type=wchar_t*, size=0x0)} {1: 0x80000000 (type=DWORD, size=0x4)} {2: 0x3 (type=DWORD, size=0x4)} {3: 0x005cde8c (type=<unknown>*, size=0x0)} {4: 0x3 (type=DWORD, size=0x4)} {5: 0x80 (type=DWORD, size=0x4)}
模块唯一标识符表打印在日志文件的末尾:
Module Table: version 3, count 70
Columns: id, containing_id, start, end, entry, checksum, timestamp, path
0, 0, 0x010d0000, 0x010da000, 0x010d1b80, 0x0000f752, 0xb5fe3575, C:WindowsSysWOW64calc.exe
1, 1, 0x6d4c0000, 0x6d621000, 0x6d563940, 0x00136d65, 0x59ce1b0b, C:UsersMaxDownloadsdrltracedrltracedynamoriolib32releasedynamorio.dll
2, 2, 0x73800000, 0x73975000, 0x7380dbf7, 0x00000000, 0x59ce1b0f, C:UsersMaxDownloadsdrltracedrltracebinrelease/drltracelib.dll
3, 3, 0x742f0000, 0x742fa000, 0x742f2a00, 0x0000c877, 0x0adc52c1, C:WindowsSystem32CRYPTBASE.dll
4, 4, 0x74300000, 0x74320000, 0x7430c9b0, 0x0002c617, 0x245970b4, C:WindowsSystem32SspiCli.dll
5, 5, 0x74410000, 0x74431000, 0x74416900, 0x0002a940, 0x88a53c1d, C:WindowsSystem32GDI32.dll
6, 6, 0x74440000, 0x74500000, 0x7446fb20, 0x000cc410, 0xd343d532, C:WindowsSystem32RPCRT4.dll
7, 7, 0x74500000, 0x74525000, 0x745047d0, 0x00026737, 0xa39c8991, C:WindowsSystem32IMM32.DLL
8, 8, 0x74550000, 0x745c7000, 0x7456e8a0, 0x00081857, 0x73b971e1, C:WindowsSystem32advapi32.dll
9, 9, 0x748f0000, 0x74929000, 0x748febd0, 0x00045303, 0xa58be652, C:WindowsSystem32cfgmgr32.dll
10, 10, 0x74930000, 0x75c78000, 0x74aa09d0, 0x01377aa6, 0x4b39926b, C:WindowsSystem32SHELL32.dll
Drltrace 可以通过指定-only_from_app
选项轻松过滤掉库间调用,并仅打印从目标应用程序的主模块(或堆)执行的 API 调用,这在生成大量日志的应用程序中非常有用。为了进行更精细的控制, -filter
选项允许用户指定过滤器配置文件,以便过滤特定的白名单函数,或忽略黑名单函数(有关示例,请参阅filter.config文件)。 Drltrace 还有几个有用的外部脚本来过滤某些库的 API 调用,仅打印可能感兴趣的 API 调用和字符串。
Drltrace主要模块在BSD下分发。
drltrace 所需的一些文件在 LGPL 下分发。有关更多详细信息,请参阅源文件。
恶意软件分析并不是一件容易的事。像 Themida 和 Armadillo 这样的复杂软件加壳器,当然还有恶意软件作者编写的数十个未命名的加壳器,加上代码和数据加密,极大地促进了(在某些情况下完全不可能)此类样本的静态逆向工程,使恶意软件分析师的工作变得复杂。在这种情况下,API 调用跟踪可以显着减少了解实际恶意意图所需的时间,并揭示有关受保护恶意代码的大量技术细节。
虽然传统的 API 挂钩技术已在多个解决方案中成功实施,但恶意软件作者对该方法进行了深入研究,并且可以轻松检测和/或绕过。此外,这些工具作为独立的重量级 GUI 应用程序(作为专有产品)分发,通常不容易集成到现有的恶意软件分析工作流程中。
如果我们看看 Linux 世界,有一个很棒的工具,叫做 ltrace。使用单个 bash 命令,我们可以轻松获取某个可执行文件的 API 调用的完整跟踪。
为什么我们没有这样的适用于 Windows 的工具(如 Linux 中的 ltrace),该工具对于现代恶意软件使用的反研究技巧也是透明的?
事实证明,有一种技术可以帮助我们为 Windows 提供这样的工具,并透明地跟踪执行程序的 API 调用。这种技术称为动态二进制检测,又名 DBI。 DBI 是一种通过注入检测代码来分析二进制应用程序在运行时的行为的技术。
然而,DBI 在恶意软件分析中的应用受到解包自动化和指令、基本块和函数调用跟踪的一些概念证明的不应有的限制。据我们所知,drltrace是第一个基于DBI的API调用追踪工具,可用于实际恶意软件分析。我们在 wiki 中提供了几个恶意软件分析示例,其中描述了 drltrace 如何在几分钟内获得有关复杂恶意样本的大量内部技术细节,甚至无需启动 IDA 或调试器。
-logdir [ .] Log directory to print library call data
-only_from_app [ false] Reports only library calls from the app
-follow_children [ true] Trace child processes
-print_ret_addr [ false] Print library call's return address
-num_unknown_args [ 2] Number of unknown libcall args to print
-num_max_args [ 6] Maximum number of arguments to print
-default_config [ true] Use default config file.
-config [ ""] The path to custom config file.
-filter [filter.config] The path of the whitelist/blacklist file.
-ignore_underscore [ false] Ignores library routine names starting with "_".
-help [ false] Print this message.
-version [ false] Print version number.
-verbose [ 1] Change verbosity.
-use_config [ true] Use config file
-grepable [ false] Grepable output
Drltrace 支持外部配置文件,用户可以在其中描述 drltrace 应如何打印某些 API 调用的参数。
HANDLE|CreateRemoteThread|HANDLE|SECURITY_ATTRIBUTES*|size_t|THREAD_START_ROUTINE*|VOID*|DWORD|__out DWORD*
每个函数参数应该用|
分隔。第一个参数是返回类型,第二个参数是函数名称本身,其余是函数参数。标记__out
用于标记输出参数,而___inout
用于标记输入+输出参数。
您可以在我们的 Wiki 页面找到如何使用 drltrace 分析复杂恶意软件的示例。
为了使日志文件的处理更加容易,我们实现了一个名为api_calls_viz.py
的脚本,该脚本可用于生成 RGB 图像,其中每个像素颜色代表唯一的 API 调用。例如,下图表示 WannaCry 恶意软件的日志文件。
图片上的大绿色区域代表 API 调用( wcscmp/wcsicmp
),用于选择具有有趣扩展名(例如 docx、xls、py)的文件来对其进行加密。紫色区域代表 API 调用 ( FindFirstFile/FindNextFile/CryptEncrypt
),用于枚举和加密磁盘上的文件和文件夹。
该脚本还可以生成生成的 RGB 图像的 HTML 表示形式,其中可以选择每个元素来显示 API 调用的名称。
原始 HTML 文件。
有关更多详细信息,请参阅api_calls_viz
目录。
您可以在此 Wiki 页面找到详细的手册。
Windows、Linux(将来的 macOS)。
x86、x64(ARM就在其中)。
C 和 C++ 标准库(以及用 Python 编写的日志处理脚本)。
我们决定在动态二进制检测框架 DynamoRIO 之上实现 API 调用跟踪器。 Drltrace 要求 DynamoRIO 执行 LoadLibrary 调用的检测,以便能够处理目标进程正在加载的新库。当进程尝试加载新库时,DynamoRIO 将控制流重定向到drltracelib.dll
。反过来,drltrace 枚举新加载的 DLL 中的导出函数,并为每个函数注册一个特殊的回调。因此,如果恶意软件调用某个导出的函数,则 drltrace 的回调将在此函数之前执行,并且该工具将能够记录所有必需的信息,例如函数名称和参数。可以在函数之后注册另一个回调以保存执行结果。
为什么不使用英特尔 Pin 呢?我们决定使用 DynamoRIO 的原因如下:
drrun.exe
的-syswide_on
选项)。然而,将来有必要在 drltrace 中针对此类情况实施特殊支持。我们的问题跟踪器包含有关 drltrace 未来的更多详细信息。
马克西姆·舒德拉克 https://github.com/mxmssh
德里克·布鲁宁 https://github.com/derekbruening
乔·泰斯塔 https://github.com/jtesta