以製作動作遊戲聞名世界的Capcom最近曝出烏龍事件。在Capcom出品的《街頭霸王5》一次更新中,它內置了一個用來防止玩家作弊的驅動程序Capcom.sys,然而這個反作弊驅動卻闖了大禍,剛發布不久就被曝光其實是一個高度危險的後門,它可以幫助任意程序獲得系統內核權限,當然也會被木馬病毒輕易利用,比如繞過沙箱、破壞殺毒軟體、HIPS等防護產品,完全瓦解系統安全體系。
Capcom中文名為卡普空株式會社,代表性遊戲有《生化危機》、《街頭霸王》、《鬼泣》等,可以說很多70後、80後玩家都是玩著Capcom的遊戲長大的。然而此次《街頭霸王5》的後門事件卻讓Capcom陷入窘境,為此專門致歉並發布了升級補丁。這裡360QVM團隊建議相關遊戲用戶儘快升級補丁,同時提醒各大安全廠商注意,儘快針對存在後門的Capcom.sys版本進行防禦。根據測試,目前國內外仍有大量殺毒軟體可以被惡意程序利用Capcom後門輕鬆擊潰。
以下360QVM團隊將對Capcom.sys進行深入分析,揭秘該驅動後門對系統安全造成的巨大隱患。
0x1 逆向分析Capcom.sys
Capcom.sys所做的就是關閉作業系統的安全機制並提升自己遊戲為管理員權限,目的在於能夠對系統上所有的文件進行操作。它預留了接口讓應用層的程序(遊戲)調用,來實現一些更高級、更自由的操作,比如防止遊戲內存修改,驗證正版用戶等。接下來開始逆向分析 Capcom.sys,看看此神奇的驅動到底做了什麼。。。
最關鍵的函數有如下5個:
1:關閉SMEP(Supervisor Mode Execution Protection)
那麼啥是SMEP呢?SMEP全稱是Supervisor Mode Execution Protection。監管模式執行保護。存在與CR4中的第20位處。
SMEP的引入是Intel考慮到系統安全而新增的機制。我們知道CPU提供了環權限的機制,也就是平常所說的ring0,ring3。當然還有ring1和ring2(甚至ring-1)。只不過windows作業系統只使用了2個環(ring0和ring3)。環的產生意味著權限的產生。不同環的權限等極也是不同的,環的數字越小,則權限越高。SMEP的存在就是為了防止不同環訪問不同權限的頁面而產生的。
在未開啟SMEP前,Supervisor Mode(ring0-2)所對應的page entry屬性可以是user或者Supervisor,也就是說page entry.u/s可以為0,也可以為1。User mode(ring-3)所對應的page entry屬性只能是user(page entry.u/s=0)。
在開啟SMEP後,Supervisor Mode(ring0-2)所對應的page entry.u/s只能為0。這也就意味著Supervisor Mode(ring0-2)將無法訪問User mode(ring3)的頁面。
Capcom.sys正是利用了這點,關閉了SMEP,使得ring0的模式可以訪問ring3的代碼,這裡所指的ring3的代碼也就是合法的shellcode了。不過這比shellcode更生猛,因為Capcom.sys可以直接訪問ring3的函數。
2:開啟SMEP(Supervisor Mode Execution Protection)
3.驅動的IOCtl通信函數(只取關鍵部分)
可以知道,當控制碼為0xAA012044時,代表的是32位模式,當控制碼為0xAA013044時,代表的是64位模式。此驅動樣本為64位,所以我們著重研究64位的控制碼0xAA013044即可。
4.漏洞利用函數
可以知道,所被調用的函數類型大致為void(*)(PVOID(*)(PUNICODE_STRING))。即該函數的第一個參數為MmGetSystemRoutineAddress的地址。
在這裡有一個非常關鍵的地方,條件判斷的第一句話,這裡猜想是Capcom為了防止此驅動濫用而設置的暗樁。所以我們構造shellcode的時候需要特別注意。
5.解密Device Name函數
// 解密設備名
// PWCHAR Funk(PWCHAR in_device_name,PWCHAR out_device_name)
_WORD *__fastcall deobfuscatetion_device_name_sub_103AC(_WORD *in_device_name, char *out_device_name)
{
_WORD *v2; // r8@1
signed __int64 v3; // rcx@1
__int16 v4; // ax@2
__int16 v5; // di@3
__int16 *v6; // rdx@3
signed __int16 v7; // r9@3
unsigned into v8; // er10@4
signed __int16 v9; // ax@5
unsigned __int16 v10; // cx@5
_WORD *v11; // rdi@16
signed __int64 v12; // rcx@16
bool v13; // zf@18
__int64 v14; // rcx@19
__int16 v15; // ax@20
__int16 v17[36]; // [sp+0h] [bp-48h]@1
v2 = in_device_name;
v3 = (char *)v17 - out_device_name;
do
{
v4 = *(_WORD *)out_device_name;
*(_WORD *)&out_device_name[v3] = *(_WORD *)out_device_name;
out_device_name += 2;
}
while ( v4 );
v5 = 0;
v6 = v17;
v7 = 21845;
if ( v17[0] )
{
while ( 1 )
{
v7 = v5 + 4 * v7;
v8 = (unsigned into)(unsigned __int16)*v6 >> 6;
if ( v8 - 1 > 2 )
break;
v9 = 0;
v10 = (((unsigned __int8)v7 ^ (unsigned __int8)*v6) - (_BYTE)v5 - (_BYTE)v8) & 0x3F;
if ( v10 >= 0xAu )
{
if ( v10 >= 0x24u )
goto LABEL_10;
v9 = v10 + 55;
}
else
{
v9 = v10 + 48;
}
if ( v10 >= 0x24u )
{
LABEL_10:
if ( v10 < 0x3Eu )
v9 = v10 + 61;
}
if ( v10 == 62 )
v9 = 46;
if ( v9 )
{
*v6 = v9;
++v6;
++v5;
if ( *v6 )
continue;
}
break;
}
}
v11 = v2;
v12 = -1i64;
do
{
if ( !v12 )
break;
v13 = *v11 == 0;
++v11;
--v12;
}
while ( !v13 );
v14 = 0i64;
do
{
v15 = v17[v14];
++v14;
v11[v14 - 2] = v15;
}
while ( v15 );
return v2;
}
這裡看的有點辣眼睛,但是我們不需要理他。因為我們可以直接使用WinObj來得知他創建的設備符號連結名為:Htsysm72FB。有了此符號連結名,我們可以使用CreateFile函數來打開它的驅動設備並且發送控制碼來利用了。。
至此,逆向分析到此結束,我們來總結一下:Capcom.sys初衷只是為Capcom自家人提供的一種反作弊的插件,從他的設備名字符串混淆與調用暗樁可以看出,他並不想讓別人使用它,但是這並沒有什麼用。從軟體安全角度上去看,此sys沒有加殼是被利用的最致命因素之一。攻擊者只需要繞過暗樁,即可調用它的驅動。
0x2 利用前的準備工作
基於之前的分析,我們知道了設備名稱的符號連接為Htsysm72FB,根據微軟的定義。我們需要在他前面加上\\.\。然後使用CreateFile函數來打開他的設備。
接著開始準備shellcode。
第一行,前8個字節是為了繞過暗樁而加入的,前8個字節需要填寫利用函數的入口地址(也就是第二行)。
第二行,實現的是CALL $+8處 等價於push第三行(利用函數的地址) && Rip=第四行(POP RAX)
第三行,為我們需要填寫的利用函數地址。
最後一行,跳向我們的利用函數地址處。
在該模板內填寫相應的內容即可。
最後,開始向Capcom.sys發送控制碼來利用此驅動。值得注意的是0xAA013044為64位模式,0xAA012044為32位模式。需要傳遞的shellcode為之前的模板+8處,以此來繞過暗樁。
0x3 基於Capcom.sys實現無籤名加載驅動
無籤名加載驅動的話題已經很老套了。
具體分析請參考j00ru的「A quick insight into the Driver Signature Enforcement「這篇文章
以及MJ0011的這篇pdf
http://www.powerofcommunity.net/poc2012/mj0011.pdf
結合兩位大牛的文章,我們知道在WIN7上,可以通過修改nt!g_CiEnabled為0來繞過,目的是讓作業系統以為你在WINPE模式中。在WIN8及以上此驗證轉移到了ci!g_CiOptions上。現在我們在WIN10 14393上做這個實驗,驗證同樣在ci!g_CiOptions。但是不同與WIN8的是,WIN10 已經把ci!g_CiOptions加入到了PatchGuard的豪華套餐中。倘若修改不還原或者修改時機恰巧撞遇PatchGuard的檢測。那麼一瞬間你將進入藍屏的節奏…關於PatchGuard,讀者可自行搜索相關內容,這裡不再展述。
1.尋找ci!g_CiOptions(Windows\System32\CI.dll)
可以發現,該變量存在於CipInitialize 函數中,但是此函數未導出,不過慶幸的是。CI.dll給我們導出了CiInitialize函數,改函數最後會調用CipInitialize。
那麼我們的思路很簡單,首先獲取導出函數地址CiInitialize,根據它找到CipInitialize函數,最後根據CipInitialize找到g_CiOptions,然後修改為8即可(由於在WIN10 14393版本上進入測試籤名模式時,該值為8)。當然得先保存一份之前的數值,便於還原。
2.注意要點
a.IRQL(中斷請求等極)
還記得sys的調用函數嗎,它的形式如下:
關閉中斷->調用Ring3利用函數->開啟中斷。
我們注意到,再執行我們的利用函數的過程中,中斷始終是處於關閉的狀態,也就是說我們的IRQL(中斷請求等極)一直處於Dispatch級別,而大多數內核函數調用的要求是IRQL==PASSIVE_LEVEL。這就會造成概率性藍屏。所以我們必須在我們的利用函數頭尾處加入_enable和_disable,來手動的配合它的流程,這樣我們就可以避免IRQL的問題了。
b.禁用KeStackAttachProcess(CR3切換)
由於該函數會切換CR3(頁目錄表基址)。並且最終返回到當前進程的CR3。而我們當前是在Ring0模式。所以顯示會發生奇妙的藍屏。。。
c.利用函數儘量簡短
因為在WIN10 14393版本上,經過測試SMEP已被加入PatchGuard豪華套餐中。所以需要儘快的將SMEP恢復,這也就意味著我們的利用函數需要儘量的簡短。當然了,時運不濟的話,可能就在那一瞬間就被檢測到了。
d.配合動態PatchGuard
一般而言,做到以上3點,加載/卸載驅動1-5次之間的藍屏機率是很小的。但是如果需要完美的話,那就要動態的幹PatchGuard了。我們知道,在WIN7以及WIN8已經有牛實現了動態幹PatchGuard並已放出,但是在WIN10上目前並沒有公開放出原始碼。不過國內已經有研究者實現了這一攻擊效果。
0x4 題外話
對於在微軟新籤名機制(具體請使用搜尋引擎搜索)下有籤名的朋友來說,這並沒有什麼用。但是如果被壞人利用了,那就比較尷尬了。因為此驅動有合法籤名,大多數殺毒軟體還沒有對其攔截,而當壞人進入內核後,那就可以想幹啥就幹啥了。
0x5 對各大安全廠商的建議
由於Capcom公司目前已經道歉,並承諾不再使用此類手段的情況來看。安全廠商完全可以把該Capcom.sys列入黑名單中,以此徹底絕殺針對該後門的一切利用。
聲明:CSDN登載此文出於傳遞更多信息之目的,並不意味著贊同其觀點或證實其描述。