使用符号获取结构体成员的偏移
由于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]