137 #define REM_DRV(arch64) ((arch64) ? (gBootDriverx64) : (gBootDriverWin32)) 138 #define REM_SIZE(arch64) ((arch64) ? (sizeof(gBootDriverx64)) : sizeof((gBootDriverWin32))) 140 #define AGENT_FLAG_STARTED 0x00000001 141 #define AGENT_FLAG_ALLOCATED 0x00000002 142 #define AGENT_FLAG_ACTIVE 0x00000004 143 #define AGENT_FLAG_COMPLETED 0x00000008 144 #define AGENT_FLAG_ALL_DONE 0x0000000F 258 if ((NULL != Agent->AgentContent) && !Agent->AgentInternal)
262 Agent->AgentContent = NULL;
291 if (!Agent->InstructionRestored)
293 if (NULL != Agent->InsCloakRegion)
298 ERROR(
"[ERROR] IntMemClkUncloakRegion failed: 0x%08x\n", status);
301 Agent->InsCloakRegion = NULL;
307 BYTE fiveByteNop[] = {0x66, 0x66, 0x66, 0x66, 0x90};
312 ERROR(
"[ERROR] IntDetModifyPublicData failed: 0x%08x\n", status);
317 ERROR(
"[ERROR] Instruction was not restored and the cloak region is NULL!\n");
322 Agent->InstructionRestored =
TRUE;
327 if (0 != Agent->BootstrapAddress)
330 if (NULL != Agent->BootCloakRegion)
335 ERROR(
"[ERROR] IntMemClkUncloakRegion failed: 0x%08x\n", status);
338 Agent->BootCloakRegion = NULL;
344 ERROR(
"[ERROR] IntWinAgentReleaseBootstrapAddress failed: 0x%08x\n", status);
347 Agent->BootstrapAddress = 0;
356 ERROR(
"[ERROR] IntWinAgentFree failed: 0x%08x\n", status);
404 ERROR(
"[ERROR] IntSlackAlloc failed: 0x%08x\n", status);
411 ERROR(
"[ERROR] IntKernVirtMemRead failed for %llx, %d: 0x%08x\n", gAgentState.
Trampoline, slackSize, status);
434 ERROR(
"[ERROR] IntMemClkCloakRegion failed: 0x%08x\n", status);
444 TRACE(
"[AGENT] Selected trampoline at 0x%016llx\n", gAgentState.
Trampoline);
471 DWORD imageSize, imageEp, ring;
475 imageSize = imageEp = ring = 0;
487 ERROR(
"[ERROR] IntCr3Read failed: 0x%08x\n", status);
494 ERROR(
"[ERROR] IntGetCurrentRing failed: 0x%08x\n", status);
498 TRACE(
"[AGENT] Initiating boot driver deployment...\n");
505 ERROR(
"[ERROR] IntLdrGetImageSizeAndEntryPoint failed: 0x%08x\n", status);
506 goto cleanup_and_exit;
511 ERROR(
"[ERROR] No entry point found!\n");
513 goto cleanup_and_exit;
520 goto cleanup_and_exit;
523 TRACE(
"[AGENT] Loading boot driver image...\n");
530 Agent->DriverAddress,
536 ERROR(
"[ERROR] IntLdrLoadPEImage failed: 0x%08x\n", status);
537 goto cleanup_and_exit;
540 TRACE(
"[AGENT] Deploying boot driver image...\n");
547 ERROR(
"[ERROR] IntVirtMemSafeWrite failed: 0x%08x\n", status);
548 goto resume_and_exit;
557 goto cleanup_and_exit;
560 TRACE(
"[AGENT] Boot driver deployment successful!\n");
604 0xc6, 0x45, 0x100, 0x02,
605 0x65, 0x48, 0x8b, 0x1c, 0x25, 0x88, 0x01, 0x00, 0x00,
606 0x0f, 0x0d, 0x8b, 0x100, 0x100, 0x00, 0x00,
607 0x0f, 0xae, 0x5d, 0x100,
608 0x65, 0x0f, 0xae, 0x14, 0x25, 0x80, 0x01, 0x00, 0x00,
625 0x80, 0x4c, 0x24, 0x01, 0x02,
627 0xff, 0x35, 0x100, 0x100, 0x100, 0x100,
634 0x64, 0x8b, 0x1d, 0x1c, 0x00, 0x00, 0x00,
649 pPattern = &functionPatternx64;
653 pPattern = &functionPatternx86;
662 ERROR(
"[ERROR] IntPeFindFunctionByPattern failed: 0x%08x\n", status);
702 0x48, 0x83, 0xec, 0x10,
706 0x48, 0x8d, 0x100, 0x100, 0x100, 0x100, 0x100,
708 0xb8, 0x81, 0x01, 0x00, 0x00,
709 0xe9, 0x100, 0x100, 0x100, 0x100,
725 0xb8, 0x1e, 0x00, 0x00, 0x00,
726 0x8d, 0x54, 0x24, 0x04,
729 0xe8, 0x100, 0x100, 0x100, 0x100,
742 for (
size_t i = 0; i <
sizeof(SyscallNumber); i++)
750 linkage,
TRUE, &rva);
759 ERROR(
"[ERROR] Failed to find syscall 0x%x kernel linkage: 0x%08x\n", SyscallNumber, status);
763 TRACE(
"[INFO] Found syscall 0x%x linkage @ 0x%016llx\n", SyscallNumber,
gGuest.
KernelVa + rva);
800 BYTE cdef, ddef, stiCount, neededStiCount;
806 if (NULL == InstructionVa)
813 bFound = bStiFound =
FALSE;
818 if (NULL == pSyscallCode)
821 goto cleanup_and_exit;
840 ERROR(
"[ERROR] IntAgentFindKiSystemServiceUser failed: 0x%08x\n", status);
841 goto cleanup_and_exit;
844 TRACE(
"[AGENT] Discovered the KiSystemServiceUser at 0x%016llx\n", syscallGva);
850 ERROR(
"[ERROR] IntKernVirtMemRead failed for syscall 0x%016llx: 0x%08x\n", syscallGva, status);
851 goto cleanup_and_exit;
871 ndstatus = NdDecodeEx(&instrux, pSyscallCode + parsed, 0x1000 - parsed, cdef, ddef);
872 if (!ND_SUCCESS(ndstatus))
874 ERROR(
"[ERROR] NdDecodeEx failed at 0x%016llx: 0x%08x\n", syscallGva + parsed, ndstatus);
881 if (ND_INS_STI == instrux.Instruction)
891 else if ((instrux.Length >= MinLen) && !ND_HAS_PREDICATE(&instrux))
894 *InstructionVa = syscallGva + parsed;
895 *InstructionLen = instrux.Length;
896 memcpy(InstructionBytes, instrux.InstructionBytes, ND_MAX_INSTRUCTION_LENGTH);
900 parsed += instrux.Length;
906 goto cleanup_and_exit;
910 if (NULL != pSyscallCode)
940 BYTE newCode[ND_MAX_INSTRUCTION_LENGTH] = {0};
941 PBYTE originalBootstrap;
944 originalBootstrap = NULL;
952 goto cleanup_and_exit;
982 goto cleanup_and_exit;
985 TRACE(
"[AGENT] Activating pending agent, %d, remaining %d\n",
1007 goto skip_bsp_injection;
1028 ERROR(
"[ERROR] IntAgentSelectBootstrapAddress failed: 0x%08x\n", status);
1029 goto unpause_and_exit;
1042 if (NULL == originalBootstrap)
1045 goto unpause_and_exit;
1051 ERROR(
"[ERROR] IntKernVirtMemRead failed for size %d on address %llx: 0x%08x\n",
1053 goto unpause_and_exit;
1066 ERROR(
"[ERROR] IntMemClkCloakRegion failed: 0x%08x\n", status);
1067 goto unpause_and_exit;
1087 ERROR(
"[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
1088 goto unpause_and_exit;
1099 ERROR(
"[ERROR] IntAgentFindInstruction failed: 0x%08x\n", status);
1100 goto unpause_and_exit;
1104 TRACE(
"[AGENT] Found suitable instruction of len %d at 0x%016llx\n", pAgent->
InstructionLen,
1108 memset(newCode, 0x90,
sizeof(newCode));
1128 ERROR(
"[ERROR] IntDetModifyPublicData failed: 0x%08x\n", status);
1129 goto unpause_and_exit;
1145 goto unpause_and_exit;
1152 TRACE(
"[AGENT] Region successfully hooked!\n");
1160 if (NULL != originalBootstrap)
1171 ERROR(
"[ERROR] IntAgentRemove failed: 0x%08x\n", status2);
1208 QWORD regs[16] = {0}, sema = 1;
1214 ERROR(
"[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
1219 Registers->R15 = regs[0];
1220 Registers->R14 = regs[1];
1221 Registers->R13 = regs[2];
1222 Registers->R12 = regs[3];
1223 Registers->R11 = regs[4];
1224 Registers->R10 = regs[5];
1225 Registers->R9 = regs[6];
1226 Registers->R8 = regs[7];
1227 Registers->Rdi = regs[8];
1228 Registers->Rsi = regs[9];
1229 Registers->Rbp = regs[10];
1230 Registers->Rbx = regs[11];
1231 Registers->Rdx = regs[12];
1232 Registers->Rcx = regs[13];
1233 Registers->Rax = regs[14];
1236 Registers->Rip = regs[15];
1239 Registers->Rsp += 16 * 8;
1245 ERROR(
"[ERROR] IntSetGprs failed: 0x%08x\n", status);
1254 ERROR(
"[ERROR] IntKernVirtMemWrite failed: 0x%08x\n", status);
1285 DWORD regs[9] = {0}, sema = 1;
1291 ERROR(
"[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
1296 Registers->Rdi = regs[0];
1297 Registers->Rsi = regs[1];
1298 Registers->Rbp = regs[2];
1299 Registers->Rbx = regs[4];
1300 Registers->Rdx = regs[5];
1301 Registers->Rcx = regs[6];
1302 Registers->Rax = regs[7];
1305 Registers->Rip = regs[8];
1308 Registers->Rsp += 9 * 4;
1314 ERROR(
"[ERROR] IntSetGprs failed: 0x%08x\n", status);
1323 ERROR(
"[ERROR] IntKernVirtMemWrite failed: 0x%08x\n", status);
1359 if (NULL == Registers)
1364 if (Registers->Rip != Agent->InstructionAddress)
1366 ERROR(
"[ERROR] RIP mismatch: 0x%016llx vs. 0x%016llx!\n", Registers->Rip, Agent->InstructionAddress);
1372 TRACE(
"[AGENT] BREAKPOINT hit, restoring original code and calling callback...\n");
1384 ERROR(
"[ERROR] IntMemClkUncloakRegion failed: 0x%08x\n", status);
1388 Agent->InsCloakRegion = NULL;
1390 Agent->InstructionRestored =
TRUE;
1394 status = Agent->InjectionCallback(0, Agent->AgentTag, Agent->Context);
1397 ERROR(
"[ERROR] Agent->InjectCallback failed: 0x%08x\n", status);
1406 ERROR(
"[ERROR] IntWinAgentRemove failed: 0x%08x\n", status);
1442 if (NULL == Registers)
1463 ERROR(
"[ERROR] IntKernVirtMemRead failed for VA 0x%016llx (offset %x): 0x%08x\n",
1464 Registers->Rsp, offset, status);
1474 ERROR(
"[ERROR] IntKernVirtMemWrite failed for VA 0x%016llx: 0x%08x\n", Registers->Rsp + offset, status);
1478 Registers->Rax = (NULL == Agent) ? 0 : ((Agent->Flags &
AGENT_FLAG_STARTED) ? 0 : Agent->BootstrapAddress);
1484 ERROR(
"[ERROR] IntSetGprs failed: 0x%08x\n", status);
1495 TRACE(
"[AGENT] HYPERCALL1 hit, storing the agent bootstrap: 0x%016llx\n", Agent->BootstrapAddress);
1500 BYTE fiveByteNop[] = {0x66, 0x66, 0x66, 0x66, 0x90};
1505 ERROR(
"[ERROR] IntDetModifyPublicData failed: 0x%08x\n", status);
1514 ERROR(
"[ERROR] IntMemClkUncloakRegion failed: 0x%08x\n", status);
1519 Agent->InsCloakRegion = NULL;
1521 Agent->InstructionRestored =
TRUE;
1535 TRACE(
"[AGENT] HYPERCALL2 hit, freeing the bootstrap at 0x%016llx\n", Agent->BootstrapAddress);
1539 ERROR(
"[ERROR] Agent termination requested, but the agent is not done yet = %x!\n", Agent->Flags);
1547 ERROR(
"[ERROR] IntAgentRemove failed: 0x%08x\n", status);
1586 ERROR(
"[ERROR] IntWinAgentRestoreState64 failed: 0x%08x\n", status);
1595 ERROR(
"[ERROR] IntWinAgentRestoreState32 failed: 0x%08x\n", status);
1628 ERROR(
"[ERROR] IntWinAgentRemove failed: 0x%08x\n", status);
1659 ERROR(
"[ERROR] IntWinAgentReleaseBootstrap failed: 0x%08x\n", status);
1666 ERROR(
"[ERROR] IntWinAgentRemoveAgentAndResetState failed: 0x%08x\n", status);
1710 if (NULL == Registers)
1720 argument = Registers->Rcx;
1723 if (Registers->Rdx == Agent->Token1)
1727 TRACE(
"[AGENT] Bootstrap reports that the agent has been allocated at 0x%016llx\n", argument);
1731 ERROR(
"[ERROR] Bootstrap reports agent allocation failed with status: 0x%08x\n", (
DWORD)Registers->Rsi);
1736 ERROR(
"[ERROR] IntWinAgentReleaseBootstrapAndRemoveAgent failed: 0x%08x\n", status);
1742 Agent->DriverAddress = argument;
1747 ERROR(
"[ERROR] IntWinAgentInjectWinDriver failed: 0x%08x\n", status);
1752 status = Agent->InjectionCallback(Agent->DriverAddress, Agent->AgentTag, Agent->Context);
1755 ERROR(
"[ERROR] Injection failed: 0x%08x\n", status);
1760 else if (Registers->Rdx == Agent->Token2)
1763 TRACE(
"[AGENT] Bootstrap reports that the agent has been started with result 0x%016llx\n", argument);
1768 ERROR(
"[ERROR] IntWinAgentReleaseBootstrap failed: 0x%08x\n", status);
1774 ERROR(
"[ERROR] Thread creation status: 0x%08x, will remove agent\n", (
DWORD)argument);
1779 ERROR(
"[ERROR] IntWinAgentRemoveAgentAndResetState failed: 0x%08x\n", status);
1785 else if (Registers->Rdx == Agent->Token3)
1787 TRACE(
"[AGENT] Bootstrap reports completion with status = 0x%08x!\n", (
DWORD)argument);
1800 TRACE(
"[AGENT] Agent bootstrap completed execution, will remove it soon.\n");
1802 status2 = Agent->CompletionCallback(Agent->DriverAddress, Agent->ErrorCode, Agent->AgentTag, Agent->Context);
1805 ERROR(
"[ERROR] CompletionCallback failed: 0x%08x\n", status2);
1808 Agent->DriverAddress = 0;
1847 QWORD arg1, arg2, op, res;
1854 if (NULL == Registers)
1866 arg1 = Registers->Rcx;
1867 arg2 = Registers->Rbx;
1871 arg1 = Registers->Rsi;
1872 arg2 = Registers->Rdi;
1875 op = Registers->Rdx;
1882 LOG(
"[AGENT] Uninit is prepared, will return error to the in-guest agent.\n");
1895 if (0 == pidToInject)
1899 if (NULL != pWinLogon)
1901 pidToInject = pWinLogon->
Pid;
1909 ERROR(
"[ERROR] Agent command structure mismatch: %lld vs %zu!\n", arg2,
sizeof(
AGENT_COMMAND));
1917 ERROR(
"[ERROR] IntKernVirtMemRead failed for %llx: 0x%08x\n", arg1, status);
1928 cmd.
Pid = pidToInject;
1929 cmd.
Type = Agent->AgentType;
1931 cmd.
Agid = Agent->Agid;
1932 cmd.
Size = Agent->AgentSize;
1935 memcpy(cmd.
Name, Agent->Name,
sizeof(cmd.
Name));
1936 memcpy(cmd.
Args, Agent->Args,
sizeof(cmd.
Args));
1952 ERROR(
"[ERROR] IntVirtMemSafeWrite failed: 0x%08x\n", status);
1965 actualCopy = (
DWORD)
MIN(arg2, Agent->AgentSize - Agent->AgentPosition);
1967 if (actualCopy > 0 && Agent->AgentPosition < Agent->AgentSize)
1972 &Agent->AgentContent[Agent->AgentPosition],
1976 ERROR(
"[ERROR] IntVirtMemSafeWrite failed at GVA 0x%016llx, size %x: 0x%08x\n",
1977 arg1, actualCopy, status);
1985 Agent->AgentPosition += (
DWORD)res;
2004 memset(modName, 0,
sizeof(modName));
2011 ERROR(
"[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
2013 goto _mod_fail_and_exit;
2018 if (NULL == wModuleName)
2022 goto _mod_fail_and_exit;
2029 wModuleName[i] = modName[i];
2034 if (0 == strcmp(modName,
"ntoskrnl.exe"))
2037 if (NULL == pDriver)
2039 ERROR(
"[ERROR] IntDriverFindByLoadOrder failed for %s: 0x%08x\n", modName, status);
2041 goto _mod_fail_and_exit;
2044 modBase = pDriver->
BaseVa;
2046 else if (0 == strcmp(modName,
"hal.dll"))
2049 if (NULL == pDriver)
2051 ERROR(
"[ERROR] IntDriverFindByLoadOrder failed for %s: 0x%08x\n", modName, status);
2053 goto _mod_fail_and_exit;
2056 modBase = pDriver->
BaseVa;
2061 if (NULL == pDriver)
2063 ERROR(
"[ERROR] IntDriierverFindByName failed for %s: 0x%08x\n", modName, status);
2065 goto _mod_fail_and_exit;
2068 modBase = pDriver->
BaseVa;
2074 if (NULL != wModuleName)
2085 res = Agent->DriverAddress;
2090 if (NULL != Agent->DeliverCallback)
2092 res = Agent->DeliverCallback(arg1, (
DWORD)arg2, Agent->Context);
2106 ERROR(
"[ERROR] Requested syscall linkage not supported by introcore: 0x%016llx\n", arg1);
2107 goto _sys_lnk_fail_and_exit;
2114 ERROR(
"[ERROR] IntWinAgentFindSyscallLinkage failed for 0x%x: 0x%08x\n", sysNo, status);
2118 _sys_lnk_fail_and_exit:
2124 LOG(
"[AGENT] Agent reports error code: 0x%08x\n", (
DWORD)arg2);
2125 Agent->ErrorCode = (
DWORD)arg2;
2128 if (Agent->ErrorCode != 0)
2133 event->AgentTag = Agent->AgentTag;
2134 event->ErrorCode = Agent->ErrorCode;
2139 WARNING(
"[WARNING] IntNotifyIntroEvent failed: 0x%x\n", status);
2149 Registers->Rdx = res;
2154 ERROR(
"[ERROR] IntSetGprs failed: 0x%08x\n", status);
2186 QWORD arg1, arg2, op;
2190 if (NULL == Registers)
2200 arg1 = Registers->Rcx;
2201 arg2 = Registers->Rbx;
2205 arg1 = (
DWORD)Registers->Rsi;
2206 arg2 = (
DWORD)Registers->Rdi;
2209 op = Registers->Rdx;
2221 event->ErrorCode = (
DWORD)arg2;
2223 LOG(
"[AGENT] User-mode stub reports error for agent with tag %d: 0x%08x\n", event->AgentTag, event->ErrorCode);
2228 WARNING(
"[WARNING] IntNotifyIntroEvent failed: 0x%x\n", status);
2238 WARNING(
"[WARNING] VMCALL received from unknown process, will ignore. Cr3 = 0x%016llx\n", Registers->Cr3);
2243 TRACE(
"[AGENT] VMCALL with op = %lld from `%s` (PID = %d) which is not an agent (previous = %d), " 2253 ERROR(
"[ERROR] IntAgentHandleRemediationVmcall failed: 0x%08x\n", status);
2262 ERROR(
"[ERROR] IntAgentHandleLogGatherVmcall failed: 0x%08x\n", status);
2312 ERROR(
"[ERROR] IntGetCurrentRing failed: 0x%08x\n", status);
2335 ERROR(
"[ERROR] IntWinAgentHandleLoader1Hypercall failed: 0x%08x\n", status);
2338 goto cleanup_and_exit;
2350 ERROR(
"[ERROR] IntWinAgentHandleLoader1Hypercall failed: 0x%08x\n", status);
2359 ERROR(
"[ERROR] IntWinAgentHandleLoader2Hypercall failed: 0x%08x\n", status);
2368 ERROR(
"[ERROR] IntWinAgentHandleBreakpointAgent failed: 0x%08x\n", status);
2375 goto cleanup_and_exit;
2381 goto cleanup_and_exit;
2389 ERROR(
"[ERROR] IntAgentActivatePendingAgent failed: 0x%08x\n", status2);
2421 ERROR(
"[ERROR] IntGetCurrentRing failed: 0x%08x\n", status);
2425 TRACE(
"VMCALL -> rip: 0x%016llx, cr3: 0x%016llx, rax: 0x%016llx, rcx: 0x%016llx, rdx: 0x%016llx, rbx: 0x%016llx\n",
2440 ERROR(
"[ERROR] VMCALL with no active agent from RIP 0x%016llx!\n", regs->
Rip);
2441 goto cleanup_and_exit;
2451 ERROR(
"[ERROR] IntWinAgentHandleDriverVmcall failed: 0x%08x\n", status);
2462 ERROR(
"[ERROR] IntWinAgentHandleAppVmcall failed: 0x%08x\n", status);
2472 ERROR(
"[ERROR] IntWinAgentActivatePendingAgent failed: 0x%08x\n", status);
2502 if (NULL == Address)
2511 TRACE(
"[AGENT] Trying to find slack inside the kernel...\n");
2518 goto cleanup_and_exit;
2522 for (
DWORD i = 1; i < 5; i++)
2525 if (NULL == pDriver)
2536 goto cleanup_and_exit;
2661 PAGENT_NAME pAgName;
2663 QWORD token1, token2, token3;
2674 if (NULL == InjectionCallback)
2679 if (NULL == CompletionCallback)
2724 if (0 == strcasecmp(pAgName->
ImageName, Name))
2726 ERROR(
"[ERROR] An agent with the name '%s' is already injected!\n", Name);
2730 goto cleanup_and_exit;
2739 TRACE(
"[AGENT] Selected tokens: 0x%016llx 0x%016llx 0x%016llx\n", token1, token2, token3);
2745 goto cleanup_and_exit;
2777 goto cleanup_and_exit;
2797 ERROR(
"[ERROR] IntLdrGetImageSizeAndEntryPoint failed: 0x%08x\n", status);
2798 goto cleanup_and_exit;
2862 if (NULL == pAgName)
2865 goto cleanup_and_exit;
2874 pAgName->
Tag = AgentTag;
2887 TRACE(
"[AGENT] Agent allocated and initialized!\n");
2895 TRACE(
"[INFO] Can't inject agent: 0x%08x\n", status);
2912 ERROR(
"[ERROR] IntWinAgentActivatePendingAgent failed: 0x%08x\n", status);
2947 if (NULL == InjectionCallback)
2961 goto cleanup_and_exit;
2978 TRACE(
"[AGENT] Agent allocated and initialized!\n");
2986 TRACE(
"[INFO] Can't inject agent: 0x%08x\n", status);
3001 ERROR(
"[ERROR] IntAgentActivatePendingAgent failed: 0x%08x\n", status);
3046 if (NULL == ImageName)
3051 if (NULL == IsAgent)
3070 if (0 == strcasecmp(ImageName, pAgName->
ImageName))
3075 *Tag = pAgName->
Tag;
3131 if (0 == strcasecmp(ImageName, pAgName->
ImageName))
3140 *Tag = pAgName->
Tag;
3149 WARNING(
"[WARNING] Agent %s already done by our logic!\n", pAgName->
ImageName);
3201 if (Counter == pAgName->
Agid)
3205 *Tag = pAgName->
Tag;
3234 WARNING(
"[WARNING] Found %s 0x%016llx in agent trampoline 0x%016llx, 0x%x\n",
3235 Type ==
ptrLiveRip ?
"live RIP" :
"stack value",
3388 ERROR(
"[ERROR] IntAgentRemove failed: 0x%08x\n", status);
3402 ERROR(
"[ERROR] IntMemClkUncloakRegion failed: 0x%08x\n", status);
3409 ERROR(
"[ERROR] The trampoline is initialized, but no cloak region was found!\n");
3416 memzero(&gAgentState,
sizeof(gAgentState));
KERNEL_DRIVER * IntDriverFindByLoadOrder(DWORD LoadOrder)
Searches a driver by its module load order.
static INTSTATUS IntWinAgentReleaseBootstrap(WIN_AGENT *Agent, IG_ARCH_REGS *Registers)
Releases the bootstrap allocated inside the guest.
#define CONTAINING_RECORD(List, Type, Member)
#define OFFSET_WIN_X86_AGENT_SIZE
static INTSTATUS IntWinAgentDeployWinDriver(PWIN_AGENT Agent)
Inject the Windows boot driver.
DWORD CompletingAgentsCount
Number of agents that are yet to complete execution.
INTSTATUS IntWinAgentInject(PFUNC_AgentInjection InjectionCallback, PFUNC_AgentCompletion CompletionCallback, PFUNC_AgentDeliver DeliverCallback, void *Context, PBYTE AgentContent, DWORD AgentSize, BOOLEAN AgentInternal, DWORD AgentTag, AGENT_TYPE AgentType, const CHAR *Name, DWORD Options, const CHAR *Args, DWORD Pid, PWIN_AGENT *Agent)
Schedule an agent injection inside the guest.
#define OFFSET_WIN_X64_FREE
struct _AGENT_STATE AGENT_STATE
#define AGENT_HCALL_ERROR
Generic error signaling hypercall.
QWORD PropperSyscallGva
Guest virtual address of the KiSystemServiceUser function.
static INTSTATUS IntWinAgentHandleAppVmcall(void *Reserved, PIG_ARCH_REGS Registers)
Handles a VMCALL issued by an application that has been injected inside the guest.
BOOLEAN InstructionRestored
True if the detours instruction has been restored.
WINDOWS_GUEST * gWinGuest
Global variable holding the state of a Windows guest.
INTSTATUS IntKernVirtMemWrite(QWORD KernelGva, DWORD Length, void *Buffer)
Writes data to a guest kernel virtual memory range.
static INTSTATUS IntWinAgentHandleLoader1Hypercall(WIN_AGENT *Agent, IG_ARCH_REGS *Registers)
Handle a hyper call initiated by the trampoline code.
A single breakpoint will be injected.
No active/pending agents.
struct _WIN_OPAQUE_FIELDS::@212 Km
Kernel mode information.
IG_ARCH_REGS Regs
The current state of the guest registers.
DWORD Index
The VCPU number.
QWORD SyscallAddress
Guest virtual address of the SYSCALL/SYSENTER handler.
#define LDR_FLAG_FIX_RELOCATIONS
If flag is set, the relocations will be applied.
unsigned int Agid
Internal use; IT'S NOT the agent tag.
QWORD SystemCr3
The Cr3 used to map the kernel.
#define INT_STATUS_SUCCESS
static INTSTATUS IntWinAgentHandleDriverVmcall(PWIN_AGENT Agent, PIG_ARCH_REGS Registers)
This function handles VMCALLs issued by the boot driver.
static INTSTATUS IntWinAgentRestoreState32(PWIN_AGENT Agent, PIG_ARCH_REGS Registers)
Restore the general purpose registers state.
INTSTATUS IntWinAgentHandleInt3(QWORD Rip, DWORD CpuNumber)
Handle a breakpoint that was initiated inside the guest.
#define INT_STATUS_DISASM_ERROR
Indicates a decoder error.
WORD Pattern[SIG_MAX_PATTERN]
We have at least pending agent waiting to be injected inside the guest.
void * ActiveAgent
There can be only one active agent at any given moment. This is the one.
unsigned int Size
The size of the agent.
#define _Out_writes_bytes_(expr)
static INTSTATUS IntWinAgentFindInstruction(BYTE MinLen, QWORD *InstructionVa, BYTE *InstructionLen, BYTE *InstructionBytes)
Searches for a suitable instruction to replace with a CALL to the trampoline code.
DWORD Options
Agent options.
#define OFFSET_WIN_X64_AGENT_TAG
DWORD Counter
Incremented on each agent injection, used to generate unique agent IDs.
INTSTATUS IntPeFindFunctionByPattern(QWORD ImageBase, WIN_UNEXPORTED_FUNCTION_PATTERN *Pattern, BOOLEAN IgnoreSectionHint, DWORD *Rva)
Find a function using a pattern.
unsigned int Type
The agent type. One of AGENT_TYPE.
static void IntWinAgentSelectTokens(QWORD *Token1, QWORD *Token2, QWORD *Token3)
Randomly select 3 tokens to be used by the bootstrap code when issuing hyper calls.
struct _LIST_ENTRY * Flink
#define OFFSET_WIN_X86_FREE
#define AGENT_HCALL_INTERNAL
Reserved for internal use.
AGENT_EVENT_TYPE Event
The type of the agent.
#define OFFSET_WIN_X64_SEMAPHORE
BYTE BootStrap[MAX_BOOTSTRAP_SIZE]
The bootstrap code.
QWORD DriverAddress
Address of the boot driver.
QWORD BaseVa
The guest virtual address of the kernel module that owns this driver object.
#define INT_SUCCESS(Status)
QWORD ExFreePoolWithTag
Guest virtual address of the ExFreePoolWithTag kernel function.
static BOOLEAN IsListEmpty(const LIST_ENTRY *ListHead)
#define OFFSET_WIN_X86_TOKEN1
BYTE gWindowsBootstrapAgentx64[0x180]
INTSTATUS IntResumeVcpus(void)
Resumes the VCPUs previously paused with IntPauseVcpus.
LIST_ENTRY Link
List entry element.
BOOLEAN IntWinAgentIsRipInsideCurrentAgent(QWORD Rip)
Return true if the given RIP points inside the currently active boot driver.
#define OFFSET_WIN_X86_TOKEN3
#define IG_MAX_AGENT_NAME_LENGTH
DWORD DriverEntryPoint
Entry point of the boot driver.
INTSTATUS IntWinAgentInjectBreakpoint(PFUNC_AgentInjection InjectionCallback, void *Context, PWIN_AGENT *Agent)
Injects a breakpoint agent inside the guest.
static INTSTATUS IntWinAgentRemoveAgentAndResetState(WIN_AGENT *Agent)
Removes the indicated agent.
QWORD BootstrapAddress
Address where the bootstrap was allocated.
Event structure for agent injection and termination.
static INTSTATUS IntWinAgentFree(PWIN_AGENT Agent, QWORD DataInfo)
Frees an agent.
static INTSTATUS IntWinAgentHandleLoader2Hypercall(PWIN_AGENT Agent, PIG_ARCH_REGS Registers)
Handles VMCALLs issued by the bootstrap code.
BYTE InstructionLen
Detoured instruction length.
#define OFFSET_WIN_X64_TOKEN3
PFUNC_AgentCompletion CompletionCallback
Completion callback.
BYTE gTrampolineAgentx64[54]
struct _AGENT_NAME AGENT_NAME
void IntWinAgentDisablePendingAgents(void)
Disables all pending agents.
static INTSTATUS IntWinAgentHandleBreakpointAgent(PWIN_AGENT Agent, PIG_ARCH_REGS Registers)
Handle an INT3 that was initiated by a breakpoint agent.
INTSTATUS IntPeFindFunctionByPatternInBuffer(BYTE *Buffer, DWORD BufferSize, WIN_UNEXPORTED_FUNCTION_PATTERN *Pattern, BOOLEAN IgnoreSectionHint, DWORD *Rva)
Find a function using a pattern.
#define HpAllocWithTag(Len, Tag)
int INTSTATUS
The status data type.
#define AGENT_COMMAND_VERSION
Agent command structure version. Increment this whenever modifying the AGENT_COMMAND structure...
DWORD OSVersion
Os version.
#define OFFSET_WIN_X64_TOKEN2
#define INT_STATUS_NOT_FOUND
BOOLEAN BootstrapAgentAllocated
True if the slack space for the bootstrap agent has been allocated.
BOOLEAN Initialized
True if the agents state has been initialized.
QWORD Token2
Token used by the bootstrap code.
QWORD ExAllocatePoolWithTag
Guest virtual address of the ExAllocatePoolWithTag kernel function.
#define IMAGE_BASE_NAME_LEN
The maximum length of a process name.
INTSTATUS IntPauseVcpus(void)
Pauses all the guest VCPUs.
INTRO_GUEST_TYPE OSType
The type of the guest.
#define INT_STATUS_OPERATION_NOT_IMPLEMENTED
Will write the contents of the patched data inside the guest.
PBYTE AgentContent
Agent contents. Can be a file, process, driver, etc.
#define OFFSET_WIN_X86_SEMAPHORE
INTSTATUS IntSlackAlloc(QWORD ModuleBase, BOOLEAN Pageable, DWORD Size, QWORD *Buffer, QWORD SecHint)
Allocate slack inside the guest.
#define AGENT_HCALL_FETCH_CHUNK
Used to get the remediation agent data.
Describes a pattern for a kernel function that is not exported.
#define TRAMPOLINE_MAX_SIZE
#define OFFSET_WIN_X86_THREAD
#define OFFSET_WIN_X64_AGENT_SIZE
INTSTATUS IntWinAgentEnableInjection(void)
enables agent injections.
void IntWinAgentCheckIfProcessAgentAndDecrement(CHAR *ImageName, BOOLEAN *IsAgent, DWORD *Tag, BOOLEAN *Removed)
Checks if a process is an agent or not, and decrements the ref count of that name.
Describes a kernel driver.
KERNEL_DRIVER * IntDriverFindByName(const void *Name)
Searches for a driver by its name.
INTSTATUS IntAgentHandleLogGatherVmcall(void *Reserved, PIG_ARCH_REGS Registers)
Handle a VMCALL issued by a log gather agent.
DWORD Agid
Agent ID. Unique for each injected agent.
QWORD PsCreateSystemThread
Guest virtual address of the PsCreateSystemThread kernel function.
#define AG_OPT_INJECT_ON_RIP_POWSTATE_CHANGE
struct _AGENT_NAME * PAGENT_NAME
Allows the code inside the region to modify the region.
#define MAX_BOOTSTRAP_SIZE
Maximum size of the bootstrap code.
A driver will be injected and started inside the kernel. NOT USED!
#define INT_STATUS_INVALID_PARAMETER_10
CHAR Name[IG_MAX_AGENT_NAME_LENGTH]
Agent name.
#define OFFSET_WIN_X86_TOKEN2
GENERIC_ALERT gAlert
Global alert buffer.
BYTE gTrampolineAgentx86[52]
void * TrampolineCloak
Cloak handle used to hide the trampoline inside the guest.
INTSTATUS IntWinAgentUnInit(void)
Uninit the agents state.
#define AGENT_HCALL_GATHER_TOOL
Log gathering tool.
DWORD PendingAgentsCount
Number of agents waiting to be activated.
DWORD BootstrapAgentsCount
Number of agents bootstrapping.
#define AGENT_HCALL_PT
Used to get the PT cache agent.
#define OFFSET_WIN_X86_JUMPBACK
INTSTATUS IntWinAgentReleaseBootstrapAddress(QWORD Address)
Releases the slack space allocated for the bootstrap code.
CHAR Args[IG_MAX_COMMAND_LINE_LENGTH]
Agent arguments.
#define INT_STATUS_ALREADY_INITIALIZED
#define OFFSET_WIN_X86_AGENT_EP
#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...
DWORD IsPreviousAgent
TRUE if this is an agent injected in a previous session.
#define OFFSET_WIN_X64_ALLOC
INTSTATUS IntDetModifyPublicData(DETOUR_TAG Tag, void const *Data, DWORD DataSize, char const *PublicDataName)
Modifies public parts of a detour handler.
__noreturn void IntBugCheck(void)
INTSTATUS IntNotifyIntroEvent(INTRO_EVENT_TYPE EventClass, void *Param, size_t EventSize)
Notifies the integrator about an introspection alert.
void * Context
Optional context. Passed along to the 3 callbacks above.
BOOLEAN SafeToInjectProcess
Will be true the moment it's safe to inject agents (the OS has booted).
unsigned long long Pointer
A pointer to the agent contents in guest memory.
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
#define AGENT_HCALL_OWN_BASE
Used to get the base of the agent module.
INTSTATUS(* PFUNC_AgentCompletion)(QWORD GuestVirtualAddress, DWORD ErrorCode, DWORD AgentTag, void *Context)
Completion callback.
static INTSTATUS IntWinAgentFindPropperSyscall(QWORD *PropperSyscall)
Find the main SYSCALL handler.
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
QWORD Trampoline
The address of the trampoline code (slacked inside the kernel).
CHAR Name[IMAGE_BASE_NAME_LEN]
Process base name.
#define IG_MAX_COMMAND_LINE_LENGTH
#define TRAMP_X64_VMCALL1
SIZE_T NameLen
Name length.
#define OFFSET_WIN_X64_AGENT_EP
DWORD BootstrapSize
The size of the bootstrap.
QWORD IntPtiGetAgentAddress(void)
Get the guest virtual address where the PT filter resides.
Informational event sent when the remediation tool is injected or terminated. See EVENT_AGENT_EVENT...
#define INT_STATUS_INVALID_PARAMETER_4
PWIN_PROCESS_OBJECT IntWinProcFindObjectByName(CHAR const *Name, BOOLEAN MustBeSystem)
Finds a process by name.
INTSTATUS(* PFUNC_AgentInjection)(QWORD GuestVirtualAddress, DWORD AgentTag, void *Context)
Injection callback.
#define AGENT_HCALL_SYS_LNK
Used to get a kernel syscall linkage address.
AGENT_HCALL HcallType
Hyper call type.
static INTSTATUS IntWinAgentReleaseBootstrapAndRemoveAgent(WIN_AGENT *Agent, IG_ARCH_REGS *Registers)
Releases the bootstrap address and removes the agent.
#define TRAMP_X86_VMCALL2
CHAR SectionHint[8]
Optional section name hint.
WIN_OPAQUE_FIELDS OsSpecificFields
OS-dependent and specific information (variables, offsets, etc).
#define HpFreeAndNullWithTag(Add, Tag)
PWIN_PROCESS_OBJECT IntWinProcFindObjectByCr3(QWORD Cr3)
Finds a process by its kernel CR3.
SIZE_T ArgsLen
Length of the arguments.
#define AGENT_HCALL_FETCH_CMD
Used to get the command structure for the agent.
INTSTATUS IntMemClkCloakRegion(QWORD VirtualAddress, QWORD Cr3, DWORD Size, DWORD Options, PBYTE OriginalData, PBYTE PatchedData, PFUNC_IntMemCloakWriteHandle WriteHandler, void **CloakHandle)
Hides a memory zone from the guest.
#define AGENT_HCALL_VE
Used to get a generically piece of data inside a pre-allocated region.
void * Name
The name of the driver.
PFUNC_AgentDeliver DeliverCallback
Delivery callback.
QWORD Token3
Token used by the bootstrap code.
QWORD KernelVa
The guest virtual address at which the kernel image.
INTSTATUS IntIcFlushAddress(PINS_CACHE Cache, QWORD Gva, QWORD Cr3)
Flush entries cached from a given address.
INTSTATUS IntWinAgentActivatePendingAgent(void)
Activates a pending agent that waits to be injected.
#define AGENT_HCALL_REM_TOOL
Used by the remediation tool.
BYTE WordSize
Guest word size. Will be 4 for 32-bit guests and 8 for 64-bit guests.
LIST_ENTRY AgentNames
List of agent names.
static void InsertTailList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
#define INT_STATUS_NO_DETOUR_EMU
Signals that no emulation is needed for this event.
#define OFFSET_WIN_X64_JUMPBACK
void IntWinAgentCheckIfProcessAgentAndIncrement(CHAR *ImageName, BOOLEAN *IsAgent, DWORD *Tag)
Checks if a process is an agent or not, and increments the ref count of that name.
size_t strlcpy(char *dst, const char *src, size_t dest_size)
#define AGENT_FLAG_ALL_DONE
#define INT_STATUS_INVALID_PARAMETER_12
DWORD Pid
Process ID (the one used by Windows).
#define AGENT_HCALL_VCPUID
Used to get the ID of the current VCPU.
#define AGENT_FLAG_ACTIVE
#define TRAMP_X86_VMCALL1
struct _AGENT_STATE * PAGENT_STATE
static void InitializeListHead(LIST_ENTRY *ListHead)
INTSTATUS IntVirtMemSafeWrite(QWORD Cr3, QWORD VirtualAddress, DWORD Size, void *Buffer, DWORD Ring)
Safely modify guest memory.
enum _AGENT_TYPE AGENT_TYPE
INTSTATUS IntReleaseBuffer(void *Buffer, DWORD Size)
#define UNREFERENCED_PARAMETER(P)
INTSTATUS IntSlackFree(QWORD Buffer)
Free slack space.
DWORD AgentPosition
Current pointer inside the agent, used to track which chunk must be injected inside the guest...
LIST_ENTRY PendingAgents
List of agents waiting to be injected.
DWORD SyscallNumbers[winKmFieldSyscallNumbersEnd]
Syscall numbers needed by agents. Indexed with values from WIN_KM_FIELD_SYSCALL_NUMBERS.
void * InstructionCache
The currently used instructions cache.
WORD OffsetJumpBack
Offset of the trampoline code which jumps back to the detoured instruction.
#define OFFSET_WIN_X86_ALLOC
DWORD KernelBufferSize
The size of the KernelBuffer.
CHAR ImageName[IMAGE_BASE_NAME_LEN]
Image base name.
#define OFFSET_WIN_X86_RELOC
unsigned int Flags
Note used.
BOOLEAN AgentInternal
True if the agent is internal to Introcore.
static INTSTATUS IntWinAgentFindSyscallLinkage(DWORD SyscallNumber, QWORD *LinkageAddress)
Find the address of the kernel linkage of a syscall.
INTSTATUS IntWinAgentInjectTrampoline(void)
Inject the agent trampoline inside the guest.
A binary blob of code will be injected and started in the kernel. NOT USED!
static uint64_t __rdtsc(void)
WORD OffsetVmcall2
Offset to the second hyper call.
char Args[AGENT_MAX_COMMAND_LINE_LENGTH]
Command line arguments used by the injected process. It is limited to AGENT_MAX_COMMAND_LINE_LENGTH b...
INTSTATUS IntSetGprs(DWORD CpuNumber, PIG_ARCH_REGS Regs)
Sets the values of the guest GPRs.
BYTE InstructionBytes[16]
Detoured instruction bytes.
#define IntDbgEnterDebugger()
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
INTSTATUS IntLdrLoadPEImage(PBYTE RawPe, DWORD RawPeSize, QWORD GuestVirtualAddress, PBYTE LoadedPe, DWORD VirtualPeSize, DWORD Flags)
Load the provided PE image at the provided guest virtual address, and return it in LoadedPe...
AGENT_TYPE AgentType
Agent type.
unsigned int Version
Structure version. Check out AGENT_COMMAND_VERSION.
PATTERN_SIGNATURE Signature
The pattern signature.
GUEST_STATE gGuest
The current guest state.
INTSTATUS IntLdrGetImageSizeAndEntryPoint(PBYTE RawPe, DWORD RawSize, DWORD *VirtualSize, DWORD *EntryPoint)
Returns the entry point and the virtual size for the provided module.
THS_PTR_TYPE
The type of pointer to be checked.
BOOLEAN IntWinAgentIsPtrInTrampoline(QWORD Ptr, THS_PTR_TYPE Type)
Check if the provided address points inside the agent trampoline.
#define AGENT_FLAG_ALLOCATED
char Name[AGENT_MAX_AGENT_NAME_LENGTH]
The agent name. This will be the file name or the process name.
DWORD Pid
PID of the process that will be the parent of the injected process.
AG_WAITSTATE IntWinAgentGetState(DWORD *Tag)
Gets the global agents state.
#define OFFSET_WIN_X64_TOKEN1
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.
The agent or the process stub reports an error.
LIST_ENTRY Link
List entry element.
#define AGENT_FLAG_COMPLETED
INTSTATUS IntCr3Read(DWORD CpuNumber, QWORD *Cr3Value)
Reads the value of the guest CR3.
BYTE gWindowsBootstrapAgentx86[0x120]
#define INT_STATUS_NOT_INITIALIZED_HINT
BYTE * KernelBuffer
A buffer containing the entire kernel image.
QWORD(* PFUNC_AgentDeliver)(QWORD GuestVirtualAddress, DWORD MaxSize, void *Context)
Called for VE and PT initialization.
char * utf16_for_log(const WCHAR *WString)
Converts a UTF-16 to a UTF-8 string to be used inside logging macros.
WORD OffsetStop
Offset to the code chunk that stops the thread (_stop label).
void IntWinAgentRemoveEntryByAgid(DWORD Counter, DWORD *Tag)
Removes an agent name from the list of names, using the ID.
void * BootCloakRegion
Cloak handle used to hide the bootstrap code.
#define INT_STATUS_INVALID_PARAMETER_1
#define INT_STATUS_NOT_SUPPORTED
INTSTATUS IntMemClkUncloakRegion(void *CloakHandle, DWORD Options)
Removes a cloak region, making the original memory contents available again to the guest...
VCPU_STATE * gVcpu
The state of the current VCPU.
INTSTATUS IntWinAgentSelectBootstrapAddress(DWORD Size, QWORD *Address)
Finds an in-guest adders that can be used to host the bootstrap code.
The Virtualization exception driver.
DWORD IsAgent
TRUE if this is an injected agent.
DWORD RefCount
Number of times this name has been used by agents.
Process agent. A process will be injected & started inside the guest.
unsigned int Pid
The process PID from which to start a process agent.
#define OFFSET_WIN_X64_THREAD
__fn_naked void trampoline(void)
The trampoline of the agent.
#define AGENT_HCALL_MOD_BASE
Used to get the base of the module indicated by edi/rcx.
enum _AG_WAITSTATE AG_WAITSTATE
INTSTATUS IntGetCurrentRing(DWORD CpuNumber, DWORD *Ring)
Read the current protection level.
static INTSTATUS IntWinAgentRemove(PWIN_AGENT Agent)
Removes the given agent.
#define UNREFERENCED_LOCAL_VARIABLE(V)
WORD OffsetVmcall1
Offset to the first hyper call.
unsigned int Synched
Always FALSE for now. Will not wait for the process agent to finish.
BYTE gTrampolineZero[4096]
Just a page filled with zeros.
QWORD IntVeGetDriverAddress(void)
Gets the guest virtual address of the VE agent.
unsigned long long * PQWORD
static AGENT_STATE gAgentState
We have an active agent, currently injected inside the guest.
QWORD Token1
Token used by the bootstrap code.
static INTSTATUS IntWinAgentRestoreState64(PWIN_AGENT Agent, PIG_ARCH_REGS Registers)
Restore the general purpose registers state.
void * InsCloakRegion
Cloak handle used to hide the detoured instruction.
QWORD InstructionAddress
Address of the detoured instruction.
The page table filtering agent.
INTSTATUS IntWinAgentHandleVmcall(QWORD Rip)
Handle a VMCALL that was executed inside the guest.
#define INT_STATUS_INVALID_PARAMETER_2
#define OFFSET_WIN_X86_AGENT_TAG
DWORD DriverSize
Size of the boot driver.
DWORD TrampolineSize
Size of the trampoline code.
void IntWinAgentInit(void)
Initialize the agents state.
int strlower_utf8(char *buf, size_t len)
File agent. A file will be dropped inside the guest.
#define AGENT_FLAG_STARTED
PFUNC_AgentInjection InjectionCallback
Injection callback.
This structure describes a running process inside the guest.
#define INT_STATUS_INSUFFICIENT_RESOURCES
#define TRAMP_X64_VMCALL2
#define INT_STATUS_INVALID_PARAMETER_3