RVA->FOA
已知内存地址adress
1、如果RVA属于头(DOS+NT)那么不需要进行计算了.因为头在文件中根内存中都是一样展开的.直接从开始位置寻找到RVA个字节即可。
2、如果不在头,就要判断在那个节里面. 判断节开始位置.跟结束位置. 我们的RVA在这个值里面.
adress-ImageBase-VirtualAddress=该内存地址在该节的相对偏移值
FOA=该内存地址在该节的相对偏移值+PointerTORawDATA
FOA->RVA
FOA-PointerTORawDATA=该文件地址在该节的相对偏移
RVA=该文件地址在该节的相对偏移+VirtualAdress
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<malloc.h>
DWORD address = 0x1009086;
void* readfile() {
FILE* filebuffer = NULL;
filebuffer = fopen("C:\\Users\\42435\\Desktop\\notepad.exe", "rb");
if (!filebuffer) {
printf("打开动态内存失败");
}
int num = 0;
fseek(filebuffer, 0, SEEK_END);
num = ftell(filebuffer);
fseek(filebuffer, 0, SEEK_SET);
LPVOID fp = NULL;
fp =malloc(num);
if (!fp) {
printf("申请动态内存失败");
}
memset(fp, 0, num);
size_t n=fread(fp, num, 1, filebuffer);
if (!n) {
printf("数据读取到内存失败\n");
}
fclose(filebuffer);
return fp;
}
int PE() {
void* fp = readfile();
PIMAGE_DOS_HEADER dosheader = NULL;
PIMAGE_NT_HEADERS NTheader = NULL;
PIMAGE_FILE_HEADER PEheader = NULL;
PIMAGE_OPTIONAL_HEADER opheader = NULL;
PIMAGE_SECTION_HEADER secheader = NULL;
dosheader = PIMAGE_DOS_HEADER(fp);
if (*((PWORD)fp) != IMAGE_DOS_SIGNATURE)
{
printf("不含MZ标志,不是exe文件!\n");
return 0;
}
NTheader = (PIMAGE_NT_HEADERS)((DWORD)fp + dosheader->e_lfanew);
PEheader = (PIMAGE_FILE_HEADER)((DWORD)NTheader + 4); // 这里必须强制类型转换
opheader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)PEheader + IMAGE_SIZEOF_FILE_HEADER);
secheader = (PIMAGE_SECTION_HEADER)((DWORD)opheader + PEheader->SizeOfOptionalHeader);
int RVA =address-opheader->ImageBase;
printf("%x\n", RVA);
int FOA = 0;
PIMAGE_SECTION_HEADER tempsecheader = secheader;
for (int i = 0; i < PEheader->NumberOfSections; i++,tempsecheader++) {
if((RVA>tempsecheader->VirtualAddress)&&(RVA<tempsecheader->VirtualAddress+tempsecheader->Misc.VirtualSize))
{
FOA = RVA - tempsecheader->VirtualAddress + tempsecheader->PointerToRawData;
break;
}
}
return FOA;
}
int main() {
int FOA = PE();
printf("%x", FOA);
return 0;
}