在这一章中我们给出RVA转FOA程序的源代码:
代码我们就不一一解释了,自己看懂或者是自己编写出来会有更深的理解
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "Function.h"
int main(int argc, char** argv) {
char* File_Buffer;
char* Image_Buffer;
//打开文件
File_Buffer=openfile();
//将File_Buffer转为Image_Buffer
Image_Buffer=FileBufferToImageBuffer(File_Buffer);
//RVA转FOA
char* foa=NULL;
char* address=NULL;
printf("请输入需要转换的地址:");
scanf("%d",address);
foa=RVATOFOA(File_Buffer,Image_Buffer,address);
return 0;
}
在这里给出函数说明文件Function.h:
//打开文件函数
//该函数完成将内存数据复制到File_Buffer
char* openfile(){
FILE *fp=NULL;
char* File_Buffer=NULL;
//打开文件
if((fp=fopen("E:\\个人\\逆向\\练习.exe","rb"))==NULL){
printf("文件打开失败!\n");
}else{
printf("文件打开成功。\n");
}
//计算文件大小
fseek(fp,0,SEEK_END);
int length=ftell(fp);
fseek(fp,0,SEEK_SET);
//动态申请内存
File_Buffer=(char*)malloc(length);
if(File_Buffer==NULL){
printf("FileBuffer内存申请失败!\n");
exit(0);
}else{
printf("FileBuffer内存申请成功。\n");
}
//将文件数据读取到File_Buffer
if(fread(File_Buffer,1,length,fp)){
printf("文件读取到FileBuffer成功。\n");
}else{
printf("文件读取到FileBuffer失败!\n");
exit(0);
}
//关闭文件
if(fclose(fp)){
printf("文件关闭失败!\n");
}else{
printf("文件关闭成功。\n");
}
return File_Buffer;
}
//将File_Buffer转到Image_Buffer函数
//该函数需要一个指针,指向File_Buffer
//该函数返回一个指针,指向Image_Buffer
char* FileBufferToImageBuffer(char* File_Buffer){
char *Image_Buffer=NULL;
//定义PE头部结构
IMAGE_DOS_HEADER *pDosHeader=(IMAGE_DOS_HEADER*)File_Buffer;
IMAGE_FILE_HEADER *pFileHeader=(IMAGE_FILE_HEADER*)(File_Buffer+pDosHeader->e_lfanew+4);
IMAGE_OPTIONAL_HEADER *pOptionalHeader=(IMAGE_OPTIONAL_HEADER*)((char*)pFileHeader+20);
IMAGE_SECTION_HEADER* pSectionHeader=(IMAGE_SECTION_HEADER*)((char*)pOptionalHeader+pFileHeader->SizeOfOptionalHeader);
//动态申请Image_Buffer内存
Image_Buffer=(char*)malloc(pOptionalHeader->SizeOfImage);
if(Image_Buffer==NULL){
printf("ImageBuffer内存申请失败!\n");
}else{
printf("ImageBuffer内存申请成功。\n");
}
//初始化申请的内存
int i;
for(i=0;i<pOptionalHeader->SizeOfImage;i++){
*(Image_Buffer+i)=0;
}
//复制所有头
int j;
for(j=0;j<pOptionalHeader->SizeOfHeaders;j++){
*(Image_Buffer+j)=*(File_Buffer+j);
}
//复制所有节到Image_Buffer中
int k,x;
for(k=0;k<pFileHeader->NumberOfSections;k++){
for(x=0;x<pSectionHeader->SizeOfRawData;x++){
*(Image_Buffer+pSectionHeader->VirtualAddress+x)=*(File_Buffer+pSectionHeader->PointerToRawData+x);
}
pSectionHeader++;
}
return Image_Buffer;
}
//RVA转FOA函数
//该函数需要两个指针,一个指向File_Buffer另一个指向Image_buffer
//该函数需要一个地址,指向要寻找的数据
//若转化成功,该函数返回一个地址,表示FOA,若转化失败,则返回NULL
char* RVATOFOA(char* File_Buffer,char* Image_Buffer,char* address){
//定义PE头部结构体
IMAGE_DOS_HEADER* pDosHeader=(IMAGE_DOS_HEADER*)File_Buffer;
IMAGE_FILE_HEADER* pFileHeader=(IMAGE_FILE_HEADER*)(File_Buffer+pDosHeader->e_lfanew+0x4);
IMAGE_OPTIONAL_HEADER* pOptionalHeader=(IMAGE_OPTIONAL_HEADER*)((char*)pFileHeader+0x20);
IMAGE_SECTION_HEADER* pSectionHeader=(IMAGE_SECTION_HEADER*)((char*)pOptionalHeader+pFileHeader->SizeOfOptionalHeader);
//地址转换
int i;
for(i=0;i<pFileHeader->NumberOfSections;i++){
if(address>(pSectionHeader->VirtualAddress)&&address<(pSectionHeader->VirtualAddress+pSectionHeader->Misc.VirtualSize)){
break;
}
pSectionHeader++;
}
if(i==pFileHeader->NumberOfSections){
printf("该地址不在任何一个节中!\n");
}else{
printf("该地址在第%d个节中。\n",i-1);
}
int pianyi=0;
pianyi=address-((int)Image_Buffer+pSectionHeader->VirtualAddress);
char* ret=(File_Buffer+pianyi);
return ret;
}
代码中有许多可以优化的地方或者是可能有不对的地方,希望大家及时指出,我会非常虚心地学习,希望我们共同进步!