PE逆向-打印导入表

admin 2023年9月25日21:05:42评论43 views字数 5905阅读19分41秒阅读模式

PE逆向-打印导入表

// 滴水三期3.27导入表.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//
#include <iostream>#include <Windows.h>#include <cstring>#include <iomanip>
using namespace std;
//向上取值函数size_t AlignUp(size_t value, size_t alignment) { return (value + alignment - 1) & ~(alignment - 1);}//得到PE文件大小long GetSize(char* fileName) { FILE* file = NULL; errno_t err = fopen_s(&file, fileName, "rb"); if (err != 0) { cout << "文件打开失败!" << endl; fclose(file); return 0; } long fileSize = 0; fseek(file, 0, SEEK_END); fileSize = ftell(file); fseek(file, 0, SEEK_SET); fclose(file); return fileSize;}
//RVA转FOADWORD RVA_TO_FOA(char* fileBuffer, long long RVAaddress) {
PIMAGE_DOS_HEADER fileDosHeader = (PIMAGE_DOS_HEADER)fileBuffer;
PIMAGE_NT_HEADERS fileNTHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)fileBuffer + fileDosHeader->e_lfanew); if (fileNTHeader->Signature != IMAGE_NT_SIGNATURE) { cout << "PE的NT头错误!" << endl; return 0; } PIMAGE_FILE_HEADER fileFileHeader = &(fileNTHeader->FileHeader); PIMAGE_OPTIONAL_HEADER fileOptionHeader = &(fileNTHeader->OptionalHeader); PIMAGE_SECTION_HEADER fileSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)fileOptionHeader + fileFileHeader->SizeOfOptionalHeader); int sectionNum = 0; for (int i = 0; i < fileFileHeader->NumberOfSections; i++) { if (RVAaddress >= (fileSectionHeader + i)->VirtualAddress && RVAaddress < (fileSectionHeader + i)->VirtualAddress + (fileSectionHeader + i)->Misc.VirtualSize) { sectionNum = i; break; } } long long offsetSize = RVAaddress - (fileSectionHeader + sectionNum)->VirtualAddress; DWORD fileAdderss = (DWORD)((fileSectionHeader + sectionNum)->PointerToRawData + offsetSize); //cout << hex <<"RVAaddress:"<< RVAaddress<<"转换====》" << "文件地址:" << fileAdderss << endl; return fileAdderss;
}

