恶意代码分析实战 --- 第十章 使用Windbg调试内核

一、安装内核调试

1.配置虚拟机

编辑C:\boot.ini ,该文件为隐藏文件,将文件按下面方式进行修改

  • /debug表示开启内核调试
  • /debugport=COM1表示使用哪个端口来连接调试系统与被调试系统
  • /baudrate=115200表示指定串口数据传输速率。
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional with Kernel Debugging" /noexecute=optin /fastdetect /debug /debugport=COM1 
/baudrate=115200

2.配置VMware

添加串口设备
在这里插入图片描述
设置串口设备。使用命名的管道**\.\pipe\com_1**,IO模式勾选轮询时主动放弃CPU
在这里插入图片描述

3.设置windbg

windbg如下配置File->Kernel Debug,baudRate选择115200,Port为\.\pipe\com_1,勾选Pipe
在这里插入图片描述
windbg preview如下配置
在这里插入图片描述
配置符号表

.sympath srv*G:\vm\XPSP3Symbols*https://msdl.microsoft.com/download/symbols 

这里的地址是本地机器上符号表的保存地址
windbg安装symbols下载地址参考下面链接https://www.cnblogs.com/csnd/p/11800535.html
双击调试配置 https://bbs.pediy.com/thread-261326.htm

4.补充xp以后的系统增加的内容

windows7以后使用BCDEdit的程序配置启动项
内核补丁保护机制PatchGuard,阻止第三方程序修改内核(代码自身、系统服务表、IDT)
在系统引导时附加系统,补丁保护不会运行,在系统引导结束后,内核调试器再附加到系统,PatchGuard会使系统崩溃
64位vista开始,强制驱动签名。关闭驱动签名(关闭nointegritychecks)

二、windbg常用命令

这里只记录一下之后用到的。详细的windbg命令以后再记录

内存读取
da 读取内存数据并以ASCII文本显示
du 读取内存数据并以Unicode文本显示
dd 读取内存数据并且以32位双字显示

内存修改(x为a u d)
ex addressToWrite dataToWrite

+ - * /算术运算
dwo用来解引用32位的指针
du dwo (esp+4)

设置断点
bp命令
每次调用GetProcAddress函数时,在不中断程序执行的前提下,打印出第二个参数
bp GetProcAddress "da dwo(esp+8);g"

列举模块
lm

反汇编
u

列出最接近给定内存地址的符号
ln 805717aa

查看一个结构的类型信息
dt nt!_DRIVER_OBJECT

显示某个地址的结构体
dt nt!_DRIVER_OBJECT 828b2648

查看ssdt
dd nt!KeServiceDescriptorTable

查看中断
!idt

查看驱动对象地址
!drvobj drvobjName

列出所有驱动
!object \Driver

三、Lab10-1

需要将Lab10-01.sys放在C:\Windows\System32目录下。

1.lab10-1.exe分析

  1. 创建驱动服务
  2. 启动服务
  3. 发生SERVICE_CONTROL_STOP信息,服务收到消息会卸载驱动
    在这里插入图片描述

2.Lab10-01.sys分析

lab10-1.sys设置了DriverUnload设置了回调函数,创建了注册表。
在这里插入图片描述
在这里插入图片描述

3.动态调试

动态运行监控注册表。

用到的一些函数和结构体
在这里插入图片描述动态调试需要在controlService前下断点,否则内核中驱动会被卸载。
在这里插入图片描述
本机windbg进行内核调试**!drvobj lab10-01 **定位设备对象(不知道设备对象名字的时候可以用!object \Driver)
在这里插入图片描述
查看Lab10-01.sys的驱动对象,并在DriverUnload回调函数下断点
在这里插入图片描述
继续运行会触发断点,单步运行可以看到调用了nt!RtlCreateRegistryKey
在这里插入图片描述
用到的数据结构和函数

发送控制码给服务
BOOL ControlService(
  SC_HANDLE        hService,
  DWORD            dwControl,
  LPSERVICE_STATUS lpServiceStatus
);

4.习题答案

1.这个程序是否直接修改了注册表(使用procmon来检查)?
procmon无法检查出注册表的修改。RegShot可以检测出注册表的修改
2.用户态的程序调用了ControlService函数,你是否能够使用WinDbg设置一个断点,以此来观察由ControlService的调用导致内核执行了怎么样的操作?
用户态无法对内核太进行调试。
3.这个程序做了些什么?
修改了注册表,关闭了防火墙

四、Lab10-2

1.Lab10-2.exe分析

  1. 提取资源文件,并写入C:\Windows\System32\Mlwx486.sys
  2. 创建服务“486 WS Driver”
  3. 启动服务

在这里插入图片描述
用resourceHack提取资源,明显是一个PE文件提取出来,继续分析
在这里插入图片描述

2.Mlwx486.sys分析

  1. 找到SSDT地址和NtQueryDirectoryFile地址
  2. 遍历SSDT找到NtQueryDirectoryFile项
  3. 修改NtQueryDirectoryFile项修改为FakeNtQueryDirectoryFile
    在这里插入图片描述
    FakeNtQueryDirectoryFile函数:循环将文件名与”Mlxw“比较,如果匹配就修改上一个的NextEntryOffset跳过匹配文件
    在这里插入图片描述

3.动态调试

直接蓝屏了没法调试。应该是有PatchGuard会检测SSDT是否被修改。
在这里插入图片描述

用到的数据结构体和函数

返回字符串代表函数的地址
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;

4.习题答案

