系统安全二进制安全 [2022]不使用hypervisor接管windows内核异常 不使用hypervisor的情况下接管内核异常: how? 让我们检查一下内核处理流程: 触发异常后,在KdTrap中通过 KdpDebugRoutineSelect 来去进行异常处理选择(有调试器走1) ```cpp __int64 __fastcall KdTrap(int a1, int a2, int a3, int a4, char a5, char a6) { if ( KdpDebugRoutineSelect ) return KdpTrap_0(a1, a2, a3, a4, a5, a6); else return KdpStub_0(a1, a2, a3, a4, a5, a6); } ``` 在异常不等于STATUS_BREAKPOINT的情况下,也就是不是int3中断的情况下,走到kdreport ```cpp char __fastcall KdpTrap_0( __int64 trapInfo, __int64 commandString, __int64 commandType, __int64 debuggerContext, char response) { char v5; // dl _QWORD *contextPointer; // rbx unsigned __int64 addressValue; // rax __int64 previousAddressValue; // rdi int subtractionResult1; // eax int subtractionResult2; // eax int subtractionResult3; // eax int subtractionResult4; // eax int printFunctionReturnValue; // eax __int64 currentAddressValue; // rax v5 = 0; contextPointer = (_QWORD *)debuggerContext; if ( *(_DWORD *)commandType != 0x80000003 ) return KdpReport(trapInfo, 0, commandType, debuggerContext); ``` 只要不是 fast error或者单步异常,走到KdExitDebugger 里面 ```cpp if ( *a3 == -1073740768 || (unsigned int)(v6 + 2147483645) <= 1 || (unsigned int)(v6 - 1073741854) <= 1 || (NtGlobalFlag & 1) != 0 ) { v9 = a6; if ( a6 || (unsigned int)v6 > 0x4000001D && v6 != 0xC0000037 && v6 < 0x40000020 ) goto LABEL_6; } else { v9 = a6; if ( a6 ) { LABEL_6: v10 = ((__int64 (*)(void))KdEnterDebugger)(); CurrentPrcb = KeGetCurrentPrcb(); v12 = v10; KdpCopyContext(*(_QWORD *)&CurrentPrcb[1].PPPagedLookasideList[3].FreeMisses, *(unsigned int *)(a4 + 48), a4); KiSaveProcessorControlState((__int64)&CurrentPrcb->ProcessorState.SpecialRegisters.MsrLStar, v13); v14 = *(_QWORD *)&CurrentPrcb[1].PPPagedLookasideList[3].FreeMisses; LOBYTE(v15) = v9; v16 = *(_DWORD *)(v14 + 48); v17 = KdpReportExceptionStateChange((__int64)a3, v14, v15); KdpCopyContext(a4, v16, *(_QWORD *)&CurrentPrcb[1].PPPagedLookasideList[3].FreeMisses); KiRestoreProcessorControlState(&CurrentPrcb->ProcessorState.SpecialRegisters.MsrLStar); LOBYTE(v18) = v12; KdExitDebugger_0(v18); result = v17; KdpControlCPressed_0 = 0; return result; } } ``` KdExitDebugger在处理完一些必要的状态后,走到 KeThawExecution_0(v6);里面 而PoAllProcIntrDisabled_0只要为0 就会调用我们的老朋友 **KeQueryPerformanceCounter** ```cpp __int64 __fastcall KeThawExecution_0(char a1) { char v2; // di __int64 v3; // rcx unsigned __int8 v4; // bl unsigned __int64 v5; // rcx unsigned __int64 v6; // rax struct _KPRCB *CurrentPrcb; // rcx __int64 result; // rax v2 = 0; if ( (KiFreezeFlag & 8) == 0 ) v2 = KdPortLocked; ((void (__fastcall *)(_QWORD, _QWORD))off_401A88[0])(0i64, 0i64); if ( !PoAllProcIntrDisabled_0 ) { MEMORY[0xFFFFF78000000350] = KeQueryPerformanceCounter(0i64).QuadPart; KiInterruptTimeErrorAccumulator = 0i64; } ``` 为什么说 **KeQueryPerformanceCounter**是我们的老朋友呢,因为这个hal层的吊东西已经被日烂了,从infinity hook到infinity hook V2. v3 v4 他已经被日烂了 这次被日的原因和infinity hook v4一模一样,是这一步出了问题: ```cpp v2 = HalpPerformanceCounter; if ( *(_DWORD *)(HalpPerformanceCounter + 0xE4) == 5 ) { v37 = 10000000i64; if ( HalpTimerReferencePage ) { if ( (*(_DWORD *)(HalpPerformanceCounter + 224) & 0x10000) != 0 ) v20 = *(_QWORD *)(HalpPerformanceCounter + 72) + (unsigned int)(*(_DWORD *)(HalpPerformanceCounter + 0x50) * HIDWORD(KeGetPcr()[1].LockArray)); else v20 = *(_QWORD *)(HalpPerformanceCounter + 72); v21 = (*(__int64 (__fastcall **)(__int64))(HalpPerformanceCounter + 112))(v20); v22 = MEMORY[0xFFFFF780000003B8]; v10.QuadPart = v22 + RtlUnsignedMultiplyHigh(v21, *((_QWORD *)HalpTimerReferencePage + 1)); } else { do { v24 = *(_QWORD *)(v2 + 0xD0); do { v25 = *(_QWORD *)(v2 + 0xC8); InternalData = HalpTimerGetInternalData(v2); v27 = (*(__int64 (__fastcall **)(__int64))(v2 + 0x70))(InternalData); _InterlockedOr(v36, 0); v28 = *(_QWORD *)(v2 + 200); } while ( v25 != v28 ); } ``` 注意其中的 ```cpp v25 = *(_QWORD *)(v2 + 0xC8); InternalData = HalpTimerGetInternalData(v2); v27 = (*(__int64 (__fastcall **)(__int64))(v2 + 0x70))(InternalData); ``` v2+0x70指向的是HalpHvCounterQueryCounter 在最新的infinity hook中也是他出了毛病,没有被PG保护 因此在满足下列条件后,即可进行内核VEH操作: ```cpp KdpDebugRoutineSelect = 1 PoAllProcIntrDisabled = 0 HalpPerformanceCounter + 0xDC != 0x40 ``` **这会PG吗?** 不 他不会.别问咋知道的,某大型软件现在正在用它全局接管内核异常 完整调用栈: ```cpp 00 fffff803`3d12cfa8 fffff803`3d21ecf8 hal!HalpTimerGetInternalData 01 fffff803`3d12cfb0 fffff803`3d4fd046 hal!KeQueryPerformanceCounter+0x168 02 fffff803`3d12cff0 fffff803`3dabee65 nt!KeThawExecution+0x4a 03 fffff803`3d12d020 fffff803`3d4f4d34 nt!KdExitDebugger+0xb1 04 fffff803`3d12d050 fffff803`3dac2419 nt!KdpReport+0xd8 05 fffff803`3d12d090 fffff803`3d2b9b90 nt!KdpTrap+0x14d 06 fffff803`3d12d0e0 fffff803`3d2b97b0 nt!KdTrap+0x2c 07 fffff803`3d12d120 fffff803`3d453602 nt!KiDispatchException+0x1e0 08 fffff803`3d12d7d0 fffff803`3d44ccf0 nt!KiExceptionDispatch+0xc2 09 fffff803`3d12d9b0 fffff803`3d449471 nt!KiBreakpointTrap+0x370 0a fffff803`3d12db48 fffff803`3d4c2a7e nt!DbgBreakPointWithStatus+0x1 0b fffff803`3d12db50 fffff803`3d4810a4 nt!KdCheckForDebugBreak+0xdbbe2 0c fffff803`3d12db80 fffff803`3d309b8d nt!KeAccumulateTicks+0x1743e4 0d fffff803`3d12dbe0 fffff803`3d30ac73 nt!KiUpdateRunTime+0x5d 0e fffff803`3d12dc30 fffff803`3d21e883 nt!KeClockInterruptNotify+0x8f3 0f fffff803`3d12df40 fffff803`3d361195 hal!HalpTimerClockInterrupt+0x63 10 fffff803`3d12df70 fffff803`3d4420ea nt!KiCallInterruptServiceRoutine+0xa5 11 fffff803`3d12dfb0 fffff803`3d4426d7 nt!KiInterruptSubDispatchNoLockNoEtw+0xea 12 fffff803`3d11f540 fffff803`3d238a0f nt!KiInterruptDispatchNoLockNoEtw+0x37 13 fffff803`3d11f6d8 fffff803`3d413925 hal!HalProcessorIdle+0xf 14 fffff803`3d11f6e0 fffff803`3d30c3d8 nt!PpmIdleDefaultExecute+0x15 15 fffff803`3d11f710 fffff803`3d30bc05 nt!PpmIdleExecuteTransition+0x648 16 fffff803`3d11fb00 fffff803`3d44435c nt!PoIdle+0x345 17 fffff803`3d11fc60 00000000`00000000 nt!KiIdleLoop+0x2c ``` 阅读全文 2022-12-21 huoji 2 条评论
系统安全二进制安全C/C++一线开发 [2022]终端安全: 一文从浅入深介绍windows WFP框架 Windows 中的 WFP 框架是一个用于网络流量管理的工具,它可以帮助用户控制数据包在网络中的流动,从而提高网络安全性和性能。本文将深入介绍 Windows 中的 WFP 框架,并通过一个简单的实例(基于 WFP 框架的 DNS 流量解析工具)让大家更好地理解它. 阅读全文 2022-12-10 huoji 0 条评论
系统安全C/C++ [2018]一些代码片段 很早之前写的(4年了,时光飞逝). 代码风格可能不太好,而且可能有bug.凑合看.懒得改了 修改进程名字 ```cpp void FuckName(PUNICODE_STRING v1, WCHAR* ProcessName) { if (v1->Buffer != 0) { RtlZeroMemory(v1->Buffer, v1->MaximumLength); RtlCopyMemory(v1->Buffer, ProcessName, wcslen(ProcessName) * 2); v1->Length = wcslen(ProcessName) * 2; } } BOOLEAN PatchImageFileName(PEPROCESS Process, char* cName) { char szNameBuff[15] = { 0 }; UCHAR* szProcessBuff = NULL; size_t cNamelen = 0; cNamelen = strlen(cName); RtlZeroMemory(szNameBuff, sizeof(szNameBuff)); if (cNamelen > 15) RtlCopyMemory(szNameBuff, cName, sizeof(szNameBuff)); else RtlCopyMemory(szNameBuff, cName, cNamelen); szProcessBuff = PsGetProcessImageFileName(Process); RtlZeroMemory(szProcessBuff, sizeof(szNameBuff)); RtlCopyMemory(szProcessBuff, szNameBuff, sizeof(szNameBuff)); return TRUE; } void PatchPEB(PEPROCESS Process, WCHAR* ProcessName) { KeAttachProcess((PEPROCESS)Process); DWORD64 _peb = *(PDWORD64)((PUCHAR)Process + g_OsData.peb); DWORD64 peb_ProcessParameters = *(PDWORD64)((ULONG_PTR)_peb + g_OsData.peb_ProcessParameters); PUNICODE_STRING peb_ImagePathName = (PUNICODE_STRING)((ULONG_PTR)peb_ProcessParameters + g_OsData.peb_ImagePathName); PUNICODE_STRING peb_WindowTitle = (PUNICODE_STRING)((ULONG_PTR)peb_ProcessParameters + g_OsData.peb_WindowTitle); PUNICODE_STRING peb_CommandLine = (PUNICODE_STRING)((ULONG_PTR)peb_ProcessParameters + g_OsData.peb_CommandLine); FuckName(peb_ImagePathName, ProcessName); FuckName(peb_WindowTitle, ProcessName); FuckName(peb_CommandLine, ProcessName); KeDetachProcess(); } BOOLEAN PathSeAuditProcessCreationInfo(PEPROCESS Process, WCHAR* ProcessName) { PUNICODE_STRING Name; PUNICODE_STRING SelocateName; SeLocateProcessImageName(Process, &SelocateName); ExFreePool(SelocateName); Name = (PUNICODE_STRING)(*(PULONG_PTR)((ULONG_PTR)Process + g_OsData.SeAuditProcessCreationInfo));//+0x468 SeAuditProcessCreationInfo FuckName(Name, ProcessName); return TRUE; } ``` 启动的时候让processnotify/imageloadnotify暂时无效(会PG,所以要快速切换) ```cpp //参数1是启用或者关闭 treadcallbacks 参数2是启用或者关闭imageloadcallbacks ULONG64 g_PspNotifyEnableMaskAddr = 0; ULONG64 GetNotifyVarAddress() { if (g_PspNotifyEnableMaskAddr == 0) { ULONG64 i = 0; PULONG64 pAddrOfFnc = 0; UNICODE_STRING fncName; //8B 05 ?? ?? ?? ?? A8 01 75 09 F0 0F BA CHAR pattern_PspNotifyEnableMask[] = "\x8B\x05\xCC\xCC\xCC\xCC\xA8\x01\x75\x09\xF0\x0F\xBA"; NTSTATUS status = UtilScanSection(g_KernelBase, "PAGE", (PCUCHAR)pattern_PspNotifyEnableMask, 0xCC, sizeof(pattern_PspNotifyEnableMask) - 1, (PVOID*)&g_PspNotifyEnableMaskAddr); if (!NT_SUCCESS(status)) { //DebugPrint("[DebugMessAge] g_PspNotifyEnableMaskAddr not found! :( \n"); return 0; } else { //g_PspNotifyEnableMaskAddr = g_PspNotifyEnableMaskAddr + 5; LONG OffsetAddr = 0; memcpy(&OffsetAddr, (UCHAR*)(g_PspNotifyEnableMaskAddr + 2), 4); pAddrOfFnc = (ULONG64*)(OffsetAddr + g_PspNotifyEnableMaskAddr + 0x6); //DebugPrint("[DebugMessAge] g_PspNotifyEnableMaskAddr : %08X \n", pAddrOfFnc); g_PspNotifyEnableMaskAddr = (ULONG64)pAddrOfFnc; return (ULONG64)g_PspNotifyEnableMaskAddr; } } else { return (ULONG64)g_PspNotifyEnableMaskAddr; } } VOID ChangeNotifyAddress(BOOLEAN enableImage) { ULONG64 varaddress = GetNotifyVarAddress(); if (varaddress) { ULONG val = *(ULONG*)(varaddress); if (!enableImage) { g_InvalidationLoadImage = true; UNSETBIT(val, 0); } else { g_InvalidationLoadImage = false; SETBIT(val, 0); } *(ULONG*)(varaddress) = val; } } ``` 句柄降权 ```cpp BOOLEAN StripHandleCallback_win10( IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry, IN HANDLE Handle, IN PVOID EnumParameter ) { BOOLEAN result = FALSE; POBJECT_TYPE ObjectType = NULL; ULONG64 Object = 0; if (g_FlagProcessPid == (HANDLE)-1) return FALSE; if (ExpIsValidObjectEntry(HandleTableEntry)) { POBJECT_TYPE ObjectType = NULL; ULONG64 Object = 0; if (Handle == (HANDLE)EnumParameter) { HandleTableEntry->GrantedAccessBits = (SYNCHRONIZE | THREAD_QUERY_LIMITED_INFORMATION); //DebugPrint("Fuck Handle: %08X \n", Handle); goto _exit; } } else { return FALSE; } _exit: // Release implicit locks _InterlockedExchangeAdd8((char*)&HandleTableEntry->VolatileLowValue, 1); // Set Unlocked flag to 1 if (HandleTable != NULL && HandleTable->HandleContentionEvent) ExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL); return FALSE; } BOOLEAN StripHandleCallback_win7(PHANDLE_TABLE_ENTRY HandleTableEntry, HANDLE Handle, PVOID EnumParameter) { POBJECT_TYPE ObjectType = NULL; ULONG64 Object = 0; if (g_FlagProcessPid == (HANDLE)-1) return FALSE; if (ExpIsValidObjectEntry(HandleTableEntry)) { if (Handle == (HANDLE)EnumParameter) { HandleTableEntry->GrantedAccessBits = (SYNCHRONIZE | THREAD_QUERY_LIMITED_INFORMATION); //DebugPrint("Fuck Handle: %08X \n", Handle); return FALSE; } } return FALSE; } VOID StripHandlePermission() { PSYSTEM_HANDLE_INFORMATION_EX HandleInfo = QueryHandleTable(); if (HandleInfo) { for (int i = 0; i < HandleInfo->NumberOfHandles; i++) { //7 是 process 属性 if (HandleInfo->Information[i].ObjectTypeNumber == 7 || HandleInfo->Information[i].ObjectTypeNumber == OB_TYPE_INDEX_PROCESS || HandleInfo->Information[i].ObjectTypeNumber == OB_TYPE_INDEX_THREAD) { if (g_FlagProcessPid == (HANDLE)-1) break; if (HandleInfo->Information[i].ProcessId == (ULONG)g_FlagProcessPid || HandleInfo->Information[i].ProcessId == 4) continue; bool bCheck = ((HandleInfo->Information[i].GrantedAccess & PROCESS_VM_READ) == PROCESS_VM_READ || (HandleInfo->Information[i].GrantedAccess & PROCESS_VM_OPERATION) == PROCESS_VM_OPERATION || (HandleInfo->Information[i].GrantedAccess & PROCESS_VM_WRITE) == PROCESS_VM_WRITE); PEPROCESS pEprocess = (PEPROCESS)HandleInfo->Information[i].Object; if (pEprocess) { HANDLE handle_pid = *(PHANDLE)((PUCHAR)pEprocess + g_OsData.UniqueProcessId); HANDLE handle_pid2 = *(PHANDLE)((PUCHAR)pEprocess + g_OsData.InheritedFromUniqueProcessId); if (bCheck && (handle_pid == g_FlagProcessPid || handle_pid2 == g_FlagProcessPid)) { pEprocess = NULL; NTSTATUS status = PsLookupProcessByProcessId((HANDLE)HandleInfo->Information[i].ProcessId, &pEprocess); if (NT_SUCCESS(status)) { //DebugPrint("Full Acess Handle! pid: %d \n", HandleInfo->Information[i].ProcessId); PHANDLE_TABLE HandleTable = *(PHANDLE_TABLE*)((PUCHAR)pEprocess + g_OsData.ObjTable); ExEnumHandleTable(HandleTable, g_isWin7 ? (DWORD64*)&StripHandleCallback_win7 : (DWORD64*)&StripHandleCallback_win10, (PVOID)HandleInfo->Information[i].Handle, NULL); ObDereferenceObject(pEprocess); } } } } } ExFreePoolWithTag(HandleInfo, POOL_TAG); } DebugPrint("StripHandlePermission Success \n"); } ``` 阅读全文 2022-11-10 huoji 0 条评论
系统安全C/C++Shellcode [2022]防止第三方DLL注入到程序中 很多恶意软件、木马、病毒、游戏外挂会进行注入然后干坏事,比如进行API hook监听行为等. 本方法适用于win8以上使用系统机制阻止第三方的dll注入 阅读全文 2022-11-04 huoji 3 条评论
系统安全二进制安全C/C++ [2022]HyperMap -通过PTE自引用直接读取物理内存 在hypervisor中的host直接操作guest物理内存的情况中,我遇到了一个棘手的问题,即所有的API都是page_code的.使用他们不安全(即便是AMD有GIF的情况下). 所以需要设计一个高效、快速的内存访问系统.即通过设置一个魔术数字,实现base + offset的guest物理内存读取.我把它称之为hypermap 阅读全文 2022-10-28 huoji 0 条评论