课后3.25作业,打印所有重定向表:
实现代码:
// 滴水三期3.25.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
using namespace std;
//得到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转FOA
DWORD RVA_TO_FOA(char* fileName, long long RVAaddress) {
//先得到大小
long fileSize = GetSize(fileName);
//得到大小后,再申请内存
char* fileBuffer = (char*)malloc(fileSize);
if (!fileBuffer) {
cout << "RVA_TO_FOA---->fileBuffer内存申请失败!" << endl;
free(fileBuffer);
return 0;
}
//如果内存申请成功,那么就要读fileBuffer,读之前,先打开文件
FILE* file = NULL;
errno_t err = fopen_s(&file, fileName, "rb");
if (err != 0) {
cout << "文件打开失败!" << endl;
free(fileBuffer);
fclose(file);
return 0;
}
//如果打开也没问题,那么就需要真正的开始读了
fread(fileBuffer, 1, fileSize, file);
if ((*(PWORD)fileBuffer) != IMAGE_DOS_SIGNATURE) {
cout << "PE文件格式错误!" << endl;;
free(fileBuffer);
fclose(file);
return 0;
}
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 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;
free(fileBuffer);
fclose(file);
return fileAdderss;
}
//FOA转RVA
//这里的FOA要减去fileBuffer
DWORD FOA_TO_RVA(char* fileName, long long FOAaddress) {
//先得到大小
long fileSize = GetSize(fileName);
//得到大小后,再申请内存
char* fileBuffer = (char*)malloc(fileSize);
if (!fileBuffer) {
cout << "FOA_TO_FOA---->fileBuffer内存申请失败!" << endl;
free(fileBuffer);
return 0;
}
//如果内存申请成功,那么就要读fileBuffer,读之前,先打开文件
FILE* file = NULL;
errno_t err = fopen_s(&file, fileName, "rb");
if (err != 0) {
cout << "文件打开失败!" << endl;
free(fileBuffer);
fclose(file);
return 0;
}
//如果打开也没问题,那么就需要真正的开始读了
fread(fileBuffer, 1, fileSize, file);
if ((*(PWORD)fileBuffer) != IMAGE_DOS_SIGNATURE) {
cout << "PE文件格式错误!" << endl;;
free(fileBuffer);
fclose(file);
return 0;
}
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 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;
free(fileBuffer);
fclose(file);
return fileAdderss;
}
void PrintAllBaseReloc(char* fileName) {
//先得到大小
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 BaseRelocTableRVA = fileOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
long BaseRelocTableSize = fileOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
//将重定位表的RVA转换成
DWORD BaseRelocTableFOA = RVA_TO_FOA(fileName, BaseRelocTableRVA);
DWORD fileBaseRelocTable = (DWORD_PTR)fileBuffer + BaseRelocTableFOA;
DWORD BlockSize = *((PDWORD)fileBaseRelocTable + 1);
bool tmp = true;
while (tmp)
{
if (*((PDWORD)fileBaseRelocTable) != 0x00 && *((PDWORD)fileBaseRelocTable + 1) != 0x00) {
DWORD PageRVA = *((PDWORD)fileBaseRelocTable);
DWORD BlockSize = *((PDWORD)fileBaseRelocTable + 1);
DWORD Offset = fileBaseRelocTable - (DWORD)fileBuffer+ 8 + i*2;
cout << hex<<left
<< "重定向表:"
<< setw(10) << "Offset:" << setw(10) << Offset
<< setw(10) << "PageRVA:" << setw(10) << PageRVA
<< setw(10) << "BlockSize:" << setw(8) << BlockSize
<< setw(15) << "Entries Count:" << (BlockSize - 8) / 2
<< endl;
for (int i = 0; i < (BlockSize - 8) / 2; i++) {
unsigned value = *((PWORD)fileBaseRelocTable + 4 + i);
unsigned short high4Bits = (value >> 12) & 0xF;
unsigned short low12Bits = value & 0xFFF;
Offset = fileBaseRelocTable - (DWORD)fileBuffer + 2;
if (high4Bits == 3) {
cout << left
<< "YES:"
<< setw(8) << "Offset:" << setw(8) << Offset
<< setw(8) << "Value:" << setw(8) << value
<< setw(8) << "Type:" << "32bit"
<< setw(20) << " low12Bits(真实偏移):" << setw(8) << low12Bits
<< setw(12) << "RVA偏移:" << PageRVA + low12Bits
<< endl;
}
else {
cout << left
<< "NO:"
<< setw(8) << "Offset:" << setw(8) << Offset
<< setw(8) << "Value:" << setw(8) << value
<< setw(8) << "Type:" << "32bit"
<< setw(20) << " low12Bits(真实偏移):" << setw(8) << low12Bits
<< setw(12) << "RVA偏移:" << PageRVA + low12Bits
<< endl;
}
}
cout << "============================================" << endl;
//循环
fileBaseRelocTable = fileBaseRelocTable + BlockSize;
tmp = true;
}
else {
tmp = false;
}
}
free(fileBuffer);
fclose(file);
}
int main()
{
char fileName[] = "C:\Users\zyjsuper\Desktop\test\dll.dll";
PrintAllBaseReloc(fileName);
}
原文始发于微信公众号(loochSec):逆向-打印重定向表
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论