1.这个程序创建文件了吗?它创建了什么文件?
C:\Windows\System32\Mlwx486.sys
2.这个程序有内核组件吗?
有。从资源文件中提取。
3.这个程序做了些什么?
通过修改SSDT的NtQueryDirectoryFile为FakeNtQueryDirectoryFIle,来隐藏文件。

五、Lab10-3

注意:需要将驱动程序放在C:\Windows\System32目录下。

1.Lab10-3.exe分析

  1. 先安装了一个服务名为:Process Helper。路径为C:\Windows\System32\Lab10-03.sys
  2. 使用COM组件,每30s 浏览器打开一次http://www.malwareanalysisbook.com/ad.html网页

rclsid注册表目录HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID
riid注册表目录**HKEY_CLASSES_ROOT\Interface**
在这里插入图片描述

2.Lab10-03.sys分析

  1. 创建设备驱动ProcHelper
  2. 设置驱动的MajorFunction。MajorFunction不同偏移代表IRP_MJ_CREATE、IRP_MJ_CLOSE和IRP_MJ_DEVICE_CONTROL。
  3. 将驱动ProcHelper与符号\DosDevices\ProcHelper链接

在这里插入图片描述

3.动态调试

动态调试主要是分析IRP_MJ_DEVICE_CONTROL对应的函数
在这里插入图片描述
在虚拟机中对DeviceIoControl下断点,启动之后在主机上用windbg连接虚拟机进行内核调试。
在!devobj ProcHelper搜索驱动对象,dt nt!_DRIVER_OBJECT 81a8ab00查看对象,dd 81a8ab00+0x38 L1c查看MajorFunction数组
在这里插入图片描述
这是第二次调试,所以地址和前面的不一样。可以看sub_10666函数主要作用就是先获取当前调用的进程的_EPROCESS并将的_LIST_ENTRY摘除
在这里插入图片描述
用到的数据结构和函数

STDAPI CoCreateInstance(
REFCLSID rclsid, //创建的Com对象的类标识符(CLSID)
LPUNKNOWN pUnkOuter, //指向接口IUnknown的指针
DWORD dwClsContext, //运行可执行代码的上下文
REFIID riid, //创建的Com对象的接口标识符
LPVOID * ppv //用来接收指向Com对象接口地址的指针变量
);
MajorFunction不同偏移代表的含义
#define IRP_MJ_CREATE                   0x00
#define IRP_MJ_CREATE_NAMED_PIPE        0x01
#define IRP_MJ_CLOSE                    0x02
#define IRP_MJ_READ                     0x03
#define IRP_MJ_WRITE                    0x04
#define IRP_MJ_QUERY_INFORMATION        0x05
#define IRP_MJ_SET_INFORMATION          0x06
#define IRP_MJ_QUERY_EA                 0x07
#define IRP_MJ_SET_EA                   0x08
#define IRP_MJ_FLUSH_BUFFERS            0x09
#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
#define IRP_MJ_SET_VOLUME_INFORMATION   0x0b
#define IRP_MJ_DIRECTORY_CONTROL        0x0c
#define IRP_MJ_FILE_SYSTEM_CONTROL      0x0d
#define IRP_MJ_DEVICE_CONTROL           0x0e
#define IRP_MJ_INTERNAL_DEVICE_CONTROL  0x0f
#define IRP_MJ_SHUTDOWN                 0x10
#define IRP_MJ_LOCK_CONTROL             0x11
#define IRP_MJ_CLEANUP                  0x12
#define IRP_MJ_CREATE_MAILSLOT          0x13
#define IRP_MJ_QUERY_SECURITY           0x14
#define IRP_MJ_SET_SECURITY             0x15
#define IRP_MJ_POWER                    0x16
#define IRP_MJ_SYSTEM_CONTROL           0x17
#define IRP_MJ_DEVICE_CHANGE            0x18
#define IRP_MJ_QUERY_QUOTA              0x19
#define IRP_MJ_SET_QUOTA                0x1a
#define IRP_MJ_PNP                      0x1b
#define IRP_MJ_PNP_POWER                IRP_MJ_PNP      // Obsolete....
#define IRP_MJ_MAXIMUM_FUNCTION         0x1b

创建驱动对象
NTSTATUS IoCreateDevice(
  PDRIVER_OBJECT  DriverObject,
  ULONG           DeviceExtensionSize,
  PUNICODE_STRING DeviceName,
  DEVICE_TYPE     DeviceType,
  ULONG           DeviceCharacteristics,
  BOOLEAN         Exclusive,
  PDEVICE_OBJECT  *DeviceObject
);
为驱动创建符号名
NTSTATUS IoCreateSymbolicLink(
  PUNICODE_STRING SymbolicLinkName,
  PUNICODE_STRING DeviceName
);
返回当前的进程
PEPROCESS IoGetCurrentProcess();

4.习题答案

1.这个程序做了些什么
加载驱动,每30秒弹出一次广告。驱动从系统_EPROCESS中摘除进程
2.一旦程序运行,怎么停止?
重启系统
3.它的内核组件做了什么操作?
从_EPROCESS->_LIST_ENTRY中摘除DeviceToControl请求进程的_LIST_ENTRY

六、总结

到这里为止《恶意代码代码分析实战》主要讲解了分析工具的使用、静态分析、动态分析、系统环境变化的抓取以及内核调试的方法。接下去才是重头戏,不同病毒的功能实现及分析。

双机内核调试入门 https://bbs.pediy.com/thread-261326.htm
Windows XP sp3 系统安装 Windbg 符号文件 Symbols 时微软失去支持的解决方案 https://www.cnblogs.com/csnd/p/11800535.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值