1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
| #include<stdio.h> #include<windows.h>
//计算数据目录表起始位置到文件头的偏移 DWORD RvaToOffset(DWORD dwRva, char* buffer); //解析导入表函数 void ImportTable(char* buffer); //解析导出表函数 void ExportTable(char* buffer); //解析重定位表函数 void RelocTable(char* buffer); //解析TLS表的函数 void TLSTable(char* buffer);
int main() { int m; FILE* pFile = NULL; char* buffer; int nFileLength = 0; char name[100]; printf("写入文件名:\n"); gets(name); fopen_s(&pFile,name, "rb"); fseek(pFile, 0, SEEK_END); nFileLength = ftell(pFile); rewind(pFile); int imageLength = nFileLength * sizeof(char) + 1; buffer = (char*)malloc(imageLength); memset(buffer, 0, nFileLength * sizeof(char) + 1); fread(buffer, 1, imageLength, pFile);
//打印DOS-Header PIMAGE_DOS_HEADER ReadDosHeader; ReadDosHeader = (PIMAGE_DOS_HEADER)buffer; printf("MS-DOS Info:\n"); printf("MZ标志位:%X\n", ReadDosHeader->e_magic); printf("PE头偏移量:%X\n", ReadDosHeader->e_lfanew); printf("----------------------------------------------------\n"); //PE-Header printf("NT Header Info:\n"); PIMAGE_NT_HEADERS ReadNTHeaders; ReadNTHeaders = (PIMAGE_NT_HEADERS)(buffer + ReadDosHeader->e_lfanew); printf("Signature:%X\n", ReadNTHeaders->Signature); printf("\n"); printf("Machine:%X\n", ReadNTHeaders->FileHeader.Machine); printf("NumberOfSections:%X\n", ReadNTHeaders->FileHeader.NumberOfSections); printf("SizeOfOptionalHeader:%X\n", ReadNTHeaders->FileHeader.SizeOfOptionalHeader); printf("Characteristics:%X\n", ReadNTHeaders->FileHeader.Characteristics); printf("\n"); printf("Magic:%X\n", ReadNTHeaders->OptionalHeader.Magic); printf("AddressOfEntryPoint:%X\n", ReadNTHeaders->OptionalHeader.AddressOfEntryPoint); printf("ImageBase:%X\n", ReadNTHeaders->OptionalHeader.ImageBase); printf("SectionAlignment:%X\n", ReadNTHeaders->OptionalHeader.SectionAlignment); printf("FileAlignment:%X\n", ReadNTHeaders->OptionalHeader.FileAlignment); printf("SizeOfImage:%X\n", ReadNTHeaders->OptionalHeader.SizeOfImage); printf("SizeOfHeader:%X\n", ReadNTHeaders->OptionalHeader.SizeOfHeaders); printf("Subsystem:%X\n", ReadNTHeaders->OptionalHeader.Subsystem); printf("NumberOfRvaAndSizes:%X\n", ReadNTHeaders->OptionalHeader.NumberOfRvaAndSizes); printf("Export表的地址:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[0].VirtualAddress); printf("Export的Size:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[0].Size); printf("Import的地址:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[1].VirtualAddress); printf("Import的Size:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[1].Size); printf("Resource的地址:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[2].VirtualAddress); printf("Resource的Size:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[2].Size); printf("Reloc表的地址:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[5].VirtualAddress); printf("Reloc的Size:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[5].Size); printf("TLS表的地址:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[9].VirtualAddress); printf("TLS的Size:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[9].Size); printf("----------------------------------------------------\n"); printf("Section Header Info:\n"); PIMAGE_SECTION_HEADER ReadSectionHeader = IMAGE_FIRST_SECTION(ReadNTHeaders); PIMAGE_FILE_HEADER pFileHeader = &ReadNTHeaders->FileHeader; for (int i = 0; i < pFileHeader->NumberOfSections; i++) { printf("Name(区段名称):%s\n", ReadSectionHeader[i].Name); printf("VOffset(起始的内存地址):%08X\n", ReadSectionHeader[i].VirtualAddress); printf("VSize(区段大小):%08X\n", ReadSectionHeader[i].SizeOfRawData); printf("ROffset(文件偏移):%08X\n", ReadSectionHeader[i].PointerToRawData); printf("RSize(文件中区段大小):%08X\n", ReadSectionHeader[i].Misc.VirtualSize); printf("Characteristics(区段属性):%08X\n", ReadSectionHeader[i].Characteristics); printf("-----------------------------------------------------\n"); } printf("=====================================================================\n"); printf("查看导入表输入1,查看导出表输入2,查看重定位表输入3,查看TLs表输入4.退出请按5:\n"); while(1) { scanf_s("%d", &m); if (m == 1) ImportTable(buffer); else if (m == 2) ExportTable(buffer); else if (m == 3) RelocTable(buffer); else if(m == 4) TLSTable(buffer); else { break; } } system("pause"); free(buffer); return 0; }
//dwRva是某个数据目录表的VirtualAddress //buffer是读取到的pe文件缓冲区 DWORD RvaToOffset(DWORD dwRva, char* buffer) { //Dos头 PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer; //PE头 PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + buffer); //区段表 PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNt); //判断是否落在头部当中 if (dwRva < pSection[0].VirtualAddress) { return dwRva; } for (int i = 0; i < pNt->FileHeader.NumberOfSections; i++) { if (dwRva >= pSection[i].VirtualAddress && dwRva <= pSection[i].VirtualAddress + pSection[i].Misc.VirtualSize) { //dwRva-pSection[i].VirtualAddress是数据目录表到区段起始地址的偏移(OFFSET) // pSection[i].PointerToRawData区段到文件头的偏移(OFFSET) return dwRva - pSection[i].VirtualAddress + pSection[i].PointerToRawData; } } } void ImportTable(char* buffer) { //Dos PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer; //PE头 PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + buffer); //定位导入表 PIMAGE_DATA_DIRECTORY pImportDir = (PIMAGE_DATA_DIRECTORY)(pNt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT); //填充结构 PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)(RvaToOffset(pImportDir->VirtualAddress, buffer) + buffer); while (pImport->Name != NULL) { char* szDllName = (char*)(RvaToOffset(pImport->Name, buffer) + buffer); printf("Dll名称:%s\n", szDllName); printf("日期时间标志:%08X\n", pImport->TimeDateStamp); printf("ForwarderChain:%08X\n", pImport->ForwarderChain); printf("名称OFFSET(库名称字符串地址):%08X\n", pImport->Name); printf("FirstThunk(IAT的地址):%08X\n", pImport->FirstThunk); printf("OriginalFirstThunk(INT的地址):%08X\n", pImport->OriginalFirstThunk); PIMAGE_THUNK_DATA pIat = (PIMAGE_THUNK_DATA)(RvaToOffset(pImport->OriginalFirstThunk, buffer) + buffer); DWORD index = 0; DWORD ImprotOffset = 0; printf("\n"); while (pIat->u1.Ordinal != 0) { printf("ThunkRva:%08X\n", pImport->OriginalFirstThunk + index); ImprotOffset = RvaToOffset(pImport->OriginalFirstThunk, buffer); printf("ThunkOffset:%08X\n", ImprotOffset + index); index += 4; if ((pIat->u1.Ordinal & 0x80000000) != 1) { PIMAGE_IMPORT_BY_NAME pName = (PIMAGE_IMPORT_BY_NAME)(RvaToOffset(pIat->u1.AddressOfData,buffer)+buffer); printf("API名称:%s ", pName->Name); printf("Hint:%04X ", pName->Hint); printf("ThunkValue:%08X\n", pIat->u1.Function); } printf("------------------------------------\n"); pIat++; } printf("-----------------------------------------------------\n"); pImport++; } }
void ExportTable(char* buffer) { //Dos头 PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer; //PE PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + buffer); //定位数据目录表中的导出表 PIMAGE_DATA_DIRECTORY pExportDir = pNt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_EXPORT; //填充导出表结构 PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)(RvaToOffset(pExportDir->VirtualAddress, buffer) + buffer); char* szName = (char*)(RvaToOffset(pExport->Name, buffer) + buffer); if (pExport->AddressOfFunctions == 0) { printf("当前没有导出表!\n"); return; } printf("导出表OFFSET:%08X\n", RvaToOffset(pExportDir->VirtualAddress, buffer)); printf("特征值:%08X\n", pExport->Characteristics); printf("基:%08X", pExport->Base); printf("名称OFFSET:%08X", pExport->Name); printf("名称:%s\n", szName); printf("函数数量:%08X\n", pExport->NumberOfFunctions); printf("函数名数量:%08X\n", pExport->NumberOfNames); printf("函数地址:%08X\n", pExport->AddressOfFunctions); printf("函数名地址:%08X\n", pExport->AddressOfNames); printf("函数名称序号地址:%08X\n", pExport->AddressOfNameOrdinals); printf("\n"); //获取函数数量 DWORD dwNumOfFUN = pExport->NumberOfFunctions; //函数名数量 DWORD dwNumOfNames = pExport->NumberOfNames; //基 DWORD dwBase = pExport->Base; //导出地址表 PDWORD pEat32 = (PDWORD)(RvaToOffset(pExport->AddressOfFunctions, buffer) + buffer); //导出名称表 PDWORD pEnt32 = (PDWORD)(RvaToOffset(pExport->AddressOfNames, buffer) + buffer); //导出序号表 PWORD pId = (PWORD)(RvaToOffset(pExport->AddressOfNameOrdinals, buffer) + buffer); for (int i = 0; i < dwNumOfFUN; i++) { if (pEat32[i] == 0) continue; DWORD Id = 0; for (; Id < dwNumOfNames; Id++) { if (pId[Id] == i) break; } if (Id == dwNumOfNames) { printf("Id:%X Address:0x%08X Name[NuLL]\n", i + dwBase, pEat32[i]); } else { char* szFunName = (char*)(RvaToOffset(pEnt32[Id], buffer) + buffer); printf("Id:%X Address:0x%08X Name[%s]\n", i + dwBase, pEat32[i],szFunName); } printf("-------------------------------------\n"); } printf("----------------------------------------------------------\n"); }
void RelocTable(char* buffer) { typedef struct _TYPE { WORD Offset : 12; WORD Type : 4; }TYPE, *PTYPE; //Dos PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer; //PE PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + buffer); //定位重定位表 PIMAGE_DATA_DIRECTORY pRelocDir = (pNt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_BASERELOC); //填充重定位表的结构 PIMAGE_BASE_RELOCATION pReloc = (PIMAGE_BASE_RELOCATION)(RvaToOffset(pRelocDir->VirtualAddress, buffer) + buffer); //定位区段 PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNt); while (pReloc->SizeOfBlock != 0) { //找到本0x1000个字节的起始位置 DWORD dwCount = (pReloc->SizeOfBlock - 8) / 2; DWORD dwRva = pReloc->VirtualAddress; PTYPE pRelocArr = (PTYPE)(pReloc + 1); printf("区段;%s\n", pSection->Name); printf("RVA:%08X\n", dwRva); printf("项目:%X H /%d D\n", pReloc->SizeOfBlock, pReloc->SizeOfBlock); //找到下一个0x1000字节的结构体 pReloc = (PIMAGE_BASE_RELOCATION)((char*)pReloc + pReloc->SizeOfBlock); for (int i = 0; i < dwCount; i++) { PDWORD pData = (PDWORD)(RvaToOffset(pRelocArr[i].Offset + dwRva, buffer) + buffer); DWORD pDataOffset = RvaToOffset(pRelocArr[i].Offset + dwRva, buffer); printf("RVA:%08X ", pRelocArr[i].Offset + dwRva); printf("区段:%08X ", *pData); printf("偏移:%08X\n ", pDataOffset); printf("------------------------------------\n"); } printf("\n"); } printf("-------------------------------------------------------------------\n"); }
void TLSTable(char* buffer) { //Dos PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer; //PE PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + buffer); //定位数据目录表中的TLS表 PIMAGE_DATA_DIRECTORY pTLSDir = (pNt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_TLS); //填充TLS结构 PIMAGE_TLS_DIRECTORY pTLS = (PIMAGE_TLS_DIRECTORY)(RvaToOffset(pTLSDir->VirtualAddress, buffer) + buffer); printf("数据块开始VA:%08X\n",pTLS->StartAddressOfRawData); printf("数据块结束VA:%08X\n",pTLS->EndAddressOfRawData); printf("索引变量VA:%08X\n",pTLS->AddressOfIndex); printf("回调表VA:%08X\n",pTLS->AddressOfCallBacks); printf("填零大小VA:%08X\n",pTLS->SizeOfZeroFill); printf("特征值VA:%08X\n",pTLS->Characteristics); printf("------------------------------\n"); }
|