HyperDbg Debugger
Loading...
Searching...
No Matches
symbol-parser.cpp File Reference

symbol parser More...

#include "pch.h"
#include "header/pdb-identity.h"

Functions

void SymSetTextMessageCallback (PVOID Handler)
 Set the function callback that will be called if any message needs to be shown.
VOID ShowMessages (const char *Fmt,...)
 Show messages.
PSYMBOL_LOADED_MODULE_DETAILS SymGetModuleBaseFromSearchMask (const char *SearchMask, BOOLEAN SetModuleNameGlobally)
 Interpret and find module base, based on module name.
BOOLEAN SymGetFieldOffsetFromModule (UINT64 Base, WCHAR *TypeName, WCHAR *FieldName, UINT32 *FieldOffset)
 Get the offset of a field from the top of a structure.
BOOLEAN SymGetDataTypeSizeFromModule (UINT64 Base, WCHAR *TypeName, UINT64 *TypeSize)
 Get the size of a data type (structure).
BOOLEAN SymInit ()
 initialize the DbgHelp symbols
BOOLEAN SymCheckAndRemoveWow64Prefix (const char *ModuleAddress, const char *PdbFileName, std::string &CustomModuleName)
 Remove wow64 extension to the module names.
BOOLEAN SymCheckNtoskrnlPrefix (const char *PdbFileName, std::string &CustomModuleName)
 Check for alternative name of ntoskrn;.
UINT32 SymLoadFileSymbol (UINT64 BaseAddress, const char *PdbFileName, const char *CustomModuleName)
 load symbol based on a file name and GUID
UINT32 SymUnloadModuleSymbol (char *ModuleName)
 Unload one module symbol.
UINT32 SymUnloadAllSymbols ()
 Unload all the symbols.
UINT64 SymConvertNameToAddress (const char *FunctionOrVariableName, PBOOLEAN WasFound)
 Convert function name to address.
BOOLEAN SymGetFieldOffset (CHAR *TypeName, CHAR *FieldName, UINT32 *FieldOffset)
 Search and show symbols.
BOOLEAN SymGetDataTypeSize (CHAR *TypeName, UINT64 *TypeSize)
 Get the size of structures from the symbols.
UINT32 SymSearchSymbolForMask (const char *SearchMask)
 Gets the offset from the symbol.
BOOLEAN SymCreateSymbolTableForDisassembler (void *CallbackFunction)
 Create symbol table for disassembler.

Variables

std::vector< PSYMBOL_LOADED_MODULE_DETAILSg_LoadedModules
BOOLEAN g_IsLoadedModulesInitialized = FALSE
BOOLEAN g_AbortLoadingExecution = FALSE
CHARg_CurrentModuleName = NULL
PVOID g_MessageHandler = NULL
 The handler for ShowMessages function this is because the user might choose not to use printf and instead use his/her handler for showing messages.
SymbolMapCallback g_SymbolMapForDisassembler = NULL

Detailed Description

symbol parser

Author
Alee Amini (alee@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)
Version
0.1
Date
2021-05-29

Function Documentation

◆ ShowMessages()

VOID ShowMessages ( const char * Fmt,
... )

Show messages.

