43 #define KERNEL_SEARCH_LIMIT (16 * ONE_MEGABYTE) 55 #define IDLE_THREAD_OFFSET_PCR ((gGuest.Guest64) ? 0x198 : 0x12C) 58 #define PROCESS_SEARCH_LIMIT_THREAD_UPPER (DWORD)((gGuest.Guest64) ? 0x220 : 0x150) 61 #define PROCESS_SEARCH_LIMIT_THREAD_LOWER (DWORD)((gGuest.Guest64) ? 0x210 : 0x150) 69 #define CR3_OFFSET_IN_KPROCESS (DWORD)((gGuest.Guest64) ? 0x28 : 0x18) 94 const DWORD maxSecCount = 10;
95 const DWORD objCount = 3;
97 DWORD objectsFound = 0;
103 if (NULL == pSections)
109 pSections, §ionCount);
112 ERROR(
"[ERROR] IntPeGetSectionHeadersByName failed for `ALMOSTRO`: 0x%08x\n", status);
113 goto cleanup_and_exit;
117 &pSections[sectionCount], NULL);
120 ERROR(
"[ERROR] IntPeGetSectionHeadersByName failed for `.data`: 0x%08x\n", status);
121 goto cleanup_and_exit;
127 for (
DWORD i = 0; i < sectionCount; i++)
132 for (
DWORD j = 0; j < pageCount; j++)
143 QWORD target = kernelBase + offset;
145 pPage.ptrValue = NULL;
152 ERROR(
"[ERROR] Failed mapping page %d of section %d: 0x%08x\n", j, i, status);
158 pPage.ptrValue = pKernel + offset;
162 if (j == pageCount - 1)
175 void *hostPtr =
gGuest.
Guest64 ? (
void *)&pPage.pPage64[parsed] : (
void *)&pPage.pPage32[parsed];
188 ((p & 0xFFFFFFFF00000000) == 0xFFFFFFFF00000000)))
193 if (pSec->
Name[0] !=
'.')
205 TRACE(
"[INTRO-INIT] Found loaded module list: 0x%llx\n", target);
221 TRACE(
"[INTRO-INIT] Found process list head: 0x%llx\n", target);
230 if (pSec->
Name[0] ==
'.')
243 TRACE(
"[INTRO-INIT] Found PFN database: 0x%llx\n", p);
257 if (objectsFound == objCount)
268 if (objectsFound == objCount)
275 if (objectsFound < objCount)
282 ERROR(
"[ERROR] MmPfnDatabase not found!\n");
287 ERROR(
"[ERROR] PsLoadedModuleList not found!\n");
292 ERROR(
"[ERROR] PsActiveProcessHead not found!\n");
301 if (NULL != pSections)
327 QWORD systemProcess = 0;
332 TRACE(
"[INTRO-INIT] IntWinGuestFindKernelObjects%d: 0x%08x\n",
gGuest.
Guest64 ? 64 : 32, status);
342 ERROR(
"[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
352 ERROR(
"[ERROR] IntKernVirtMemFetchQword failed: 0x%08x\n", status);
406 for (
DWORD i = 256; i < 512; i++)
410 LOG(
"[SELFMAP] Found index = %d (0x%x)\n", i, i);
419 ERROR(
"[ERROR] Self map index not found!\n");
486 for (
DWORD i = 256; i < 512; i++)
498 goto _cleanup_and_leave;
504 for (
DWORD i = 4; i < 512; i++)
509 goto _cleanup_and_leave;
520 WARNING(
"[WARNING] We have a translation, but different physical addresses for 0x%016llx: " 521 "0x%016llx != 0x%016llx\n", KernelAddress, GvaTranslation->PhysicalAddress, nkt.
PhysicalAddress);
524 goto _cleanup_and_leave;
559 const QWORD startPhys = StartPhysical;
560 const QWORD endPhys = EndPhysical;
561 QWORD currentCr3 = 0;
564 if (NULL == SystemCr3)
572 ERROR(
"[ERROR] IntCr3Read failed: 0x%08x\n", status);
576 if (currentCr3 >= startPhys && currentCr3 < endPhys)
578 LOG(
"[WINGUEST STATIC] The current CR3 0x%016llx is already the system cr3!\n", currentCr3);
579 *SystemCr3 = currentCr3;
587 ERROR(
"[ERROR] IntTranslateVirtualAddressEx failed for 0x%016llx with cr3 0x%016llx: 0x%08x\n",
588 KernelAddress, currentCr3, status);
624 initEntry = initEntry->
Flink;
629 ERROR(
"[ERROR] IntSwapMemRemoveTransaction failed for %llx:%x: 0x%08x\n",
660 ERROR(
"[ERROR] IntRegisterBreakpointHandler failed: 0x%08x\n", status);
698 ERROR(
"[ERROR] IntWinDrvObjUninit failed: 0x%08x\n", status);
727 ERROR(
"[ERROR] IntCr4Unprotect failed: 0x%08x\n", status);
757 ERROR(
"[ERROR] IntWinIdtProtectAll failed: 0x%08x\n", status);
767 ERROR(
"[ERROR] IntMsrSyscallProtect failed: 0x%08x\n", status);
777 ERROR(
"[ERROR] IntCr4Protect failed: 0x%08x\n", status);
787 ERROR(
"[ERROR] IntIdtrProtect failed: 0x%08x\n", status);
797 ERROR(
"[ERROR] IntGdtrProtect failed: 0x%08x\n", status);
807 ERROR(
"[ERROR] IntWinSudProtectSudExec failed: 0x%08x\n", status);
817 ERROR(
"[ERROR] IntWinSudProtectIntegrity failed: 0x%08x\n", status);
827 ERROR(
"[ERROR] IntWinIntObjProtect failed: 0x%08x\n", status);
859 ERROR(
"[ERROR] %s not found: 0x%08x\n",
"PsCreateSystemThread", status);
868 ERROR(
"[ERROR] %s not found: 0x%08x\n",
"ExAllocatePoolWithTag", status);
877 ERROR(
"[ERROR] %s not found: 0x%08x\n",
"ExFreePoolWithTag", status);
881 TRACE(
"[INTRO-INIT] Found API function ExFreePoolWithTag @ 0x%016llx...\n", gWinGuest->
ExFreePoolWithTag);
886 ERROR(
"[ERROR] %s not found: 0x%08x\n",
"NtBuildNumber", status);
893 ERROR(
"[ERROR] Failed getting NtBuildNumber value: %08x\n", status);
897 TRACE(
"[INTRO-INIT] Found NtBuildNumber @ 0x%016llx with value 0x%08x...\n",
903 ERROR(
"[ERROR] %s not found: 0x%08x\n",
"NtBuildLab", status);
910 ERROR(
"[ERROR] Failed getting NtBuildLab value for kernel base 0x%016llx:0x%08x\n",
gGuest.
KernelVa, status);
914 TRACE(
"[INTRO-INIT] Found NtBuildLab @ 0x%016llx with value: `%s`\n",
922 ERROR(
"[ERROR] %s not found: 0x%08x\n",
"KeServiceDescriptorTable RVA", status);
929 ERROR(
"[ERROR] Failed getting KeServiceDescriptorTable value: %08x\n", status);
938 ERROR(
"[ERROR] Failed getting KeServiceDescriptorTable number of services: %08x\n", status);
944 ERROR(
"[ERROR] The number of services in the SSDT is higher than expected: %u\n",
949 TRACE(
"[INTRO-INIT] Found KeServiceDescriptorTable @ 0x%016llx with table at 0x%016llx and %d functions...\n",
975 #define WIN_SHARED_USER_DATA_OFFSET_PRODUCT 0x264 999 *ProductType = productType;
1003 #undef WIN_SHARED_USER_DATA_OFFSET_PRODUCT 1032 ERROR(
"[ERROR] IntWinGuestResolveImports failed: 0x%08x\n", status);
1036 goto leave_and_unload;
1047 goto leave_and_unload;
1057 WARNING(
"[WARNING] IntWinGuestFetchProductType failed: 0x%08x, will not be able to determine whether it is a " 1058 "server or not\n", status);
1071 goto leave_and_unload;
1090 ERROR(
"[ERROR] IntWinGuestFindKernelObjects failed: 0x%08x\n", status);
1096 WARNING(
"[WARNING] Introcore load was aborted!\n");
1099 goto leave_and_unload;
1102 TRACE(
"[INTRO-INIT] Kernel objects successfully identified!\n");
1107 ERROR(
"[ERROR] IntWinAgentInjectTrampoline failed: 0x%08x\n", status);
1108 goto leave_and_unload;
1114 ERROR(
"[ERROR] IntWinApiHookAll failed: 0x%08x\n", status);
1115 goto leave_and_unload;
1121 ERROR(
"[ERROR] IntSwapgsStartMitigation failed: 0x%08x\n", status);
1122 goto leave_and_unload;
1128 ERROR(
"[ERROR] IntWinDrvIterateLoadedModules failed: 0x%08x\n", status);
1129 goto leave_and_unload;
1135 ERROR(
"[ERROR] Failed finding kernel module!\n");
1136 goto leave_and_unload;
1139 LOG(
"[INTRO-INIT] Kernel loaded @ 0x%016llx size of image = 0x%llx timedate stamp = 0x%08x\n",
1145 ERROR(
"[ERROR] IntWinHalCreateHalData failed: 0x%08x\n", status);
1146 goto leave_and_unload;
1152 ERROR(
"[ERROR] IntWinProcIterateGuestProcesses failed: 0x%08x\n", status);
1153 goto leave_and_unload;
1159 ERROR(
"[ERROR] IntWinGuestActivateProtection failed: 0x%08x\n", status);
1160 goto leave_and_unload;
1168 ERROR(
"[ERROR] IntVeDeployAgent failed: 0x%08x\n", status);
1173 TRACE(
"[WINGUEST] Ensuring no thread will return into our hooks!\n");
1178 ERROR(
"[ERROR] IntThrSafeCheckThreads failed: 0x%08x\n", status);
1179 goto leave_and_unload;
1186 TRACE(
"[WINGUEST] Introspection successfully initialized!\n");
1255 ERROR(
"[ERROR] Callback came after we have no more sections to read...\n");
1257 goto resume_and_exit;
1266 TRACE(
"[WINGUEST STATIC] Since we are called asynchronously we will finish the initialization...\n");
1271 ERROR(
"[ERROR] IntWinGuestFinishInit failed: 0x%08x\n", status);
1276 if (Flags & SWAPMEM_FLAG_ASYNC_CALL)
1311 DWORD secStartOffset, secCount;
1316 unmapNtHeaders =
FALSE;
1323 ERROR(
"[ERROR] IntPeValidateHeader failed: 0x%08x\n", status);
1329 ERROR(
"[ERROR] Inconsistent MZPE image!\n");
1351 ERROR(
"[ERROR] Failed mapping VA 0x%016llx to host: 0x%08x\n",
1356 unmapNtHeaders =
TRUE;
1383 ERROR(
"[ERROR] Failed mapping VA 0x%016llx to host: 0x%08x\n",
1388 unmapNtHeaders =
TRUE;
1403 ERROR(
"[ERROR] Sections get outside the first page. We don't support this yet!\n");
1409 ERROR(
"[ERROR] Sections get outside the first page. We don't support this yet!\n");
1431 for (
DWORD i = 0; i < secCount; i++)
1433 DWORD secActualSize;
1442 ERROR(
"[ERROR] We cannot have a section starting at 0!\n");
1449 ERROR(
"[ERROR] We cannot have a section starting at 0!\n");
1460 ERROR(
"[ERROR] Section %d seems corrupted: sizeOfImage = 0x%x, secstart = 0x%x, secsize = 0x%x\n",
1467 (0 == memcmp(pSec->
Name,
"INITKDBG",
sizeof(
"INITKDBG") - 1) ||
1468 (0 == memcmp(pSec->
Name,
"ERRATA",
sizeof(
"ERRATA") - 1))))
1483 ERROR(
"[ERROR] IntKernVirtMemRead failed for 0x%016llx -> 0x%016llx %s: 0x%08x\n",
1486 pSec->
Name, status);
1506 void *swapHandle = NULL;
1515 pSwp->
Size = secActualSize;
1519 WARNING(
"Section %d / %d is not in memory, will do a swap mem read\n", i, secCount);
1532 ERROR(
"[ERROR] IntSwapMemReadData failed: 0x%08x\n", status);
1537 if (NULL != swapHandle)
1544 if (retSize != secActualSize)
1546 ERROR(
"We requested %08x bytes, but got %08x!\n", secActualSize, retSize);
1558 TRACE(
"[WINGUEST STATIC] All sections were present in memory!\n");
1563 ERROR(
"[ERROR] IntWinGuestFinishInit failed: 0x%08x\n", status);
1618 ERROR(
"[ERROR] IntWinGuestReadKernel failed: 0x%08x\n", status);
1657 DWORD smallestBuild, biggestBuild;
1673 ERROR(
"[ERROR] IntCamiGetWinSupportedList failed with count %u: 0x%08x\n", cb, status);
1677 TRACE(
"[INFO] %d supported os versions from cami\n", cb);
1680 if (NULL == pNtList)
1688 ERROR(
"[ERROR] IntCamiGetWinSupportedList failed: 0x%08x\n", status);
1689 goto cleanup_and_exit;
1693 smallestBuild = pNtList[0];
1694 biggestBuild = pNtList[cb - 1];
1710 DWORD val = pPage[i];
1712 if ((val & 0xf0000000) != 0xf0000000 ||
1713 (val & 0xf000ffff) != val ||
1714 (val & 0xffff) > biggestBuild ||
1715 (val & 0xffff) < smallestBuild)
1720 for (
DWORD j = 0; j < cb; j++)
1722 if (pNtList[j] == (val & 0xFFFF))
1724 TRACE(
"[WINGUEST STATIC] Found an NtBuildNumber 0x%08x (%d) @ 0x%016llx\n",
1725 val, val & 0xffff, gva + i *
sizeof(
DWORD));
1727 *NtBuildNumber = pNtList[j];
1729 goto cleanup_and_exit;
1755 if (NULL != pNtList)
1800 const DWORD maxSecCount = 10;
1801 DWORD sectionCount = 0;
1804 void *mappedSecPage = NULL;
1820 WARNING(
"[WARNING] Gva 0x%016llx is not in a good section of 0x%016llx, discardable: %d, " 1821 "execute: %d, writable: %d",
1822 KernelGva, KernelBase, !!(pSec[0].Characteristics & IMAGE_SCN_MEM_DISCARDABLE),
1823 !!(pSec[0].Characteristics & IMAGE_SCN_MEM_EXECUTE),
1824 !!(pSec[0].Characteristics & IMAGE_SCN_MEM_WRITE));
1826 goto cleanup_and_exit;
1832 pSec, §ionCount);
1835 WARNING(
"[WARNING] IntPeGetSectionHeadersByName failed for `ALMOSTRO`: 0x%08x, secCount = %d\n", status, sectionCount);
1838 goto cleanup_and_exit;
1844 WARNING(
"[WARNING] Presumed base 0x%016llx has no .data section!\n", KernelBase);
1846 goto cleanup_and_exit;
1851 for (
DWORD iSec = 0; iSec < sectionCount; iSec++)
1853 if ((pSec[iSec].VirtualAddress &
PAGE_OFFSET) != 0)
1855 WARNING(
"[WARNING] Base 0x%016llx has section start 0x%08x which is not page aligned!\n",
1856 KernelBase, pSec[iSec].VirtualAddress);
1858 goto cleanup_and_exit;
1863 WARNING(
"[WARNING] Section %d has size too big: 0x%08x\n", iSec, pSec[iSec].Misc.
VirtualSize);
1865 goto cleanup_and_exit;
1868 for (
QWORD page = KernelBase + pSec[iSec].VirtualAddress;
1874 if (page == ((KernelBase + pSec[iSec].VirtualAddress + pSec[iSec].Misc.
VirtualSize) &
PAGE_MASK))
1882 WARNING(
"[WARNING] IntVirtMemMap failed for 0x%016llx: 0x%08x. .data seems paged " 1883 "out for 0x%016llx!\n", page, status, KernelBase);
1884 goto cleanup_and_exit;
1890 *(
DWORD *)((size_t)mappedSecPage + current);
1892 if (currentptr == KernelBase)
1894 TRACE(
"[INFO] Found PsNtosImageBase = 0x%016llx at address 0x%016llx!\n",
1895 KernelBase, page + current);
1897 goto cleanup_and_exit;
1906 if (NULL != mappedSecPage)
1923 WARNING(
"[WARNING] PsNtosImageBase not found for 0x%016llx!\n", KernelBase);
1952 QWORD kernelBase, limit;
1971 if ((hostPage[0] ==
'M' && hostPage[1] ==
'Z'))
1976 WARNING(
"[WARNING] IntWinGuestValidateKernel failed: 0x%08x\n", status);
1992 if (NULL != hostPage)
1999 ERROR(
"[ERROR] Could not find the kernel headers in the first %lldMB!\n",
2004 *KernelBase = kernelBase;
2027 DWORD activeCount = CpuCount;
2030 for (
DWORD i = 0; i < CpuCount; i++)
2047 if (0 == cr3 || 0 == (cr0 &
CR0_PG))
2054 if (activeCount != CpuCount)
2056 WARNING(
"[WARNING] The active cpu count (%d) is different than the actual cpu count (%d)\n",
2057 activeCount, CpuCount);
2060 TRACE(
"[INTRO-INIT] Active CPU Count: %d\n", activeCount);
2091 QWORD kernelCr3OffsetPcr;
2095 DWORD csType, mapSize;
2096 INSTRUX offsetInstrux;
2101 kernelCr3OffsetPcr = kpcr = 0;
2117 ERROR(
"[ERROR] Failed to map Syscall page: 0x%08x\n", status);
2118 goto cleanup_and_exit;
2127 for (
DWORD i = 0; i < mapSize;)
2131 CHAR nd[ND_MIN_BUF_SIZE] = { 0 };
2141 NdToText(&instrux, 0,
sizeof(nd), nd);
2148 if (ND_INS_MOV == instrux.Instruction && 2 == instrux.ExpOperandsCount &&
2149 ND_OP_REG == instrux.Operands[0].Type &&
2150 ND_REG_GPR == instrux.Operands[0].Info.Register.Type)
2153 (instrux.Operands[0].Info.Register.Reg == offsetInstrux.Operands[0].Info.Register.Reg))
2158 if (ND_OP_MEM == instrux.Operands[1].Type && instrux.Operands[1].Info.Memory.HasSeg &&
2159 instrux.Operands[1].Info.Memory.HasDisp &&
2160 ((
gGuest.
Guest64 && NDR_GS == instrux.Operands[1].Info.Memory.Seg) ||
2161 (!
gGuest.
Guest64 && NDR_FS == instrux.Operands[1].Info.Memory.Seg)))
2163 memcpy(&offsetInstrux, &instrux,
sizeof(instrux));
2166 TRACE(
"[INFO] Found a possible offset instruction: %s\n", nd);
2174 memzero(&offsetInstrux,
sizeof(offsetInstrux));
2182 else if (bFound && ND_INS_MOV_CR == instrux.Instruction && 2 == instrux.ExpOperandsCount &&
2183 ND_OP_REG == instrux.Operands[0].Type && ND_OP_REG == instrux.Operands[1].Type &&
2184 ND_REG_CR == instrux.Operands[0].Info.Register.Type &&
2185 NDR_CR3 == instrux.Operands[0].Info.Register.Reg &&
2186 offsetInstrux.Operands[0].Info.Register.Reg == instrux.Operands[1].Info.Register.Reg)
2188 kernelCr3OffsetPcr = offsetInstrux.Operands[1].Info.Memory.Disp;
2190 TRACE(
"[INFO] Found a valid second instruction: %s\n", nd);
2191 TRACE(
"[INFO] We will use the last possible offset instruction!\n");
2196 i += instrux.Length;
2199 if (0 == kernelCr3OffsetPcr)
2201 ERROR(
"[ERROR] Could not find a valid instruction to get kernel cr3!");
2203 goto cleanup_and_exit;
2206 TRACE(
"[INTRO-INIT] Found KernelDirectoryTableBase offset in PCR at %llx\n", kernelCr3OffsetPcr);
2211 ERROR(
"[ERROR] IntFindKernelPcr failed: 0x%08x\n", status);
2212 goto cleanup_and_exit;
2215 TRACE(
"[INTRO-INIT] Found PCR at 0x%016llx\n", kpcr);
2220 ERROR(
"[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
2221 goto cleanup_and_exit;
2250 QWORD pcr, idleThread, idleProcess;
2255 pcr = idleThread = idleProcess = 0;
2263 ERROR(
"[ERROR] IntFindKernelPcr failed: 0x%08x\n", status);
2276 ERROR(
"[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
2280 TRACE(
"[INFO] Idle thread [%d] @ 0x%016llx\n",
gVcpu->
Index, idleThread);
2285 ERROR(
"[ERROR] IntVirtMemMap failed: 0x%08x\n", status);
2287 goto cleanup_and_exit;
2295 QWORD supposedCr3 = 0;
2308 TRACE(
"[INFO] Found a potentially valid idle process at offset 0x%08x -> 0x%016llx\n",
2327 TRACE(
"[INFO] Found a valid idle process cr3 at offset 0x%08x @ 0x%016llx -> 0x%016llx\n",
2365 DWORD activeCpuCount;
2368 void *swapHandle = NULL;
2371 QWORD kernelBase = 0;
2372 QWORD kernelBaseIdt = 0;
2373 DWORD ntBuildNumber = 0;
2380 memzero(gWinGuest,
sizeof(*gWinGuest));
2393 ERROR(
"[ERROR] IntVeInit failed: 0x%08x; will continue, but will not use #VE.\n", status);
2397 TRACE(
"[INTRO-INIT] #VE initialized successfully!\n");
2407 ERROR(
"[ERROR] IntGsRead failed: 0x%08x\n", status);
2411 TRACE(
"[INTRO-INIT] IA32_GS_BASE_MSR = 0x%016llx \n", gsBase);
2420 ERROR(
"[ERROR] IntFsRead failed: 0x%08x\n", status);
2424 TRACE(
"[INTRO-INIT] IA32_FS_BASE_MSR = 0x%016llx \n", fsBase);
2440 ERROR(
"[ERROR] Failed reading the syscall msr: 0x%08x\n", status);
2445 ERROR(
"[ERROR] SYSCALL MSR 0x%016llx is not valid!\n", msrValue);
2451 TRACE(
"[INTRO-INIT] Found SYSCALL handler @ 0x%016llx\n", msrValue);
2456 ERROR(
"[ERROR] IntCr3Read failed: 0x%08x\n", status);
2466 ERROR(
"[ERROR] IntWinGuestFindKernelCr3 failed: 0x%08x\n", status);
2483 ERROR(
"[ERROR] IntIdtGetEntry failed: %08x\n", status);
2489 TRACE(
"[INTRO-INIT] Found first interrupt handler @ 0x%016llx\n", idtValue);
2493 WARNING(
"[WARNING] First interrupt handler @ 0x%016llx is not valid\n", idtValue);
2501 ERROR(
"[ERROR] IntWinGuestFindKernel failed: %08X\n", status);
2506 LOG(
"[INTRO-INIT] Found the base of the ntoskrnl.exe [SYSCALL] @ VA 0x%016llx\n", kernelBase);
2515 ERROR(
"[ERROR] IntWinGuestFindKernel failed: 0x%08X\n", status);
2524 LOG(
"[INTRO-INIT] Found the base of the ntoskrnl.exe [IDT] @ VA 0x%016llx\n", kernelBaseIdt);
2527 if (kernelBaseIdt && kernelBase != kernelBaseIdt)
2529 WARNING(
"[WARNING] SYSCALL & IDT handlers point in different drivers (0x%016llx vs 0x%016llx).\n",
2530 kernelBase, kernelBaseIdt);
2532 kernelBase = kernelBaseIdt;
2539 ERROR(
"[ERROR] IntWinGuestFindBuildNumber failed: 0x%08X\n", status);
2569 ERROR(
"[ERROR] IntWinGuestFindIdleCr3 failed: 0x%08x\n", status);
2585 ERROR(
"[ERROR] IntWinGuestFindSelfMapIndex failed: 0x%08x\n", status);
2608 ERROR(
"[ERROR] IntWinGuestInit failed: 0x%08x\n", status);
2635 ERROR(
"[ERROR] Failed reading the kernel headers: 0x%08x\n", status);
2640 if (NULL != swapHandle)
2700 count = snprintf(VersionString, VersionStringSize,
"%s %s", gWinGuest->
ServerVersionString,
2701 strcasestr(FullString,
"lts") ?
"ltsb" :
"");
2708 count = snprintf(VersionString, VersionStringSize,
"%s %s %s", gWinGuest->
VersionString,
2709 strcasestr(FullString,
"lts") ?
"ltsb" :
"", appendix);
2717 if ((
DWORD)count >= VersionStringSize)
#define IMAGE_SCN_MEM_EXECUTE
static INTSTATUS IntWinGuestFetchProductType(WIN_PRODUCT_TYPE *ProductType)
Obtains the Windows product type.
static INTSTATUS IntWinGuestFindSelfMapIndex(void)
Finds the self map index.
#define INT_STATUS_GUEST_OS_NOT_SUPPORTED
Indicates that the guest operating system is not supported.
INTSTATUS IntWinAgentUnInit(void)
Uninit the agents state.
#define THS_CHECK_SWAPGS
Will check if any RIP is inside a mitigated SWAPGS gadget.
static INTSTATUS IntWinGuestFindKernel(QWORD KernelGva, QWORD *KernelBase)
Searches for the base of the Windows kernel image.
struct _IMAGE_NT_HEADERS64 * PIMAGE_NT_HEADERS64
QWORD PhysicalAddress
The physical address to which VirtualAddress translates to.
INTSTATUS IntPeGetSectionHeaderByRva(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD GuestRva, IMAGE_SECTION_HEADER *SectionHeader)
Given a relative virtual address, return the section header which describes the section the RVA lies ...
INTSTATUS IntIdtFindBase(DWORD CpuNumber, QWORD *Base, WORD *Limit)
Returns the IDT base and limit for a guest CPU.
#define CONTAINING_RECORD(List, Type, Member)
#define ROUND_UP(what, to)
void IntGuestSetIntroErrorState(INTRO_ERROR_STATE State, INTRO_ERROR_CONTEXT *Context)
Updates the value of the gErrorState and the value of the gErrorStateContext.
#define INTRO_OPT_VE
Enable the Virtualization exception page table access pre-filtering agent (64-bit Windows only)...
struct _IMAGE_FILE_HEADER IMAGE_FILE_HEADER
INTSTATUS IntVirtMemUnmap(void **HostPtr)
Unmaps a memory range previously mapped with IntVirtMemMap.
QWORD MmPfnDatabase
Guest virtual address of the PFN data base.
INTSTATUS IntWinGuestActivateProtection(void)
Activates the protection for a Windows guest.
static INTSTATUS IntWinGuestFindKernelObjects(void)
Searches for kernel objects.
INTSTATUS IntIdtGetEntry(DWORD CpuNumber, DWORD Entry, QWORD *Handler)
Get the handler of an interrupt from the IDT.
DWORD Index
The VCPU number.
INTSTATUS IntIdtrProtect(void)
Enable IDTR protection.
BOOLEAN Initialized
True if the VCPU is initialized and used by the guest, False if it is not.
QWORD SyscallAddress
Guest virtual address of the SYSCALL/SYSENTER handler.
INTSTATUS IntPeFindKernelExport(const char *Name, QWORD *ExportGva)
Find an export inside the NT kernel image.
QWORD SystemCr3
The Cr3 used to map the kernel.
#define INT_STATUS_SUCCESS
INTSTATUS IntFsRead(DWORD CpuNumber, QWORD *FsValue)
Reads the IA32_FS_BASE guest MSR.
#define PAGE_REMAINING(addr)
WIN_KERNEL_DRIVER Win
Valid only for Windows guests.
INTSTATUS IntReadString(QWORD StrGva, DWORD MinimumLength, BOOLEAN AnsiOnly, char **String, DWORD *StringLength)
Reads a string from the guest kernel memory.
INTSTATUS IntWinHalCreateHalData(void)
Initializes gHalData.
DWORD KernelSize
The size of the kernel.
#define KERNEL_SEARCH_LIMIT
The maximum size of the area of memory in which the kernel base is searched for.
INTSTATUS IntWinGuestNew(void)
Starts the initialization and protection process for a new Windows guest.
WORD IdtLimit
The current IDT limit.
INTSTATUS IntSwapMemReadData(QWORD Cr3, QWORD VirtualAddress, DWORD Length, DWORD Options, void *Context, DWORD ContextTag, PFUNC_PagesReadCallback Callback, PFUNC_PreInjectCallback PreInject, void **SwapHandle)
Reads a region of guest virtual memory, and calls the indicated callback when all the data is availab...
struct _LIST_ENTRY * Flink
Information not yet loaded.
The product type is unknown.
void IntWinHalUninit(void)
Frees any resources held by gHalData and removes all the HAL protections.
QWORD BaseVa
The guest virtual address of the kernel module that owns this driver object.
#define IMAGE_SCN_MEM_WRITE
#define PROCESS_SEARCH_LIMIT_THREAD_UPPER
The upper limit of the area in which the idle process is searched.
#define INT_SUCCESS(Status)
QWORD ExFreePoolWithTag
Guest virtual address of the ExFreePoolWithTag kernel function.
INTSTATUS IntWinSudProtectIntegrity(void)
Initializes the SharedUserData integrity protection.
LIST_ENTRY Link
Link inside the WINDOWS_GUEST.InitSwapHandles list.
A critical structure was not found inside the guest kernel.
static INTSTATUS IntWinGuestFindBuildNumber(QWORD KernelGva, BOOLEAN Guest64, BOOLEAN IsKptiInstalled, DWORD *NtBuildNumber)
Finds the NtBuildNumber kernel variable.
INTSTATUS IntResumeVcpus(void)
Resumes the VCPUs previously paused with IntPauseVcpus.
void IntWinAgentInit(void)
Initialize the agents state.
BOOLEAN ProtectionActivated
IMAGE_FILE_HEADER FileHeader
WIN_PRODUCT_TYPE ProductType
The product type. Obtained directly from the guest during initialization.
static INTSTATUS IntWinGuestFindKernelCr3(QWORD Syscall)
Searches for the kernel Cr3.
#define INT_STATUS_NOT_NEEDED_HINT
INTSTATUS IntPeGetSectionHeadersByName(QWORD ImageBase, BYTE *ImageBaseBuffer, PCHAR Name, DWORD NumberOfSectionHeadersAllocated, QWORD Cr3, IMAGE_SECTION_HEADER *SectionHeaders, DWORD *NumberOfSectionHeadersFilled)
Return all the section headers matching the indicated Name.
#define HpAllocWithTag(Len, Tag)
INTSTATUS IntWinDrvObjUninit(void)
Removes all the driver objects in the gWinDriverObjects.
int INTSTATUS
The status data type.
QWORD Size
The size of the kernel module that owns this driver object.
The operating system version is not supported.
INTSTATUS IntMsrSyscallProtect(void)
Enable protection for all SYSCALL and SYSENTER MSRs.
DWORD OSVersion
Os version.
QWORD gEventId
The ID of the current event.
#define INT_STATUS_NOT_FOUND
DWORD NumberOfServices
The number of entries in the SSDT.
#define WIN_SHARED_USER_DATA_OFFSET_PRODUCT
INTSTATUS IntWinIntObjProtect(void)
Protects the interrupt objects which are present in the KPRCB's InterruptObject array.
QWORD IntroActiveEventId
The event ID on which introcore became active.
QWORD ExAllocatePoolWithTag
Guest virtual address of the ExAllocatePoolWithTag kernel function.
#define TRFLG_NONE
No special options.
#define INTRO_OPT_PROT_KM_SUD_INTEGRITY
Enable integrity checks over various SharedUserData fields, as well as the zero-filled zone after the...
PCHAR ServerVersionString
A NULL terminated string containing Windows server version information.
void IntWinGuestUninit(void)
Uninits a Windows guest.
WINDOWS_GUEST _WindowsGuest
Linux specific information. Valid when OSType is introGuestWindows.
PVCPU_STATE VcpuArray
Array of the VCPUs assigned to this guest. The index in this array matches the VCPU number...
BOOLEAN IntWinGuestIsIncreasedUserVa(void)
Check if the guest has an increased user address space.
static INTSTATUS IntWinGuestFindSystemCr3(QWORD KernelAddress, QWORD *SystemCr3, QWORD StartPhysical, QWORD EndPhysical)
Searches for the system Cr3 in a range of physical addresses.
#define INT_STATUS_LOAD_ABORTED
Indicates that Introcore loading was aborted.
static INTSTATUS IntWinGuestResolveImports(void)
Obtains the addresses of public variable and functions exposed by the Windows kernel.
INTSTATUS IntCr4Unprotect(void)
Disables the CR4 protection.
INTSTATUS IntPauseVcpus(void)
Pauses all the guest VCPUs.
#define INTRO_OPT_PROT_KM_IDT
INTRO_GUEST_TYPE OSType
The type of the guest.
INTSTATUS IntThrSafeCheckThreads(QWORD Options)
Checks if any of the guest threads have their RIP or have any stack pointers pointing to regions of c...
INTSTATUS IntNotifyIntroActive(void)
INTSTATUS IntWinDrvCreateFromAddress(QWORD ModuleInfo, QWORD Flags)
Adds a driver to introspection's LoadedModuleList (gKernelDrivers). This way we avoid lots of mapping...
#define WIN_SHARED_USER_DATA_PTR
The address where the SharedUserData is mapped in the Windows kernel.
static DWORD IntWinGetActiveCpuCount(DWORD CpuCount)
Gets the number of active CPUs used by the guest.
DWORD TimeDateStamp
The driver`s internal timestamp (from the _IMAGE_FILE_HEADER).
INTSTATUS IntGdtrProtect(void)
Enable GDTR protection.
BOOLEAN KptiActive
True if KPTI is enabled on this guest, False if it is not.
QWORD PsCreateSystemThread
Guest virtual address of the PsCreateSystemThread kernel function.
#define INTRO_OPT_PROT_KM_MSR_SYSCALL
Exposes the functions used to provide Windows Threads related support.
INTSTATUS IntWinSudProtectSudExec(void)
Protects SharedUserData against executions by establishing an EPT hook on it.
DWORD MappingsCount
The number of entries inside the MappingsTrace and MappingsEntries arrays.
A kernel export was not found.
The object was detected after it was created.
#define INT_STATUS_ALIGNMENT_INCONSISTENCY
INTSTATUS IntSwapMemRemoveTransaction(void *Transaction)
Remove a transaction.
DWORD Size
The size of the read.
QWORD Flags
The entry that maps VirtualAddress to PhysicalAddress, together with all the control bits...
INTSTATUS IntKernVirtMemFetchDword(QWORD GuestVirtualAddress, DWORD *Data)
Reads 4 bytes from the guest kernel memory.
#define IDLE_THREAD_OFFSET_PCR
The offset of the IdleThread field inside the _KPCR.
static INTSTATUS IntWinGuestFinishInit(void)
Finalizes the Windows initialization once the entire kernel is read.
INTSTATUS IntFindKernelPcr(DWORD CpuNumber, QWORD *Pcr)
Finds the address of the Windows kernel _KPCR.
QWORD PsActiveProcessHead
Guest virtual address of the PsActiveProcessHead kernel variable.
QWORD PsLoadedModuleList
Guest virtual address of the PsLoadedModuleList kernel variable.
#define INT_STATUS_NOT_INITIALIZED
INTSTATUS IntSysenterRead(DWORD CpuNumber, QWORD *SysCs, QWORD *SysEip, QWORD *SysEsp)
Queries the IA32_SYSENTER_CS, IA32_SYSENTER_EIP, and IA32_SYSENTER_ESP guest MSRs.
INTSTATUS IntKernVirtMemFetchQword(QWORD GuestVirtualAddress, QWORD *Data)
Reads 8 bytes from the guest kernel memory.
The kernel image was not found.
#define IG_CURRENT_VCPU
For APIs that take a VCPU number as a parameter, this can be used to specify that the current VCPU sh...
#define CR3_OFFSET_IN_KPROCESS
The offset of the DirectoryTableBase field inside _KPROCESS.
WIN_PRODUCT_TYPE
The type of the Windows OS.
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
QWORD Current
The currently used options.
INTSTATUS IntCr0Read(DWORD CpuNumber, QWORD *Cr0Value)
Reads the value of the guest CR0.
INTSTATUS IntWinPfnIsMmPfnDatabase(QWORD MmPfnDatabase)
Checks if a a guest virtual address points to MmPfnDatabase.
static INTSTATUS IntWinGuestKernelHeadersInMemory(WIN_INIT_SWAP *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, void *Data, DWORD DataSize, DWORD Flags)
Handles the swap in of the kernel MZPE headers.
WINDOWS_GUEST * gWinGuest
Global variable holding the state of a Windows guest.
INTSTATUS IntVeInit(void)
Initialize the VE system.
#define INTRO_OPT_PROT_KM_IDTR
Enable interrupt descriptor-table registers protection.
QWORD IdtBase
Original IDT base.
#define INTRO_OPT_PROT_KM_INTERRUPT_OBJ
Enable protection against modifications of interrupt objects from KPRCB's InterruptObject.
QWORD Ssdt
Guest virtual address of the SSDT structure inside the kernel.
INTSTATUS IntDecDecodeInstructionFromBuffer(PBYTE Buffer, size_t BufferSize, IG_CS_TYPE CsType, void *Instrux)
Decode an instruction from the provided buffer.
#define IS_KERNEL_POINTER_WIN(is64, p)
Checks if a guest virtual address resides inside the Windows kernel address space.
BOOLEAN GuestInitialized
True if the OS-specific portion has been initialized.
TIMER_FRIENDLY void IntDumpBuffer(const void *Buffer, QWORD Gva, DWORD Length, DWORD RowLength, DWORD ElementLength, BOOLEAN LogHeader, BOOLEAN DumpAscii)
This function dumps a given buffer in a user friendly format.
#define HpFreeAndNullWithTag(Add, Tag)
INTSTATUS IntGsRead(DWORD CpuNumber, QWORD *GsValue)
Reads the IA32_GS_BASE guest MSR.
static BOOLEAN IntWinGuestIsSystemCr3(QWORD KernelAddress, const VA_TRANSLATION *GvaTranslation, QWORD Cr3)
Checks if a Cr3 is the system Cr3.
#define INT_STATUS_INVALID_DATA_STATE
#define INT_STATUS_INVALID_INTERNAL_STATE
QWORD KernelVa
The guest virtual address at which the kernel image.
INTSTATUS IntWinProcIterateGuestProcesses(PFUNC_IterateListCallback Callback, QWORD Aux)
Iterates the in-guest process list and calls Callback for each entry.
union _IMAGE_SECTION_HEADER::@214 Misc
struct _IMAGE_NT_HEADERS * PIMAGE_NT_HEADERS32
BYTE WordSize
Guest word size. Will be 4 for 32-bit guests and 8 for 64-bit guests.
INTSTATUS IntWinDrvIsListHead(QWORD PsLoadedModuleListGva, void *PsLoadedModuleList, QWORD KernelLdr)
Used to identify WINDOWS_GUEST::PsLoadedModuleList.
static void InsertTailList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
INTSTATUS IntTranslateVirtualAddressEx(QWORD Gva, QWORD Cr3, DWORD Flags, VA_TRANSLATION *Translation)
Translates a guest virtual address to a guest physical address.
#define IntPeGetSectionHeaderByName(Base, Buff, Name, Cr3, Sec)
QWORD VirtualAddress
The guest virtual address that will be read.
#define SWAPMEM_FLAG_ASYNC_CALL
void IntWinGuestCancelKernelRead(void)
Cancels the kernel read.
static INTSTATUS IntWinGuestSectionInMemory(WIN_INIT_SWAP *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, void *Data, DWORD DataSize, DWORD Flags)
Handles the swap in of a kernel section done while the WINDOWS_GUEST.KernelBuffer is read...
DWORD SelfMapIndex
The self map index.
static void InitializeListHead(LIST_ENTRY *ListHead)
DWORD CpuCount
The number of logical CPUs.
INTSTATUS IntWinApiHookAll(void)
Iterates through all hookable APIs and sets requested hooks.
#define UNREFERENCED_PARAMETER(P)
void IntDriverUninit(void)
Uninitializes the drivers submodule.
#define INT_STATUS_DATA_BUFFER_TOO_SMALL
INTSTATUS IntWinGetVersionString(DWORD FullStringSize, DWORD VersionStringSize, CHAR *FullString, CHAR *VersionString)
Gets the version string for a Windows guest.
#define WIN_KM_FIELD(Structure, Field)
Macro used to access kernel mode fields inside the WIN_OPAQUE_FIELDS structure.
DWORD KernelBufferSize
The size of the KernelBuffer.
#define INT_STATUS_INVALID_DATA_VALUE
void IntWinProcUninit(void)
This function removes all process objects from the list, and registers the calls the cleanup function...
#define THS_CHECK_DETOURS
Will check if any RIP is inside detours.
INTSTATUS IntPeValidateHeader(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD ImageBaseBufferSize, INTRO_PE_INFO *PeInfo, QWORD Cr3)
Validates a PE header.
PCHAR VersionString
A NULL terminated string containing Windows version information.
INTSTATUS IntSyscallRead(DWORD CpuNumber, QWORD *SysStar, QWORD *SysLstar)
Queries the IA32_STAR, and IA32_LSTAR guest MSRs.
#define _In_reads_bytes_(expr)
#define PROCESS_SEARCH_LIMIT_THREAD_LOWER
The lower limit of the area in which the idle process is searched.
Holds information about a Windows guest.
#define INT_STATUS_INVALID_OBJECT_TYPE
#define SWAPMEM_OPT_BP_FAULT
If set, the #PF will be generated from an int3 detour. Use this when injecting kernel PFs...
__must_check INTSTATUS IntVirtMemMap(QWORD Gva, DWORD Length, QWORD Cr3, DWORD Flags, void **HostPtr)
Maps a guest virtual memory range inside Introcore virtual address space.
INTSTATUS IntWinDrvIterateLoadedModules(PFUNC_IterateListCallback Callback, QWORD Aux)
Used to iterate trough the WINDOWS_GUEST::PsLoadedModuleList.
INTSTATUS IntWinGuestInit(void)
Initializes a new Windows guest.
INTSTATUS IntWinProcAdd(QWORD Eprocess, QWORD Aux)
Adds a new process to the Introcore list of processes.
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
INTSTATUS IntRegisterBreakpointHandler(PFUNC_IntBreakpointCallback Callback)
INTSTATUS IntWinProcIsPsActiveProcessHead(QWORD Gva)
Checks if a guest memory area is the list head of the process list (PsActiveProcessHead) ...
QWORD KeServiceDescriptorTable
Guest virtual address of the KeServiceDescriptorTable variable.
GUEST_STATE gGuest
The current guest state.
INTSTATUS IntWinIdtProtectAll(void)
Activates the IDT protection for all the guest CPUs.
INTSTATUS IntVirtMemRead(QWORD Gva, DWORD Length, QWORD Cr3, void *Buffer, DWORD *RetLength)
Reads data from a guest virtual memory range.
#define FIX_GUEST_POINTER(is64, x)
Masks the unused part of a Windows guest virtual address.
struct _IMAGE_SECTION_HEADER * PIMAGE_SECTION_HEADER
#define IMAGE_SCN_MEM_DISCARDABLE
LIST_HEAD InitSwapHandles
A list of swap handles used to read KernelBuffer.
DWORD RemainingSections
The number of kernel sections not yet read into KernelBuffer.
INTSTATUS IntKernVirtMemRead(QWORD KernelGva, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest kernel virtual memory range.
KERNEL_DRIVER * IntDriverFindByAddress(QWORD Gva)
Returns the driver in which Gva resides.
INTSTATUS IntSwapgsStartMitigation(void)
Scan the kernel for vulnerable SWAPGS gadgets, and mitigate CVE-2019-1125, when such gadgets are foun...
BOOLEAN KptiInstalled
True if KPTI was detected as installed (not necessarily active).
IMAGE_FILE_HEADER FileHeader
The initialization swap handle.
PAGING_MODE Mode
The paging mode used by the guest.
INTSTATUS IntWinGuestIsSupported(void)
Load os information from cami.
INTSTATUS IntCr3Read(DWORD CpuNumber, QWORD *Cr3Value)
Reads the value of the guest CR3.
__must_check INTSTATUS IntPhysMemMap(QWORD PhysAddress, DWORD Length, DWORD Flags, void **HostPtr)
Maps a guest physical address inside Introcore VA space.
Encapsulates information about a virtual to physical memory translation.
BYTE * KernelBuffer
A buffer containing the entire kernel image.
KERNEL_DRIVER * KernelDriver
Points to the driver object that describes the kernel image.
void IntWinUmCacheUninit(void)
Uninit the module cache system. This will remove all cache entries. Use this during Introcore uninit...
#define INT_STATUS_NOT_SUPPORTED
#define INTRO_OPT_PROT_KM_SUD_EXEC
Enable protection against executions on SharedUserData.
VCPU_STATE * gVcpu
The state of the current VCPU.
UINT8 Name[IMAGE_SIZEOF_SHORT_NAME]
DWORD NtBuildNumberValue
The value of the NtBuildNumber kernel variable.
INTSTATUS IntWinGuestFindIdleCr3(void)
Searches the Cr3 used by the idle process.
DWORD ActiveCpuCount
The number of CPUs actually used by the guest.
#define INTRO_OPT_PROT_KM_CR4
Enable CR4.SMEP and CR4.SMAP protection.
DWORD SizeOfImage
Size of the image.
#define INT_STATUS_NOT_READY
BOOLEAN Image64Bit
True if the image is 64 bit.
struct _IMAGE_DOS_HEADER * PIMAGE_DOS_HEADER
BOOLEAN DisableOnReturn
Set to True if after returning from this event handler, introcore must be unloaded.
static INTSTATUS IntWinGuestReadKernel(PBYTE KernelHeaders)
Reads the whole kernel image in memory, including swapped-out sections.
INTSTATUS IntWinAgentInjectTrampoline(void)
Inject the agent trampoline inside the guest.
unsigned long long * PQWORD
INTSTATUS IntCr4Protect(void)
Activates the Cr4 protection.
INTSTATUS IntVeDeployAgent(void)
Inject the VE agent inside the guest.
void * SwapHandle
The actual swap handle returned by IntSwapMemRead.
INTSTATUS IntPhysMemUnmap(void **HostPtr)
Unmaps an address previously mapped with IntPhysMemMap.
#define IMAGE_SCN_MEM_NOT_PAGED
INTSTATUS IntNotifyIntroDetectedOs(INTRO_GUEST_TYPE OsType, DWORD OsVersion, BOOLEAN Is64)
Wrapper over GLUE_IFACE.NotifyIntrospectionDetectedOs.
#define INT_STATUS_INVALID_PARAMETER_2
static INTSTATUS IntWinGuestValidateKernel(QWORD KernelBase, QWORD KernelGva, BYTE *KernelHeaders)
Validates if the presumed kernel base is the real kernel base, based on various checks.
INTSTATUS IntHandleBreakpoint(void *GuestHandle, QWORD GuestPhysicalAddress, DWORD CpuNumber)
Handle guest breakpoints.
INTRO_PROT_OPTIONS CoreOptions
The activation and protection options for this guest.
UINT16 SizeOfOptionalHeader
INTSTATUS IntCamiGetWinSupportedList(BOOLEAN KptiInstalled, BOOLEAN Guest64, DWORD *NtBuildNumberList, DWORD *Count)
Return a list of supported Windows NtBuildNumbers.
#define INTRO_OPT_PROT_KM_GDTR
Enable global descriptor-table registers protection.
static INTSTATUS IntWinGuestFindKernelObjectsInternal(void)
Finds all the objects of interest from the Windows kernel.
#define INT_STATUS_INVALID_DATA_SIZE
#define INT_STATUS_INSUFFICIENT_RESOURCES