大纲:
对UPGDSED源码进行分析,并浅析其绕过PG和DSE方式。
小插曲:
(1)、要在内核搞事情,就必须加载驱动。加载驱动的道路充满荆棘,先是有杀软的加载驱动拦截,后是有MS的 PG 和 DSE 保护。杀软那一关已经过了,但后面还有PG和DSE。
(2)、逐渐深入研究,发现Fyyre和EP_X0FF两位大牛早已经绕过了,并且公布了UPGDSED源码。在这里表示敬佩。
(3)、时间有限,接下来我能做的,就是分析UPGDSED源码,和尽可能多得学习各种绕过的方法。所以UPGDSED源码分析会先发布,而绕过PG和DSE方法会逐步更新。
(4)、为Win10_1803做准备。(据说1803的PG发生了大变化)。
大牛请留下指导or绕过~:)
一、PatchGuard
隐藏驱动过PG:
https://github.com/Sqdwr/HideDriver
https://github.com/ZhuHuiBeiShaDiao/NewHideDriverEx
二、Dedicated Support Engineer
0day漏洞绕过DSE:
http://www.powerofcommunity.net/poc2012/mj0011.pdf
https://github.com/shjalayeri/DriveCrypt
吊销正规签名过DSE:
https://bbs.pediy.com/thread-187348.htm
白名单驱动绕过DSE:
http://www.kernelmode.info/forum/viewtopic.php?f=11&t=3322
三、UPGDSED
EP_X0FF源码:
参考资料:
https://github.com/hfiref0x/UPGDSED
http://www.kernelmode.info/forum/viewtopic.php?f=11&t=4707&p=30269&hilit=DSE#p30269
1、环境
以 win10_1709_16299.15 BIOS启动为例分析:
2、UPGDSED的准备流程
主干简单的述下:
(1)、PGDSED准备了两种结构体,分别为 用作补丁的PATCH结构体 和 符号SYMBOL结构体。
(2)、PGDSED在修补内核文件时,有两种找到目标函数的方式,分别为 通过符号查找 和 通过特征码查找。
1、准备工作
PATCH结构体 和 SYMBOL结构体:
并定义一些修补函数的全局变量。
分别提取 "dbghelp.dll" 和 "symsrv.dll" 转至目录C:\Users\User\AppData\Local\Temp
加载Temp目录下的"dbghelp.dll" 和 "symsrv.dll",并建立符号模型。
将C:\Windows\System32目录下的"ntoskrnl.exe" 和 "winload.exe" 拷贝至C:\Users\User\AppData\Local\Temp目录下,
并分别更名为"ntkrnlmp.exe" 和 "osloader.exe"。
有两个函数 ScanNtos() 和 ScanWinload() 会分别对"ntkrnlmp.exe" 和 "osloader.exe" 进行扫描修补。
这里以SeValidateImageData为例:
将"ntkrnlmp.exe"映射进内存,并加载符号列表 和 初始化Symbol结构体数组。
然后调用专门的函数,处理对应内核文件的函数字节。
介绍两种找到目标修改点的方式。
通过符号查找 和 通过FindPattern特征码查找。
Symbol查找:
判断版本,通过Symbol数组,查找目标函数名,返回函数地址。
要修改函数的哪个位置,把位置的特征码赋值给Pattern,并设置扫描大小ScanSize。
如果获取符号失败,则采用
FindPattern特征码方式:
定位到"EGAP"区段。区段的大小即扫描大小。
赋值更长更确定的特征码给Pattern。
设置跳过字节。
遍历找到指定位置。
最后转换文件偏移,Address加上SkipBytes,保存在PATCH全局变量。
3、ScanNtos() 和 ScanWinload() 分析(重点)
分析,并做出前后对比。
system32 "ntoskrnl.exe" -->> Temp "ntkrnlmp.exe"
SeValidateImageData:
FindPattern数据:
unsigned char ptSeValidateImageData_2_15063_16299[] = { 0xB8, 0x28, 0x04, 0x00, 0xC0, 0xEB };
SkipBytes字节:
#define ptSkipBytesSeValidateImageData_9600_16299 1
PatchData数据:
// Patch data for SeValidateImageData STATUS_SUCCESS
unsigned char pdSeValidateImageData[] = { 0x0, 0x0, 0x0, 0x0 };
修改前:
修改后:
CcInitializeBcbProfiler:
符号搜索:
Address = (ULONG_PTR)SymbolAddressFromName(TEXT("CcInitializeBcbProfiler"));
FindPattern数据:
//Windows 10+
unsigned char ptCcInitializeBcbProfiler_10240_16299[] = {
0x40, 0x55, 0x53, 0x56, 0x57, 0x41, 0x54, 0x41,
0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x8D, 0x6C,
0x24, 0xE1, 0x48, 0x81, 0xEC, 0xB8, 0x00, 0x00,
0x00
};
PatchData数据:
unsigned char pdCcInitializeBcbProfiler[] = { 0xB0, 0x01, 0xC3 };
修改前:
修改后:
KeInitAmd64SpecificState:
符号搜索:
Address = (ULONG_PTR)SymbolAddressFromName(TEXT("KeInitAmd64SpecificState"));
FindPattern数据:
//Windows 8/8.1/10 (TH1/TH2/RS1/RS2/RS3)
unsigned char ptKeInitAmd64SpecificState_9200_16299[] = { 0x48, 0x83, 0xEC, 0x28, 0x83, 0x3D };
PatchData数据:
unsigned char pdKeInitAmd64SpecificState[] = { 0x33, 0xC0, 0xC3 };
修改前:
修改后:
ExpLicenseWatchInitWorker:
符号搜索:
Address = (ULONG_PTR)SymbolAddressFromName(TEXT("ExpLicenseWatchInitWorker"));
FindPattern数据:
//Windows 8.1/10 TH1/TH2/RS1/RS3
unsigned char ptExpLicenseWatchInitWorker2[] = { 0x40, 0x53, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8B, 0x05 };
PatchData数据:
unsigned char pdExpLicenseWatchInitWorker[] = { 0x33, 0xC0, 0xC3 };
修改前:
修改后:
SepInitializeCodeIntegrity:
符号搜索:
ScanPtr = (PVOID)SymbolAddressFromName(TEXT("SepInitializeCodeIntegrity"));
FindPattern数据:
//Windows 10 RS3
unsigned char ptSepInitializeCodeIntegrity2_16299[] = {
0x48, 0x89, 0x5C, 0x24, 0x08, 0x57,
0x48, 0x83, 0xEC, 0x20, 0xBB, 0xC0,
0x00, 0x00, 0x00
};
&&-->>
unsigned char ptSepInitializeCodeIntegrity_16299[] = { 0x8B, 0xCF, 0xFF };
PatchData数据:
unsigned char pdSepInitializeCodeIntegrity[] = { 0x31, 0xC9 };
修改前:
修改后:
system32 "winload.exe" -->> Temp "osloader.exe"
ImgpValidateImageHash:
符号搜索:
// Invalid
Address = (ULONG_PTR)SymbolAddressFromName(TEXT("ImgpValidateImageHash"));
FindPattern数据:
unsigned char ptImgpValidateImageHash_16299[] = {
0x48, 0x8B, 0xC4, 0x4C, 0x89, 0x48, 0x20, 0x44, 0x89, 0x40, 0x18, 0x48, 0x89, 0x50, 0x10, 0x48,
0x89, 0x48, 0x08, 0x55, 0x53, 0x56, 0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48,
0x8D, 0xA8, 0xA8, 0xFE, 0xFF, 0xFF
};
PatchData数据:
unsigned char pdImgpValidateImageHash[] = { 0x33, 0xC0, 0xC3 };
修改前:
修改后:
另:
加命令行参数"-pf"启动程序,将会忽略掉KeInitAmd64SpecificState 和 ExpLicenseWatchInitWorker,而选择 KiFilterFiberContext 进行修补。
KiFilterFiberContext:
符号搜索:
Address = (ULONG_PTR)SymbolAddressFromName(TEXT("KiFilterFiberContext"));
FindPattern数据:
//Windows 10 RS3
unsigned char ptKiFilterFiberContext_16299[] = {
0x48, 0x89, 0x5C, 0x24, 0x08, 0x55, 0x56,
0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56,
0x41, 0x57, 0x48, 0x8D, 0x6C, 0x24, 0xD9,
0x48, 0x81, 0xEC, 0x90, 0x00, 0x00, 0x00
};
PatchData数据:
unsigned char pdKiFilterFiberContext[] = { 0xB0, 0x01, 0xC3 };
修改前:
修改后:
4、后续修补及操作
逐个PATCH修改内核文件。
修正文件的校验和。
将文件移至system32。
Temp "ntkrnlmp.exe" && Temp "osloader.exe" -->> system32
设置BCD条目。
cmd以下命令:
bcdedit.exe -create {71A3C7FC-F751-4982-AEC1-E958357E6813} -d "Patch Guard Disabled" -application OSLOADER
bcdedit.exe -set {71A3C7FC-F751-4982-AEC1-E958357E6813} device partition=C:
bcdedit.exe -set {71A3C7FC-F751-4982-AEC1-E958357E6813} osdevice partition=C:
bcdedit.exe -set {71A3C7FC-F751-4982-AEC1-E958357E6813} systemroot \Windows
bcdedit.exe -set {71A3C7FC-F751-4982-AEC1-E958357E6813} path \Windows\system32\osloader.exe
bcdedit.exe -set {71A3C7FC-F751-4982-AEC1-E958357E6813} kernel ntkrnlmp.exe
bcdedit.exe -set {71A3C7FC-F751-4982-AEC1-E958357E6813} recoveryenabled 0
bcdedit.exe -set {71A3C7FC-F751-4982-AEC1-E958357E6813} nx OptIn
bcdedit.exe -set {71A3C7FC-F751-4982-AEC1-E958357E6813} nointegritychecks 1
bcdedit.exe -set {71A3C7FC-F751-4982-AEC1-E958357E6813} inherit {bootloadersettings}
bcdedit.exe -displayorder {71A3C7FC-F751-4982-AEC1-E958357E6813} -addlast
bcdedit.exe -timeout 10
bcdedit.exe -set bootmenupolicy legacy
BCD加入的配置信息:
Windows 启动加载器
-------------------
标识符 {71a3c7fc-f751-4982-aec1-e958357e6813}
device partition=C:
path \Windows\system32\osloader.exe
description Patch Guard Disabled
inherit {bootloadersettings}
recoveryenabled No
nointegritychecks Yes
osdevice partition=C:
systemroot \Windows
kernel ntkrnlmp.exe
nx OptIn
三、UPGDSED浅析
主要对(二 . 3)的探究,原理浅析。
源码采用的是静态绕过PG和DSE。
1、PG
资料准备中,很快更新。
2、DSE
资料准备中,很快更新。
参考资料:
原文:
https://www.symantec.com/content/dam/symantec/docs/security-center/white-papers/assessment-windows-vista-kernel-mode-06-en.pdf
译文:
3、校验修改
修改了ntoskrnl.exe就必须修改winload.exe 的 ImgpValidateImageHash,因为ImgpValidateImageHash会对文件的数字签名和文件的完整性进行校验,修改头部字节让它返回STATUS_SUCCESS即可。
附言:
研究这些费了不少时间,而且研究MS Edge的保护也花了不少时间,等搞完后要好好研究内核的一些骚操作。
还有,此篇文章未完待续,因为1803还没搞定呢。
KID