Parameters
Fmtformat string message
Fmtformat string message
...arguments
Returns
VOID
144{
145 va_list ArgList;
146 va_list Args;
147
148 if (g_MessageHandler == NULL)
149 {
150 va_start(Args, Fmt);
151 vprintf(Fmt, Args);
152 va_end(Args);
153 }
154 else
155 {
157 va_start(ArgList, Fmt);
158 INT SprintfResult = vsprintf_s(TempMessage, Fmt, ArgList);
159 va_end(ArgList);
160
161 if (SprintfResult != -1)
162 {
163 //
164 // There is another handler
165 //
167 }
168 }
169}
int INT
Definition BasicTypes.h:43
#define TCP_END_OF_BUFFER_CHARS_COUNT
count of characters for tcp end of buffer
Definition Constants.h:442
#define COMMUNICATION_BUFFER_SIZE
Packet size for TCP connections.
Definition Constants.h:338
int(* SendMessageWithParamCallback)(const char *Text)
Callback type that can be used to be used as a custom ShowMessages function (by passing message as a ...
Definition DataTypes.h:155
PVOID g_MessageHandler
The handler for ShowMessages function this is because the user might choose not to use printf and ins...
Definition globals.h:460

◆ SymCheckAndRemoveWow64Prefix()

BOOLEAN SymCheckAndRemoveWow64Prefix ( const char * ModuleAddress,
const char * PdbFileName,
std::string & CustomModuleName )

Remove wow64 extension to the module names.

Parameters
ModuleAddress
PdbFileName
Returns
BOOLEAN
524{
525 char ModuleName[_MAX_FNAME] = {0};
526 char PdbModuleName[_MAX_FNAME] = {0};
527
528 //
529 // Determine the name of the file
530 //
531 _splitpath(ModuleAddress, NULL, NULL, ModuleName, NULL);
532 _splitpath(PdbFileName, NULL, NULL, PdbModuleName, NULL);
533
534 //
535 // Convert ModuleName to lowercase
536 //
537 std::transform(ModuleName, ModuleName + strlen(ModuleName), ModuleName, [](unsigned char c) { return std::tolower(c); });
538
539 //
540 // Convert PdbModuleName to lowercase
541 //
542 std::transform(PdbModuleName, PdbModuleName + strlen(PdbModuleName), PdbModuleName, [](unsigned char c) { return std::tolower(c); });
543
544 //
545 // Compare the lowercase strings
546 //
547 if (std::strcmp(ModuleName, PdbModuleName) == 0)
548 {
549 return FALSE;
550 }
551 else
552 {
553 // Convert ModuleAddress to lowercase
554 std::string LowerModuleAddress(ModuleAddress);
555 std::transform(LowerModuleAddress.begin(), LowerModuleAddress.end(), LowerModuleAddress.begin(), [](unsigned char c) { return std::tolower(c); });
556
557 if (PdbModuleName[0] == 'w' && LowerModuleAddress.find(":\\windows\\system32") != std::string::npos)
558 {
559 //
560 // Set CustomModuleName to lowercase ModuleName
561 //
562 CustomModuleName = std::string(ModuleName);
563
564 return TRUE;
565 }
566 else
567 {
568 return FALSE;
569 }
570 }
571}
#define TRUE
Definition BasicTypes.h:114
#define FALSE
Definition BasicTypes.h:113

◆ SymCheckNtoskrnlPrefix()

BOOLEAN SymCheckNtoskrnlPrefix ( const char * PdbFileName,
std::string & CustomModuleName )

Check for alternative name of ntoskrn;.

Parameters
PdbFileName
CustomModuleName
Returns
BOOLEAN
583{
584 char PdbModuleName[_MAX_FNAME] = {0};
585
586 //
587 // Determine the name of the file
588 //
589 _splitpath(PdbFileName, NULL, NULL, PdbModuleName, NULL);
590
591 //
592 // Convert PdbModuleName to lowercase
593 //
594 std::transform(PdbModuleName, PdbModuleName + strlen(PdbModuleName), PdbModuleName, [](unsigned char c) { return std::tolower(c); });
595
596 //
597 // Is it "nt" module or not
598 //
599 // Names of kernel
600 // NTOSKRNL.EXE : 1 CPU
601 // NTKRNLMP.EXE : N CPU, SMP
602 // NTKRNLPA.EXE : 1 CPU, PAE
603 // NTKRPAMP.EXE : N CPU SMP, PAE
604 //
605 if (strcmp(PdbModuleName, ("ntkrnlmp")) == 0 || strcmp(PdbModuleName, ("ntoskrnl")) == 0 ||
606 strcmp(PdbModuleName, ("ntkrpamp")) == 0 || strcmp(PdbModuleName, ("ntkrnlpa")) == 0)
607 {
608 CustomModuleName = "nt";
609 return TRUE;
610 }
611
612 //
613 // Not nt module
614 //
615 return FALSE;
616}

◆ SymConvertNameToAddress()

UINT64 SymConvertNameToAddress ( const char * FunctionOrVariableName,
PBOOLEAN WasFound )

Convert function name to address.

Parameters
FunctionOrVariableNamethe name of the function or variable to convert
WasFound
Returns
UINT64
901{
902 BOOLEAN Found = FALSE;
903 UINT64 Address = NULL;
904 UINT64 Buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR) + sizeof(UINT64) - 1) / sizeof(UINT64)];
905 PSYMBOL_INFO Symbol = (PSYMBOL_INFO)Buffer;
906 string FinalModuleName;
907 string TempName(FunctionOrVariableName);
908 string ExtractedModuleName;
909 string FunctionName;
910
911 //
912 // Not found by default
913 //
914 *WasFound = FALSE;
915
916 //
917 // Retrieve the address from name
918 //
919 Symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
920 Symbol->MaxNameLen = MAX_SYM_NAME;
921
922 //
923 // *** Check if the module has an alternative name, then replace the
924 // original name with alternative name ***
925 //
926
927 //
928 // Check if '!' is present in the function or variable name
929 //
930 SIZE_T FoundIndex = TempName.find('!');
931 if (FoundIndex != std::string::npos)
932 {
933 ExtractedModuleName = TempName.substr(0, FoundIndex);
934 FunctionName = TempName.substr(FoundIndex + 1);
935
936 //
937 // Convert module name to lower-case
938 //
939 std::transform(ExtractedModuleName.begin(), ExtractedModuleName.end(), ExtractedModuleName.begin(), [](unsigned char c) {
940 return std::tolower(c);
941 });
942
943 //
944 // Check if the we find it with an alternative module name or not
945 //
946 for (auto item : g_LoadedModules)
947 {
948 //
949 // Check for the module name
950 //
951 if (strcmp((const char *)item->ModuleName, ExtractedModuleName.c_str()) == 0)
952 {
953 string ModuleName(item->ModuleName);
954 FinalModuleName = ModuleName + "!" + FunctionName;
955 break;
956 }
957
958 //
959 // Check for the alternative module name
960 //
961 if (strcmp((const char *)item->ModuleAlternativeName, ExtractedModuleName.c_str()) == 0)
962 {
963 //
964 // Replace the alternative module name with original module name
965 //
966 string ModuleName(item->ModuleName);
967 FinalModuleName = ModuleName + "!" + FunctionName;
968 break;
969 }
970 }
971 }
972 else
973 {
974 //
975 // It doesn't contain a module name, so we'll use 'nt' by default
976 //
977 for (auto item : g_LoadedModules)
978 {
979 //
980 // Check for the module name
981 //
982 if (strcmp((const char *)item->ModuleAlternativeName, "nt") == 0)
983 {
984 //
985 // Replace the alternative module name with original module name
986 //
987 string ModuleName(item->ModuleName);
988 FinalModuleName = ModuleName + "!" + TempName;
989 break;
990 }
991 }
992 }
993
994 //
995 // Check if the final module name is not empty
996 //
997 if (FinalModuleName.empty())
998 {
999 *WasFound = FALSE;
1000 return NULL;
1001 }
1002
1003 if (SymFromName(GetCurrentProcess(), FinalModuleName.c_str(), Symbol))
1004 {
1005 //
1006 // SymFromName returned success
1007 //
1008 Found = TRUE;
1009 Address = Symbol->Address;
1010 }
1011 else
1012 {
1013 //
1014 // SymFromName failed
1015 //
1016 Found = FALSE;
1017
1018 //
1019 // ShowMessages("symbol not found (%x)\n", GetLastError());
1020 //
1021 }
1022
1023 *WasFound = Found;
1024 return Address;
1025}
UCHAR BOOLEAN
Definition BasicTypes.h:35
char CHAR
Definition BasicTypes.h:33
NULL()
Definition test-case-generator.py:530
std::vector< PSYMBOL_LOADED_MODULE_DETAILS > g_LoadedModules
Definition symbol-parser.cpp:20

◆ SymCreateSymbolTableForDisassembler()

BOOLEAN SymCreateSymbolTableForDisassembler ( void * CallbackFunction)

Create symbol table for disassembler.

mainly used by disassembler for 'u' command

Parameters
CallbackFunction
Returns
BOOLEAN
1243{
1244 BOOL Ret = FALSE;
1245 BOOLEAN Result = TRUE;
1246
1247 //
1248 // Set the callback function to deliver the name of module!ObjectName
1249 //
1251
1252 //
1253 // Create a symbol table from all modules
1254 //
1255 for (auto item : g_LoadedModules)
1256 {
1257 //
1258 // Set module name
1259 //
1260 g_CurrentModuleName = (char *)item->ModuleName;
1261
1262 //
1263 // Call the callback for the current module
1264 //
1265 Ret = SymEnumSymbols(
1266 GetCurrentProcess(), // Process handle of the current process
1267 item->BaseAddress, // Base address of the module
1268 NULL, // Mask (NULL -> all symbols)
1269 SymDeliverDisassemblerSymbolMapCallback, // The callback function
1270 NULL // A used-defined context can be passed here, if necessary
1271 );
1272
1273 if (!Ret)
1274 {
1275 //
1276 // A module did not added correctly
1277 //
1278 // ShowMessages("err, symbol enum failed (%x)\n", GetLastError());
1279 Result = FALSE;
1280 }
1281 }
1282
1283 return Result;
1284}
int BOOL
Definition BasicTypes.h:25
VOID(* SymbolMapCallback)(UINT64 Address, char *ModuleName, char *ObjectName, unsigned int ObjectSize)
Callback type that should be used to add list of Addresses to ObjectNames.
Definition Symbols.h:67
CHAR * g_CurrentModuleName
Definition symbol-parser.cpp:23
SymbolMapCallback g_SymbolMapForDisassembler
Definition symbol-parser.cpp:25
BOOL CALLBACK SymDeliverDisassemblerSymbolMapCallback(SYMBOL_INFO *SymInfo, ULONG SymbolSize, PVOID UserContext)

◆ SymGetDataTypeSize()

BOOLEAN SymGetDataTypeSize ( CHAR * TypeName,
UINT64 * TypeSize )

Get the size of structures from the symbols.

Parameters
TypeNamethe type (structure) name to query
TypeSizepointer to receive the size of the data type
Returns
BOOLEAN Whether the module is found successfully or not
1127{
1128 BOOL Ret = FALSE;
1129 UINT32 Index = 0;
1131 BOOLEAN Result = FALSE;
1132
1133 //
1134 // Find module info
1135 //
1136 SymbolInfo = SymGetModuleBaseFromSearchMask(TypeName, TRUE);
1137
1138 //
1139 // Check if module is found
1140 //
1141 if (SymbolInfo == NULL)
1142 {
1143 //
1144 // Module not found or there was an error
1145 //
1146 return FALSE;
1147 }
1148
1149 //
1150 // Remove the *!Name from TypeName as it not supports module name
1151 // at the beginning of a type name
1152 //
1153 while (TypeName[Index] != '\0')
1154 {
1155 if (TypeName[Index] == '!')
1156 {
1157 TypeName = (CHAR *)(TypeName + Index + 1);
1158 break;
1159 }
1160
1161 Index++;
1162 }
1163
1164 //
1165 // Convert FieldName to wide-char, it's because SymGetTypeInfo supports
1166 // wide-char
1167 //
1168 const SIZE_T TypeNameSize = strlen(TypeName) + 1;
1169 WCHAR * TypeNameW = (WCHAR *)malloc(sizeof(wchar_t) * TypeNameSize);
1170
1171 if (TypeNameW == NULL)
1172 {
1173 printf("err, could not allocate buffer");
1174 return FALSE;
1175 }
1176
1177 RtlZeroMemory(TypeNameW, sizeof(wchar_t) * TypeNameSize);
1178 mbstowcs(TypeNameW, TypeName, TypeNameSize);
1179
1180 Result = SymGetDataTypeSizeFromModule(SymbolInfo->ModuleBase, TypeNameW, TypeSize);
1181
1182 free(TypeNameW);
1183
1184 return Result;
1185}
unsigned int UINT32
Definition BasicTypes.h:54
printf("ho")
UINT64 ModuleBase
Definition symbol-parser.h:31
BOOLEAN SymGetDataTypeSizeFromModule(UINT64 Base, WCHAR *TypeName, UINT64 *TypeSize)
Get the size of a data type (structure).
Definition symbol-parser.cpp:427
PSYMBOL_LOADED_MODULE_DETAILS SymGetModuleBaseFromSearchMask(const char *SearchMask, BOOLEAN SetModuleNameGlobally)
Interpret and find module base, based on module name.
Definition symbol-parser.cpp:180
struct _SYMBOL_LOADED_MODULE_DETAILS * PSYMBOL_LOADED_MODULE_DETAILS

◆ SymGetDataTypeSizeFromModule()

BOOLEAN SymGetDataTypeSizeFromModule ( UINT64 Base,
WCHAR * TypeName,
UINT64 * TypeSize )

Get the size of a data type (structure).

Parameters
Base
TypeName
TypeSize
Returns
BOOLEAN Whether the module is found successfully or not
428{
429 //
430 // Allocate a buffer to back the SYMBOL_INFO structure
431 //
432 const DWORD SizeOfStruct =
433 sizeof(SYMBOL_INFOW) + ((MAX_SYM_NAME - 1) * sizeof(wchar_t));
434 UINT8 SymbolInfoBuffer[SizeOfStruct];
435 auto SymbolInfo = PSYMBOL_INFOW(SymbolInfoBuffer);
436
437 //
438 // Initialize the fields that need initialization
439 //
440 SymbolInfo->SizeOfStruct = sizeof(SYMBOL_INFOW);
441 SymbolInfo->MaxNameLen = MAX_SYM_NAME;
442
443 //
444 // Retrieve a type index for the type we're after
445 //
446 if (!SymGetTypeFromNameW(GetCurrentProcess(), Base, TypeName, SymbolInfo))
447 {
448 // ShowMessages("err, SymGetTypeFromName failed (%x)\n",
449 // GetLastError());
450 return FALSE;
451 }
452
453 if (!SymGetTypeInfo(GetCurrentProcess(), Base, SymbolInfo->TypeIndex, TI_GET_LENGTH, TypeSize))
454 {
455 // ShowMessages("err, SymGetTypeInfo failed (%x)\n",
456 // GetLastError());
457 return FALSE;
458 }
459
460 // ShowMessages("type size : %llx\n", TypeSize);
461
462 return TRUE;
463}
unsigned char UINT8
Definition BasicTypes.h:52
unsigned long DWORD
Definition BasicTypes.h:38

◆ SymGetFieldOffset()

BOOLEAN SymGetFieldOffset ( CHAR * TypeName,
CHAR * FieldName,
UINT32 * FieldOffset )

Search and show symbols.

mainly used by the 'x' command

Parameters
TypeName
FieldName
FieldOffset
Returns
BOOLEAN Whether the module is found successfully or not
1039{
1040 BOOL Ret = FALSE;
1041 UINT32 Index = 0;
1043 BOOLEAN Result = FALSE;
1044
1045 //
1046 // Find module info
1047 //
1048 SymbolInfo = SymGetModuleBaseFromSearchMask(TypeName, TRUE);
1049
1050 //
1051 // Check if module is found
1052 //
1053 if (SymbolInfo == NULL)
1054 {
1055 //
1056 // Module not found or there was an error
1057 //
1058 return FALSE;
1059 }
1060
1061 //
1062 // Remove the *!Name from TypeName as it not supports module name
1063 // at the beginning of a type name
1064 //
1065 while (TypeName[Index] != '\0')
1066 {
1067 if (TypeName[Index] == '!')
1068 {
1069 TypeName = (CHAR *)(TypeName + Index + 1);
1070 break;
1071 }
1072
1073 Index++;
1074 }
1075
1076 //
1077 // Convert TypeName to wide-char, it's because SymGetTypeInfo supports
1078 // wide-char
1079 //
1080 const SIZE_T TypeNameSize = strlen(TypeName) + 1;
1081 WCHAR * TypeNameW = (WCHAR *)malloc(sizeof(wchar_t) * TypeNameSize);
1082
1083 if (TypeNameW == NULL)
1084 {
1085 printf("err, could not allocate buffer");
1086 return FALSE;
1087 }
1088
1089 RtlZeroMemory(TypeNameW, sizeof(wchar_t) * TypeNameSize);
1090 mbstowcs(TypeNameW, TypeName, TypeNameSize);
1091
1092 //
1093 // Convert FieldName to wide-char, it's because SymGetTypeInfo supports
1094 // wide-char
1095 //
1096 const SIZE_T FieldNameSize = strlen(FieldName) + 1;
1097 WCHAR * FieldNameW = (WCHAR *)malloc(sizeof(wchar_t) * FieldNameSize);
1098
1099 if (FieldNameW == NULL)
1100 {
1101 printf("err, could not allocate buffer");
1102 free(TypeNameW);
1103 return FALSE;
1104 }
1105
1106 RtlZeroMemory(FieldNameW, sizeof(wchar_t) * FieldNameSize);
1107 mbstowcs(FieldNameW, FieldName, FieldNameSize);
1108
1109 Result = SymGetFieldOffsetFromModule(SymbolInfo->ModuleBase, TypeNameW, FieldNameW, FieldOffset);
1110
1111 free(TypeNameW);
1112 free(FieldNameW);
1113
1114 return Result;
1115}
BOOLEAN SymGetFieldOffsetFromModule(UINT64 Base, WCHAR *TypeName, WCHAR *FieldName, UINT32 *FieldOffset)
Get the offset of a field from the top of a structure.
Definition symbol-parser.cpp:298

