逆向笔记——PE文件相对虚拟地址(RVA)转文件偏移地址(FOA)
生活随笔
收集整理的這篇文章主要介紹了
逆向笔记——PE文件相对虚拟地址(RVA)转文件偏移地址(FOA)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
手工
編譯一個帶有全局變量的exe
這是代碼
#include <stdio.h>
int globalVar = 0x12345678;
void main()
{
printf("globalVar = %x, RVA=%x
",globalVar,&globalVar); //RVA=424a30 | FOA=424a30-400000=24a30
}
打印出來的是全局變量globalVar 在內存中的地址 VA=424a30
PETool看基址=00400000,RVA=VA-ImageBase=424a30-00400000 = 24a30
再看看在內存中、文件中的對齊方式
1、如果在內存中和文件中的對齊方式是一致的,那么 RVA=FOA=24a30
2、如果它們的對齊方式不一樣,那么 FOA = 節.PointToRawData+差值偏差
差值偏差=RVA - 節.VirtuallAddress,如果想不通,看下圖:
我這里的對齊方式是一樣的,所以FOA=24a30
PE編輯工具打開exe文件,找24a30地址的值,改之為 66666666
保存,運行exe看這時候的值
代碼實現 RVA->FVA
步驟:
代碼:
#include <stdio.h>
#include <windows.h>
/************************
功能:內存中的相對虛擬偏移轉換為文件中的偏移
步驟:假設x是需要計算FOA的內存地址
1、先計算 RVA = x-ImageBase
2、計算差值偏差 y = RVA-節.VirtualAddress
3、計算FOA=節.PointToRawData+y
*************************/
unsigned char* FileBuffer(const char* FileName);
unsigned char* RVAToFVA(unsigned char* x) //x的位置
{
unsigned char* FVA=NULL;
unsigned char* RVA=NULL;
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNtHeaders;
PIMAGE_SECTION_HEADER pSectionHeader;
//打開文件映射到filebuffer
unsigned char* fileBuffer = FileBuffer("test.exe");
//得到 PIMAGE_OPTIONAL_HEADER=>ImageBase PIMAGE_SECTION_HEADER=>VirtualAddress PointToRawData
pDosHeader = (PIMAGE_DOS_HEADER)fileBuffer;
pNtHeaders = (PIMAGE_NT_HEADERS)(fileBuffer + pDosHeader->e_lfanew);
pSectionHeader = (PIMAGE_SECTION_HEADER)(pNtHeaders+1);
printf("%x
",pNtHeaders->OptionalHeader.ImageBase);
RVA = x-pNtHeaders->OptionalHeader.ImageBase;
//判斷是否在DOS+NT頭部內,是則RVA=FOA
if(x<=(unsigned char*)pNtHeaders->OptionalHeader.SizeOfHeaders)
{
FVA = RVA;
printf("在頭部FVA=RVA=%x
",FVA);
return FVA;
}
//判斷在哪個節
unsigned int i=0;
for(i=0;i<pNtHeaders->FileHeader.NumberOfSections;i++)
{
printf("%x
",pSectionHeader[i].PointerToRawData);
printf("%x
",pSectionHeader[i].VirtualAddress);
if(RVA>=(unsigned char*)pSectionHeader[i].VirtualAddress && RVA<=(unsigned char*)(pSectionHeader[i].VirtualAddress+pSectionHeader[i].Misc.VirtualSize) )
{
//在這個節:計算偏差->計算FOA
FVA = pSectionHeader[i].PointerToRawData+(RVA-pSectionHeader[i].VirtualAddress);
printf("在%s節中,FVA=%x
", pSectionHeader[i].Name,FVA);
return FVA;
}
}
return NULL;
}
void main()
{
unsigned char* x = (unsigned char*)0x424a30;
RVAToFVA(x); //內存中的虛擬地址
}
//將PE文件讀到FileBuffer
unsigned char* FileBuffer(const char* FileName)
{
unsigned char* Heap = NULL;
FILE* Stream;
//打開文件
Stream = fopen(FileName,"rb");
//計算文件大小
fseek(Stream,0,SEEK_END);
long FileSize = ftell(Stream);
fseek(Stream,0,SEEK_SET);
//分配堆空間
Heap = (unsigned char*)malloc(sizeof(char)*FileSize);
//將文件拷到堆
fread(Heap,sizeof(char),FileSize,Stream);
fclose(Stream);
return Heap;
}
FVA->RVA 原理同上
設x 為節數據的任意一位置
1.計算差值偏移:
差值 = x - 節.PointerToRawData(節數據在文件中開始的位置)
2.計算RVA
RVA = 差值 + 節.VirtuallAddress(節數據在內存中展開的位置)
3.計算虛擬地址:
VA = RVA + ImageBase
判斷x在哪一個節中的條件: x <= 節.PointerToRawData + 節.SizeofRawData
總結
以上是生活随笔為你收集整理的逆向笔记——PE文件相对虚拟地址(RVA)转文件偏移地址(FOA)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么借钱要上央行征信?
- 下一篇: Spark --jars 依赖包的优先级