admin 发表于 2024-12-24 19:58:57

使用符号获取结构体成员的偏移

由于WIN10更新太猛,直接把结构体成员偏移写死在代码里已经不可靠了,所以在可以联网的情况下,我建议使用符号获取结构体成员的偏移。
编译以下代码后,需要在EXE文件的同目录下放置dbghelp.dll、symsrv.dll、symsrv.yes。如果不知道在哪里获得这些文件,可以先下载并运行一次WKE,然后把WKE输出的相关文件复制过来即可。
以下是完整可编译的C代码,演示了获取fltmgr!_FLT_FILTER结构体里Operations成员的偏移:
#include <stdio.h>
#include <Windows.h>
#include <psapi.h>
#include <Imagehlp.h>

#pragma comment(lib, "PSAPI.lib")
#pragma comment(lib, "DbgHelp.lib")
#pragma comment(lib, "ImageHlp.lib")

/*enum SymTagEnum
{
      SymTagNull,
      SymTagExe,
      SymTagCompiland,
      SymTagCompilandDetails,
      SymTagCompilandEnv,
      SymTagFunction,
      SymTagBlock,
      SymTagData,
      SymTagAnnotation,
      SymTagLabel,
      SymTagPublicSymbol,
      SymTagUDT,
      SymTagEnum,
      SymTagFunctionType,
      SymTagPointerType,
      SymTagArrayType,
      SymTagBaseType,
      SymTagTypedef,
      SymTagBaseClass,
      SymTagFriend,
      SymTagFunctionArgType,
      SymTagFuncDebugStart,
      SymTagFuncDebugEnd,
      SymTagUsingNamespace,
      SymTagVTableShape,
      SymTagVTable,
      SymTagCustom,
      SymTagThunk,
      SymTagCustomType,
      SymTagManagedType,
      SymTagDimension
};*/

typedef struct _SYMBOL_GET_STRUCT_OFFSET
{
      char StructureName;
      WCHAR MemberName;
      ULONG offset;
}SYMBOL_GET_STRUCT_OFFSET, *PSYMBOL_GET_STRUCT_OFFSET;

PVOID GetDriverBaseA(char *DriverName)
{
      DWORD cbNeed = 0,i = 0;
      PVOID *ppDrvBas = NULL, RetVal = NULL;
      if(EnumDeviceDrivers(NULL,0,&cbNeed))
      {
                ppDrvBas = (PVOID*)malloc(cbNeed);
                if(ppDrvBas)
                {
                        if(EnumDeviceDrivers(ppDrvBas,cbNeed,&cbNeed))
                        {
                              for(i=0;i<cbNeed/sizeof(SIZE_T);i++)
                              {
                                        char path={0};
                                        if(GetDeviceDriverBaseNameA(ppDrvBas,path,MAX_PATH))
                                        {
                                                if(!stricmp(path,DriverName))
                                                {
                                                      RetVal = ppDrvBas;
                                                      break;
                                                }
                                        }
                              }
                        }
                        free(ppDrvBas);
                }
      }
      return RetVal;
}

BOOLEAN CALLBACK EnumSymbolStructureRoutine(PSYMBOL_INFO psi, ULONG SymSize, PVOID Context)
{
      if(Context)
      {
                PSYMBOL_GET_STRUCT_OFFSET pInfo = (PSYMBOL_GET_STRUCT_OFFSET)Context;
                if(!strcmp(psi->Name,(const char*)(pInfo->StructureName)))
                {
                        DWORD i, dwChildrenCount = 0;
                        if(SymGetTypeInfo(GetCurrentProcess(), psi->ModBase, psi->TypeIndex, TI_GET_CHILDRENCOUNT, &dwChildrenCount))
                        {
                              TI_FINDCHILDREN_PARAMS *pChildren = (TI_FINDCHILDREN_PARAMS *)malloc(sizeof(TI_FINDCHILDREN_PARAMS) + sizeof(DWORD) * dwChildrenCount);
                              if(pChildren)
                              {
                                    pChildren->Count = dwChildrenCount;
                                    pChildren->Start = 0;
                                        if(SymGetTypeInfo(GetCurrentProcess(), psi->ModBase, psi->TypeIndex, TI_FINDCHILDREN, pChildren))
                                        {
                                          if(psi->Tag==SymTagUDT)
                                          {
                                                      for(i = 0; i < dwChildrenCount; i++)
                                                      {
                                                                WCHAR *pwszTypeName = NULL;
                                                                if(SymGetTypeInfo(GetCurrentProcess(), psi->ModBase, pChildren->ChildId, TI_GET_SYMNAME, &pwszTypeName))
                                                                {
                                                                        if(!wcscmp(pwszTypeName, (const wchar_t*)(pInfo->MemberName)))
                                                                        {
                                                                              DWORD dwMemberOffset;
                                                                              if(SymGetTypeInfo(GetCurrentProcess(), psi->ModBase, pChildren->ChildId, TI_GET_OFFSET, &dwMemberOffset))
                                                                              {
                                                                                        pInfo->offset = dwMemberOffset;
                                                                              }
                                                                        }
                                                                        LocalFree(pwszTypeName);
                                                                        if(pInfo->offset)
                                                                        {
                                                                              break;
                                                                        }
                                                                }
                                                      }
                                                }
                                        }
                                        free(pChildren);
                                        if(pInfo->offset)
                                        {
                                                return FALSE;
                                        }
                              }
                        }
                }
      }
      return TRUE;
}

ULONG SymbolGetStructureOffset(PVOID DriverBase, PCHAR StructureName, PWCHAR MemberName)
{
      SYMBOL_GET_STRUCT_OFFSET info = {0};
      strcpy(info.StructureName, StructureName);
      wcscpy(info.MemberName, MemberName);
      SymEnumTypes(GetCurrentProcess(),(ULONG64)DriverBase,(PSYM_ENUMERATESYMBOLS_CALLBACK)EnumSymbolStructureRoutine,&info);
      return info.offset;
}

void main()
{
      if(SymInitialize(GetCurrentProcess(), "srv*c:\\symbols*http://msdl.microsoft.com/download/symbols", 0))
      {
                PVOID fmbase = GetDriverBaseA("fltmgr.sys");printf("base: 0x%p\r\n",fmbase);
                if(fmbase)
                {
                        DWORD64 base = SymLoadModule64(GetCurrentProcess(), 0, "c:\\windows\\system32\\drivers\\fltmgr.sys", 0, (DWORD64)fmbase, 0);
                        if(base)
                        {
                              ULONG offset = SymbolGetStructureOffset(fmbase,"_FLT_FILTER",L"Operations");
                              printf("_FLT_FILTER->Operations: 0x%x\r\n",offset);
                        }
                }
      }
      SymCleanup(GetCurrentProcess());system("pause");
}





页: [1]
查看完整版本: 使用符号获取结构体成员的偏移