【本文主题】:谈谈上次遗留的“干掉吾爱破解OD等工具的模块枚举检测”
【实验平台】:Win7 x64
【开发平台】:Win10 x64 + VS2017
【调试工具】:Ollydbg
【本文作者】:小迪xiaodi,一个非著名技术段子文章菜鸟写手
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1.判断DLL句柄是否有效,有效就说明该DLL存在于进程中
2. 递减模块的引用计数,且判断是否为0
3. 调用模块的DllMain函数响应 DLL_PROCESS_DETACH消息
4.从进程空间撤销对DLL的内存映射
然后我们通过对第四个步骤的分析,采用HOOK
FreeLibrary
函数中的
ZwUnmapViewOfSection函数,实现了擦除DLL痕迹隐藏DLL的功能,但是出现了一丢丢的问题,那就是被某些“强大”的工具检测并枚举了出来,那么为什么会这样呢?今天我们进来分析分析~
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
结语:
把一些新奇的想法用代码去做实验实现还是比较有意思的,技术有些粗陋,重要的是享受过程(其实就是我菜)
文章开头说到“远程调Call”几个字眼,那么下节实验的题目就来了~
经过几天的努力,我的毕业论文终于写的差不多了,老师说:
OK,那咱们继续回论坛吹水~
前段日子呢,写了个《VC黑防日记(一):DLL隐藏和逆向(上)》的水文,也得到论坛的带佬对我“能力”的认可:
那我们今天,继续来混一下字数,谈谈上次遗留的的问题——干掉吾爱破解OD这类工具对HOOK FreeLibrary方式隐藏DLL的检测
怎么干呢,很简单,就是让它没了:
注入进去DLL之后,拷贝DLL镜像到一块内存地址,然后卸载DLL后,再把内存镜像还原回原地址
这样子,只是简单的内存数据复制,而DLL的确被卸载了,拷贝后的DLL内存数据,只要计算下导出函数地址便可以调用,相当于远程调Call.
在此,也要感谢上次各位老哥推荐的灵活的方法思路,本文章并未进行复现,有机会可以一块儿写出来,在此表示感谢!
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0x01:回顾
我们上次是通过分析FreeLibrary函数的流程得知大概分为四个步骤:
1.判断DLL句柄是否有效,有效就说明该DLL存在于进程中
2. 递减模块的引用计数,且判断是否为0
3. 调用模块的DllMain函数响应 DLL_PROCESS_DETACH消息
4.从进程空间撤销对DLL的内存映射
然后我们通过对第四个步骤的分析,采用HOOK
FreeLibrary
函数中的
ZwUnmapViewOfSection函数,实现了擦除DLL痕迹隐藏DLL的功能,但是出现了一丢丢的问题,那就是被某些“强大”的工具检测并枚举了出来,那么为什么会这样呢?今天我们进来分析分析~
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0x02:分析
既然我们上次HOOK
ZwUnmapViewOfSection出现了小问题,能不能对
ZwUnmapViewOfSection做一些小手脚呢,暂时我的知识储备还不够,处理不了,但是我选择了其他的绕过方式,在讲这个方式之前,我们先了解一部分逆向的理论知识:
我们上次是通过分析FreeLibrary函数的流程得知大概分为四个步骤:
虚拟地址描述符:
大家都知道,在x86的平台上Windows操作系统为每个进程描述了一个完整的4G的地址空间,这4G空间由低位2G的用户地址空间和高位2G的系统地址空间构成。每个进程的用户地址空间是相互隔离的,不可见的。但是系统地址空间是各个进程间共享的,对于进程有不同的视图。用户的私有的数据代码还有加载的动态链接库(DLL)都存放在用户地址空间中。现在有个问题是,总要有个地方记录着这2G地址空间,到底那些被预留了,那些被提交了,那些被访问了吧。还有个问题就是,对于程序来讲,地址不是连续的,是分段的。代码段、数据段、堆、栈等等。可是进程的空间是连续的,从0x0000000到0x7FFFFFF。总要有个数据结构描述程序的各个段对应那段地址空间。这两个重要任务就交个了VAD,即虚拟地址描述符(Virtual Address Descriptor)。
VAD组织成了一个AVL自平衡二叉树(参考Mark Russinovich的《深入解析Windows操作系统》),这种组织方式完全是方便快速查找。树中的每一个节点代表了一段虚拟地址空间。所以程序的代码段,数据段,堆段都会各种占用一个或多个VAD节点,由一个MMVAD结构完整描述。
内核空间并不受VAD的管理。
https://baike.baidu.com/item/%E8%99%9A%E6%8B%9F%E5%9C%B0%E5%9D%80%E6%8F%8F%E8%BF%B0%E7%AC%A6/295257?fr=aladdin
大家都知道,在x86的平台上Windows操作系统为每个进程描述了一个完整的4G的地址空间,这4G空间由低位2G的用户地址空间和高位2G的系统地址空间构成。每个进程的用户地址空间是相互隔离的,不可见的。但是系统地址空间是各个进程间共享的,对于进程有不同的视图。用户的私有的数据代码还有加载的动态链接库(DLL)都存放在用户地址空间中。现在有个问题是,总要有个地方记录着这2G地址空间,到底那些被预留了,那些被提交了,那些被访问了吧。还有个问题就是,对于程序来讲,地址不是连续的,是分段的。代码段、数据段、堆、栈等等。可是进程的空间是连续的,从0x0000000到0x7FFFFFF。总要有个数据结构描述程序的各个段对应那段地址空间。这两个重要任务就交个了VAD,即虚拟地址描述符(Virtual Address Descriptor)。
VAD组织成了一个AVL自平衡二叉树(参考Mark Russinovich的《深入解析Windows操作系统》),这种组织方式完全是方便快速查找。树中的每一个节点代表了一段虚拟地址空间。所以程序的代码段,数据段,堆段都会各种占用一个或多个VAD节点,由一个MMVAD结构完整描述。
内核空间并不受VAD的管理。
https://baike.baidu.com/item/%E8%99%9A%E6%8B%9F%E5%9C%B0%E5%9D%80%E6%8F%8F%E8%BF%B0%E7%AC%A6/295257?fr=aladdin
分析一下:
1.有个玩意儿叫做“虚拟地址描述符”,存放了DLL的内存空间使用情况数据结构。
2.如果正常调用
ZwUnmapViewOfSection,内存地址所对应的“VAD”就会从树中摘除。
3.我们上次hook了
ZwUnmapViewOfSection,刚好使得被注入的DLL的 “内存空间数据结构”无法从整体的“二叉树”结构中消除。
结论:
1.如果不HOOK
ZwUnmapViewOfSection
,就假戏真做,DLL就真的被卸载了。
2.如果HOOK了
ZwUnmapViewOfSection,就很难受,虚拟地址描述符清除不掉,还是过不了吾爱破解OD的检测。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-1-11 18:59
被小迪xiaodi编辑
,原因: