_get_next_member_name怎么实现
时间: 2023-08-02 10:10:54 浏览: 55
`_get_next_member_name` 函数的实现需要用到一些Windows API,具体来说是 `ImageNtHeader`、`ImageDirectoryEntryToData`、`ImageRvaToVa` 等函数。以下是一个简单的实现示例代码:
```c++
#include <Windows.h>
#include <DbgHelp.h>
const char* _get_next_member_name(const char* className, size_t* offset) {
const char* memberName = nullptr;
IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)GetModuleHandle(nullptr);
IMAGE_NT_HEADERS* pNTHeader = (IMAGE_NT_HEADERS*)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew);
IMAGE_SECTION_HEADER* pSectionHeader = IMAGE_FIRST_SECTION(pNTHeader);
for (int i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++) {
if (strcmp((char*)pSectionHeader->Name, ".rdata") == 0) {
DWORD_PTR rdataBase = (DWORD_PTR)GetModuleHandle(nullptr) + pSectionHeader->VirtualAddress;
DWORD_PTR rdataEnd = rdataBase + pSectionHeader->Misc.VirtualSize;
PIMAGE_SECTION_HEADER pRdataHeader = pSectionHeader;
PIMAGE_SECTION_HEADER pRsrcHeader = pSectionHeader + 1;
DWORD_PTR rsrcBase = (DWORD_PTR)GetModuleHandle(nullptr) + pRsrcHeader->VirtualAddress;
DWORD_PTR rsrcEnd = rsrcBase + pRsrcHeader->Misc.VirtualSize;
IMAGE_RESOURCE_DIRECTORY* pRootDirectory = (IMAGE_RESOURCE_DIRECTORY*)rsrcBase;
IMAGE_RESOURCE_DIRECTORY_ENTRY* pRootEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(pRootDirectory + 1);
int typeOffset = 0x0;
IMAGE_RESOURCE_DIRECTORY* pTypeDirectory = nullptr;
IMAGE_RESOURCE_DIRECTORY_ENTRY* pTypeEntry = nullptr;
IMAGE_RESOURCE_DIRECTORY* pNameDirectory = nullptr;
IMAGE_RESOURCE_DIRECTORY_ENTRY* pNameEntry = nullptr;
IMAGE_RESOURCE_DIRECTORY* pLanguageDirectory = nullptr;
IMAGE_RESOURCE_DIRECTORY_ENTRY* pLanguageEntry = nullptr;
for (int rootIndex = 0; rootIndex < pRootDirectory->NumberOfIdEntries + pRootDirectory->NumberOfNamedEntries; rootIndex++) {
if (pRootEntry[rootIndex].NameIsString) {
IMAGE_RESOURCE_DIR_STRING_U* pName = (IMAGE_RESOURCE_DIR_STRING_U*)(rsrcBase + pRootEntry[rootIndex].NameOffset);
if (wcsncmp(pName->NameString, L"TYPEINFO", pName->Length) == 0) {
typeOffset = pRootEntry[rootIndex].OffsetToDirectory;
break;
}
}
}
if (typeOffset > 0) {
pTypeDirectory = (IMAGE_RESOURCE_DIRECTORY*)(rsrcBase + typeOffset);
pTypeEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(pTypeDirectory + 1);
for (int typeIndex = 0; typeIndex < pTypeDirectory->NumberOfIdEntries + pTypeDirectory->NumberOfNamedEntries; typeIndex++) {
if (!pTypeEntry[typeIndex].NameIsString) {
if (pTypeEntry[typeIndex].Id == 0x7) {
pNameDirectory = (IMAGE_RESOURCE_DIRECTORY*)(rsrcBase + pTypeEntry[typeIndex].OffsetToDirectory);
pNameEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(pNameDirectory + 1);
for (int nameIndex = 0; nameIndex < pNameDirectory->NumberOfIdEntries + pNameDirectory->NumberOfNamedEntries; nameIndex++) {
if (pNameEntry[nameIndex].NameIsString) {
IMAGE_RESOURCE_DIR_STRING_U* pName = (IMAGE_RESOURCE_DIR_STRING_U*)(rsrcBase + pNameEntry[nameIndex].NameOffset);
if (strcmp((char*)pName->NameString, className) == 0) {
pLanguageDirectory = (IMAGE_RESOURCE_DIRECTORY*)(rsrcBase + pNameEntry[nameIndex].OffsetToDirectory);
pLanguageEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(pLanguageDirectory + 1);
for (int languageIndex = 0; languageIndex < pLanguageDirectory->NumberOfIdEntries + pLanguageDirectory->NumberOfNamedEntries; languageIndex++) {
if (!pLanguageEntry[languageIndex].NameIsString) {
DWORD_PTR symbolAddress = (DWORD_PTR)ImageDirectoryEntryToData(GetModuleHandle(nullptr), TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT);
PIMAGE_EXPORT_DIRECTORY pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)symbolAddress;
DWORD_PTR* pFuncAddress = (DWORD_PTR*)(symbolAddress + (DWORD_PTR)pExportDirectory->AddressOfFunctions);
DWORD_PTR* pNameAddress = (DWORD_PTR*)(symbolAddress + (DWORD_PTR)pExportDirectory->AddressOfNames);
WORD* pOrdinalAddress = (WORD*)(symbolAddress + (DWORD_PTR)pExportDirectory->AddressOfNameOrdinals);
DWORD_PTR classVTableAddress = 0;
for (int i = 0; i < pExportDirectory->NumberOfFunctions; i++) {
if (strcmp((char*)(symbolAddress + pNameAddress[i]), className) == 0) {
classVTableAddress = (DWORD_PTR)pFuncAddress[pOrdinalAddress[i]];
break;
}
}
if (classVTableAddress > 0) {
DWORD_PTR* pVTable = (DWORD_PTR*)*(DWORD_PTR*)classVTableAddress;
int memberIndex = 0;
while (true) {
DWORD_PTR* pMemberAddress = (DWORD_PTR*)(pVTable[memberIndex]);
if (*pMemberAddress == 0) {
break;
}
if (*pMemberAddress >= rdataBase && *pMemberAddress < rdataEnd) {
DWORD_PTR memberOffset = *pMemberAddress - rdataBase;
if (memberOffset == *offset) {
memberName = (const char*)(pMemberAddress + 1);
*offset += sizeof(DWORD_PTR);
break;
}
}
memberIndex++;
}
}
}
if (memberName != nullptr) {
break;
}
pLanguageEntry++;
}
}
}
if (memberName != nullptr) {
break;
}
pNameEntry++;
}
}
}
if (memberName != nullptr) {
break;
}
pTypeEntry++;
}
}
break;
}
pSectionHeader++;
}
return memberName;
}
```
需要注意的是,由于这个函数的实现依赖于一些Windows API,因此在使用前需要先添加相关的头文件和库文件,并且在调用该函数时需要保证程序已经加载了相关的模块。