9 #define KSYM_NUM_SYMBOLS_CAP 200000 10 #define KSYM_TOKEN_TABLE_SIZE_CAP 2000 11 #define KSYM_NAMES_CACHE_SIZE_CAP 2000000 12 #define KSYM_TOKEN_ARRAY_CACHE_SIZE 256 77 const char *pKallsymsNames = gKallsymsBuffers.
NamesBuffer + Offset;
78 const BYTE *pData = (
const BYTE *)pKallsymsNames;
84 WARNING(
"[WARNING] Wrong symbol size %d. \n", length);
89 nextOffset = Offset + length + 1;
147 if (!
LIX_FIELD(Info, HasKsymAbsolutePercpu))
194 ERROR(
"[ERROR] IntVirtMemMap failed for GVA 0x%016llx with status: 0x%08x\n", currentAddr, status);
206 if (pPage[i] > pPage[i + 1] ||
207 pPage[i + 1] >= pPage[i + 2] ||
208 pPage[i + 2] >= pPage[i + 3] ||
209 pPage[i + 3] >= pPage[i + 4] ||
210 pPage[i + 4] >= pPage[i + 5] ||
211 pPage[i + 5] >= pPage[i + 6] ||
212 pPage[i + 6] >= pPage[i + 7] ||
213 pPage[i + 7] >= pPage[i + 8] ||
214 pPage[i + 8] >= pPage[i + 9] ||
215 pPage[i + 9] >= pPage[i + 10] ||
216 pPage[i + 10] >= pPage[i + 11] ||
217 pPage[i + 11] >= pPage[i + 12] ||
218 pPage[i + 12] >= pPage[i + 13] ||
219 pPage[i + 13] >= pPage[i + 14] ||
220 pPage[i + 14] >= pPage[i + 15])
225 startAddr = currentAddr + i * 4ull;
235 ERROR(
"[ERROR] IntVirtMemRead failed for GVA 0x%016llx with status: 0x%08x\n", startAddr, status);
242 if (
LIX_FIELD(Info, HasKsymAbsolutePercpu))
244 if (ptr[i] == -1 && ptr[i + 1] == -1)
251 if (ptr[i] == 0 && ptr[i + 1] == 0)
258 if (ptr[i] < ptr[i - 1])
270 TRACE(
"[KALLSYMS RELATIVE] Found indexes start @%llx\n", startAddr);
287 *Address = startAddr;
311 QWORD currentAddr = 0;
324 ERROR(
"[ERROR] IntVirtMemMap failed for GVA 0x%016llx with status: 0x%08x\n", currentAddr, status);
330 if (pPage[i] == -1 && pPage[i + 1] == -1)
332 firstNegative =
TRUE;
341 if (!firstPositive && pPage[i] > 0)
343 firstPositive =
TRUE;
349 endAddr = currentAddr + i * 4ull;
355 endAddr = currentAddr + i * 4ull;
359 if (
LIX_FIELD(Info, HasKsymAbsolutePercpu))
361 if ((!firstPositive && pPage[i] < 0) ||
362 (firstPositive && pPage[i + 1] >= pPage[i]))
369 if (pPage[i] <= pPage[i + 1])
375 endAddr = currentAddr + i * 4ull;
385 QWORD relativeBase = 0;
386 DWORD numberOfNames = 0;
387 DWORD foundNames = (
DWORD)(endAddr - StartAddress) / 4;
392 ERROR(
"[ERROR] IntKernVirtMemFetchQword failed for GVA 0x%016llx with status: 0x%08x\n",
408 endAddr += (endAddr - StartAddress) * 2;
414 ERROR(
"[ERROR] IntKernVirtMemFetchDword failed for GVA 0x%016llx with status: 0x%08x\n",
420 TRACE(
"[KALLSYMS] num_symbols (found): %d\n", foundNames);
423 if ((foundNames > numberOfNames &&
424 foundNames - numberOfNames > 0x40) ||
425 (foundNames < numberOfNames &&
426 numberOfNames - foundNames > 0x40))
434 ERROR(
"[ERROR] Kallsyms number of names exceeds the limit: %u vs %u",
447 gKallsymsBuffers.
Indexes -= numberOfNames * 8ull;
477 QWORD tableOffsetsStartAddr = 0;
482 ERROR(
"[ERROR] IntKsymRelativeFindOffsetTableStart failed with status: 0x%08x\n", status);
489 ERROR(
"[ERROR] IntKsymRelativeFindOffsetTableEnd failed with status: 0x%08x\n", status);
517 while (gvaStart < gLixGuest->Layout.RoDataEnd)
524 ERROR(
"[ERROR] IntVirtMemMap failed for GVA 0x%016llx with status: 0x%08x\n", gvaStart, status);
559 if (pPage[i] < pPage[i + 1] &&
560 pPage[i + 1] < pPage[i + 2] &&
561 pPage[i + 2] < pPage[i + 3] &&
562 pPage[i + 3] < pPage[i + 4] &&
563 pPage[i + 4] < pPage[i + 5] &&
564 pPage[i + 5] < pPage[i + 6] &&
565 pPage[i + 6] < pPage[i + 7])
567 addrStart = gvaStart + i * 8ull;
580 QWORD val = pPage[i];
582 if ((val > 0) && (val < 0x3FFFF))
585 numGva = gvaStart + i * 8ull;
586 TRACE(
"[INFO] Found num_symbols start at 0x%016llx: %d\n", gvaStart + i * 8ull, num);
599 WARNING(
"[WARNING] Unordered list: 0x%016llx 0x%016llx\n", prev, val);
606 WARNING(
"[WARNING] Found an invalid pointer (prev 0x%016llx) 0x%016llx @ 0x%016llx\n",
607 prev, val, gvaStart + i * 8ull);
614 if (addrStart && num)
625 if (!addrStart || !num)
632 gKallsymsBuffers.
Addresses = numGva - num * 8ull;
633 gKallsymsBuffers.
Names = numGva + 8;
657 QWORD *pMarkers = NULL;
659 QWORD currentAddr = StartAddress;
662 if (StartAddress %
sizeof(
QWORD) != 0)
664 ERROR(
"[ERROR] The provided address is not aligned (0x%016llx)!\n", StartAddress);
676 ERROR(
"[ERROR] IntVirtMemMap failed for GVA 0x%016llx with status: 0x%08x\n", currentAddr, status);
683 if (pMarkers == NULL)
688 if (*pMarkers > 0xffffffff)
690 *EndAddress = currentAddr;
696 prevAddr = currentAddr;
713 if (pMarkers != NULL)
741 DWORD *pMarkers = NULL;
745 QWORD currentAddr = StartAddress;
747 if (StartAddress %
sizeof(
DWORD) != 0)
749 ERROR(
"[ERROR] The provided address is not aligned (0x%016llx)!\n", StartAddress);
756 if (NULL == pMarkers)
764 if (size ==
sizeof(*pMarkers))
770 size +=
sizeof(*pMarkers);
773 remaining = size -
sizeof(*pMarkers);
778 ERROR(
"[ERROR] IntVirtMemMap failed for GVA 0x%016llx with status: 0x%08x\n", currentAddr, status);
785 currentAddr +=
sizeof(*pMarkers);
786 remaining -=
sizeof(*pMarkers);
788 if (*pMarkers >= * (pMarkers + 1))
790 *EndAddress = currentAddr;
808 if (pMarkers != NULL)
836 BYTE *pSymbol = NULL;
838 QWORD currentAddr = StartAddress;
847 ERROR(
"[ERROR] IntVirtMemMap failed for 0x%016llx: 0x%08x\n", currentAddr, status);
857 prevAddr = currentAddr;
858 currentAddr += *pSymbol + 1ull;
867 pSymbol += *pSymbol + 1ull;
876 *EndAddress = currentAddr;
901 WORD indexes[0x5] = { 0 };
902 char tokenSlice[0x30] = { 0 };
903 DWORD remainingTokenLength = (
DWORD)
sizeof(tokenSlice);
904 QWORD currentAddr = TokenTableStart;
911 ERROR(
"[ERROR] IntKernVirtMemRead failed for GVA 0x%016llx with status: 0x%08x\n", TokenTableStart, status);
918 WORD length = (
WORD)
strlen_s(&tokenSlice[indexes[i - 1]], remainingTokenLength) + 1;
919 indexes[i] = indexes[i - 1] + length;
920 remainingTokenLength -= length;
922 if ((
int)remainingTokenLength < 0)
924 ERROR(
"[ERROR] %zu bytes not enough to find indexes. Stopped at %d!\n",
sizeof(tokenSlice), i);
932 WORD idx[
sizeof(indexes) /
sizeof(indexes[0])];
941 ERROR(
"[ERROR] IntVirtMemMap failed for GVA 0x%016llx with status: 0x%08x\n", currentAddr, status);
951 ERROR(
"[ERROR] IntKernVirtMemRead failed for GVA 0x%016llx with status: 0x%08x\n", currentAddr, status);
962 memcpy(idx, pIndex,
sizeof(idx));
968 if (idx[j] != indexes[j])
977 *IndexesTableStart = currentAddr;
983 prevAddr = currentAddr;
993 pIndex = (
WORD *)((
BYTE *)pIndex + 8);
1030 QWORD currentAddr = 0;
1031 QWORD tokenTableStart = 0;
1033 char *pTokenTable = NULL;
1034 char *pNames = NULL;
1035 QWORD *pAddresses = NULL;
1049 ERROR(
"[ERROR] IntKsymInitRelative failed: %08x\n", status);
1053 TRACE(
"[KALLSYMS] indexes : 0x%016llx\n", gKallsymsBuffers.
Indexes);
1061 ERROR(
"[ERROR] IntKsymInitAbsolute failed: %08x\n", status);
1065 TRACE(
"[KALLSYMS] addresses : 0x%016llx\n", gKallsymsBuffers.
Addresses);
1069 TRACE(
"[KALLSYMS] names : 0x%016llx\n", gKallsymsBuffers.
Names);
1074 ERROR(
"[ERROR] IntKsymFindNamesTableEnd failed with status: 0x%08x\n", status);
1077 currentAddr =
ALIGN_UP(currentAddr, 8);
1079 if (
LIX_FIELD(Info, HasKsymReducedSize))
1090 ERROR(
"[ERROR] Failed finding the start of token_table!\n");
1094 tokenTableStart =
ALIGN_UP(currentAddr, 8);
1095 TRACE(
"[KALLSYMS] token_table : 0x%016llx\n", tokenTableStart);
1100 ERROR(
"[ERROR] IntKsymFindIndexesTableStart failed with status: 0x%08x\n", status);
1108 ERROR(
"[ERROR] Tokens table size exceeds the introcore limit: %u vs %u\n",
1115 TRACE(
"[KALLSYMS] token_index : 0x%016llx\n", currentAddr);
1123 ERROR(
"[ERROR] IntKernVirtMemRead failed for GVA 0x%016llx with status: 0x%08x\n", currentAddr, status);
1128 if (NULL == pTokenTable)
1136 ERROR(
"[ERROR] IntKernVirtMemRead failed for GVA 0x%016llx with status: 0x%08x\n", currentAddr, status);
1140 size = (
DWORD)(tokenTableStart - gKallsymsBuffers.
Names);
1144 ERROR(
"[ERROR] Kallsyms names size exceeds the introcore limit: %u vs %u",
1153 TRACE(
"[INFO] Cache kallsyms names: %d bytes\n", size);
1165 ERROR(
"[ERROR] IntKernVirtMemRead failed for GVA 0x%016llx with status: 0x%08x\n", currentAddr, status);
1173 TRACE(
"[INFO] Cache kallsyms addresses: %d bytes\n", size);
1176 if (NULL == pAddresses)
1185 ERROR(
"[ERROR] IntKernVirtMemRead failed for GVA 0x%016llx with status: 0x%08x\n", currentAddr, status);
1198 if (NULL != pTokenTable)
1203 if (NULL != pAddresses)
1248 _Out_ char *SymName,
1277 if (NULL == SymName)
1297 while (high - low > 1)
1299 INT32 mid = low + (high - low) / 2;
1321 INT32 next = low + 1;
1335 *SymStart = symStart;
1338 for (
INT32 i = 0; i < low; i++)
1344 ERROR(
"[ERROR] Failed expanding symbol (offset: %d)!\n", offset);
1352 ERROR(
"[ERROR] Failed expanding symbol (offset: %d)!\n", offset);
1362 _In_ const char *Name,
1400 nameLen = strlen(Name);
1401 regexp = Name[nameLen - 1] ==
'*';
1410 ERROR(
"[ERROR] Failed expanding symbol\n");
1414 if ((!regexp && 0 == strcmp(Name, symName)) ||
1415 (regexp && strlen(symName) >= nameLen && 0 == memcmp(Name, symName, nameLen - 1)))
INTSTATUS IntVirtMemUnmap(void **HostPtr)
Unmaps a memory range previously mapped with IntVirtMemMap.
#define KSYM_NUM_SYMBOLS_CAP
The maximum number of symbols allowed to be in kallsyms.
static INTSTATUS IntKsymInitRelative(void)
Initializes the kallsyms subsystem for kernels compiled with CONFIG_KALLSYMS_BASE_RELATIVE.
static DWORD IntKsymExpandSymbol(DWORD Offset, DWORD MaxLength, char *Name)
Expands a kallsyms symbol name.
QWORD SystemCr3
The Cr3 used to map the kernel.
#define INT_STATUS_SUCCESS
#define PAGE_REMAINING(addr)
DWORD KernelSize
The size of the kernel.
INTSTATUS IntKsymFindByAddress(QWORD Gva, DWORD Length, char *SymName, QWORD *SymStart, QWORD *SymEnd)
Finds the symbol which is located at the given address.
struct _KALLSYMS_BUFFERS KALLSYMS_BUFFERS
Describes the structure of the internal kallsyms buffers and other data required for the semantic rec...
Describes the structure of the internal kallsyms buffers and other data required for the semantic rec...
WORD TokenIndex[KSYM_TOKEN_ARRAY_CACHE_SIZE]
The tokens array cached internally.
static INTSTATUS IntKsymFindMarkersTableEnd(QWORD StartAddress, QWORD *EndAddress)
Finds the end of 'kallsyms_markers' table.
QWORD RoDataStart
The guest virtual address where the read-only data starts.
#define INT_SUCCESS(Status)
#define HpAllocWithTag(Len, Tag)
int INTSTATUS
The status data type.
QWORD CodeEnd
The guest virtual address where the code ends.
QWORD CodeStart
The guest virtual address where the code starts.
#define INT_STATUS_NOT_FOUND
INTSTATUS IntKsymInit(void)
Initialize the kallsyms subsystem based on the os info provided by LIX_FIELD(Info, HasKsym*).
static INTSTATUS IntKsymRelativeFindOffsetTableEnd(QWORD StartAddress)
Finds the end of 'kallsyms_offsets' memory region.
INTRO_GUEST_TYPE OSType
The type of the guest.
static INTSTATUS IntKsymFindNamesTableEnd(QWORD StartAddress, QWORD *EndAddress)
Finds the end of 'kallsyms_names' table.
char * NamesBuffer
The internal name cache used for a faster symbol lookup.
QWORD IntKsymFindByName(const char *Name, QWORD *SymEnd)
Searches the given Name in kallsyms and returns the Start & End offset.
char * TokenTable
The internal tokens table.
static INTSTATUS IntKsymRelativeFindOffsetTableStart(QWORD *Address)
Finds the start of 'kallsyms_offsets' memory region.
#define PAGE_FRAME_NUMBER(addr)
static INTSTATUS IntKsymFindIndexesTableStart(QWORD TokenTableStart, QWORD *IndexesTableStart)
Finds the start of 'kallsyms_token_index' table.
static INTSTATUS IntKsymFindMarkersReducedTableEnd(QWORD StartAddress, QWORD *EndAddress)
Finds the end of 'kallsyms_markers' table.
INTSTATUS IntKernVirtMemFetchDword(QWORD GuestVirtualAddress, DWORD *Data)
Reads 4 bytes from the guest kernel memory.
#define IS_KERNEL_POINTER_LIX(p)
#define INT_STATUS_NOT_INITIALIZED
INTSTATUS IntKernVirtMemFetchQword(QWORD GuestVirtualAddress, QWORD *Data)
Reads 8 bytes from the guest kernel memory.
#define INT_STATUS_UNSUCCESSFUL
#define KSYM_TOKEN_TABLE_SIZE_CAP
The maximum size allowed for the tokens table size.
INT32 NumberOfNames
The number of symbols available in kallsyms.
BOOLEAN Initialized
The flag that marks whether the kallsyms module is initialized or not.
#define LIX_FIELD(Structure, Field)
Macro used to access fields inside the LIX_OPAQUE_FIELDS structure.
#define HpFreeAndNullWithTag(Add, Tag)
#define INT_STATUS_INVALID_DATA_STATE
#define INT_STATUS_INVALID_INTERNAL_STATE
DWORD TokenTableSize
The size of the internal tokens table.
QWORD KernelVa
The guest virtual address at which the kernel image.
#define KSYM_TOKEN_ARRAY_CACHE_SIZE
The size of tokens array cache.
#define LIX_SYMBOL_NAME_LEN
The max length of the ksym as defined by Linux kernel.
static KALLSYMS_BUFFERS gKallsymsBuffers
Contains information about kallsyms required for the semantic reconstruction.
QWORD RoDataEnd
The guest virtual address where the read-only data ends.
QWORD * AddressesBuffer
The internal addresses buffer.
__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.
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
static QWORD IntKsymGetAddress(INT32 Index)
Returns the address of the symbol located at the given index in the symbols table.
GUEST_STATE gGuest
The current guest state.
INTSTATUS IntVirtMemRead(QWORD Gva, DWORD Length, QWORD Cr3, void *Buffer, DWORD *RetLength)
Reads data from a guest virtual memory range.
static INTSTATUS IntKsymInitAbsolute(void)
Initializes the kallsyms subsystem for kernels compiled without CONFIG_KALLSYMS_BASE_RELATIVE.
INTSTATUS IntKernVirtMemRead(QWORD KernelGva, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest kernel virtual memory range.
struct _LINUX_GUEST::@123 Layout
#define KSYM_NAMES_CACHE_SIZE_CAP
The maximum size allowed for the names.
QWORD Addresses
The guest virtual address of Addresses table.
INT32 * IndexesBuffer
The Internal indexes buffer.
QWORD Indexes
The guest virtual address of Indexes table.
#define INT_STATUS_NOT_SUPPORTED
QWORD Names
The guest virtual address of the names table.
LINUX_GUEST * gLixGuest
Global variable holding the state of a Linux guest.
#define INT_STATUS_INVALID_DATA_SIZE
#define INT_STATUS_INSUFFICIENT_RESOURCES
#define INT_STATUS_INVALID_PARAMETER_3
struct _KALLSYMS_BUFFERS * PKALLSYMS_BUFFERS