selph
selph
发布于 2021-11-07 / 1182 阅读
0
0

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

笔记

驱动与内核代码

驱动程序不直接与应用进行通信,而是通过设备对象进行(如:硬盘盘符C:),设备对象也不一定是真的物理设备

驱动程序需要加载到内核空间才能工作(DLL是需要加载到进程空间)

驱动程序通过注册回调函数提供功能(DLL通过导出表提供功能),R3请求服务的时候会触发回调函数。

Windows会为每个驱动创建一个驱动对象,以参数的形式提供给驱动入口程序DriverEntry函数,在这个函数里会用回调函数填充驱动对象,然后会创建一个用户程序可以访问的设备对象来与用户程序进行通信

Windows XP配置双机调试

编辑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" /noexecute=optin /fastdetect /debug /debugport=com1 /baudrate=115200

下次开机的时候就可以选择调试模式了

虚拟机配置则还是添加串口,配置命名管道\\.\pipe\com_1,把轮询选上

接下来启动虚拟机和windbg即可

内核程序基本分析

要确定调用了恶意驱动中的哪些代码,首先需要找到驱动对象,知道驱动名字则可以通过!drvobj 驱动名称查看,也可以用!object \Driver来浏览驱动对象

得到驱动地址,就可以查看其结构:dt nt!_DRIVER_OBJECT

0: kd> dt nt!_driver_object
   +0x000 Type             : Int2B			
   +0x002 Size             : Int2B
   +0x004 DeviceObject     : Ptr32 _DEVICE_OBJECT
   +0x008 Flags            : Uint4B
   +0x00c DriverStart      : Ptr32 Void
   +0x010 DriverSize       : Uint4B
   +0x014 DriverSection    : Ptr32 Void
   +0x018 DriverExtension  : Ptr32 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING
   +0x024 HardwareDatabase : Ptr32 _UNICODE_STRING
   +0x028 FastIoDispatch   : Ptr32 _FAST_IO_DISPATCH
   +0x02c DriverInit       : Ptr32     long 
   +0x030 DriverStartIo    : Ptr32     void 
   +0x034 DriverUnload     : Ptr32     void 
   +0x038 MajorFunction    : [28] Ptr32     long	// 指向主函数表首项的指针 

驱动对象的主函数表每个索引表示不同类型的请求会调用哪个回调函数

通过命令devhandles 设备对象句柄可以查看是哪些应用在使用这个设备对象

Rootkit

内核态代码只能被用户态的syscall,sysenter,int 2e来访问

Rootkit程序可能会Hook SSDT来隐藏自己,可以通过检查SSDT表函数地址(应该位于ntoskrnl.exe范围内)来判断哪个函数被Hook了,ARK工具也都有提供Hook检查

得到Hook的地址了,通过lm命令列出模块信息,看看Hook函数位于哪个模块地址内

定位驱动程序之后就可以开始分析了,主要查找分析的安装Hook的函数和Hook函数

新版本Windows有一个烦人的东西叫做PatchGuard,阻止第三方代码修改内核代码,不然就蓝屏

作业

Lab 10-1:

分析目标:LAb10-1.exe,Lab10-01.sys

  1. 这个程序是否直接修改了注册表(使用procmon检查)?

    答:没有

  2. 用户态程序调用了ControlService函数,是否能使用windbg设置一个断点,观察由于ControlService的调用导致内核执行了咋样的操作?

    答:用户态:

    exe程序WinMain内容很简洁,就是单纯的加载驱动的流程,驱动位置硬编码为:C:\\Windows\\System32\\Lab10-01.sys,所以需要把驱动放过去,才能运行成功,在驱动加载完成后,用户程序调用了ControlService函数:

    image-20211014195543490

    参数控制码是写死的1,也就是SERVICE_CONTROL_STOP,功能是使用服务句柄去停止服务,而这个服务句柄正是程序之前启动的驱动服务

    内核态:

    代码就做了一件事,给驱动对象34h偏移处赋了值,也就是指定了DriverUnload函数

    image-20211014200156009

    这个驱动程序在安装的时候没有进行任何操作,只能是在卸载的时候执行功能了,我的虚拟机坏了没法dbg虚拟机了,说一下动态调试的思路:通过windbg命令!drvobj 对象名称找到驱动对象地址,通过dt NT!_DRIVER_ENTRY Addr查看驱动对象内容,找到入口点

  3. 这个程序做了什么?

    接下来看看驱动卸载函数做了什么:(F5查看更方便)

    image-20211017095527444

    创建了三个注册表Key,然后向其中两个写入值

Lab 10-2:

分析目标:Lav10-02.exe

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

    主程序进去后:很显眼的几个资源释放功能常用API,这里创建了文件C:\\Windows\\System32\\Mlwx486.sys

    image-20211017103355687

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

    有内核组件,在资源释放结束后,程序紧接着进行了驱动加载并启动的操作:

    image-20211017103616467

  3. 这个程序做了什么?

    这个程序有资源文件,用ResourceHacker把资源文件提取出来,拖进IDA分析:

    image-20211017104704838

    这个驱动程序初始化了两个字符串,一个是系统函数名称,一个是SSDT全局变量名称,然后获取这两个东西的地址,遍历SSDT,找到指定函数的位置,保存原SSDT和当前SSDT制定项,然后修改SSDT指定项,是个SSDT Hook,运行起来去火绒剑里看一下发现KeServiceDescriptorTable函数被Hook了,和静态分析的结论对上了

    查看Hook函数的功能:

    image-20211017105234545

    大概浏览一下,可以看出,这个Hook函数里把原函数执行了一遍,然后对执行结果进行修改,如果文件名为某个值,就不返回有

    难怪我从system32目录里找不到这个驱动文件呢,原来在这做手脚了。。。。

    这个程序的功能是隐藏驱动程序

Lab 10-3:

分析目标:Lab10-3.exe,Lab10-03.sys

  1. 这个程序做了什么?

    这个程序首先依然是安装驱动,驱动位置在C:\Windows\System32\Lab10-03.sys(这个过程就不截图了)

    然后接着打开设备对象:

    image-20211017110226235

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

    image-20211017110330487

  2. 一旦程序运行,要怎么停止它?

    任务管理器找不到这个进程(用火绒剑一下就能关掉。。。),应该是这个程序加载了内核组件,内核组件做了隐藏处理,接下来看一下驱动:首先是创建了设备对象,创建成功的话,就给主函数集指定处理函数,否则就删除驱动对象然后退出

    image-20211017111157327

    经过查阅,得知不同索引执行不同的IRP请求,通过VS的F12看比较清晰:

    image-20211017111649706

    这里的前两个,也就是创建和关闭的处理函数是个默认处理:给个响应就结束了

    image-20211017111814892

    关键是索引14的这个函数,这是IO通信用的,里面的F5不太好看懂,就看反汇编吧:

    image-20211017112808730

    这里是获取了当前进程的指针,然后通过偏移进行进程断链操作进行隐藏,所以R3层面的任务管理器看不到进程了,要关掉进程,得通过关闭这个驱动才行(重启),或者从R0层面去关闭

  3. 它的内核组件做了什么?

    断链隐藏进程,分析见上文问题2


评论