PE 获取导入表 导出表 节信息等都需要RVAToFileOffset,这个函数里面依赖于节表头的信息.在畸形PE中节表头里面的字段有些是不对的,需要调整,实际中发现PEID0.94对这种情况无能为力,但是0.95却可能轻松应对,于是调试了下PEID0.95 ,发现他的RVAToFileOffset和网络上流传的并无区别,只是在调用它之前已经对节表头进行了调整,具体在0045D6B0函数中,于是分析了下这个函数发现了调用方法和具体参数,我们可以在调整节表后再调用RVAToFileOffset就可以了,下面是IDA 结合自己分析的那个函数代码
附件中有例子和VC6的工程代码,里面的例子路径根据实际路径修改下
ShowPeInFo("C:\\1.exe");("C:\\1.exe")改为实际路径
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// this2 + 0 pMap IN
// + 4 FileSize IN
// + 8 pMap IN
// + 12 pNtHeader IN
// + 16 pFileHeader IN
// + 20 pOptionHeader IN
// + 24 第一个节表头 IN
// + 28 第一个节表头 新分配内存中的 经过调整后的节表头 OUT
// + 32 节数目 IN
// + 36 文件粒度 IN
// + 40 FileAlignment - 1 IN
// + 44 SectionAlignment - 1 IN
//
char __thiscall my_TiaoZhengSecHeader(int this2, char a2)
{
int this1; // esi@1
int pOptionalHeader; // eax@1
int pFileHeader; // edx@1
int NumOfSection; // ecx@1
unsigned int v6; // eax@2
char v7; // bl@2
int pVirtualAddress; // ecx@3
void *pMallocSecHeader; // eax@7
void *pMallocSecHeader1; // edi@7
int FileSize; // eax@8
int pFirstSecHeader; // esi@8
char result; // al@8
unsigned int v14; // ebx@12
int pPointerToRawData; // eax@13
int SizeOfRawData; // edx@18
int v17; // edi@20
int VirtualSize; // ecx@20
int VirtualSize2; // ecx@20
int VirtualAddress; // edx@20
int PointerToRawData; // edx@25
unsigned int FileSize2; // ecx@25
unsigned int v23; // edi@27
this1 = this2;
pOptionalHeader = *(_DWORD *)(this2 + 20);
*(_DWORD *)(this2 + 40) = *(_DWORD *)(pOptionalHeader + 36) - 1;// FileAlignment - 1
*(_DWORD *)(this2 + 44) = *(_DWORD *)(pOptionalHeader + 32) - 1;// SectionAlignment - 1
pFileHeader = *(_DWORD *)(this2 + 16);
*(_DWORD *)(this2 + 36) = (*(_DWORD *)(pOptionalHeader + 60) + 511) & 0xFFFFFE00;// +60 = SizeOfHeaders
NumOfSection = *(_WORD *)(pFileHeader + 2);
*(_DWORD *)(this1 + 32) = NumOfSection;
if ( *(_DWORD *)(pOptionalHeader + 32) < 0x1000u )// SectionAlignment < 0x1000
{
v6 = 0;
v7 = 1;
if ( !NumOfSection )
{
LABEL_6:
*(_DWORD *)(this1 + 32) = 1;
goto LABEL_7;
}
pVirtualAddress = *(_DWORD *)(this1 + 24) + 12;
while ( *(_DWORD *)(pVirtualAddress + 8) == *(_DWORD *)pVirtualAddress )
{
++v6;
pVirtualAddress += 40;
if ( v6 >= *(_DWORD *)(this1 + 32) )
goto LABEL_6;
}
if ( a2 )
return 0;
}
v7 = 0;
LABEL_7:
pMallocSecHeader = malloc(40 * *(_DWORD *)(this1 + 32));// 节头大小 * 节数目
pMallocSecHeader1 = pMallocSecHeader;
*(_DWORD *)(this1 + 28) = pMallocSecHeader;
if ( v7 )
{
*(_DWORD *)pMallocSecHeader = 0;
*((_DWORD *)pMallocSecHeader + 1) = 0;
*((_DWORD *)pMallocSecHeader + 2) = 0;
*((_DWORD *)pMallocSecHeader + 3) = 0;
*((_DWORD *)pMallocSecHeader + 4) = 0;
*((_DWORD *)pMallocSecHeader + 5) = 0;
*((_DWORD *)pMallocSecHeader + 6) = 0;
*((_DWORD *)pMallocSecHeader + 7) = 0;
*((_DWORD *)pMallocSecHeader + 8) = 0;
*((_DWORD *)pMallocSecHeader + 9) = 0;
FileSize = *(_DWORD *)(this1 + 4);
*((_DWORD *)pMallocSecHeader1 + 2) = FileSize;
*((_DWORD *)pMallocSecHeader1 + 4) = FileSize;
*((_DWORD *)pMallocSecHeader1 + 9) = 0xE00000E0u;
pFirstSecHeader = *(_DWORD *)(this1 + 24);
*(_DWORD *)pMallocSecHeader1 = *(_DWORD *)pFirstSecHeader;
*((_DWORD *)pMallocSecHeader1 + 1) = *(_DWORD *)(pFirstSecHeader + 4);// pSec->VirtualAddress
result = 1;
}
else
{
MemCpyN(pMallocSecHeader, *(_DWORD *)(this1 + 24), 40 * *(_DWORD *)(this1 + 32));// 复制节表头到申请的内存中
v14 = 0;
if ( *(_DWORD *)(this1 + 32) ) // 节数目
{
pPointerToRawData = (int)((char *)pMallocSecHeader1 + 20);
do
{
if ( !*(_DWORD *)(pPointerToRawData - 12) )// MISC == 0
*(_DWORD *)(pPointerToRawData - 12) = *(_DWORD *)(pPointerToRawData - 4);// VirtualSize = SizeOfRawData
if ( !*(_DWORD *)pPointerToRawData ) // PointerToRawData == 0
*(_DWORD *)(pPointerToRawData - 4) = 0;// SizeOfRawData = 0
SizeOfRawData = *(_DWORD *)(pPointerToRawData - 4);
if ( !SizeOfRawData )
*(_DWORD *)pPointerToRawData = 0;
v17 = SizeOfRawData + (*(_DWORD *)pPointerToRawData & 0x1FF);
*(_DWORD *)pPointerToRawData &= 0xFFFFFE00u;// 关键一句
*(_DWORD *)(pPointerToRawData - 4) = v17;// SizeOfRawData = v17
VirtualSize = *(_DWORD *)(pPointerToRawData - 12);
*(_DWORD *)(pPointerToRawData - 4) = ((~*(_DWORD *)(this1 + 40) & (*(_DWORD *)(this1 + 40) + v17)) + 511) & 0xFFFFFE00;// + 40 == FileAlignment - 1
VirtualSize2 = (VirtualSize + 4095) & 0xFFFFF000;
VirtualAddress = *(_DWORD *)(pPointerToRawData - 8) & 0xFFFFF000;
*(_DWORD *)(pPointerToRawData - 8) = VirtualAddress;
*(_DWORD *)(pPointerToRawData - 12) = VirtualSize2;
if ( (unsigned int)VirtualSize2 < *(_DWORD *)(pPointerToRawData - 4) )
*(_DWORD *)(pPointerToRawData - 4) = VirtualSize2;
if ( (unsigned int)VirtualAddress < *(_DWORD *)(this1 + 36) && VirtualAddress )// + 36 = 文件粒度
*(_DWORD *)(this1 + 36) = VirtualAddress;
PointerToRawData = *(_DWORD *)pPointerToRawData;
FileSize2 = *(_DWORD *)(this1 + 4);
if ( *(_DWORD *)pPointerToRawData <= FileSize2 )
{
v23 = *(_DWORD *)(pPointerToRawData - 4);
if ( v23 > FileSize2 || PointerToRawData + v23 > FileSize2 )
*(_DWORD *)(pPointerToRawData - 4) = FileSize2 - PointerToRawData;
}
else
{
*(_DWORD *)(pPointerToRawData - 4) = 0;
}
++v14;
pPointerToRawData += 40;
}
while ( v14 < *(_DWORD *)(this1 + 32) );
}
result = 1;
}
return result;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)