19 #define LIX_MM_PROT_MASK BIT(63) 90 #define for_next_task(_task, _var_name) list_for_next(_task, gLixTasks, LIX_TASK_OBJECT, _var_name) 95 #define for_each_task(_var_name) list_for_each(gLixTasks, LIX_TASK_OBJECT, _var_name) 100 #define for_each_protected_task(_var_name) list_for_each_link(gLixProtectedTasks, LIX_TASK_OBJECT, \ 101 ExploitProtProcLink, _var_name) 106 #define for_each_task_to_protect(_var_name) list_for_each(gLixTasksToProtect, LIX_PROTECTED_PROCESS, _var_name) 117 #define for_each_path(_var_name) list_for_each(gLixTaskPaths, LIX_TASK_PATH, _var_name) 139 for (i = len - 1; i && (path[i] !=
'/'); i--);
141 return path + i + !!(path[i] ==
'/');
157 for (; i && path[i] ==
'/'; i--)
218 if (pPath->DentryGva == DentryGva)
229 ERROR(
"[ERROR] IntLixFileGetPath failed for %llx: %08x\n", FileGva, status);
240 ERROR(
"[ERROR] IntReadString failed for %llx: %08x\n", PathGva, status);
262 if (NULL == pPath->
Path)
268 memcpy(pPath->
Path, path, len + 1ull);
301 ERROR(
"[ERROR] IntLixFileGetDentry failed for file %llx: %08x\n", FileGva, status);
380 if (Task->KernelMode)
385 else if (Task->IsThread)
391 return (gLixTaskLogLevel.
Execs || (Protected && gLixTaskLogLevel.
ProtExecs));
395 return (gLixTaskLogLevel.
Forks || (Protected && gLixTaskLogLevel.
ProtForks));
419 if (NULL == InitTask)
432 startGva < gLixGuest->Layout.DataEnd;
441 ERROR(
"[ERROR] IntVirtMemMap failed for 0x%016llx 0x%08x\n", startGva, status);
447 QWORD parent, mm, signal;
457 ERROR(
"[ERROR] IntVirtMemFetchQword failed: 0x%08x\n", status);
463 parent = *(
QWORD *)(p + offset +
LIX_FIELD(TaskStruct, RealParent));
477 ERROR(
"[ERROR] IntKernVirtMemFetchQword failed: 0x%08x\n", status);
497 ERROR(
"[ERROR] IntKernVirtMemFetchQword failed for 0x%016llx: 0x%08x\n",
518 ERROR(
"[ERROR] IntKernVirtMemFetchQword failed: 0x%08x\n", status);
536 ERROR(
"[ERROR] Failed reading process name @ 0x%016llx: 0x%08x\n",
537 ts +
LIX_FIELD(TaskStruct, Comm), status);
543 if (0 != memcmp(comm,
"swapper",
sizeof(
"swapper") - 1))
548 comm[
sizeof(comm) - 1] = 0;
550 TRACE(
"[LIXTASK] Found init_task @ 0x%016llx with name %s\n", ts, comm);
598 ERROR(
"[ERROR] IntVirtMemMap failed for %llx: %08x\n",
gTaskMapped, status);
634 DWORD remaining = Size;
640 memcpy(Buffer,
gTaskPtr1 + Offset, toRead);
652 ERROR(
"[ERROR] IntVirtMemMap failed for %llx: %08x\n", nextPage, status);
662 memcpy(Buffer,
gTaskPtr1 + Offset, Size);
724 if (Task->KernelMode)
734 ERROR(
"[ERROR] Fetching mm failed in task 0x%016llx: 0x%08x\n", Task->Gva, status);
750 if (Parent && Parent->MmGva == mmGva)
752 Task->Cr3 = Parent->Cr3;
760 ERROR(
"[ERROR] IntKernVirtMemFetchQword failed for GVA 0x%016llx: 0x%08x\n",
761 mmGva +
LIX_FIELD(MmStruct, Pgd), status);
762 goto _cleanup_and_exit;
767 ERROR(
"[ERROR] The PGD 0x%016llx @ 0x%016llx (offset %x) is not a valid one!\n",
772 goto _cleanup_and_exit;
778 ERROR(
"[ERROR] Failed translating PGD 0x%016llx: 0x%08x\n", pgd, status);
814 if (TaskStruct == NULL)
827 ERROR(
"[ERROR] IntGsRead failed for cpu %d: 0x%08x.\n", CpuNumber, status);
833 WARNING(
"[WARNING] 'gs' for cpu %d is not in kernel mode: %llx\n", CpuNumber, gsBase);
840 ERROR(
"[ERROR] IntKernVirtMemPatchQword failed for gva 0x%llx with status: 0x%08x\n",
847 ERROR(
"[ERROR] Current task 0x%016llx is not valid!\n", current);
851 *TaskStruct = current;
963 if (pTask->Cr3 == Cr3)
988 if (pTask->MmGva == MmGva)
1014 if (pTask->MmGva == MmGva)
1040 if (pTask->Gva == TaskStruct)
1066 if (pTask->Pid == Pid)
1123 QWORD trapFrameGva, kmStack;
1128 ERROR(
"[ERROR] Failed to read km stack pointer for task %s (%d 0x%llx). Status: 0x%08x\n",
1129 Task->Comm, Task->Pid, Task->Gva, status);
1133 trapFrameGva = kmStack +
LIX_FIELD(Info, ThreadSize) -
sizeof(*TrapFrame);
1135 memzero(TrapFrame,
sizeof(*TrapFrame));
1161 if ((pProt->NamePattern && Task->Path &&
IntMatchPatternUtf8(pProt->NamePattern, Task->Path->Name, 0)) ||
1174 _In_ const void *Name,
1189 WARNING(
"[WARNING] Unsupported string encoding: %d\n", Encoding);
1197 pProcess->Protection.Current = pProcess->Protection.Original & ~(Options->ForceOff);
1198 pProcess->Protection.Beta = Options->ForceBeta;
1199 pProcess->Protection.Feedback = Options->ForceFeedback;
1201 TRACE(
"[CAMI] Protected process info updated. Original : 0x%llx, Current : 0x%llx, " 1202 "Beta : 0x%llx, Feedback : 0x%llx", pProcess->Protection.Original, pProcess->Protection.Current,
1203 pProcess->Protection.Beta, pProcess->Protection.Feedback);
1235 ERROR(
"[ERROR] IntIcFlushVaSpace failed: 0x%08x\n", status);
1243 CRITICAL(
"[ERROR] IntKernVirtMemFetchQword failed for mm %llx: %08x\n", Task->MmGva, status);
1253 ERROR(
"[ERROR] IntKernVirtMemPatchQword failed for mm %llx: %08x\n", Task->MmGva, status);
1257 if (Task->HookObject)
1262 ERROR(
"[ERROR] IntHookObjectDestroy failed: %08x", status);
1299 ERROR(
"[ERROR] Requesting to protect process '%s' (%d, %llx, %llx)but it has no CR3 (mm 0x%016llx)!\n",
1300 Task->ProcName, Task->Pid, Task->Gva, Task->Cr3, Task->MmGva);
1304 if (Task->StaticDetected)
1308 DWORD mmUsers = 0, mmCount = 0;
1313 ERROR(
"[ERROR] Failed getting mm_users: %08x\n", status);
1320 ERROR(
"[ERROR] Failed getting mm_count: %08x\n", status);
1324 if (0 == mmUsers || 0 == mmCount)
1326 WARNING(
"[WARNING] Process %s (%d, %llx, %llx) has a dying mm @ %llx: (%d, %d)!\n",
1327 Task->Comm, Task->Pid, Task->Gva, Task->Cr3, Task->MmGva, mmUsers, mmCount);
1337 ERROR(
"[ERROR] IntHookObjectCreate failed: %08x\n", status);
1344 ERROR(
"[ERROR] IntLixMmPopulateVmas failed: 0x%08x\n", status);
1345 goto _free_and_exit;
1353 ERROR(
"[ERROR] IntKernVirtMemFetchQword failed for mm %llx: %08x\n", Task->MmGva, status);
1354 goto _free_and_exit;
1363 ERROR(
"[ERROR] IntKernVirtMemPatchQword failed for mm %llx: %08x\n", Task->MmGva, status);
1364 goto _free_and_exit;
1398 if (Task->Interpreter)
1419 Task->Context = pProt->
Context;
1423 Task->Protection.Mask = 0;
1427 Task->RootProtectionMask = Task->Protection.Mask;
1434 Task->Protection.Mask = Parent->RootProtectionMask;
1435 Task->Protection.Beta = Parent->Protection.Beta;
1436 Task->Protection.Feedback = Parent->Protection.Feedback;
1438 Task->RootProtectionMask = Parent->RootProtectionMask;
1439 Task->Context = Parent->Context;
1442 if (0 == Task->Protection.Mask)
1447 sameCr3 = Parent && (Task->Cr3 == Parent->Cr3);
1461 ERROR(
"[ERROR] Process '%s' (%d, %llx, %llx) will not be exploit-protected: %08x!\n",
1462 Task->ProcName, Task->Pid, Task->Gva, Task->Cr3, status);
1471 if (!sameCr3 && (Task->Protection.Mask == 0))
1473 ERROR(
"[ERROR] Task %s, 0x%016llx failed to activate any protection!\n", Task->Comm, Task->Gva);
1475 Task->Protected =
FALSE;
1487 TRACE(
"[PROC] Activated protection %llx for '%s' (%d, %llx, %llx)\n",
1488 Task->Protection.Mask, Task->ProcName, Task->Pid, Task->Gva, Task->Cr3);
1491 Task->Protected =
TRUE;
1509 if (!Task->Protected)
1517 WARNING(
"[WARNING] Process '%s' (%d, %llx, %llx) failed to deactivate protection: %08x\n",
1518 Task->ProcName, Task->Pid, Task->Gva, Task->Cr3, status);
1523 LOG(
"[PROC] Deactivated protection for %s '%s' (%d, %llx, %llx)!\n",
1524 Task->IsThread ?
"thread" :
"process", Task->ProcName,
1525 Task->Pid, Task->Gva, Task->Cr3);
1528 Task->Protection.Mask = 0;
1529 Task->RootProtectionMask = 0;
1531 Task->Protected =
FALSE;
1552 QWORD vmaStart, vmaEnd, iter, file;
1553 DWORD argc, curLength, allocationSize;
1554 BYTE *pMapping = NULL;
1559 ERROR(
"[ERROR] IntVirtMemMap failed for %llx: 0x%08x\n", BinprmGva, status);
1575 ERROR(
"[ERROR] IntVirtMemMap failed for %llx: 0x%08x\n", file, status);
1586 ERROR(
"[ERROR] VMA limits are not PAGE_SIZE aligned: start=0x%llx end = 0x%llx", vmaStart, vmaEnd);
1590 if (vmaStart >= vmaEnd)
1592 ERROR(
"[ERROR] Start of vma_struct %llx is bigger or equal that the end %llx!\n", vmaStart, vmaEnd);
1598 ERROR(
"[ERROR] Argpage VMA is to big: 0x%llu. Cmdline will not be fetched\n", vmaEnd - vmaStart);
1603 for (iter = vmaStart;
1607 if ((iter >= vmaEnd) || NULL == pMapping)
1609 ERROR(
"[ERROR] Could not read cmdline. Not a single page from VMA 0x%llx to 0x%llx is present!\n",
1615 allocationSize = (
DWORD)(vmaEnd - iter);
1618 if (NULL == Process->CmdLine)
1628 while ((0 == curLength) && (parsed <
PAGE_SIZE) && (0 == pMapping[parsed]))
1635 if (0 == pMapping[parsed])
1642 Process->CmdLine[curLength] =
' ';
1646 Process->CmdLine[curLength] = pMapping[parsed];
1663 WARNING(
"[WARNING] Reached end of vma, but there are %d more args to be read!\n", argc);
1670 ERROR(
"[ERROR] IntVirtMemMap failed: %08x\n", status);
1676 if (curLength >= allocationSize)
1678 curLength = allocationSize - 1;
1681 Process->CmdLine[curLength] = 0;
1682 Process->CmdLineLength = curLength;
1702 Task->ProcName = Task->Path->Path;
1703 Task->ProcNameLength = (
DWORD)Task->Path->PathLength;
1707 Task->ProcName = Task->Comm;
1708 Task->ProcNameLength = strlen(Task->Comm);
1730 ERROR(
"[ERROR] IntLixFileGetDentry failed for %llx: %08x\n", FileGva, status);
1734 if (!
IS_ERR(DPathGva) && DPathGva)
1739 if (NULL == Task->Path)
1767 QWORD pathGva, interpGva;
1778 UpdatedTask->ActualParent = OriginalTask->Parent;
1779 UpdatedTask->AgentTag = OriginalTask->AgentTag;
1780 UpdatedTask->Context = OriginalTask->Context;
1781 UpdatedTask->CreationTime = OriginalTask->CreationTime;
1782 UpdatedTask->Gva = OriginalTask->Gva;
1783 UpdatedTask->IsThread =
FALSE;
1784 UpdatedTask->KernelMode =
FALSE;
1785 UpdatedTask->Parent = OriginalTask->Parent;
1786 UpdatedTask->RealParent = OriginalTask->RealParent;
1787 UpdatedTask->Tgid = OriginalTask->Tgid;
1788 UpdatedTask->Pid = OriginalTask->Pid;
1790 memcpy(UpdatedTask->Comm, OriginalTask->Comm,
sizeof(UpdatedTask->Comm));
1794 UpdatedTask->ReExecToSelf =
FALSE;
1799 ERROR(
"[ERROR] IntVirtMemMap failed for GVA 0x%016llx: 0x%08x\n", BinprmGva, status);
1800 goto _cleanup_and_exit;
1806 ERROR(
"[ERROR] _IntLixTaskStartMap failed for task %llx: 0x%08x\n", UpdatedTask->Gva, status);
1807 goto _cleanup_and_exit;
1816 ERROR(
"[ERROR] _IntLixTaskRead failed for %llx: %08x\n",
1817 UpdatedTask->Gva +
LIX_FIELD(TaskStruct, InExecve), status);
1819 else if (0 == (in &
BIT(
LIX_FIELD(TaskStruct, InExecveBit))))
1821 ERROR(
"[ERROR][CRITICAL] in_execve is not in fact set: 0x%02x\n", in);
1828 ERROR(
"[ERROR] IntLixTaskFetchMm failed for %s: 0x%08x. The process cannot be protected!\n",
1829 UpdatedTask->ProcName, status);
1837 if (interpGva && interpGva != pathGva)
1839 status =
IntReadString(interpGva, 2,
FALSE, &UpdatedTask->Interpreter, &UpdatedTask->InterpLength);
1842 UpdatedTask->Interpreter = NULL;
1843 UpdatedTask->InterpLength = 0;
1851 ERROR(
"[ERROR] Failed getting the PID from task_struct %llx: %08x\n",
1852 UpdatedTask->Gva +
LIX_FIELD(TaskStruct, Pid), status);
1854 else if (exitSignal < 0)
1862 ERROR(
"[ERROR] Failed getting the group_leader from task_struct %llx: %08x\n",
1863 UpdatedTask->Gva +
LIX_FIELD(TaskStruct, GroupLeader), status);
1868 if (NULL == pGroupLeader)
1873 ERROR(
"[ERROR] IntKernVirtMemFetchDword failed for %llx: %08x\n",
1874 groupLeader +
LIX_FIELD(TaskStruct, Pid), status);
1879 pid = pGroupLeader->
Pid;
1882 if (UpdatedTask->Pid != pid)
1884 TRACE(
"[INFO] Process '%s' changes PID from %d to %d\n", UpdatedTask->ProcName, UpdatedTask->Pid, pid);
1886 UpdatedTask->Pid = pid;
1891 if (OriginalTask->ExeFileDentry == UpdatedTask->ExeFileDentry)
1893 UpdatedTask->ReExecToSelf =
TRUE;
1896 if ((!UpdatedTask->ReExecToSelf) && OriginalTask->Interpreter && UpdatedTask->Interpreter)
1898 if (OriginalTask->InterpLength == UpdatedTask->InterpLength &&
1899 0 == strcmp(OriginalTask->Interpreter, UpdatedTask->Interpreter))
1901 UpdatedTask->ReExecToSelf =
TRUE;
1916 ERROR(
"[ERROR] IntLixCredAdd failed for %s (%d 0x%llx). Status: 0x%08x\n",
1917 UpdatedTask->Comm, UpdatedTask->Pid, UpdatedTask->Gva, status);
1918 UpdatedTask->Creds = NULL;
1960 if (Created && Task->ReExecToSelf)
1966 memzero(pProcEvent,
sizeof(*pProcEvent));
1968 pProcEvent->
Created = Created;
1969 pProcEvent->
Protected = Task->Protected != 0;
1970 pProcEvent->
Crashed = Crashed;
1973 if (!StaticDetected)
1997 WARNING(
"[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
2019 if (!Task->AgentTag)
2025 memzero(pAgentEvent,
sizeof(*pAgentEvent));
2032 pAgentEvent->
AgentTag = Task->AgentTag;
2038 WARNING(
"[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
2068 ERROR(
"[ERROR] IntLixTaskGetTrapFrame failed: %08x\n", status);
2072 if (NULL != StackBase || NULL != StackLimit)
2077 ERROR(
"[ERROR] Failed to find stack limits for process %s (%d 0x%llx), rsp: 0x%llx. Status:0x%08x\n",
2078 Task->Comm, Task->Pid, Task->Gva, trapFrame.
Rsp, status);
2082 if (NULL != StackBase)
2087 if (NULL != StackLimit)
2089 *StackLimit = limit;
2093 if (NULL != StackPointer)
2095 *StackPointer = trapFrame.
Rsp;
2135 ERROR(
"[ERROR] Failed getting the flags in task 0x%016llx: 0x%08x\n", TaskStruct, status);
2141 TRACE(
"[INFO] Task with 0x%llx is dying while initializing (static: %d)... Will ignore.\n",
2142 TaskStruct, StaticDetected);
2156 pTask->
Gva = TaskStruct;
2161 ERROR(
"[ERROR] Failed getting the 'PID' in task 0x%016llx: 0x%08x\n", pTask->
Gva, status);
2162 goto _free_and_exit;
2165 if (!StaticDetected)
2173 ERROR(
"[ERROR] [CRITICAL] There is already an existing task with PID %d\n", pTask->
Pid);
2175 LOG(
"[ERROR] %s%s %s (%d/%d, %16llx)]\n",
2176 pExistingTask->
IsThread ?
"Thread" :
"Process",
2179 pExistingTask->
Pid, pExistingTask->
Tgid, pExistingTask->
Gva);
2186 ERROR(
"[ERROR] Failed getting the 'tgid' in task 0x%016llx: 0x%08x\n", pTask->
Gva, status);
2187 goto _free_and_exit;
2194 ERROR(
"[ERROR] Failed reading 'comm' in task 0x%016llx: 0x%08x\n", pTask->
Gva, status);
2195 goto _free_and_exit;
2218 (!pTask->
IsThread && RealParent->Pid == 1))
2227 pActualParent = RealParent;
2231 if (NULL == pActualParent)
2233 WARNING(
"[WARNING] Task with TGID %d is dead\n", pTask->
Tgid);
2234 pActualParent = RealParent;
2240 pTask->
Parent = Parent->Gva;
2244 QWORD time[2] = {0};
2249 ERROR(
"[ERROR] Failed getting the start time in task 0x%016llx: 0x%08x\n", pTask->
Gva, status);
2250 goto _free_and_exit;
2263 ERROR(
"[ERROR] Failed getting the start time in task 0x%016llx: 0x%08x\n", pTask->
Gva, status);
2264 goto _free_and_exit;
2276 ERROR(
"[ERROR] IntLixTaskFetchMm failed: 0x%08x. This task (%s) cannot be protected!\n",
2277 status, pTask->
Comm);
2295 ERROR(
"[ERROR] IntKernVirtMemFetchQword failed for %llx: %08x\n",
2297 goto _initialize_and_prot;
2303 ERROR(
"[ERROR] IntLixFileGetDentry failed for %llx: %08x\n", file, status);
2304 goto _initialize_and_prot;
2310 _initialize_and_prot:
2327 ERROR(
"[ERROR] IntLixTaskActivateProtection failed for %s (%llx): 0x%08x\n", pTask->
Comm, pTask->
Gva, status);
2344 ERROR(
"[ERROR] IntLixCredAdd failed for task %s (%d 0x%llx) with status: 0x%08x!. Creds gva: 0x%llx\n",
2345 pTask->
Comm, pTask->
Pid, pTask->
Gva, status, creds);
2350 ERROR(
"[ERROR] _IntLixTaskRead failed for task %s (%d 0x%llx): 0x%08x\n",
2351 pTask->
Comm, pTask->
Pid, pTask->
Gva, status);
2359 ERROR(
"[ERROR] Failed to get user mode stack for process %s (%d, 0x%llx). Status: 0x%08x\n",
2360 pTask->
Comm, pTask->
Pid, pTask->
Gva, status);
2366 pTask->
Dpi.
StolenTokens = RealParent->Dpi.StolenTokens || Parent->Dpi.StolenTokens;
2372 LOG(
"[%s]%s %s (%s), (%d/%d, %llx, %llx) [from %s%s %s (%d, %16llx)]\n",
2373 pTask->
Exec ?
"EXEC" :
"FORK",
2379 pActualParent->
IsThread ?
"Thread" :
"Process",
2382 pActualParent->
Pid, pActualParent->
Gva);
2386 LOG(
"[THREAD]%s %s, (%d/%d, %llx, %llx)\n",
2400 if (StaticDetected && pTask->
Exec)
2437 if (Task->Protected)
2446 if (NULL != Task->Interpreter)
2451 if (NULL != Task->CmdLine)
2471 char specialChar =
'?';
2479 Task->Gva +
LIX_FIELD(TaskStruct, Comm) + 14,
2485 ERROR(
"[ERROR] IntVirtMemSafeWrite failed for task %llx: 0x%08x\n", Task->Gva, status);
2506 if (Task->Protected)
2509 wasProtected =
TRUE;
2512 signal = ExitCode & 0x7f;
2514 if ((ExitCode & 0x80) ||
2530 WARNING(
"[WARNING] Task %s (%d, %llx, %llx) was marked to be killed, but the signal it received is %d",
2531 Task->ProcName, Task->Pid, Task->Cr3, Task->Gva, signal);
2548 if (!Task->IsThread && !Task->KernelMode && Task->Cr3 != 0)
2554 ERROR(
"[ERROR] IntIcFlushVaSpace failed: 0x%08x\n", status);
2566 LOG(
"[EXIT] %s %s (%d, %llx, %llx), crashed: %d, signal: %d\n",
2567 Task->IsThread ?
"Thread" :
"Process", Task->ProcName, Task->Pid,
2568 Task->Cr3, Task->Gva, crashed, signal);
2571 if (!Task->IsThread)
2603 ERROR(
"[ERROR] We do not have any known DPI flag set -> Flags:0x%x\n", Flags);
2630 memzero(pEvent,
sizeof(*pEvent));
2656 WARNING(
"[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
2676 if (Task->Dpi.IsPivoted)
2681 if (Task->Dpi.StolenTokens)
2718 ERROR(
"[ERROR] IntLixValidateProcessCreationRights called with object type %d!\n", ObjectType);
2723 if (ChildTask->ReExecToSelf)
2729 if (ParentTask->KernelMode)
2738 if (originator.
PcType == 0)
2750 ERROR(
"[ERROR] IntExceptUserGetOriginator failed with status: 0x%08x.\n", status);
2759 ERROR(
"[ERROR] IntExceptGetVictimProcessCreation failed with status: 0x%08x.\n", status);
2771 LOG(
"[PROCESS CREATION] Process creation blocked. Process `%s` tried to start using process `%s`",
2772 ChildTask->Comm, ParentTask->Comm);
2783 LOG(
"[PROCESS CREATION] Process creation blocked. Process `%s` tried to start with DPI using process `%s`",
2784 ChildTask->Comm, ParentTask->Comm);
2817 if (NULL == Task || Task->KernelMode)
2827 if (NULL == IsPivoted)
2832 if (Task->UserStack.Valid)
2842 if (!Task->IsThread)
2846 WARNING(
"[WARNING] Parent task %s (%d 0x%llx) is not a thread and doesn't have a valid mm pointer!\n",
2847 Task->Comm, Task->Pid, Task->Gva);
2849 goto _check_altstack;
2855 ERROR(
"[ERROR] Failed to read start_stack from mm. Task %s (%d 0x%llx), MmGva 0x%llx, status: 0x%08x\n",
2856 Task->Comm, Task->Pid, Task->Gva, Task->MmGva, status);
2863 ERROR(
"[ERROR] Failed to find VAD for task->mm.start_stack(0x%llx) for process %s (%d 0x%llx). " 2864 "Status: 0x%08x\\n", base, Task->Comm, Task->Pid, Task->Gva, status);
2879 ERROR(
"[ERROR] Failed to read alt stack. Task %s (%d 0x%llx), status: 0x%08x\n",
2880 Task->Comm, Task->Pid, Task->Gva, status);
2890 ERROR(
"[ERROR] Failed to find alt stack (0x%llx) VAD for process %s (%d 0x%llx). Status: 0x%08x\n",
2891 base, Task->Comm, Task->Pid, Task->Gva, status);
2925 if (ParentTask->KernelMode)
2933 ERROR(
"[ERROR] Failed to get user mode stack pointer for parent task %s (%d 0x%llx). Status: 0x%08x\n",
2934 ParentTask->Comm, ParentTask->Pid, ParentTask->Gva, status);
2941 ERROR(
"[ERROR] IntLixTaskIsStackPivoted failed for stack ptr 0x%llx with status 0x%08x.", stackPointer, status);
2960 QWORD binprm, dPathResult;
2966 QWORD oldProtectionMask;
2967 static DWORD taskCount = 0;
2972 if (NULL == pOldTask)
2974 ERROR(
"[ERROR] No task on for exec!\n");
3001 ERROR(
"[ERROR] Failed updating process contents from the linux_binprm @ %16llx: 0x%08x\n",
3016 ERROR(
"[ERROR] We couldn't get path for process, the comm will be the old one!\n");
3028 TRACE(
"[INIT] Init process re-executes itself\n");
3047 goto _action_not_allowed;
3056 _action_not_allowed:
3062 ERROR(
"[ERROR] IntDetSetReturnValue failed: %08x\n", status);
3079 ERROR(
"[ERROR] IntLixTaskActivateProtection failed for %s: 0x%08x\n", pTask->
Comm, status);
3091 ERROR(
"[ERROR] IntLixTaskFetchCmdLine failed with status: 0%08x\n", status);
3098 ERROR(
"[ERROR] IntLixCmdLineInspect failed with status: 0%08x\n", status);
3107 LOG(
"[EXEC] %s %s (%d, %llx, %llx) exec to %s (interp: %s)\n",
3113 LOG(
"[EXEC] %s %s (%d, %llx, %llx) exec to %s\n",
3131 if ((oldLen != newLen) || (0 != memcmp(pOldTask->
Comm, pTask->
Comm, oldLen)))
3162 ERROR(
"[ERROR] IntLixVdsoDynamicProtect failed with status: 0x%08x.", status);
3171 ERROR(
"[ERROR] IntDetSetReturnValue failed: %08x\n", status);
3195 ERROR(
"[ERROR] IntLixTaskAdd failed for %llx on cpu %d: 0x%08x\n",
3224 memzero(pInjEvent,
sizeof(*pInjEvent));
3250 WARNING(
"[WARNING] IntNotifyIntroEvent failed: 0x%08x\n", status);
3282 pSource = pVictim = NULL;
3287 ERROR(
"[ERROR] IntLixTaskGetCurrentStruct failed: 0x%08x\n", status);
3293 if ((Pid && pProc->Pid == (
DWORD)Victim) || (!Pid && pProc->Gva == Victim))
3298 if (pProc->Gva == currentTask)
3303 if ((NULL != pVictim) && (NULL != pSource))
3309 if (NULL == pVictim || NULL == pSource)
3317 LOG(
"[PTRACE] Injection from %s (%d, %llx) into %s (%d, %llx)\n",
3329 memzero(&originator,
sizeof(originator));
3330 memzero(&victim,
sizeof(victim));
3338 ERROR(
"[ERROR] Failed getting originator: 0x%08x\n", status);
3339 goto _send_notification;
3349 ERROR(
"[ERROR] Failed getting modified zone: 0x%08x\n", status);
3350 goto _send_notification;
3360 LOG(
"[INJECTION] Block injection from process %s (%d) into process %s (%d)\n",
3367 LOG(
"[INJECTION] Allow injection from process %s into process %s\n",
3407 ERROR(
"[ERROR] IntLixTaskHandleInjection failed: %08x\n", status);
3408 goto _emulate_and_leave;
3415 ERROR(
"[ERROR] IntDetoursGstSetReturnValue failed: 0x%08x\n", status);
3448 ERROR(
"[ERROR] IntLixTaskHandleInjection failed: %08x\n", status);
3449 goto _emulate_and_leave;
3457 ERROR(
"[ERROR] IntLixTaskHandleSetRegs failed: %08x\n", status);
3458 goto _emulate_and_leave;
3463 WARNING(
"[WARNING] The request argument (%llx) for 'ptrace' is allowed ...\n", request);
3465 goto _emulate_and_leave;
3473 ERROR(
"[ERROR] IntDetoursGstSetReturnValue failed: 0x%08x\n", status);
3497 TRACE(
"[INFO] Task dying without being in the list... Ignore it!");
3503 LOG(
"[ERROR] Init task is exiting, something isn't right...\n");
3533 QWORD currentThread;
3535 QWORD signalListHead = 0;
3544 ERROR(
"[ERROR] Failed reading the signal struct: 0x%08x\n", status);
3550 ERROR(
"[ERROR] task->signal value (0x%llx) does not point to a valid kernel memory location.", signal);
3557 ERROR(
"[ERROR] Failed reading from the signal struct: 0x%08x\n", status);
3569 else if (nrThreads < 0)
3571 ERROR(
"[ERROR] Negative number of threads: %d\n", nrThreads);
3576 signalListHead = signal +
LIX_FIELD(Ungrouped, SignalListHead);
3581 ERROR(
"[ERROR] Failed getting the first task from signal 0x%016llx\n", signalListHead);
3585 currentThread -=
LIX_FIELD(TaskStruct, ThreadNode);
3591 ERROR(
"[ERROR] Failed getting the next task from 0x%016llx\n",
3592 currentThread +
LIX_FIELD(TaskStruct, ThreadNode));
3600 ERROR(
"[ERROR] Thread 0x%llx does not point to a valid kernel memory location.\n", currentThread);
3604 currentThread -=
LIX_FIELD(TaskStruct, ThreadNode);
3606 status = Callback(currentThread, Aux);
3621 ERROR(
"[ERROR] Failed getting the next task from 0x%016llx\n",
3622 currentThread +
LIX_FIELD(TaskStruct, ThreadNode));
3631 ERROR(
"[ERROR] We didn't processed enough threads. Remaining: %d\n", nrThreads);
3634 else if (nrThreads < 0)
3636 ERROR(
"[ERROR] We processed more threads. Over: %d\n", nrThreads);
3665 QWORD currentThread;
3666 QWORD signal, threadListHead;
3675 ERROR(
"[ERROR] Failed reading the signal struct: 0x%08x\n", status);
3681 ERROR(
"[ERROR] task->signal value (0x%llx) does not point to a valid kernel memory location.", signal);
3688 ERROR(
"[ERROR] Failed reading from the signal struct: 0x%08x\n", status);
3700 else if (nrThreads < 0)
3702 ERROR(
"[ERROR] Negative number of threads: %d\n", nrThreads);
3707 threadListHead = TaskStructGva +
LIX_FIELD(TaskStruct, ThreadGroup);
3712 ERROR(
"[ERROR] Failed getting the first task from signal 0x%016llx\n", threadListHead);
3720 ERROR(
"[ERROR] Thread 0x%llx does not point to a valid kernel memory location.\n", currentThread);
3724 currentThread -=
LIX_FIELD(TaskStruct, ThreadGroup);
3726 status = Callback(currentThread, Aux);
3741 ERROR(
"[ERROR] Failed getting the next task from 0x%016llx\n",
3742 currentThread +
LIX_FIELD(TaskStruct, ThreadGroup));
3751 ERROR(
"[ERROR] We didn't processed enough threads. Remaining: %d\n", nrThreads);
3754 else if (nrThreads < 0)
3756 ERROR(
"[ERROR] We processed more threads. Over: %d\n", nrThreads);
3782 if (0 !=
LIX_FIELD(TaskStruct, ThreadGroup))
3786 else if (0 !=
LIX_FIELD(TaskStruct, ThreadNode))
3814 QWORD initGva, currentTask;
3820 ERROR(
"[ERROR] Failed finding the init_task: 0x%08x\n", status);
3827 status = Callback(initGva, Aux);
3846 ERROR(
"[ERROR] Failed getting the first task from 0x%016llx\n", initGva +
LIX_FIELD(TaskStruct, Tasks));
3850 currentTask -=
LIX_FIELD(TaskStruct, Tasks);
3856 ERROR(
"[ERROR] task_struct 0x%llx does not point to a valid kernel memory location.\n", currentTask);
3860 status = Callback(currentTask, Aux);
3875 ERROR(
"[ERROR] Failed getting the next task from 0x%016llx\n",
3876 currentTask +
LIX_FIELD(TaskStruct, Tasks));
3880 currentTask -=
LIX_FIELD(TaskStruct, Tasks);
3911 if (NULL == pInitTask)
3916 pInitTask->
Gva = TaskGva;
3917 TRACE(
"[LIXTASK] Init task @ 0x%016llx\n", pInitTask->
Gva);
3920 pInitTask->
Parent = TaskGva;
3923 pInitTask->
Path = NULL;
3934 ERROR(
"[ERROR] Failed getting PID of the init process @0x%016llx: 0x%08x\n",
3935 pInitTask->
Gva, status);
3939 sizeof(pInitTask->
Comm),
3945 ERROR(
"[ERROR] Failed reading init process name @ 0x%016llx: 0x%08x\n",
3947 pInitTask->
Comm[0] = 0;
3951 pInitTask->
Comm[
sizeof(pInitTask->
Comm) - 1] = 0;
3955 if ((0 ==
LIX_FIELD(TaskStruct, ThreadGroup)) && (0 ==
LIX_FIELD(TaskStruct, ThreadNode)))
3957 QWORD signal, flink;
3962 ERROR(
"[ERROR] Failed reading the init's signal struct: 0x%08x\n", status);
3969 ERROR(
"[ERROR] Failed reading from init's signal struct: 0x%08x\n", status);
3976 ERROR(
"[ERROR] Signal's struct is not good: 0x%016llx 0x%016llx 0x%016llx\n", flink, signal, TaskGva);
4023 ERROR(
"[ERROR] IntLixTaskCreateInitTask failed: 0x%08x\n", status);
4029 QWORD parentTs, realParentTs;
4032 parentTs = realParentTs = 0;
4037 ERROR(
"[ERROR] _IntLixTaskStartMap failed for %llx: %08x\n", TaskGva, status);
4044 ERROR(
"[ERROR] Failed getting the real parent: %08x\n", status);
4051 ERROR(
"[ERROR] Failed getting the parent: %08x\n", status);
4056 if (NULL == pParent)
4058 WARNING(
"[WARNING] IntLixTaskFindByGva failed for parent 0x%016llx\n", parentTs);
4061 if (NULL == pParent)
4063 ERROR(
"[ERROR] IntLixTaskFindByPid failed for PID 1!\n");
4072 if (parentTs == realParentTs)
4074 pRealParent = pParent;
4080 if (NULL == pRealParent)
4082 WARNING(
"[WARNING] IntLixTaskFindByGva failed for real parent 0x%016llx\n", realParentTs);
4083 pRealParent = pParent;
4091 status =
IntLixTaskCreate(pParent, pRealParent, TaskGva, StaticDetected != 0, NULL);
4094 ERROR(
"[ERROR] IntLixTaskCreate failed: 0x%08x\n", status);
4125 QWORD oldProtection;
4127 oldProtection = Task->Protection.Mask;
4129 if (NewProtection == oldProtection)
4134 if (0 == NewProtection)
4136 LOG(
"[PROT] Removing %s %s (%llx, %llx, %d) from protection", Task->Exec ?
"exec process" :
"fork process",
4137 Task->Comm, Task->Gva, Task->Cr3, Task->Pid);
4141 Task->Protected =
FALSE;
4146 LOG(
"[PROT] Changing protection flags for `%s` (Pid %d, ts 0x%016llx): 0x%llx -> 0x%llx\n",
4147 Task->Comm, Task->Pid, Task->Gva, oldProtection, NewProtection);
4153 LOG(
"[PROT] PROC_OPT_PROT_EXPLOIT disabled -> enabled for %s (%llx, %d)\n",
4154 Task->Comm, Task->Cr3, Task->Pid);
4161 WARNING(
"[WARNING] Process '%s' (%d, %llx, %llx) will not be exploit-protected: %08x!\n",
4162 Task->ProcName, Task->Pid, Task->Gva, Task->Cr3, status);
4169 LOG(
"[PROT] PROC_OPT_PROT_EXPLOIT enabled -> disabled for %s (%llx, %d)\n",
4170 Task->Comm, Task->Cr3, Task->Pid);
4175 ERROR(
"[ERROR] Process '%s' (%d, %llx, %llx) failed to deactivate protection: %08x\n",
4176 Task->ProcName, Task->Pid, Task->Gva, Task->Cr3, status);
4185 LOG(
"[PROT] PROC_OPT_REMEDIATE %s for process %s, %d\n",
4186 0 != (
PROC_OPT_REMEDIATE & NewProtection) ?
"disabled -> enabled" :
"enabled -> disabled",
4187 Task->Comm, Task->Pid);
4192 LOG(
"[PROCESS] PROC_OPT_KILL_ON_EXPLOIT %s for process %s, %d\n",
4194 Task->Comm, Task->Pid);
4199 LOG(
"[PROCESS] PROC_OPT_PROT_WRITE_MEM %s for process %s, %d\n",
4201 Task->Comm, Task->Pid);
4206 LOG(
"[PROCESS] PROC_OPT_PROT_PTRACE %s for process %s, %d\n",
4208 Task->Comm, Task->Pid);
4213 LOG(
"[PROCESS] PROC_OPT_BETA %s for process %s, %d\n",
4214 0 != (
PROC_OPT_BETA & NewProtection) ?
"disabled -> enabled" :
"enabled -> disabled",
4215 Task->Comm, Task->Pid);
4218 Task->Protected =
TRUE;
4219 Task->Protection.Mask = NewProtection;
4220 Task->RootProtectionMask = NewRootProtection;
4221 Task->Context = Context;
4250 QWORD protMask, childProtMask, protBetaMask, protFeedbackMask;
4253 if (pTask->IsThread)
4258 if (!(ProtProc->NamePattern && pTask->Path &&
4265 protMask = Remove ? 0 : ProtProc->Protection.Current;
4266 context = Remove ? 0 : ProtProc->Context;
4267 protBetaMask = Remove ? 0 : ProtProc->Protection.Beta;
4268 protFeedbackMask = Remove ? 0 : ProtProc->Protection.Feedback;
4270 if (pTask->Context != context)
4272 pTask->Context = context;
4275 pTask->Protection.Beta = protBetaMask;
4276 pTask->Protection.Feedback = protFeedbackMask;
4278 if (pTask->Protection.Mask == protMask)
4286 ERROR(
"[ERROR] IntLixTaskChangeProtectionFlags failed for 0x%016llx (Cr3 0x%016llx): 0x%08x\n",
4287 pTask->Gva, pTask->Cr3, status);
4293 if (pChild->Exec || pChild->ActualParent != pTask->Gva)
4301 pChild->Protection.Beta = 0;
4302 pChild->Protection.Feedback = 0;
4307 childProtMask = pTask->Protection.Mask;
4308 pChild->Protection.Beta = pTask->Protection.Beta;
4309 pChild->Protection.Feedback = pTask->Protection.Feedback;
4311 context = pTask->Context;
4313 if (pTask->Cr3 == pChild->Cr3 || 0 == pChild->Cr3)
4323 ERROR(
"[ERROR] IntLixTaskChangeProtectionFlags failed for 0x%016llx (Cr3 0x%016llx): 0x%08x\n",
4324 pChild->Gva, pChild->Cr3, status);
4335 _In_ const char *ProcessName,
4356 if (NULL == ProcessName)
4361 nameLen = strlen(ProcessName);
4365 ERROR(
"[ERROR] Names longer than 64K are not supported!\n");
4371 if ((pExtProt->NamePattern && 0 == strncasecmp(pExtProt->NamePattern, ProcessName, nameLen + 1)) ||
4372 0 == strncasecmp(pExtProt->CommPattern, ProcessName,
MIN(
LIX_COMM_SIZE, nameLen + 1)))
4374 LOG(
"[PROT] Process %s already protected as %s with %llx... Update the protection to %llx\n",
4375 ProcessName, pExtProt->NamePattern ? pExtProt->NamePattern : pExtProt->CommPattern,
4376 pExtProt->Protection.Original, ProtectionMask);
4378 pExtProt->Protection.Original = ProtectionMask;
4379 pExtProt->Protection.Current = ProtectionMask;
4380 pExtProt->Protection.Beta = 0;
4381 pExtProt->Protection.Feedback = 0;
4383 pExtProt->Context = Context;
4402 ERROR(
"[ERROR] Process '%s' will not be protected as there is not enough memory available\n", ProcessName);
4422 LOG(
"[PROT] Process %s / %s protected with %llx\n",
4431 ERROR(
"[ERROR] IntLixTaskAdjustProtection failed for '%s': %08x\n", pProt->
CommPattern, status);
4440 _In_ const char *ProcessName
4455 if (NULL == ProcessName)
4460 nameLen = strlen(ProcessName);
4464 if (0 == strncasecmp(pExtProt->NamePattern, ProcessName, nameLen + 1))
4466 LOG(
"Remove process %s from protected list!\n", pExtProt->NamePattern);
4481 ERROR(
"[ERROR] IntLixTaskAdjustProtection failed for '%s': %08x\n", pProt->
CommPattern, status);
4517 ERROR(
"[ERROR] IntLixTaskAdjustProtection failed for '%s': %08x\n", pProt->
CommPattern, status);
4539 char *cmd = CommandLine;
4545 if (!pTask->AgentTag)
4550 len = snprintf(cmd, Length,
"%s %d ", pTask->Path ? pTask->Path->Name : pTask->Comm, pTask->Pid);
4556 if ((
DWORD)len >= Length)
4590 if (NULL != pProt->NamePattern)
4620 if (!pProc->IsThread)
4630 LOG(
"We have no processes in the system!\n");
4636 for (
DWORD i = 0; i < Level - 1; i++)
4643 else if (Level >= 1)
4654 if (!Task->IsThread)
4656 NLOG(
"%6d/%-6d: %s %-40s CR3: 0x%016llx, prot: %d/%llx, mm_struct: 0x%016llx, task_struct: 0x%016llx, " 4657 "flags: %08x%s%s, parent: 0x%016llx, real_parent: 0x%016llx\n",
4658 Task->Pid, Task->Tgid,
4659 Task->Exec ?
"EXEC" :
"FORK",
4662 Task->Protected, Task->Protection.Mask,
4666 Task->Interpreter ?
", by interpreter " :
"",
4667 Task->Interpreter ? Task->Interpreter :
"",
4668 Task->Parent, Task->RealParent);
4675 sizeof(newComm) - 1,
4683 NLOG(
"%6d/%-6d: %-16s / %-16s task_struct: 0x%016llx, prot: %d/%llx, flags: %08x, parent: 0x%016llx, " 4684 "real_parent: 0x%016llx\n",
4685 Task->Pid, Task->Tgid, Task->Comm, newComm, Task->Gva, Task->Protected,
4686 Task->Protection.Mask, flags, Task->Parent, Task->RealParent);
4696 if (!pProc->IsThread && pProc->Parent == Task->Gva)
4700 else if (pProc->IsThread && pProc->Tgid == Task->Pid)
4738 if (pThread->IsThread && pThread->KernelMode)
4746 if (NULL == Thread || !Thread->IsThread || !Thread->KernelMode)
4750 LOG(
"We have no kernel thread in the system!\n");
4756 for (i = 0; i < Level; i++)
4769 NLOG(
"%6d/%-6d : %-16s task_struct: 0x%016llx, prot: %d/%llx, flags: %08x\n",
4770 Thread->Pid, Thread->Tgid, Thread->Comm, Thread->Gva,
4771 Thread->Protected, Thread->Protection.Mask, flags);
4775 if (pThread->Parent == Thread->Gva)
4806 if (!pTask->IsThread)
4808 LOG(
"Process %s (%s), PID: %d, TS 0x%016llx, Mm 0x%016llx, Parent 0x%016llx, RealParent 0x%016llx, " 4809 "Protected: %d/%llx\n", !pTask->Exec ?
"(no exec)" : pTask->Path ? pTask->Path->Path :
"(no path)",
4810 pTask->Comm, pTask->Pid, pTask->Gva, pTask->MmGva,
4811 pTask->Parent, pTask->RealParent,
4812 pTask->Protected, pTask->Protection.Mask);
4818 LOG(
" [%016llx -> %016llx] : %08llx [file @%016llx] @ %016llx Hooked=%d (%c%c%c)\n",
4819 pVma->Start, pVma->End, pVma->Flags, pVma->File, pVma->Gva, pVma->Hook ? 1 : 0,
4820 (pVma->Flags &
VM_EXEC) ?
'X' :
'-',
4821 (pVma->Flags &
VM_WRITE) ?
'W' :
'-',
4822 (pVma->Flags &
VM_READ) ?
'R' :
'-');
4831 if (!pThr->IsThread)
4836 if (pThr->Tgid != pTask->Tgid)
4841 LOG(
"----> Thread %s %d/%d @ 0x%016llx, Parent 0x%016llx, RealParent 0x%016llx, Protected: %d/%llx\n",
4842 pThr->Comm, pThr->Pid, pThr->Tgid, pThr->Gva,
4843 pThr->Parent, pThr->RealParent,
4844 pThr->Protected, pThr->Protection.Mask);
4851 if (pKThread->IsThread && pKThread->KernelMode)
4853 LOG(
"Kernel Thread %s, P(TG)ID %d/%d, CR3 0x%016llx, TS 0x%016llx, Parent 0x%016llx, " 4854 "RealParent 0x%016llx, ActualParent 0x%016llx, Protected: %d/%llx\n",
4855 pKThread->Comm, pKThread->Pid, pKThread->Tgid,
4859 pKThread->RealParent,
4860 pKThread->ActualParent,
4861 pKThread->Protected,
4862 pKThread->Protection.Mask);
4880 LOG(
"# %04d %s, %llx, '%s'\n",
4883 pProt->Protection.Original,
4884 pProt->NamePattern ? pProt->NamePattern :
"(none)");
4904 if (NULL == Callback)
4914 WARNING(
"[WARNING] Callback failed: 0x%08x\n", status);
4944 WORD userModeTasks = 0;
4949 LOG(
"[LIX-GUEST] Found system state '%d'\n", systemState);
4965 if (pTask->KernelMode)
4972 if (pTerminateTask != NULL)
4982 pTerminateTask = pTask;
4987 pTerminateTask = pTask;
4992 if (pTerminateTask == NULL)
4997 LOG(
"[LIX-GUEST] Found shutdown/reboot task '%s'\n", pTerminateTask->
Comm);
4999 if (userModeTasks > 6)
5051 ERROR(
"[ERROR] IntExceptUserGetOriginator failed with status: 0x%08x\n", status);
5061 ERROR(
"[ERROR] IntExceptGetVictimProcess failed with status: 0x%08x\n", status);
5080 ERROR(
"[ERROR] IntDetoursGstSetReturnValue failed: 0x%08x\n", status);
BOOLEAN StolenTokens
TRUE if credentials for this process have been altered.
char * ProcName
The process name that is always valid. It's set depending which info is available in order: Path...
INTSTATUS IntLixTaskGetTrapFrame(const LIX_TASK_OBJECT *Task, LIX_TRAP_FRAME *TrapFrame)
Retrieves the trap frame for a Linux task.
struct _EVENT_MEMCOPY_VIOLATION::@297 Originator
enum _INTRO_ACTION_REASON INTRO_ACTION_REASON
The reason for which an INTRO_ACTION was taken.
LIX_OPAQUE_FIELDS OsSpecificFields
OS-dependent and specific information.
static INTSTATUS IntLixTaskFetchMm(QWORD MmStruct, LIX_TASK_OBJECT *Task, LIX_TASK_OBJECT *Parent)
Fetches the CR3 of a Linux task.
INTSTATUS IntLixTaskGetUserStack(LIX_TASK_OBJECT *Task, QWORD *StackPointer, QWORD *StackBase, QWORD *StackLimit)
Finds the user mode stack limits for a Linux process.
QWORD Cr3
The CR3 for this process.
void IntLixCredsVerify(LIX_TASK_OBJECT *Task)
Verifies whether the credentials of a process has been altered or not.
INTSTATUS IntLixAccessRemoteVmHandler(void *Detour)
Detour handler for __access_remote_vm.
Sent for unauthorized process creation alerts. See EVENT_PROCESS_CREATION_VIOLATION.
BOOLEAN Valid
Set to True if the information in the structure is valid, False otherwise.
void IntLixTaskUninit(void)
Uninitializes the Linux process subsystem.
INTSTATUS IntVirtMemUnmap(void **HostPtr)
Unmaps a memory range previously mapped with IntVirtMemMap.
static LIST_HEAD gLixTaskPaths
The list with all cached paths.
void IntLixTaskDumpAsTree(void)
Dump the process tree.
INTSTATUS IntLixMmFindVmaRange(QWORD Gva, LIX_TASK_OBJECT *Task, QWORD *VmaStart, QWORD *VmaEnd)
Finds the VMA limits that contain an address.
An internal error occurred (no memory, pages not present, etc.).
INTRO_PROCESS Victim
The process that was compromised.
BOOLEAN IntPolicyCoreForceBetaIfNeeded(QWORD Flag, INTRO_ACTION *Action)
Checks if a forced action should be taken even if the log-only mode is active.
static INTSTATUS IntLixTaskHandleInjection(QWORD Victim, BOOLEAN Pid, QWORD InjectionFlag, BOOLEAN *Block)
Handles the injection into a protected process.
INTSTATUS IntHookObjectDestroy(HOOK_OBJECT_DESCRIPTOR **Object, DWORD Flags)
Destroy an entire hook object. All regions belonging to this object will be removed.
Describe the introcore protection options.
IG_ARCH_REGS Regs
The current state of the guest registers.
BOOLEAN Created
True if the process was created, False if it was terminated.
DWORD Index
The VCPU number.
#define INTRO_OPT_PROT_DPI_STACK_PIVOT
Enable process creation protection for pivoted stack.
void IntLixTaskDump(void)
Dumps the process list.
MITRE_ID MitreID
The Mitre ID that corresponds to this attack.
char * basename_s(char *path, size_t len)
Returns a pointer inside a path string pointing to the beginning of the file base name...
static LIST_HEAD gLixProtectedTasks
The list with all tasks that are currently protected.
#define CLEAN_PHYS_ADDRESS64(x)
static QWORD IntLixUserToKernelPgd(QWORD Pgd)
Translates the value of a user page global directory to it's corresponding kernel value when KPTI is ...
QWORD SystemCr3
The Cr3 used to map the kernel.
#define INT_STATUS_SUCCESS
BOOLEAN IntPolicyCoreTakeAction(QWORD Flag, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason)
Returns the action that should be taken for a core introspection option.
Event structure for process creation/termination.
INTRO_PROCESS Process
The process that attempted the access.
Measures user mode exceptions checks.
#define PAGE_REMAINING(addr)
INTSTATUS IntReadString(QWORD StrGva, DWORD MinimumLength, BOOLEAN AnsiOnly, char **String, DWORD *StringLength)
Reads a string from the guest kernel memory.
#define for_each_path(_var_name)
list_for_each wrapper used to iterate cached paths.
Event structure for process creation violation events.
CAMI_STRING_ENCODING
Describes the encoding of a string received from the CAMI file.
#define _Out_writes_bytes_(expr)
INTSTATUS IntLixTaskSendExceptionEvent(DWORD Signal, LIX_TASK_OBJECT *Task)
Sends an event that contains the information about signal received by the provided task...
INTSTATUS IntLixVdsoDynamicProtect(void)
This function activates the protection for the vDSO image.
static BOOLEAN IntLixTaskMustLog(const LIX_TASK_OBJECT *Task, BOOLEAN Protected)
Controls whether information about a task must be logged or not.
User-mode non executable zone.
Process creation violation.
static void IntLixTaskPathFree(LIX_TASK_PATH **Path)
Release a LIX_TASK_PATH object.
AGENT_EVENT_TYPE Event
The type of the agent.
LIX_TASK_OBJECT * IntLixTaskFindByGva(QWORD TaskStruct)
Finds Linux process with the provided "task_struct" guest virtual address.
QWORD Gva
The guest virtual address of the task_struct.
static void IntLixTaskSendAgentEvent(LIX_TASK_OBJECT *Task, DWORD ExitCode, BOOLEAN Created)
Sends an agent event.
#define IN_RANGE_INCLUSIVE(x, start, end)
BOOLEAN ShutDown
True if the system process protection is in beta (log-only) mode.
DWORD UmThreads
If the user mode threads events should be logged.
#define INT_SUCCESS(Status)
static BOOLEAN IsListEmpty(const LIST_ENTRY *ListHead)
INTSTATUS IntDetSetReturnValue(DETOUR const *Detour, IG_ARCH_REGS *Registers, QWORD ReturnValue)
Sets the return value for a hooked guest function.
LIX_AGENT_TAG IntLixAgentDecProcRef(const char *Name, BOOLEAN *Removed)
Checks if a process is an agent or not, and decrements the ref count of that name.
#define CR3_LONG_MODE_MASK
QWORD Flags
A combination of ALERT_FLAG_* values describing the alert.
INTSTATUS IntExceptGetVictimProcessCreation(void *Process, INTRO_OBJECT_TYPE ObjectType, EXCEPTION_VICTIM_ZONE *Victim)
This function is used to get the information about the victim for process-creation violation...
static LIX_TASK_PATH * IntLixTaskPathGetByFile(QWORD FileGva)
Get a LIX_TASK_PATH object based on the guest virtual address of a "file" structure.
The action was not allowed because there was no reason to allow it.
INTSTATUS IntLixTaskAddProtected(const char *ProcessName, QWORD ProtectionMask, QWORD Context)
Adds a protected process name pattern.
Event structure for agent injection and termination.
void * InitProcessObj
The LIX_TASK_OBJECT of the 'init' process.
The agent process finished execution.
void sanitize_path(char *path, size_t len, size_t *new_len)
Sanitizes an Unix path by removing trailing path delimiters.
void IntLixTaskUpdateProtection(void)
Adjusts protection for all active Linux processes.
struct _LIX_TASK_OBJECT::@137 UserStack
User stack information.
static INTSTATUS IntLixTaskDeactivateExploitProtection(LIX_TASK_OBJECT *Task)
Deactivates exploit protection for a Linux task.
QWORD Parent
Depends if this is a thread or a process.
#define for_each_protected_task(_var_name)
list_for_each wrapper used to iterate protected tasks.
#define INT_STATUS_NOT_NEEDED_HINT
INTSTATUS IntLixTaskIsUserStackPivoted(LIX_TASK_OBJECT *Task, QWORD Ptr, BOOLEAN *IsPivoted)
Verifies whether the stack of a Linux process is pivoted or not.
Process creation violation DPI.
DWORD Tgid
The task Thread-Group-ID.
Describes a user-mode originator.
#define INTRO_OPT_PROT_DPI
Aggregates all the deep process inspection flags.
static LIST_HEAD gLixTasksToProtect
The list with all tasks that should be protected.
static INTSTATUS IntLixTaskCreate(LIX_TASK_OBJECT *Parent, LIX_TASK_OBJECT *RealParent, QWORD TaskStruct, BOOLEAN StaticDetected, LIX_TASK_OBJECT **Task)
Creates a Linux process object.
LIX_TASK_PATH * Path
The path of the file executed.
#define HpAllocWithTag(Len, Tag)
int INTSTATUS
The status data type.
#define PROC_OPT_PROT_PTRACE
Blocks thread hijacking attempts inside the target process (Linux only).
LIX_TASK_OBJECT * IntLixTaskProtFindByMm(QWORD MmGva)
Finds the protected Linux process having the provided mm guest virtual address.
DWORD ExitStatus
The exit code of the process.
DWORD OSVersion
Os version.
int IntLixGuestGetSystemState(void)
Get the system state of the Linux guest.
QWORD CreationTime
The creation timestamp for this process.
#define INT_STATUS_NOT_FOUND
static LIX_TASK_PATH * IntLixTaskPathGetByPath(QWORD PathGva, QWORD DentryGva)
Get a LIX_TASK_PATH object based on the guest virtual address of a path string.
DWORD IsPreviousAgent
TRUE if this process is an agent remaining from a previous session.
QWORD Base
The user mode stack base.
#define PAGE_COUNT(addr, bytes)
static const char * gLixTerminatingTasks[]
Linux processes signaling that the guest OS is shutting down.
DWORD RefCount
The number of references for this cache entry.
BOOLEAN IntMatchPatternUtf8(const CHAR *Pattern, const CHAR *String, DWORD Flags)
Matches a pattern using glob match.
PCHAR NamePattern
Full application file name.
Describes a path cache entry.
INTRO_PROCESS CurrentProcess
The agent process.
void IntLixProcUpdateProtectedProcess(const void *Name, const CAMI_STRING_ENCODING Encoding, const CAMI_PROT_OPTIONS *Options)
Updates the protection flags for Linux tasks that should be protected based on options received via C...
void IntLixMmDestroyVmas(LIX_TASK_OBJECT *Task)
Remove protection for the VMAs belonging to a process.
Sent for code/data injection alerts. See EVENT_MEMCOPY_VIOLATION.
EVENT_PROCESS_CREATION_VIOLATION ProcessCreation
static INTSTATUS IntLixTaskAdjustProtections(const LIX_PROTECTED_PROCESS *ProtProc, BOOLEAN Remove)
Adjusts the protection flags for processes associated with the LIX_PROTECTED_PROCESS object...
#define LIX_PTI_PGTABLE_SWITCH_BIT
The bit marking whether the kernel memory is mapped in a PGD.
void IntLixCredRemove(LIX_CREDS **Creds)
Removes the integrity protection for the credentials set that belong to a process.
void IntAlertFillCpuContext(BOOLEAN CopyInstruction, INTRO_CPUCTX *CpuContext)
Fills the current CPU context for an alert.
Encapsulates a protected Linux process.
DWORD ErrorCode
The error code of the event. Success is 0.
INTRO_PC_VIOLATION_TYPE PcType
Valid if the current violation is DPI Process Creation Violation.
QWORD RealParent
The process which called fork()
INTSTATUS(* PFUNC_LixTaskIterateTasks)(LIX_TASK_OBJECT *Task)
DWORD CommHash
The CRC32 checksum of the Comm field.
#define INTRO_OPT_PROT_KM_VDSO
Enable vDSO image protection (Linux only).
#define INTRO_MATCH_TRUNCATED
If set, matching functions like IntMatchPatternUtf8 will match up until the first wild char encounter...
#define LIX_CREATE_VERSION(K, Patch, Sublevel)
char * CmdLine
The process command line.
#define INT_STATUS_BREAK_ITERATION
Can be used by iteration callbacks to break the iteration early.
void IntAlertFillVersionInfo(INTRO_VIOLATION_HEADER *Header)
Fills version information for an alert.
QWORD IntAlertProcGetFlags(QWORD ProtectionFlag, const void *Process, INTRO_ACTION_REASON Reason, QWORD AdditionalFlags)
Returns the flags for an alert.
QWORD IntLixGetKernelCr3(QWORD Cr3)
Transforms an user CR3 into a kernel CR3 on systems with KPTI enabled and active. ...
BOOLEAN KptiActive
True if KPTI is enabled on this guest, False if it is not.
#define PAGE_FRAME_NUMBER(addr)
QWORD Feedback
Flags that will be forced to feedback only mode.
QWORD ExeFileDentry
The guest virtual address of the executable file's "dentry" structure.
Execution through API call.
Access Token Manipulation.
INTRO_ACTION_REASON Reason
The reason for which Action was taken.
void IntUDRemoveAllEntriesForCr3(const QWORD Cr3)
Remove all pending UD entries for a given virtual address space.
static INTSTATUS _IntLixTaskStartMap(QWORD TaskGva)
Map the task_struct in order to perform further reads from it without any overhead.
static void IntLixTaskSendBlockedEvent(LIX_TASK_OBJECT *OldTask, LIX_TASK_OBJECT *NewTask, INTRO_ACTION Action, INTRO_ACTION_REASON Reason, DWORD PcType)
Sends a blocked process creation event.
QWORD Limit
The user mode stack limit.
static void IntLixTaskRemoveEntry(LIX_TASK_OBJECT *Task)
Removes a Linux process from the process list.
static void IntLixTaskDumpTree(LIX_TASK_OBJECT *Task, DWORD Level)
Dumps the user mode tasks tree.
static INTSTATUS IntLixTaskFetchCmdLine(LIX_TASK_OBJECT *Process, QWORD BinprmGva)
Fetches the command line for a Linux process on the exec() system call.
GENERIC_ALERT gAlert
Global alert buffer.
DWORD Execs
If exec events should be logged.
LIX_TASK_OBJECT * IntLixTaskFindByPid(DWORD Pid)
Finds the Linux process having the provided PID.
enum _INTRO_OBJECT_TYPE INTRO_OBJECT_TYPE
The type of the object protected by an EPT hook.
static LIST_HEAD gLixTasks
The list with all tasks inside the guest OS.
#define LIX_MM_PROT_MASK
The bit used to mark a memory space as protected.
INTRO_VIOLATION_HEADER Header
The alert header.
QWORD Current
The currently used protection flags.
struct _LIX_TASK_LOG LIX_TASK_LOG
This structure contains control bits for linux process logging.
INTSTATUS IntKernVirtMemFetchDword(QWORD GuestVirtualAddress, DWORD *Data)
Reads 4 bytes from the guest kernel memory.
INTRO_VIOLATION_HEADER Header
The alert header.
INTSTATUS IntCamiUpdateProcessProtectionInfo(void *ProtectedProcess)
Update a process' protection flags using the ones from CAMI.
EVENT_MEMCOPY_VIOLATION Injection
QWORD DataStart
The guest virtual address where the data starts.
#define INITIAL_CRC_VALUE
BOOLEAN IntPolicyProcTakeAction(QWORD Flag, void const *Process, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason)
Returns the action that should be taken for a process protection option.
INTSTATUS IntLixGetInitTask(QWORD *InitTask)
Finds the guest virtual address of the "init_task".
#define IS_KERNEL_POINTER_LIX(p)
static INTSTATUS IntLixTaskCreateInitTask(QWORD TaskGva, LIX_TASK_OBJECT **Task)
Creates the init task object.
DWORD ProtForks
If forks performed by protected processes should be logged.
INTSTATUS IntKernVirtMemFetchQword(QWORD GuestVirtualAddress, QWORD *Data)
Reads 8 bytes from the guest kernel memory.
#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...
EVENT_PROCESS_EVENT Process
static INTSTATUS _IntLixTaskRead(DWORD Offset, DWORD Size, void *Buffer)
Perform a read from the previously mapped "task_struct" structure.
struct _LINUX_GUEST::@126 Layout
INTRO_CPUCTX CpuContext
The context of the CPU that triggered the alert.
static void IntLixTaskDeactivateProtection(LIX_TASK_OBJECT *Task)
Deactivates protection for a Linux process.
#define INTRO_OPT_EVENT_PROCESSES
Enable process creation and termination events (generates introEventProcessEvent events).
INTSTATUS IntNotifyIntroEvent(INTRO_EVENT_TYPE EventClass, void *Param, size_t EventSize)
Notifies the integrator about an introspection alert.
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
The parent of a process has a stolen access token when it created the child.
QWORD Original
The original protection flags as received from integrator.
#define INTRO_OPT_PROT_UM_MISC_PROCS
static void IntLixTaskGetPath(QWORD FileGva, QWORD DPathGva, LIX_TASK_OBJECT *Task)
Read and set the path for a Linux process.
static void IntLixTaskSendTaskEvent(LIX_TASK_OBJECT *Task, DWORD ExitCode, BOOLEAN Created, BOOLEAN Crashed, BOOLEAN StaticDetected)
Sends a process event.
QWORD Current
The currently used options.
INTSTATUS IntLixTaskHandlePtrace(void *Detour)
Handles the ptrace() system call.
static LIX_TASK_PATH * IntLixTaskPathGetByDentry(QWORD FileGva, QWORD PathGva, QWORD DentryGva)
Get the LIX_TASK_PATH object associated with a given path.
static void IntLixTaskSendInjectionEvent(LIX_TASK_OBJECT *Source, LIX_TASK_OBJECT *Victim, INTRO_ACTION Action, INTRO_ACTION_REASON Reason)
Sends an injection event.
static INTSTATUS IntLixTaskIterateThreadNode(QWORD TaskStructGva, PFUNC_IterateListCallback Callback, QWORD Aux)
Iterates the threads of a Linux process based on the thread node..
INTRO_PROCESS CurrentProcess
The currently active process.
DWORD Exec
TRUE if the process did exec at least once.
static void IntLixValidateExecStack(LIX_TASK_OBJECT *ParentTask, LIX_TASK_OBJECT *CurrentTask)
Validates the user mode stack of a process upon an exec() system call.
Informational event sent when the remediation tool is injected or terminated. See EVENT_AGENT_EVENT...
INTRO_PROCESS Child
The process that is being created or terminated.
BOOLEAN Valid
TRUE if the values inside this structure are valid.
DWORD IsThread
TRUE if it's a thread, not a process.
INTSTATUS IntTranslateVirtualAddress(QWORD Gva, QWORD Cr3, QWORD *PhysicalAddress)
Translates a guest virtual address to a guest physical address.
INTSTATUS IntLixTaskHandleFork(void *Detour)
Handles the fork() system call performed by a linux process.
INTSTATUS(* PFUNC_IterateListCallback)(QWORD Node, QWORD Aux)
#define PROC_OPT_KILL_ON_EXPLOIT
The parent of a process had a pivoted stack when it created the child.
#define LIX_FIELD(Structure, Field)
Macro used to access fields inside the LIX_OPAQUE_FIELDS structure.
#define HpFreeAndNullWithTag(Add, Tag)
INTSTATUS IntGsRead(DWORD CpuNumber, QWORD *GsValue)
Reads the IA32_GS_BASE guest MSR.
#define INT_STATUS_INVALID_DATA_STATE
#define INT_STATUS_INVALID_INTERNAL_STATE
QWORD Context
The context supplied in the protection policy.
Memory access violations that cross a process boundary.
DWORD AgentTag
Unique agent tag. See INTRO_DEP_AG_TAGS.
static LIX_TASK_PATH * IntLixTaskPathGetRef(LIX_TASK_PATH *Path)
Increases the reference counter for a LIX_TASK_PATH object.
static void InsertAfterList(LIST_ENTRY *Pivot, LIST_ENTRY *Item)
DWORD Forks
If forks should be logged.
Informational event sent when a process is created or terminated by the guest. See EVENT_PROCESS_EVEN...
static void IntLixValidateProcessCreationRights(LIX_TASK_OBJECT *ChildTask, LIX_TASK_OBJECT *ParentTask, INTRO_OBJECT_TYPE ObjectType, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason)
Validates process creation rights (both PC and DPI).
BOOLEAN Protected
True if the process is protected.
String will be encoded in utf-8.
#define PROC_OPT_PROT_SCAN_CMD_LINE
Uses third party engines to scan the command line of a process.
DWORD ProtExecs
If an exec performed by a protected process should be logged.
QWORD Context
Context from integrator.
INTSTATUS IntLixTaskGetAgentsAsCli(char *CommandLine, DWORD Length)
Returns a string with the command lines of all active agents.
INTSTATUS IntLixTaskHandleExec(void *Detour)
Handles the exec() system call of a linux process.
INTSTATUS IntLixTaskAdd(QWORD TaskGva, QWORD StaticDetected)
Creates and adds a Linux process in the internal list.
static void InsertTailList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
DWORD IntLixTaskGetExecCount(void)
Returns the number of processes that have performed an exec.
size_t strlcpy(char *dst, const char *src, size_t dest_size)
CHAR CommPattern[16]
Process name pattern (supports glob patterns). Will be used if there is no path.
LIST_ENTRY ExploitProtProcLink
Linkage in the protected processes list.
INTSTATUS IntLixTaskGetCurrentTaskStruct(DWORD CpuNumber, QWORD *TaskStruct)
Reads the guest virtual address of the task currently running on a CPU.
INTSTATUS IntExceptUserGetOriginator(void *Process, BOOLEAN ModuleWrite, QWORD Address, INSTRUX *Instrux, EXCEPTION_UM_ORIGINATOR *Originator)
This function is used to get the information about the user-mode originator.
INTSTATUS IntLixFileGetDentry(QWORD File, QWORD *Dentry)
Reads the value of the dentry field of the 'struct file'.
#define ALERT_FLAG_NOT_RING0
If set, the alert was triggered in ring 1, 2 or 3.
static void InitializeListHead(LIST_ENTRY *ListHead)
static DWORD IntLixTaskGetDpiMitreId(DWORD Flags)
Returns the MITRE ID for the process creation violation flag.
INTSTATUS IntVirtMemSafeWrite(QWORD Cr3, QWORD VirtualAddress, DWORD Size, void *Buffer, DWORD Ring)
Safely modify guest memory.
DWORD KernelMode
TRUE if this process/thread is inside kernel mode.
Describes the modified zone.
#define UNREFERENCED_PARAMETER(P)
#define PROC_OPT_PROT_EXPLOIT
Blocks malicious execution attempts.
char * Name
The path base name.
Exposes the functions used to schedule an asynchronous command line scan and receives its result...
void * InstructionCache
The currently used instructions cache.
#define INT_STATUS_DATA_BUFFER_TOO_SMALL
static void IntLixTaskMarkAgent(LIX_TASK_OBJECT *Task)
Marks a Linux process as being an Introcore agent.
LIST_ENTRY Link
Entry inside the gLixProtectedTasks list.
#define PROC_OPT_PROT_CORE_HOOKS
Blocks hooks being set on core user-mode DLLs.
#define INT_STATUS_INVALID_DATA_VALUE
size_t NameLength
The size of the base name.
INTSTATUS IntLixCmdLineInspect(LIX_TASK_OBJECT *Task)
Send a command line scan request to the scan engines.
#define PROC_OPT_PROT_PREVENT_CHILD_CREATION
Prevent the process from creating child processes (other than instances of itself).
INTSTATUS IntLixTaskHandleDoExit(void *Detour)
Handles the exit() system call.
static INTSTATUS IntLixTaskChangeProtectionFlags(LIX_TASK_OBJECT *Task, QWORD NewProtection, QWORD NewRootProtection, QWORD Context)
Adjust the protection of a Linux process based on a new set of rules.
static INTSTATUS IntLixTaskActivateExploitProtection(LIX_TASK_OBJECT *Task)
Activates exploit protection for a Linux task.
LIX_CREDS * Creds
The LIX_CREDS reference for the credentials of this process.
INTRO_PC_VIOLATION_TYPE PcType
The type of process creation violation.
enum _INTRO_ACTION INTRO_ACTION
Event actions.
BOOLEAN IntPolicyProcForceBetaIfNeeded(QWORD Flag, void *Process, INTRO_ACTION *Action)
Checks if a forced action should be taken even if the process log-only mode is active.
static QWORD IntLixKernelToUserPgd(QWORD Pgd)
Translates the value of a kernel page global directory to it's corresponding user value when KPTI is ...
#define LIX_PROCESSES_MAX_COUNT
The maximum number of processes allowed.
char * Interpreter
If this was a script executed through an interpretor.
QWORD DentryGva
The guest virtual address of the "dentry" structure associated with this path.
LIX_AGENT_TAG IntLixAgentIncProcRef(const char *Name)
Checks if a process is an agent or not, and increments the ref count of that name.
#define INT_STATUS_INVALID_OBJECT_TYPE
INTSTATUS IntLixTaskHandleVmRw(void *Detour)
Handles the process_vm_writev() system call.
LIX_TASK_OBJECT * IntLixTaskFindByMm(QWORD MmGva)
Finds the Linux process having the provided mm guest virtual address.
__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.
This structure contains control bits for linux process logging.
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
size_t PathLength
The size of the path.
char Comm[LIX_COMM_SIZE]
The short name of the executable.
#define LIX_COMM_SIZE
The maximum size of the process comm.
static INTSTATUS IntLixTaskActivateProtection(LIX_TASK_OBJECT *Task, LIX_TASK_OBJECT *Parent)
Activates protection for a Linux process.
GUEST_STATE gGuest
The current guest state.
LIX_TASK_OBJECT * IntLixTaskFindByCr3(QWORD Cr3)
Finds the Linux process having the provided Cr3.
QWORD MmGva
The guest virtual address of the "mm_struct".
void IntLixMmListVmas(QWORD Mm, LIX_TASK_OBJECT *Process)
LIST_ENTRY Link
The list node.
LIST_ENTRY Link
Linkage in the global task list.
INTSTATUS IntExceptGetVictimProcess(void *Process, QWORD DestinationGva, DWORD Length, QWORD ZoneFlags, EXCEPTION_VICTIM_ZONE *Victim)
This function is used to get the information about the victim process for injection violations...
DWORD ProtUmThreads
If events related to threads created by protected process should be logged.
static LIX_PROTECTED_PROCESS * IntLixTaskShouldProtect(const LIX_TASK_OBJECT *Task)
Checks whether a Linux task should be protected or not.
INTRO_PROCESS Originator
The process that attempted the violation.
LIX_TASK_LOG gLixTaskLogLevel
The global structure controlling linux process logging.
struct _EVENT_MEMCOPY_VIOLATION::@298 Victim
BOOLEAN IntLixTaskGuestTerminating(void)
Check whether the guest OS is terminating or not.
#define PROC_OPT_BETA
Process is monitored, but in log-only mode so no actions will be blocked.
INTRO_ACTION Action
The action that was taken as the result of this alert.
INTSTATUS IntKernVirtMemRead(QWORD KernelGva, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest kernel virtual memory range.
struct _LIX_TASK_OBJECT::@136 Protection
Protection specific flags.
#define PROC_OPT_PROT_WRITE_MEM
Blocks foreign write inside the target process.
struct _LIX_TASK_OBJECT::@138 Dpi
DPI related information.
INTSTATUS IntLixMmPopulateVmas(LIX_TASK_OBJECT *Task)
Populate the Introcore VMAs linked list by iterating the one inside the guest.
LIX_TASK_OBJECT * IntLixTaskGetCurrent(DWORD CpuNumber)
Finds the task that is currently running on the given CPU.
static void IntLixTaskDestroy(LIX_TASK_OBJECT *Task, DWORD ExitCode)
Destroys a Linux process after protection for it is removed.
DWORD Protected
TRUE if the process is protected.
#define LIST_HEAD_INIT(Name)
INTSTATUS IntKernVirtMemPatchQword(QWORD GuestVirtualAddress, QWORD Data)
Writes 8 bytes in the guest kernel memory.
QWORD Beta
Flags that were forced to beta mode.
#define INT_STATUS_INVALID_PARAMETER_1
DWORD KmThreads
If the kernel threads events should be logged.
#define INT_STATUS_NOT_SUPPORTED
INTRO_PROCESS CurrentProcess
The current process.
#define PROC_OPT_REMEDIATE
Any event inside the process will trigger the injection of the remediation tool.
VCPU_STATE * gVcpu
The state of the current VCPU.
BOOLEAN Crashed
True if the process crashed.
static INTSTATUS IntLixTaskIterateThreads(QWORD TaskStructGva, PFUNC_IterateListCallback Callback, QWORD Aux)
Iterates the threads of a Linux process.
The action was blocked because there was no exception for it.
DWORD Crc32String(const char *String, DWORD InitialCrc)
Computes the CRC for a NULL-terminated utf-8 string.
INTSTATUS IntLixCredAdd(QWORD CredsGva, LIX_CREDS **Creds)
Adds a cred structure in the integrity protected credentials list.
INTSTATUS IntIcFlushVaSpace(PINS_CACHE Cache, QWORD Cr3)
Flush an entire virtual address space.
char * Path
The full path string.
The agent process started execution.
static INTSTATUS IntLixTaskIterateThreadGroup(QWORD TaskStructGva, PFUNC_IterateListCallback Callback, QWORD Aux)
Iterates the threads of a Linux process based on the thread group.
void IntLixTaskDumpProtected(void)
Dumps the list with processes that Introcore should protect.
#define PTRACE_SETFPXREGS
#define CRITICAL(fmt,...)
static INTSTATUS IntLixTaskCreateFromBinprm(LIX_TASK_OBJECT *OriginalTask, QWORD BinprmGva, QWORD PathGva, LIX_TASK_OBJECT *UpdatedTask)
Updates the contents of a previously forked process from it's new linux_binprm (used by the loader)...
BOOLEAN BugCheckInProgress
INTRO_PROCESS Parent
The parent of the process.
QWORD SourceVirtualAddress
The virtual address of the source buffer.
void IntAlertFillLixCurrentProcess(INTRO_PROCESS *EventProcess)
Saves the current Linux process inside an event.
struct _LIX_PROTECTED_PROCESS::@123 Protection
What protection policies should be applied.
INTSTATUS IntLixTaskIterateTasks(PFUNC_LixTaskIterateTasks Callback)
Call the Callback parameter for each task saved internally.
QWORD DestinationVirtualAddress
The virtual address of the destination buffer.
Exploitation for Client Execution.
BYTE Version
The version field of the version string.
QWORD ActualParent
The parent, based on tgid. Only relevant for threads.
static void IntLixTaskSetProcName(LIX_TASK_OBJECT *Task)
Sets the name for a Linux process.
INTSTATUS IntLixTaskIterateGuestTasks(PFUNC_IterateListCallback Callback, QWORD Aux)
Iterates the guest process list and calls the provided callback for each process and thread found...
QWORD IntKsymFindByName(const char *Name, QWORD *SymEnd)
Searches the given Name in kallsyms and returns the Start & End offset.
static DWORD IntLixTaskGetDpiViolationFlags(LIX_TASK_OBJECT *Task)
Returns the DPI flags for a Linux process.
static void _IntLixTaskFinishMap(void)
Unmaps a previously mapped "task_struct".
#define for_each_task(_var_name)
list_for_each wrapper used to iterate Linux tasks.
#define list_for_each(_head, _struct_type, _var)
#define for_each_task_to_protect(_var_name)
list_for_each wrapper used to iterate tasks that should be protected.
DWORD CurrentTaskOffset
The offset of the current task from GS.
INTSTATUS IntLixTaskRemoveProtected(const char *ProcessName)
Removes a pattern of processes to be protected.
void IntAlertFillLixProcess(const LIX_TASK_OBJECT *Task, INTRO_PROCESS *EventProcess)
Saves information about a Linux process inside an event.
#define for_next_task(_task, _var_name)
list_for_next wrapper used to iterate tasks from a given node.
#define ZONE_WRITE
Used for write violation.
#define INT_STATUS_INVALID_PARAMETER_2
INTRO_PROT_OPTIONS CoreOptions
The activation and protection options for this guest.
LIST_HEAD Vmas
The list head for the VMAs from the memory space of this process.
INTSTATUS IntHookObjectCreate(DWORD ObjectType, QWORD Cr3, void **Object)
Create a new hook object.
void IntExcept(EXCEPTION_VICTIM_ZONE *Victim, void *Originator, EXCEPTION_TYPE Type, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason, INTRO_EVENT_TYPE EventClass)
This function is the entry point for the exception mechanism.
LINUX_GUEST * gLixGuest
Global variable holding the state of a Linux guest.
#define INT_STATUS_INVALID_DATA_SIZE
INTSTATUS IntLixFileGetPath(QWORD FileStructGva, char **Path, DWORD *Length)
Gets the path that corresponds to the provided FileStructGva (guest virtual address of the 'struct fi...
DWORD StaticDetected
TRUE if the process was detected using a static scan (during static init).
static void IntLixTaskDumpKernelThreadTree(LIX_TASK_OBJECT *Thread, DWORD Level)
Dumps the kthreads tree.
#define INT_STATUS_INSUFFICIENT_RESOURCES
QWORD Mask
The protection flags enabled for this process.
#define INT_STATUS_INVALID_PARAMETER_3
LIX_AGENT_TAG AgentTag
The agent tag, if this process is an agent.