简单构造个畸形PE
本帖最后由 ximo 于 2010-3-18 00:02 编辑本文主要讲述下如何简单的手动构造个畸形PE,比如使得入口点为0。处理的结果是使得PEiD等PE工具识别出错,导致无法用OD进行调试(貌似被强大的海风的SOD给和谐掉了)。
原理就是TLS的应用,手动添加个TLS就可以用来干坏事了。
方法:
1.找个空白地,构造TLS,填写TLS的值
2.修改PE可选头里的数据目录表里的TLS的RVA为你写入的地址
3.在TLS里的TLS回调地址处修改成原始的入口地址
4.其余的TLS结构,如果原来就存在TLS,比如delphi程序,则写回原来的值,否则可以用0填充
5.此时,原来的入口地址你可以随意修改,比如修改为0,或者修改成很大的一个数,使PE工具无法正常识别
效果为:
但是此时文件能够正常运行
下面是核心代码,代码写的很挫,仅仅是示例,有兴趣的自己修改吧
//定义个新的要写入的TLS结构
struct _New_TLS
{
DWORD dwStartAddressOfRawData;
DWORD dwEndAddressOfRawData;
DWORD dwAddressOfIndex;
DWORD dwAddressOfCallBacks;
DWORD dwSizeOfZeroFill;
DWORD dwCharacteristics;
}MyNewTLS;
//2个所要用到的关键转化,RVA跟Offset的互换
//Offset转RVA
DWORD OffsetToRVA(LPVOID lpBase,DWORD FileOffset)
{
PIMAGE_DOS_HEADER MyDosHeader;
PIMAGE_NT_HEADERS MyNtHeader;
PIMAGE_SECTION_HEADER MySectionHeader;
MyDosHeader=(PIMAGE_DOS_HEADER)lpBase;
MyNtHeader=(PIMAGE_NT_HEADERS)((long)lpBase+MyDosHeader->e_lfanew);
MySectionHeader=(PIMAGE_SECTION_HEADER)((UINT32)MyNtHeader+0x18+(UINT32)MyNtHeader->FileHeader.SizeOfOptionalHeader);
int NumOfSection;
NumOfSection=MyNtHeader->FileHeader.NumberOfSections;
DWORD dwSizeOfSection;
dwSizeOfSection=sizeof(IMAGE_SECTION_HEADER);
if (FileOffset<MySectionHeader->PointerToRawData)
{
return FileOffset;
}
else
{
for(int i=0;i<NumOfSection;i++)
{
if (FileOffset>=MySectionHeader->PointerToRawData && FileOffset<MySectionHeader->PointerToRawData+MySectionHeader->SizeOfRawData)
{
DWORD dwTMP=FileOffset-MySectionHeader->PointerToRawData;
DWORD dwRVA=MySectionHeader->VirtualAddress+dwTMP;
return dwRVA;
}
else
{
MySectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)MySectionHeader+dwSizeOfSection);
}
}
}
return 0;
}
//RVA转Offset
DWORD RVAToOffset(LPVOID lpBase,DWORD VirtualAddress)
{
PIMAGE_DOS_HEADER MyDosHeader;
PIMAGE_NT_HEADERS MyNtHeader;
PIMAGE_SECTION_HEADER MySectionHeader;
MyDosHeader=(PIMAGE_DOS_HEADER)lpBase;
MyNtHeader=(PIMAGE_NT_HEADERS)((long)lpBase+MyDosHeader->e_lfanew);
MySectionHeader=(PIMAGE_SECTION_HEADER)((UINT32)MyNtHeader+0x18+(UINT32)MyNtHeader->FileHeader.SizeOfOptionalHeader);
int NumOfSection;
NumOfSection=MyNtHeader->FileHeader.NumberOfSections;
DWORD dwSizeOfSection;
dwSizeOfSection=sizeof(IMAGE_SECTION_HEADER);
if (VirtualAddress<MySectionHeader->VirtualAddress)
{
return VirtualAddress;
}
else
{
for(int i=0;i<NumOfSection;i++)
{
if(VirtualAddress>=MySectionHeader->VirtualAddress&&VirtualAddress<MySectionHeader->VirtualAddress+MySectionHeader->Misc.VirtualSize)
{
DWORD dwTmp=MySectionHeader->VirtualAddress-MySectionHeader->PointerToRawData;
DWORD Offset=VirtualAddress-dwTmp;
return Offset;
}
else
{
MySectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)MySectionHeader+dwSizeOfSection);
}
}
}
return 0;
}
//打开文件,创建文件映射
HANDLE hFile;
hFile=CreateFile(m_path,GENERIC_WRITE|GENERIC_READ,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile==INVALID_HANDLE_VALUE)
{
return;
}
HANDLE hMap;
hMap=CreateFileMapping(hFile,NULL,PAGE_READWRITE,NULL,NULL,NULL);
if (hMap==NULL)
{
CloseHandle(hFile);
return;
}
LPVOID lpBase;
lpBase=MapViewOfFile(hMap,FILE_MAP_WRITE,0,0,0);
if (lpBase==NULL)
{
CloseHandle(hMap);
CloseHandle(hFile);
return;
}
//验证PE的有效性
PIMAGE_DOS_HEADER MyDosHeader;
MyDosHeader=(PIMAGE_DOS_HEADER)lpBase;
if (MyDosHeader->e_magic!='ZM')
{
UnmapViewOfFile(lpBase);
CloseHandle(hMap);
CloseHandle(hFile);
return;
}
DWORD FileSize;
FileSize=GetFileSize(hFile,NULL);
if (MyDosHeader->e_lfanew>FileSize)
{
UnmapViewOfFile(lpBase);
CloseHandle(hMap);
CloseHandle(hFile);
return;
}
PIMAGE_NT_HEADERS MyNtHeader;
MyNtHeader=(PIMAGE_NT_HEADERS)((long)lpBase+MyDosHeader->e_lfanew);
if (MyNtHeader->Signature!='EP')
{
UnmapViewOfFile(lpBase);
CloseHandle(hMap);
CloseHandle(hFile);
return;
}
if (MyNtHeader->OptionalHeader.AddressOfEntryPoint==0)
{
UnmapViewOfFile(lpBase);
CloseHandle(hMap);
CloseHandle(hFile);
return;
}
//搜索32个字节的空隙,目的是用来写TLS
//起始地址可以选择从第一个区段开始
PIMAGE_SECTION_HEADER MySectionHeader;
MySectionHeader=(PIMAGE_SECTION_HEADER)((UINT32)MyNtHeader+0x18+(UINT32)MyNtHeader->FileHeader.SizeOfOptionalHeader);
DWORD dwBegin=MySectionHeader->VirtualAddress;
int iCount=0;
DWORD dwAddr;
for (int i=dwBegin;i<FileSize;i++)
{
BYTE tmp=(BYTE)*(DWORD*)((DWORD)lpBase+i);
if (tmp==0)
{
iCount++;
}
else
{
if (iCount>=32 &&((i-iCount)%2==0))
{
dwAddr=i-iCount;
break;
}
else
{
iCount=0;
}
}
}
//判断所要写入的地址的所在区段,然后修改区段属性使得可写
int NumOfSection;
NumOfSection=MyNtHeader->FileHeader.NumberOfSections;
DWORD dwSizeOfSection;
dwSizeOfSection=sizeof(IMAGE_SECTION_HEADER);
for(int j=0;j<NumOfSection;j++)
{
if (dwAddr>=MySectionHeader->PointerToRawData && dwAddr<MySectionHeader->PointerToRawData+MySectionHeader->SizeOfRawData)
{
MySectionHeader->Characteristics=0xE0000040;
break;
}
else
{
MySectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)MySectionHeader+dwSizeOfSection);
}
}
//填充TLS
DWORD dwTLS,dwTLSCallBack,dwTLSIndex;
dwTLS=dwAddr;//TLSRVA
dwTLSCallBack=dwAddr+24;
dwTLSIndex=dwAddr+28;
DWORD dwTLSRVA=MyNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress;
if (dwTLSRVA!=0)
{
PIMAGE_TLS_DIRECTORY MyOldTLSHeader=(PIMAGE_TLS_DIRECTORY)((DWORD)lpBase+RVAToOffset(lpBase,dwTLSRVA));
MyNewTLS.dwStartAddressOfRawData=MyOldTLSHeader->StartAddressOfRawData;
MyNewTLS.dwEndAddressOfRawData=MyOldTLSHeader->EndAddressOfRawData;
MyNewTLS.dwAddressOfIndex=MyOldTLSHeader->AddressOfIndex;
MyNewTLS.dwAddressOfCallBacks=(OffsetToRVA(lpBase,dwTLSCallBack)+MyNtHeader->OptionalHeader.ImageBase);
MyNewTLS.dwSizeOfZeroFill=MyOldTLSHeader->SizeOfZeroFill;
MyNewTLS.dwCharacteristics=MyOldTLSHeader->Characteristics;
}
else
{
MyNewTLS.dwStartAddressOfRawData=0;
MyNewTLS.dwEndAddressOfRawData=0;
MyNewTLS.dwAddressOfIndex=(OffsetToRVA(lpBase,dwTLSIndex)+MyNtHeader->OptionalHeader.ImageBase);
MyNewTLS.dwAddressOfCallBacks=(OffsetToRVA(lpBase,dwTLSCallBack)+MyNtHeader->OptionalHeader.ImageBase);
MyNewTLS.dwSizeOfZeroFill=0;
MyNewTLS.dwCharacteristics=0;
}
MyNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress=OffsetToRVA(lpBase,dwTLS);//修正tls的RVA
PIMAGE_TLS_DIRECTORY MyNewTlsHeader=(PIMAGE_TLS_DIRECTORY)(dwTLS+(DWORD)lpBase);
MyNewTlsHeader->StartAddressOfRawData=MyNewTLS.dwStartAddressOfRawData;
MyNewTlsHeader->EndAddressOfRawData=MyNewTLS.dwEndAddressOfRawData;
MyNewTlsHeader->AddressOfIndex=MyNewTLS.dwAddressOfIndex;
MyNewTlsHeader->AddressOfCallBacks=MyNewTLS.dwAddressOfCallBacks;
MyNewTlsHeader->SizeOfZeroFill=MyNewTLS.dwSizeOfZeroFill;
MyNewTlsHeader->Characteristics=MyNewTLS.dwCharacteristics;
//修改TLS的回调地址处为原始的入口地址
DWORD dwOEP=MyNtHeader->OptionalHeader.ImageBase+MyNtHeader->OptionalHeader.AddressOfEntryPoint;
DWORD dwWrite;
SetFilePointer(hFile,dwTLSCallBack,NULL,FILE_BEGIN);
WriteFile(hFile,&dwOEP,sizeof(DWORD),&dwWrite,NULL);
//改写入口地址,随意修改,比如我修改为0
MyNtHeader->OptionalHeader.AddressOfEntryPoint=0; //入口为0
//收尾
UnmapViewOfFile(lpBase);
CloseHandle(hMap);
CloseHandle(hFile);
O了,这样就构造完了。最后放个bin吧,试了下,效果还行。
:http://www.52pojie.cn
:http://www.80dfj.org 恩,这么好的贴就不用加精华了. 东西不错,下个玩玩!! 呵呵!学习了…… 膜拜ing。。。
悄悄的告诉楼主, 兼容性还有带提高。。。哈哈 这个好玩,我准备加到我修改的link 实现之
呵呵 哈哈,我喜欢 好东西啊 不错不错!!!! 这个不错,学习一下 东西不错,支持!!!!!!!!