恶意代码分析实战 7 WinDbg

配置WinDbg双机调试。

  1. 下载Windbg(WDK)。
    1. 事实上你自己的win10上应该会自带。
    2. vmware_gmzXkb24Et.png
  2. 配置WinXP虚拟机的boot.ini
    1. vmware_17tUupogcG.png
    2. vmware_KGKjsqIW51.png
    3. vmware_eIz49bW2o2.png
    4. 改成如图所示的样子vmware_lqPbWfkHO8.png
  3. 修改主机上Windb的属性。

修改成如图所示:
explorer_4g6wC4LCE4.png

  1. 启动WinXP选择调试状态,启动Windbg即可开始调试。

7.1 Lab 10-1

分析
首先,使用一些静态分析技术来检查这个可执行文件。
vmware_DQJdmkAtWw.png像是有什么窗口之类的。
vmware_UZwELigy2a.png,这个程序可能创建了一个服务。
vmware_iNl5qUABC6.png,Lab 10-01.sys可能包含了这个服务的代码。
分析该Lab 10-01.sys文件,发现导入表只有三个函数,第一个函数是KeTickCount,剩下两个函数是RtlCreateRegistry和RtlWriteRegistryValue,这告诉我们驱动可能访问了注册表。
vmware_fE89DX5Dam.png
这些字符串看起来很想是注册表键值,然后开头的\Registry\Machine却比较怪异,并不像是诸如HKLM此类的常见注册表根键。当从内核态访问列表时,前缀\Registry\Machine等同于用户态程序访问的HKEY_LOCAL_MACHINE。EnableFirewall置为0,表示禁用Windows XP自带的防火墙。
vmware_xxQq4Xftqj.png
vmware_6qf0BRS7nV.png
由于这些字符串预示着恶意代码写了注册表,所以我们打开procmon来验证我们的假设。procmon中显示有一些读注册表的调用,但是仅有一个写注册表的调用:RegSetValue写了HKLM\SOFTWARE\Policies\Microsoft\Cryptography\RNG\Seed键值。
vmware_KvfKcFWN4p.png
这个注册表键值一直改变,对于恶意代码分析毫无意义,但是因为涉及到内核代码,我们需要确保驱动没有秘密地修改注册表。接下来我们打开执行文件,移动到主函数,发现只有四个函数调用。
vmware_QZmMZfJyQv.png
首先,它在①调用了OpenSCMangagerA获取服务管理器的句柄,然后在②调用CreateServiceA,创建一个名为Lab 10-01的服务。CreateServiceA调用告诉我们服务使用了"C:\Windows\System32\Lab10-01.sys"中的代码,服务类型为3,意味着这个文件将被加载到内核。(好奇怪,没看到3)
chrome_RWGUf9OWYy.png
如果CreateServiceA调用失败,代码会使用相同的服务名调用OpenServiceA。
如果因为服务已经存在而导致调用CreateServiceA失败,这将打开Lab 10-01服务的句柄。
vmware_LA6dOeEfO0.png
接下来,程序将调用StartServiceA来启动服务,最后u,调用ControlService。ControlService的第二个参数是发送控制消息的类型。本例中。它的值是1,查询文档,我们发现他是SERVICE_CONTROL_STOP,这将会卸载驱动,并调用驱动的卸载函数。
chrome_PfbtmzdIHV.png
vmware_psSntVBKBg.png
使用IDA Pro查看 Lab 10-01.sys
在试图使用WinDbg分析这个驱动之前,我们可以用IDA Pro打开这个驱动,来检查它的DriverEntry函数。当打开驱动文件,移动到它的入口时,看到如下代码。
vmware_5Pj4lI9lxj.png
这个函数是驱动的入口点,但是它不是DriverEntry函数。编译器在DriverEntry的周围插入封装代码。真正的DriverEntry函数位于sub_10906。
vmware_Hk0Ic5X5lG.png
函数的主体部分似乎将一个偏移量转移到另一个内存位置。除此之外,它没有进行任何函数调用,也没有与系统进行交互。
使用WinDbg分析Lab10-01.sys
现在我们可以使用WinDbg检查一下Lab10-01.sys,来查看调用ControlService卸载Lab10-01.sys时会发生什么事。用户空间可执行的代码加载Lab10-01.sys,然后立即卸载它。如果我们在运行恶意可执行程序之前使用内核调试器,因为此时驱动还未在内存中,所以我们还不能检查它。但是,如果我们等待应用程序运行完成,那时驱动又已经从内存中卸载了。
为了在Lab10-01.sys载入内存后,使用WinDbg分析它,在虚拟机中,我们将可执行程序载入到WinDbg中。使用下列命令,我们在驱动加载和卸载之间设置一个断点(在ControlService调用上):
vmware_K0TuTutywp.png
使用OllyDbg下一个断点。
vmware_hNgdiutS11.png
启动WinDbg进行调试,输入命令来获取驱动对象。