//FOA转RVA//这里的FOA要减去fileBufferDWORD FOA_TO_RVA(char* fileBuffer, long long FOAaddress) {
PIMAGE_DOS_HEADER fileDosHeader = (PIMAGE_DOS_HEADER)fileBuffer;
PIMAGE_NT_HEADERS fileNTHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)fileBuffer + fileDosHeader->e_lfanew); if (fileNTHeader->Signature != IMAGE_NT_SIGNATURE) { cout << "PE的NT头错误X!" << endl; return 0; } PIMAGE_FILE_HEADER fileFileHeader = &(fileNTHeader->FileHeader); PIMAGE_OPTIONAL_HEADER fileOptionHeader = &(fileNTHeader->OptionalHeader); PIMAGE_SECTION_HEADER fileSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)fileOptionHeader + fileFileHeader->SizeOfOptionalHeader); int sectionNum = 0; for (int i = 0; i < fileFileHeader->NumberOfSections; i++) { if (FOAaddress >= (fileSectionHeader + i)->PointerToRawData && FOAaddress < (fileSectionHeader + i)->PointerToRawData + (fileSectionHeader + i)->SizeOfRawData) { sectionNum = i; break; } } long long offsetSize = FOAaddress - (fileSectionHeader + sectionNum)->PointerToRawData; DWORD fileAdderss = (DWORD)((fileSectionHeader + sectionNum)->VirtualAddress + offsetSize); //cout << hex <<"RVAaddress:"<< RVAaddress<<"转换====》" << "文件地址:" << fileAdderss << endl; return fileAdderss;
}
//要移动导出表,需要新增一个节,因此,我们需要先给dll文件新增加一个节void PrintImportTable(char* fileName) { //先得到大小 long long fileSize = GetSize(fileName); //得到大小后,再申请内存 这里为了简单,我就不重新申请了内存了,所以,这里就直接将后面需要扩大的节的大小写进来 char* fileBuffer = (char*)malloc(fileSize); if (!fileBuffer) { cout << "RVA_TO_FOA---->fileBuffer内存申请失败!" << endl; free(fileBuffer); return; } //如果内存申请成功,那么就要读fileBuffer,读之前,先打开文件 FILE* file = NULL; errno_t err = fopen_s(&file, fileName, "rb"); if (err != 0) { cout << "文件打开失败!" << endl; free(fileBuffer); fclose(file); return; } //如果打开也没问题,那么就需要真正的开始读了 fread(fileBuffer, 1, fileSize, file); if ((*(PWORD)fileBuffer) != IMAGE_DOS_SIGNATURE) { cout << "PE文件格式错误!" << endl;; free(fileBuffer); fclose(file); return; } PIMAGE_DOS_HEADER fileDosHeader = (PIMAGE_DOS_HEADER)fileBuffer;
PIMAGE_NT_HEADERS fileNTHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)fileBuffer + fileDosHeader->e_lfanew); if (fileNTHeader->Signature != IMAGE_NT_SIGNATURE) { cout << "PE的NT头错误!" << endl; free(fileBuffer); fclose(file); return; } PIMAGE_FILE_HEADER fileFileHeader = &(fileNTHeader->FileHeader); PIMAGE_OPTIONAL_HEADER fileOptionHeader = &(fileNTHeader->OptionalHeader); PIMAGE_SECTION_HEADER fileSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)fileOptionHeader + fileFileHeader->SizeOfOptionalHeader); //以上步骤与之前类似 //找到导入表RVA DWORD importTableRVA = fileOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; PIMAGE_IMPORT_DESCRIPTOR importTable = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)fileBuffer + RVA_TO_FOA(fileBuffer, importTableRVA));
//Name是RVA地址 //cout << "第一个DLL名称:" << hex << (importTable + 1)->Name << endl << sizeof(IMAGE_IMPORT_DESCRIPTOR) << endl;; //cout << "数值:" << importTable << endl; //因为不知道导入表有多少个,只知道,在导入表后会有sizeof(IMAGE_IMPORT_DESCRIPTOR)个0,因此我们需要用while循环 while (importTable->Characteristics != 0 || importTable->FirstThunk != 0 || importTable->ForwarderChain != 0 || importTable->Name != 0 || importTable->OriginalFirstThunk != 0 || importTable->TimeDateStamp != 0) { char* importTableName = (char*)((DWORD_PTR)fileBuffer + RVA_TO_FOA(fileBuffer, importTable->Name));
cout << "=================================================" << endl; cout << "导入表名:" << hex << left << setw(15) << importTableName << " 磁盘偏移:" << RVA_TO_FOA(fileBuffer, importTableRVA) << "OriginalFirstThunk:" << importTable->OriginalFirstThunk << endl;
//打印INT表 PDWORD intTables = (PDWORD)((DWORD_PTR)fileBuffer+RVA_TO_FOA(fileBuffer,importTable->OriginalFirstThunk)); //因为INT表我们也不知道有多少个,所以还是需要while循环。而且还需要进行判断,如果最高位是1,则要去除最高位,剩下的是导出序号,如果不是1,则是指向byName表。 while (*intTables != 0) { if ((*intTables & 0x80000000) == 0x80000000) { uint32_t lower31Bits = (*intTables) & 0x7FFFFFFF; cout << "INT表存放值:" << hex << left << setw(10) << *intTables << "序号:" << lower31Bits << endl; } else { PIMAGE_IMPORT_BY_NAME intTablesByNameTable = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)fileBuffer + RVA_TO_FOA(fileBuffer, *intTables)); char* intTablesByNameTableInName = intTablesByNameTable->Name; cout << "INT表存放值:" << hex << left << setw(10) << *intTables <<setw(8)<< "name:" << setw(25)<<intTablesByNameTableInName << "nameFOA:" << RVA_TO_FOA(fileBuffer, *intTables) << endl; } intTables++; }
//在打印IAT表,该表在运行前与INT表中的值一样 //打印INT表 PDWORD iatTables = (PDWORD)((DWORD_PTR)fileBuffer + RVA_TO_FOA(fileBuffer, importTable->FirstThunk)); while (*iatTables) { cout << "iatTables:" << *iatTables << endl; iatTables++; }
importTableRVA = importTableRVA + sizeof(IMAGE_IMPORT_DESCRIPTOR); importTable++;
}

free(fileBuffer); fclose(file);

}

int main(){ char fileName[] = "C:\Users\zyjsuper\Desktop\test\IPMsg.exe"; PrintImportTable(fileName);}


原文始发于微信公众号(loochSec):PE逆向-打印导入表

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年9月25日21:05:42
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   PE逆向-打印导入表http://cn-sec.com/archives/2066984.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息