◆ SymGetFieldOffsetFromModule()

BOOLEAN SymGetFieldOffsetFromModule ( UINT64 Base,
WCHAR * TypeName,
WCHAR * FieldName,
UINT32 * FieldOffset )

Get the offset of a field from the top of a structure.

Parameters
Base
TypeName
FieldName
FieldOffset

This function is derived from: https://github.com/0vercl0k/sic/blob/master/src/sic/sym.cc

Returns
BOOLEAN Whether the module is found successfully or not
299{
300 BOOLEAN Found = FALSE;
301
302 //
303 // Allocate a buffer to back the SYMBOL_INFO structure
304 //
305 const DWORD SizeOfStruct =
306 sizeof(SYMBOL_INFOW) + ((MAX_SYM_NAME - 1) * sizeof(wchar_t));
307 UINT8 SymbolInfoBuffer[SizeOfStruct];
308 auto SymbolInfo = PSYMBOL_INFOW(SymbolInfoBuffer);
309
310 //
311 // Initialize the fields that need initialization
312 //
313 SymbolInfo->SizeOfStruct = sizeof(SYMBOL_INFOW);
314 SymbolInfo->MaxNameLen = MAX_SYM_NAME;
315
316 //
317 // Retrieve a type index for the type we're after
318 //
319 if (!SymGetTypeFromNameW(GetCurrentProcess(), Base, TypeName, SymbolInfo))
320 {
321 // ShowMessages("err, SymGetTypeFromName failed (%x)\n",
322 // GetLastError());
323 return FALSE;
324 }
325
326 //
327 // Now that we have a type, we need to enumerate its children to find the
328 // field we're after. First step is to get the number of children
329 //
330 const ULONG TypeIndex = SymbolInfo->TypeIndex;
331 DWORD ChildrenCount = 0;
332 if (!SymGetTypeInfo(GetCurrentProcess(), Base, TypeIndex, TI_GET_CHILDRENCOUNT, &ChildrenCount))
333 {
334 // ShowMessages("err, SymGetTypeInfo failed (%x)\n",
335 // GetLastError());
336 return FALSE;
337 }
338
339 //
340 // Allocate enough memory to receive the children ids
341 //
342 auto FindChildrenParamsBacking = std::make_unique<UINT8[]>(
343 sizeof(_TI_FINDCHILDREN_PARAMS) + ((ChildrenCount - 1) * sizeof(ULONG)));
344 auto FindChildrenParams =
345 (_TI_FINDCHILDREN_PARAMS *)FindChildrenParamsBacking.get();
346
347 //
348 // Initialize the structure with the children count
349 //
350 FindChildrenParams->Count = ChildrenCount;
351
352 //
353 // Get all the children ids
354 //
355 if (!SymGetTypeInfo(GetCurrentProcess(), Base, TypeIndex, TI_FINDCHILDREN, FindChildrenParams))
356 {
357 // ShowMessages("err, SymGetTypeInfo failed (%x)\n",
358 // GetLastError());
359 return FALSE;
360 }
361
362 //
363 // Now that we have all the ids, we can walk them and find the one that
364 // matches the field we're looking for
365 //
366
367 for (DWORD ChildIdx = 0; ChildIdx < ChildrenCount; ChildIdx++)
368 {
369 //
370 // Grab the child name
371 //
372 const ULONG ChildId = FindChildrenParams->ChildId[ChildIdx];
373 WCHAR * ChildName = nullptr;
374 SymGetTypeInfo(GetCurrentProcess(), Base, ChildId, TI_GET_SYMNAME, &ChildName);
375
376 //
377 // Grab the child size - this is useful to know if a field is a bit or a
378 // normal field
379 //
380 UINT64 ChildSize = 0;
381 SymGetTypeInfo(GetCurrentProcess(), Base, ChildId, TI_GET_LENGTH, &ChildSize);
382
383 //
384 // Does this child's name match the field we're looking for?
385 //
386 Found = FALSE;
387 if (wcscmp(ChildName, FieldName) == 0)
388 {
389 //
390 // If we have found the field, now we need to find its offset if
391 // it's a normal field, or its bit position if it is a bit
392 //
393 const IMAGEHLP_SYMBOL_TYPE_INFO Info =
394 (ChildSize == 1) ? TI_GET_BITPOSITION : TI_GET_OFFSET;
395 SymGetTypeInfo(GetCurrentProcess(), Base, ChildId, Info, FieldOffset);
396
397 Found = TRUE;
398 }
399
400 //
401 // Even if we have found a match, we need to clean up the memory
402 //
403 LocalFree(ChildName);
404 ChildName = nullptr;
405
406 //
407 // We can now break out of the loop if we have what we came looking for
408 //
409 if (Found)
410 {
411 break;
412 }
413 }
414
415 return Found;
416}
unsigned long ULONG
Definition BasicTypes.h:31