!drvobj Lab10-01

windbg_s0b904BJRG.png
命令!drvobj输出给我们提供了驱动对象的地址,因为在设备对象列表中没有设备列出,所有以我们明白这个驱动没有供用户空间中应用程序访问的设备。
可以使用 !object \Driver 命令获取当前内核中驱动对象列表。
获取了对驱动对象的地址,就可以使用dt命令查看它。

dt _DRIVER_OBJECT 8a1158b0

windbg_u0uOyXq9z8.png
我们尝试确定驱动卸载时调用的函数——偏移量为0x034的信息DriverUnload。然后,我们使用如下命令设置一个断点。

bp 0xba799486

然后恢复运行。
windbg_zngZ9n2DId.png
windbg_3U0ODLJNH8.png
文件被加载到ba799000。从上文中,可以得知,卸载函数位于0xba799486。我们从0xba799486减去0xba799000得到偏移量。然后在IDA中跳转到卸载函数。例如,如果IDA中架子基地址0性00000,那么我们在IDA Pro中地址0星00486处找到卸载函数。
继续运行会触发断点,单步运行可以看到调用了nt!RtlCreateRegistryKey
windbg_01e9rxVax9.png
chrome_UN4dJWtBmr.png

NTSTATUS RtlWriteRegistryValue(
  _In_     ULONG  RelativeTo,
  _In_     PCWSTR Path,
  _In_     PCWSTR ValueName,
  _In_     ULONG  ValueType,
  _In_opt_ PVOID  ValueData,
  _In_     ULONG  ValueLength
);
  1. 这个程序是否直接修改了注册表(使用procmon来检查)?

唯一的写入是写入一个随机值,其他的探测不到。

  1. 用户态的程序调用了ControlService函数,你是否能够使用WinDbg设置一个断点,以此来观察由ControlService的调用导致内核执行了怎么样的操作?

使用OllyDbg将可执行文件下断点到函数前,然后使用另外一个操作系统的WinDbg,使用!drvobj命令获得驱动设备的句柄,它包含一个卸载函数的指针。接下来,在驱动的卸载函数上设置一个断点。重启可执行文件之后,断点将会被出发。

  1. 这个程序做了些什么?

修改了注册表,并关闭了防火墙。

7.2 Lab10-02

