假设我有一些代码
_declspec(noinline) void foo() {
printf("...");
}
而且我已经像这样将可执行文件映射到内存中
#include <Windows.h>
#include <stdio.h>
_declspec(noinline) void foo() {
printf("...");
}
int main(int argc, char* argv[]) {
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)GetModuleHandle(NULL);
IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)((UCHAR*)dos + dos->e_lfanew);
return 0;
}
如何将 &foo 转换为可执行文件中的偏移量?这甚至可能吗?
编辑:我尝试了@moonshadow 的解决方案,但函数的地址总是在 .text 部分之外,如下所示
#include <Windows.h>
#include <stdio.h>
IMAGE_SECTION_HEADER* getSection(const IMAGE_NT_HEADERS* nt_headers, unsigned section) {
return reinterpret_cast<IMAGE_SECTION_HEADER*>(
(UCHAR*)nt_headers->OptionalHeader.DataDirectory +
nt_headers->OptionalHeader.NumberOfRvaAndSizes*sizeof(IMAGE_DATA_DIRECTORY) +
section*sizeof(IMAGE_SECTION_HEADER)
);
}
_declspec(noinline) void foo() {
printf("...");
}
int main(int argc, char* argv[]) {
HANDLE hFile = CreateFileA(argv[0], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE hFileMapObj = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
UCHAR* content = static_cast<UCHAR*>(MapViewOfFile(hFileMapObj, FILE_MAP_READ, 0, 0, 0));
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)content;
IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)((UCHAR*)dos + dos->e_lfanew);
for(int i = 0; i < nt->FileHeader.NumberOfSections; i++) {
auto sec = getSection(nt, i);
printf("%s\n", sec->Name);
DWORD va = sec->VirtualAddress + nt->OptionalHeader.ImageBase;
printf("0x%x - 0x%x\n\n", va, va + sec->SizeOfRawData);
}
auto text = getSection(nt, 0);
printf("%s\n0x%x\n", text->Name, (DWORD)foo);
foo();
return 0;
}
知道这里出了什么问题吗?