◆ SymGetModuleBaseFromSearchMask()

PSYMBOL_LOADED_MODULE_DETAILS SymGetModuleBaseFromSearchMask ( const char * SearchMask,
BOOLEAN SetModuleNameGlobally )

Interpret and find module base, based on module name.

Parameters
SearchMaskthe search mask to find module
SetModuleNameGloballywhether to set module name globally
Returns
PSYMBOL_LOADED_MODULE_DETAILS NULL means error or not found, otherwise it returns the instance of loaded module based on search mask
181{
182 string Token;
183 char ModuleName[_MAX_FNAME] = {0};
184 int Index = 0;
185 char Ch = '\0';
186
187 if (!g_IsLoadedModulesInitialized || SearchMask == NULL)
188 {
189 //
190 // no module is loaded or search mask is invalid
191 //
192 return NULL;
193 }
194
195 //
196 // Convert search mask to string
197 //
198 string SearchMaskString(SearchMask);
199
200 //
201 // Check if the string contains '!'
202 //
203 char Delimiter = '!';
204 if (SearchMaskString.find(Delimiter) != std::string::npos)
205 {
206 //
207 // Found
208 //
209 Token = SearchMaskString.substr(0, SearchMaskString.find(Delimiter));
210
211 strcpy(ModuleName, Token.c_str());
212
213 if (ModuleName[0] == '\0')
214 {
215 //
216 // Invalid name
217 //
218 return NULL;
219 }
220
221 //
222 // Convert module name to lowercase
223 //
224 while (ModuleName[Index])
225 {
226 Ch = ModuleName[Index];
227
228 //
229 // convert ch to lowercase using toLower()
230 //
231 ModuleName[Index] = tolower(Ch);
232
233 Index++;
234 }
235 }
236 else
237 {
238 //
239 // There is no '!' in the middle of the search mask so,
240 // we assume that the module is nt
241 //
242 RtlZeroMemory(ModuleName, _MAX_FNAME);
243
244 ModuleName[0] = 'n';
245 ModuleName[1] = 't';
246 }
247
248 //
249 // ************* Interpret based on remarks type name *************
250 //
251 for (auto item : g_LoadedModules)
252 {
253 //
254 // Check for the module name
255 //
256 if (strcmp((const char *)item->ModuleName, ModuleName) == 0)
257 {
258 if (SetModuleNameGlobally)
259 {
260 g_CurrentModuleName = (char *)item->ModuleName;
261 }
262
263 return item;
264 }
265
266 //
267 // Check for alternative module name
268 //
269 if (strcmp((const char *)item->ModuleAlternativeName, ModuleName) == 0)
270 {
271 if (SetModuleNameGlobally)
272 {
273 g_CurrentModuleName = (char *)item->ModuleAlternativeName;
274 }
275
276 return item;
277 }
278 }
279
280 //
281 // If the function continues until here then it means
282 // that the module not found
283 //
284 return NULL;
285}
BOOLEAN g_IsLoadedModulesInitialized
Definition symbol-parser.cpp:21

◆ SymInit()

BOOLEAN SymInit ( )

initialize the DbgHelp symbols

Returns
BOOLEAN
472{
473 BOOL Ret = FALSE;
474 DWORD Options = 0;
475
476 //
477 // Get options
478 //
479 Options = SymGetOptions();
480
481 //
482 // SYMOPT_DEBUG option asks DbgHelp to print additional troubleshooting
483 // messages to debug output - use the debugger's Debug Output window
484 // to view the messages
485 //
486 Options |= SYMOPT_DEBUG;
487 Options |= SYMOPT_CASE_INSENSITIVE;
488 SymSetOptions(Options);
489
490 //
491 // Initialize DbgHelp and load symbols for all modules of the current process
492 //
493 Ret = SymInitialize(
494 GetCurrentProcess(), // Process handle of the current process
495 NULL, // No user-defined search path -> use default
496 FALSE // Do not load symbols for modules in the current process
497 );
498
499 if (!Ret)
500 {
501 ShowMessages("err, symbol init failed (%x)\n",
502 GetLastError());
503 return FALSE;
504 }
505
506 //
507 // Indicate that at least one module is loaded
508 //
510
511 return TRUE;
512}
VOID ShowMessages(const char *Fmt,...)
Show messages.
Definition symbol-parser.cpp:143

