将映像的偏移地址转换为文件的偏移地址
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 6 typedef unsigned char BYTE; 7 typedef unsigned short WORD; 8 typedef unsigned int DWORD; 9 10 #define IMAGE_SIZEOF_SHORT_NAME 8 11 typedef struct _Section_Header 12 { 13 BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; 14 union 15 { 16 DWORD Physical_Address; 17 DWORD Virtual_Size; 18 }Misc; 19 DWORD Virtual_Address; 20 DWORD SizeOfRawData; 21 DWORD PointerToRawData; 22 DWORD PointerToRelocations; 23 DWORD PointerToLinenumbers; 24 WORD NumberOfRelocations; 25 WORD NumberOfLinenumbers; 26 DWORD Characteristics; 27 28 }Section_Header; 29 30 typedef struct _PE_Information 31 { 32 DWORD Dos_Header_e_lfanew; 33 WORD File_Header_NumberOfSections; 34 WORD File_Header_SizeOfOptionHeader; 35 DWORD Option_Header_SectionAlignment; 36 DWORD Option_Header_FileAlignment; 37 DWORD Option_Header_SizeOfImage; 38 DWORD Option_Header_SizeOfHeaders; 39 DWORD File_Header_Offset; 40 DWORD Optional_Header_Offset; 41 DWORD Section_Header_Offset; 42 Section_Header* PSection = (Section_Header*)malloc(sizeof(Section_Header) * File_Header_NumberOfSections); 43 44 }PE_Information; 45 46 typedef struct _Rva_And_Raw 47 { 48 DWORD Raw; 49 DWORD Rva; 50 }Rva_And_Raw; 51 52 //读取文件长度 53 int File_Lenth(FILE* p) 54 { 55 fseek(p, 0, SEEK_END); 56 int len = ftell(p); 57 fseek(p, 0, SEEK_SET); 58 return len; 59 } 60 61 //生成文件缓冲区 62 char* File_Read(const char* p, int& length) 63 { 64 //文件指针 65 FILE* pf = fopen(p, "rb"); 66 67 //获得文件长度 68 length = File_Lenth(pf); 69 70 //分配FileBuffer的空间 71 char* pt = (char*)malloc(sizeof(char) * length); 72 73 //读入到空间中 74 fread(pt, length, 1, pf); 75 76 fclose(pf); 77 return pt; 78 } 79 80 //读取PE_Header的数据 81 void Get_PE_Information(PE_Information* PE,char* pt) 82 { 83 memcpy(&PE->Dos_Header_e_lfanew, pt + 0x3C, 4); 84 85 PE->File_Header_Offset = PE->Dos_Header_e_lfanew + 4; 86 87 memcpy(&PE->File_Header_NumberOfSections, pt + PE->File_Header_Offset + 2, 2); 88 89 memcpy(&PE->File_Header_SizeOfOptionHeader, pt + PE->File_Header_Offset + 0x10, 2); 90 91 PE->Optional_Header_Offset = PE->File_Header_Offset + 0x14; 92 93 PE->Section_Header_Offset = PE->Optional_Header_Offset + PE->File_Header_SizeOfOptionHeader; 94 95 memcpy(&PE->Option_Header_FileAlignment, pt + PE->Optional_Header_Offset + 0x24, 4); 96 97 memcpy(&PE->Option_Header_SectionAlignment, pt + PE->Optional_Header_Offset + 0x20, 4); 98 99 memcpy(&PE->Option_Header_SizeOfHeaders, pt + PE->Optional_Header_Offset + 0x3c, 4); 100 101 memcpy(&PE->Option_Header_SizeOfImage, pt + PE->Optional_Header_Offset + 0x38, 4); 102 103 memcpy(PE->PSection, pt + PE->Section_Header_Offset, sizeof(Section_Header) * PE->File_Header_NumberOfSections); 104 } 105 106 //创建ImageBuffer 107 char* Image_Read(char* pt,PE_Information PE) 108 { 109 //申请ImageBuffer的空间 110 char* pi = (char*)malloc(PE.Option_Header_SizeOfImage); 111 112 //填充0 113 memset(pi, 0, PE.Option_Header_SizeOfImage); 114 115 //复制头 116 memcpy(pi, pt, PE.Option_Header_SizeOfHeaders); 117 118 //复制节区 119 for (int i = 0; i < PE.File_Header_NumberOfSections; i++) 120 { 121 memcpy(pi + PE.PSection[i].Virtual_Address, pt + PE.PSection[i].PointerToRawData, PE.PSection[i].SizeOfRawData); 122 } 123 124 return pi; 125 } 126 127 void Rva_To_Raw(Rva_And_Raw* R,PE_Information PE) 128 { 129 int Pos;//在第几个节区 130 131 for (int i = 0; i < PE.File_Header_NumberOfSections; i++) 132 { 133 if (R->Rva >= PE.PSection[i].Virtual_Address && R->Rva <= PE.PSection[i].Virtual_Address + PE.PSection[i].SizeOfRawData) 134 Pos = i; 135 } 136 137 int offset = R->Rva - PE.PSection[Pos].Virtual_Address; 138 //rva相对于virtualaddress的偏移 139 140 R->Raw = PE.PSection[Pos].PointerToRawData + offset; 141 142 } 143 144 int main() 145 { 146 int length; 147 148 char* pt = File_Read("C:/Windows/System32/notepad.exe", length); 149 PE_Information PE; 150 151 Get_PE_Information(&PE, pt); 152 153 char* pi = Image_Read(pt, PE); 154 155 Rva_And_Raw R; 156 157 R.Rva = 0x1001; 158 159 Rva_To_Raw(&R,PE); 160 161 printf("Raw:%X\n", R.Raw); 162 163 return 0; 164 165 }
主要步骤是:
1.映像中地址,减去首地址,获得映像中的偏移RVA
2.与VirtualAddress和VirtualAddress+SizeOfRawData进行比较,确定地址所在的节区
3.将RVA和VirtualAddress相减,得到节区内的偏移大小
4.在文件中找到对应的节区,PointerToRawData+节区内的偏移就是RAW的值了
原文:https://www.cnblogs.com/yanmo/p/14526129.html