ximo 发表于 2010-3-17 23:04

简单构造个畸形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

Hmily 发表于 2010-3-17 23:14

恩,这么好的贴就不用加精华了.

fulee 发表于 2010-3-17 23:07

东西不错,下个玩玩!!

czjh2008 发表于 2010-3-17 23:35

呵呵!学习了……

blueapplez 发表于 2010-3-17 23:57

膜拜ing。。。
悄悄的告诉楼主, 兼容性还有带提高。。。哈哈

icy 发表于 2010-3-18 00:05

这个好玩,我准备加到我修改的link 实现之

呵呵

rwr 发表于 2010-3-18 17:13

哈哈,我喜欢

libicheng 发表于 2010-3-19 00:08

好东西啊   不错不错!!!!

cool168 发表于 2010-5-28 20:25

这个不错,学习一下

zq784161329 发表于 2010-5-29 14:42

东西不错,支持!!!!!!!!
页: [1] 2 3
查看完整版本: 简单构造个畸形PE