◆ SymLoadFileSymbol()

UINT32 SymLoadFileSymbol ( UINT64 BaseAddress,
const char * PdbFileName,
const char * CustomModuleName )

load symbol based on a file name and GUID

Parameters
BaseAddress
PdbFileName
CustomModuleName
Returns
UINT32
629{
630 DWORD FileSize = 0;
631 int Index = 0;
632 char Ch = '\0';
633 char ModuleName[_MAX_FNAME] = {0};
634 char AlternateModuleName[_MAX_FNAME] = {0};
635 PSYMBOL_LOADED_MODULE_DETAILS ModuleDetails = NULL;
636
637 //
638 // Check if the loaded modules are initialized or not
639 //
641 {
642 //
643 // Initialize the symbol table
644 //
645 SymInit();
646 }
647
648 //
649 // Determine the base address and the file size
650 //
651 if (!SymGetFileParams(PdbFileName, FileSize))
652 {
653 ShowMessages("err, cannot obtain file parameters (internal error)\n");
654 return -1;
655 }
656
657 //
658 // Determine the name of the file
659 //
660 _splitpath(PdbFileName, NULL, NULL, ModuleName, NULL);
661
662 //
663 // Move to alternate list
664 //
665 strcpy(AlternateModuleName, ModuleName);
666
667 //
668 // Convert module name to lowercase
669 //
670 while (ModuleName[Index])
671 {
672 Ch = ModuleName[Index];
673
674 //
675 // convert ch to lowercase using toLower()
676 //
677 ModuleName[Index] = tolower(Ch);
678
679 Index++;
680 }
681
682 //
683 // Allocate buffer to store the details
684 //
685 ModuleDetails = (SYMBOL_LOADED_MODULE_DETAILS *)malloc(sizeof(SYMBOL_LOADED_MODULE_DETAILS));
686
687 if (ModuleDetails == NULL)
688 {
689 ShowMessages("err, allocating buffer for storing symbol details (%x)\n",
690 GetLastError());
691 return -1;
692 }
693
694 RtlZeroMemory(ModuleDetails, sizeof(SYMBOL_LOADED_MODULE_DETAILS));
695
696 ModuleDetails->ModuleBase = SymLoadModule64(
697 GetCurrentProcess(), // Process handle of the current process
698 NULL, // Handle to the module's image file (not needed)
699 PdbFileName, // Path/name of the file
700 NULL, // User-defined short name of the module (it can be NULL)
701 BaseAddress, // Base address of the module (cannot be NULL if .PDB file is
702 // used, otherwise it can be NULL)
703 FileSize // Size of the file (cannot be NULL if .PDB file is used,
704 // otherwise it can be NULL)
705 );
706
707 if (ModuleDetails->ModuleBase == NULL)
708 {
709 ShowMessages("err, loading symbols failed (%x)\n",
710 GetLastError());
711
712 free(ModuleDetails);
713 return -1;
714 }
715
716#ifndef DoNotShowDetailedResult
717
718 //
719 // Load symbols for the module
720 //
721 ShowMessages("loading symbols for: %s\n", PdbFilePath);
722
723 ShowMessages("load address: %I64x\n", ModuleDetails.ModuleBase);
724
725 //
726 // Obtain and display information about loaded symbols
727 //
728 SymShowSymbolInfo(ModuleDetails.ModuleBase);
729
730#endif // !DoNotShowDetailedResult
731
732 //
733 // Make the details (to save)
734 //
735 ModuleDetails->BaseAddress = BaseAddress;
736 strcpy((char *)ModuleDetails->ModuleName, ModuleName);
737 strcpy((char *)ModuleDetails->PdbFilePath, PdbFileName);
738
739 //
740 // Save the custom module name (if any)
741 //
742 if (CustomModuleName != NULL)
743 {
744 strcpy((char *)ModuleDetails->ModuleAlternativeName, CustomModuleName);
745 }
746
747 //
748 // Save it
749 //
750 g_LoadedModules.push_back(ModuleDetails);
751
752 return 0;
753}
UINT64 BaseAddress
Definition symbol-parser.h:30
char PdbFilePath[MAX_PATH]
Definition symbol-parser.h:34
char ModuleAlternativeName[_MAX_FNAME]
Definition symbol-parser.h:33
char ModuleName[_MAX_FNAME]
Definition symbol-parser.h:32
BOOLEAN SymInit()
initialize the DbgHelp symbols
Definition symbol-parser.cpp:471
VOID SymShowSymbolInfo(UINT64 ModBase)
struct _SYMBOL_LOADED_MODULE_DETAILS SYMBOL_LOADED_MODULE_DETAILS
Hold detail about the loaded modules.
BOOL SymGetFileParams(const char *FileName, DWORD &FileSize)

◆ SymSearchSymbolForMask()

UINT32 SymSearchSymbolForMask ( const char * SearchMask)

Gets the offset from the symbol.

