VT下的SsdtHook

利用 VT 来达到 Hook SSDT 的目的

思路:

1. 我们直接 Hook 原本 KiFastCallEntry 地址

// 修改 sysenter 指令的EIP
__writemsr(0x176, (ULONG)MyKiFastCallEntry);

2. 在我们的 KiFastCallEntry 地址中替换 SSDT 地址

VOID _declspec(naked) MyKiFastCallEntry(VOID)
{
	__asm
	{
		cmp eax, 0x1000; 如果是影子表(不处理)
		jge jmp_oldAddress; 跳回原来的 KiFastCallEntry

		cmp [FuncTable + eax * 4], 0; 如果该函数没被Hook
		jz	jmp_oldAddress;

		mov     ecx, 23h
		push    30h
		pop     fs
		mov     ds, cx
		mov     es, cx
		mov     ecx, fs : [0x40];
		mov     esp, [ecx + 4]
		push    23h
		push    edx
		pushfd

		push    2
		add     edx, 8
		popfd
		or byte ptr[esp + 1], 2
		push    1Bh
		push    dword ptr ds : [0FFDF0304h]
		push    0
		push    ebp
		push    ebx
		push    esi
		push    edi
		mov     ebx, fs :[0x1c]
		push    3Bh
		mov     esi, [ebx + 0x124]
		push    dword ptr[ebx]
		mov     dword ptr[ebx], 0FFFFFFFFh
		mov     ebp, [esi + 0x28]
		push    1
		sub     esp, 48h
		sub     ebp, 29Ch
		mov		byte ptr[esi + 0x13A], 1
		cmp     ebp, esp
		jnz     jmp_KiTrap06;

		and     dword ptr[ebp + 2Ch], 0
		test	byte ptr[esi + 3], 0DFh
		mov[esi + 0x128], ebp
		jnz     Dr_FastCallDrSave

	handler1:
		mov     ebx, [ebp + 0x60]
		mov     edi, [ebp + 0x68]
		mov[ebp + 0Ch], edx
		mov		dword ptr[ebp + 8], 0BADB0D00h
		mov[ebp + 0], ebx
		mov[ebp + 4], edi
		sti

	handler2:
		mov     edi, eax;
		shr     edi, 8;
		and     edi, 10h;
		mov     ecx, edi; 
		lea		edi, [MyKeServiceDescriptorTable + edi]; 修改为我们的 SSDT 表
		//add     edi, [esi + 0xBC]
		mov     ebx, eax
		jmp		g_KiFastCallEntryRet;

	Dr_FastCallDrSave:
		test    dword ptr[ebp + 70h], 20000h
		jnz     Dr_FastCallDrSave1
		test    byte ptr[ebp + 6Ch], 1
		jz      handler1

	Dr_FastCallDrSave1:
		mov     ebx, dr0
		mov     ecx, dr1
		mov     edi, dr2
		mov[ebp + 18h], ebx
		mov[ebp + 1Ch], ecx
		mov[ebp + 20h], edi
		mov     ebx, dr3
		mov     ecx, dr6
		mov     edi, dr7
		mov[ebp + 24h], ebx
		mov[ebp + 28h], ecx
		xor		ebx, ebx
		mov[ebp + 2Ch], edi
		mov     dr7, ebx
		mov     edi, fs : [20h]
		mov     ebx, [edi + 2F4h]
		mov     ecx, [edi + 2F8h]
		mov     dr0, ebx
		mov     dr1, ecx
		mov     ebx, [edi + 2FCh]
		mov     ecx, [edi + 300h]
		mov     dr2, ebx
		mov     dr3, ecx
		mov     ebx, [edi + 304h]
		mov     ecx, [edi + 308h]
		mov     dr6, ebx
		mov     dr7, ecx
		jmp     handler1

	jmp_KiTrap06:
		mov     ecx, fs : [40h]
		mov     esp, [ecx + 4]
		push    0
		push    0
		push    0
		push    0
		push    23h
		push    0
		push    20202h
		push    1Bh
		push    0
		jmp     gJmp_KiTrap06;
	jmp_oldAddress:
		jmp g_oldKiFastCallEntry;
	}
}

3. 利用 VT 当其要读取 MSR 0x176,给他原来的 KiFastCallEntry 地址

void VMX_Rdmsr()
{
	GuestSaveRegister * guestRegister = GetGuestSaveRegisterByCpuNumber();
	
	switch (guestRegister->Ecx)
	{
	case MSR_IA32_SYSENTER_EIP:
		// 如果是读取 MSR 0x176, 给他原来 KiFastCallEntry 地址
		guestRegister->Eax = g_oldKiFastCallEntry;

		break;
	case MSR_IA32_SYSENTER_ESP:
		guestRegister->Eax = asm_vmxread(GUEST_SYSENTER_ESP);
		break;
	case MSR_IA32_SYSENTER_CS:
		guestRegister->Eax = asm_vmxread(GUEST_SYSENTER_CS);
		break;
	default:
		guestRegister->Eax = __readmsr(guestRegister->Ecx);
		break;
	}
}

从而达到隐藏 Hook 的目的

项目 Code 打包在附件

SsdtHookByVt

原创文章,转载请注明: 转载自Windows内核安全驱动编程

本文链接地址: VT下的SsdtHook

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注