分析
查看文件的导入表。
vmware_vghgcrAYCL.png
vmware_6UZA95GPQM.png
这几个函数告诉我们这个程序创建并启动衣蛾服务。因为程序也调用了CreateFile和WriteFile,说明这个程序可能创建一个文件,而LoadResource和FindResource则说明了该程序对Lab10-02.exe的资源节做了某些处理。
认识到程序可能对资源节进行了操作,我们使用Ressource Hacker来检查资源节。我们可以发现在资源节中藏了另外的一个PE头文件。
vmware_QnTILAGbBd.png
使用ProcessMon进行监视发现,该程序创建了一个文件,但我们在当前目录下却并不能查找到该文件。
vmware_5qbT9pJFBh.png
查找Rootkit
为了进一步的调查,我们要检查我们的内核驱动是否被加载。我们使用sc命令,检查运行我们内核驱动程序的服务状态。
vmware_u1lApRF17s.png
我们查询名为486 WS Driver的服务,它在CreateService中被指定。我们看到这个服务仍然运行②,这告诉我们在内核代码中。奇怪的是仍然运行,但是它没有在硬盘上。现在为了确定怎么回事,我们使用WinDbg机型调试。使用lm命令,查看驱动是否被真正加载。我们看到一个与Lab10-02.exe创建文件名匹配的条目:
windbg_3BFRVlqKfM.png
现在,我们确定了文件名为Mlwx486.sys的驱动被载入到内存,但是文件没有在硬盘上显示,这暗示了它可能是一个Rookit。
接下来,我们检查SSDT的所有修改项。
windbg_cjGjTEfuuy.png
我们可以看到有一处条目所在的内存位置很明显位与ntoskrn1模块的范围之外,位与Mlwx486.sys驱动内。为了确定替换了哪个函数,我们回复虚拟机安装Rootkit之前的状态,以便于我们查看存储在SSDT中的哪个函数被覆盖了。
分析函数

  1. 找到SSDT地址和NtQueryDirectoryFile地址
  2. 遍历SSDT找到NtQueryDirectoryFile项
  3. 修改NtQueryDirectoryFile项修改为FakeNtQueryDirectoryFile

vmware_j90Vcg5lJC.png
sub_10486函数:循环将文件名与”Mlxw“比较,如果匹配就修改上一个的NextEntryOffset跳过匹配文件
vmware_daLpfPssN5.png

返回字符串代表函数的地址
PVOID MmGetSystemRoutineAddress(
  PUNICODE_STRING SystemRoutineName
);
根据传入的目录句柄返回下面的各种文件信息
__kernel_entry NTSYSCALLAPI NTSTATUS NtQueryDirectoryFile(
  HANDLE                 FileHandle,
  HANDLE                 Event,
  PIO_APC_ROUTINE        ApcRoutine,
  PVOID                  ApcContext,
  PIO_STATUS_BLOCK       IoStatusBlock,
  PVOID                  FileInformation,
  ULONG                  Length,
  FILE_INFORMATION_CLASS FileInformationClass,
  BOOLEAN                ReturnSingleEntry,
  PUNICODE_STRING        FileName,
  BOOLEAN                RestartScan
);
结构体
typedef struct _FILE_BOTH_DIR_INFORMATION {
    
    
  ULONG         NextEntryOffset;//指向下一个结构体
  ULONG         FileIndex;
  LARGE_INTEGER CreationTime;
  LARGE_INTEGER LastAccessTime;
  LARGE_INTEGER LastWriteTime;
  LARGE_INTEGER ChangeTime;
  LARGE_INTEGER EndOfFile;
  LARGE_INTEGER AllocationSize;
  ULONG         FileAttributes;
  ULONG         FileNameLength;
  ULONG         EaSize;
  CCHAR         ShortNameLength;
  WCHAR         ShortName[12];
  WCHAR         FileName[1];
} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;

  1. 这个程序创建文件了吗?它创建了什么文件?

创建了文件,C:\Windows\System32\Mlwx486.sys。

  1. 这个程序有内核组件吗?

有内核组件,就在Lab10-02.exe的资源节中。

  1. 这个程序做了些什么?

通过修改SSDT的NtQueryDirectoryFile为FakeNtQueryDirectoryFIle,来隐藏文件。

7.3 Lab10-03

  1. 这个程序做了些什么?

· 这个程序首先依然是安装驱动,驱动位置在C:\Windows\System32\Lab10-03.sys
然后接着打开设备对象:

通过IO通信给驱动发送了控制码0ABCDEF01h,接下来的几个函数初始化了COM对象,并在每30s执行一次某个函数,这个函数有一个参数是这个网址字符串,经过在虚拟机运行程序可知,这是每30s弹出一个广告网页。

加载驱动,每30秒弹出一次广告。驱动从系统_EPROCESS中摘除进程

  1. 一旦程序运行,怎么停止?

重启系统。

  1. 它的内核组件做了什么操作?

内核组件负责响应,从进程链表中摘除进程的DeviceIoControl请求。

猜你喜欢

转载自blog.csdn.net/weixin_61823031/article/details/128758129
今日推荐