驱动开发:内核中实现进程内存转储
多数ARK反内核工具中都存在驱动级别的内存转存功能,该功能可以将应用层中运行进程的内存镜像转存到特定目录下,内存转存功能在应对加壳程序的分析尤为重要,当进程在内存中解码后,我们可以很容易的将内存镜像导出,从而更好的对样本进行分析,当然某些加密壳可能无效但绝大多数情况下是可以被转存的。
在上一篇文章《内核R3与R0内存映射拷贝》
介绍了一种方式SafeCopyMemory_R3_to_R0
可以将应用层进程的内存空间映射到内核中,要实现内存转储功能我们还是需要使用这个映射函数,只是需要在此函数上增加一些功能而已。
在实现转存之前,需要得到两个东西,进程内模块基地址
以及模块长度
这两个参数是必不可少的,至于内核中如何得到指定进程的模块数据,在很早之前的文章《内核中枚举进线程与模块》
中有详细的参考方法,这里就在此基础之上实现一个简单的进程模块遍历功能。
如下代码中使用的就是枚举
进程PEB
结构得到更多参数的具体实现,如果不懂得可以研读《内核通过PEB得到进程参数》
这篇文章此处不再赘述。
|
如上我们指定获取应用层lyshark.exe
进程的模块信息,并可得到以下输出效果:
上篇文章中的代码就不再啰嗦了,这里只给出内存转存的核心代码ProcessDumps
的实现流程:
ProcessDumps 代码的功能是将一个进程的内存空间转储(Dump)到磁盘上的一个文件中,该函数接收三个参数,并返回内存转存的状态;
- 参数 pEprocess:要转储的进程的PEPROCESS结构体指针。
- 参数 nBase:要转储的内存空间的基地址。
- 参数 nSize:要转储的内存空间的大小。
- 函数返回值:转储操作的状态,如果成功则返回 STATUS_SUCCESS,否则返回一个表示错误原因的 NTSTATUS 值。
该函数的实现也非常简单,通过SafeCopyMemory_R3_to_R0
函数将应用层中的进程内存映射到内核层中的pBuffer
堆中,当映射完成后再通过ZwWriteFile
函数将这段内存写出到磁盘中完成转存,函数ProcessDumps
的具体流程如下:
- 1.检查参数 pEprocess 和 nSize 是否为 NULL 或为 0,如果是,则直接返回 STATUS_UNSUCCESSFUL,表示操作失败。
- 2.分配一个大小为 nSize 的缓冲区,用于存储要转储的内存空间。
- 3.如果要转储的进程不是当前进程,则将当前线程切换到要转储的进程的上下文中,以便能够访问要转储的进程的内存空间。
- 4.调用函数 SafeCopyMemory_R3_to_R0,将要转储的内存空间中的数据复制到缓冲区中。
- 5.如果线程被切换到了要转储的进程的上下文中,则将线程切换回当前进程的上下文中。
- 6.调用ZwCreateFile创建一个表示输出文件的句柄。
- 7.通过ZwWriteFile将缓冲区中的数据写入到输出文件中。
- 8.最后ZwClose关闭输出文件句柄并释放缓冲区内存。
很简单只是利用了SafeCopyMemory_R3_to_R0
将进程内存读取到缓冲区内,并将缓冲区写出到C盘目录下,默认将转存数据保存为lyshark_dumps.exe
;
NTSTATUS ProcessDumps(PEPROCESS pEprocess, ULONG_PTR nBase, ULONG nSize) |
转存后效果如下图所示:
至于导出的进程无法运行只是没有修复而已(后期会讲),可以打开看看是没错的。