Parameters
SearchMask
Returns
UINT32
1196{
1197 BOOL Ret = FALSE;
1199
1200 //
1201 // Get the module info
1202 //
1203 SymbolInfo = SymGetModuleBaseFromSearchMask(SearchMask, TRUE);
1204
1205 //
1206 // Check to see if module info is found
1207 //
1208 if (SymbolInfo == NULL)
1209 {
1210 //
1211 // Module not found or there was an error
1212 //
1213 return -1;
1214 }
1215
1216 Ret = SymEnumSymbols(
1217 GetCurrentProcess(), // Process handle of the current process
1218 SymbolInfo->ModuleBase, // Base address of the module
1219 SearchMask, // Mask (NULL -> all symbols)
1220 SymDisplayMaskSymbolsCallback, // The callback function
1221 NULL // A used-defined context can be passed here, if necessary
1222 );
1223
1224 if (!Ret)
1225 {
1226 ShowMessages("err, symbol enum failed (%x)\n",
1227 GetLastError());
1228 }
1229
1230 return 0;
1231}
BOOL CALLBACK SymDisplayMaskSymbolsCallback(SYMBOL_INFO *SymInfo, ULONG SymbolSize, PVOID UserContext)

◆ SymSetTextMessageCallback()

void SymSetTextMessageCallback ( PVOID Handler)

Set the function callback that will be called if any message needs to be shown.

Parameters
HandlerFunction that handles the messages
128{
129 g_MessageHandler = Handler;
130
131 //
132 // Set the pdbex's message handler
133 //
134 pdbex_set_logging_method_export(Handler);
135}

◆ SymUnloadAllSymbols()

UINT32 SymUnloadAllSymbols ( )

Unload all the symbols.

Returns
UINT32
823{
824 BOOL Ret = FALSE;
825 BOOLEAN IsAnythingLoaded = FALSE;
826
827 //
828 // Check if it's already initialized
829 //
831 {
832 return 0;
833 }
834
835 for (auto item : g_LoadedModules)
836 {
837 //
838 // At least one module is loaded
839 //
840 IsAnythingLoaded = TRUE;
841
842 //
843 // Unload symbols for the module
844 //
845 Ret = SymUnloadModule64(GetCurrentProcess(), item->ModuleBase);
846
847 if (!Ret)
848 {
849 // ShowMessages("err, unload symbol failed (%x)\n",
850 // GetLastError());
851 }
852
853 free(item);
854 }
855
856 //
857 // Check if there is at least one module is loaded
858 //
859 if (!IsAnythingLoaded)
860 {
861 //
862 // Nothing is loaded yet!
863 //
864 return 0;
865 }
866
867 //
868 // Clear the list
869 //
870 g_LoadedModules.clear();
871
872 //
873 // Uninitialize DbgHelp
874 //
875 Ret = SymCleanup(GetCurrentProcess());
876
877 if (!Ret)
878 {
879 ShowMessages("err, symbol cleanup failed (%x)\n", GetLastError());
880 return 0;
881 }
882
883 //
884 // It's not initialized anymore
885 //
887
888 return 0;
889}

◆ SymUnloadModuleSymbol()

UINT32 SymUnloadModuleSymbol ( char * ModuleName)

Unload one module symbol.

Parameters
ModuleName
Returns
UINT32
764{
765 BOOLEAN OneModuleFound = FALSE;
766 BOOL Ret = FALSE;
767 UINT32 Index = 0;
768
769 for (auto item : g_LoadedModules)
770 {
771 Index++;
772
773 if (strcmp(item->ModuleName, ModuleName) == 0 || strcmp(item->ModuleAlternativeName, ModuleName) == 0)
774 {
775 //
776 // Unload symbol for the module
777 //
778 Ret = SymUnloadModule64(GetCurrentProcess(), item->ModuleBase);
779
780 if (!Ret)
781 {
782 ShowMessages("err, unload symbol failed (%x)\n",
783 GetLastError());
784 return -1;
785 }
786
787 OneModuleFound = TRUE;
788
789 free(item);
790
791 break;
792 }
793 }
794
795 if (!OneModuleFound)
796 {
797 //
798 // Not found
799 //
800 return -1;
801 }
802
803 //
804 // Remove it from the vector
805 //
806 std::vector<PSYMBOL_LOADED_MODULE_DETAILS>::iterator it = g_LoadedModules.begin();
807 std::advance(it, --Index);
808 g_LoadedModules.erase(it);
809
810 //
811 // Success
812 //
813 return 0;
814}

Variable Documentation

◆ g_AbortLoadingExecution

BOOLEAN g_AbortLoadingExecution = FALSE

◆ g_CurrentModuleName

CHAR* g_CurrentModuleName = NULL

◆ g_IsLoadedModulesInitialized

BOOLEAN g_IsLoadedModulesInitialized = FALSE

◆ g_LoadedModules

std::vector<PSYMBOL_LOADED_MODULE_DETAILS> g_LoadedModules

◆ g_MessageHandler

PVOID g_MessageHandler = NULL

The handler for ShowMessages function this is because the user might choose not to use printf and instead use his/her handler for showing messages.

◆ g_SymbolMapForDisassembler

SymbolMapCallback g_SymbolMapForDisassembler = NULL