PE文件深入(一)

11月25日2015 windows编程 PE 看评论
PE文件是 windows平台上可执行文件的一个标准,可执行文件不仅包括.exe文件,还包括.dll 和.sys等文件。这些文件都是有一定格式的,要不然,操作系统不知道怎样加载可执行文件。我们都知道,自从x86有了保护模式 之后,应用程序一般都是运行在ring3级别。为了达到以前那种自由出入 windows的目的,有的人就通过给系统装驱动来实现目标,驱动运行在
ring0级别,拥有最高权限。但是,驱动程序一般比较复杂,写出一个象样的驱动不仅需要经验,更需要时间以及对操作系统的深入了解。 比较通用的做法就是利用 windows的API去实现我们想要的功能,这样能节省不少时间。但是,杀毒软件一般能实现那种没有加壳、加花的木马病毒,加了之后,有的时候也能杀,要看特征码和杀毒软件的查杀方式。不管怎么样,加壳加花还是必须的,至少会把自己包裹一层,避免被查杀。加壳、加花要对PE有深刻的理解。

PE文件是分节区的,详细的资料请参考<>、MSDN上关于PE文件的资料。

下面的程序是:打开一个可执行文件,判断是否为PE文件,然后再读出PE文件头,比如文件的建议装入地址。然后再就是遍历所有的节区信息。主要的技术是:程序的异常处理,win32不能像汇编那样去利用SEH处理异常,暂时来个简单的吧。因为,如果打开的文件不是可执行文件,指针操作非法,程序会抛出异常。

主要的代码入下:

#include "info.h"
#include  "resource.h"
#pragma  comment(lib,"comctl32.lib")  
HINSTANCE  hInst;   TCHAR uu[2000],szFileName[MAX_PATH];
HWND hWim; 
CHARRANGE  sctr; 
INT_PTR CALLBACK PeI(HWND,UINT,WPARAM,LPARAM); 
void  RRco(HWND,char*);
LONG WINAPI _MyHand(struct _EXCEPTION_POINTERS* ExceptionInfo); 
void _safe(void);  
int APIENTRY WinMain(HINSTANCE hInstance,                     
HINSTANCE hPrevInstance,                               
LPTSTR     lpCmdLine,                                
int    nCmdShow)

UNREFERENCED_PARAMETER(hPrevInstance);  
UNREFERENCED_PARAMETER(lpCmdLine);  
MSG msg;   
hInst=GetModuleHandle(NULL);              
InitCommonControls();    
sctr.cpMax=-1;    
sctr.cpMin=0;  
SetUnhandledExceptionFilter(_MyHand);     
DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1),NULL,PeI);   
while(GetMessage(&msg,NULL,0,0))   
{      
TranslateMessage(&msg);      
DispatchMessage(&msg);     }    
return (int)msg.wParam; 
}

INT_PTR CALLBACK PeI(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{  
UNREFERENCED_PARAMETER(lParam);    
OPENFILENAME stOpen;        
switch (message)  

case WM_INITDIALOG:   hWim=hDlg;        
SendMessage(GetDlgItem(hDlg,IDC_EDIT1),EM_EXLIMITTEXT,(WPARAM)0,(LPARAM)-1);   
SendMessage(GetDlgItem(hDlg,IDC_EDIT1),EM_SETTEXTMODE,(WPARAM)TM_PLAINTEXT,(LPARAM)NULL);         
return (INT_PTR)TRUE;   break;        
case WM_COMMAND:   switch(LOWORD(wParam))   

case IDOK:   
ZeroMemory(&stOpen,sizeof(stOpen));  
stOpen.lStructSize=sizeof(OPENFILENAME);         
stOpen.hwndOwner=hWim;           
stOpen.lpstrFile=szFileName;       
stOpen.nMaxFile=MAX_PATH;    
stOpen.Flags=OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST;           
stOpen.lpstrFilter="exe Files(*.exe)*.exeAll Files(*.*)*.*";     
 if(GetOpenFileName(&stOpen))       RRco(hDlg,szFileName);     
  else   MessageBox(hDlg,"请选择文件!","没有选择文件",MB_ICONSTOP);    
  break;   
case IDM_READ:  
MessageBox(hDlg,"read record","Button read",MB_OK);   
break;  
case IDM_SAVE:  
 MessageBox(hDlg,"save record","Button save",MB_OK);    
break;   
case IDCANCEL: 
EndDialog(hDlg, LOWORD(wParam));  
ExitProcess(1);    
break;   
}
//WM_COMMANDswitch  
return (INT_PTR)TRUE;   break; 
}//switch 
return (INT_PTR)FALSE; 
}  
void  RRco(HWND  hwc,char *s) 

HWND hwt;  DWORD ccR;  
char *ps;  IMAGE_DOS_HEADER *pdher;  
IMAGE_NT_HEADERS *pntHdr;     
IMAGE_SECTION_HEADER *psecHdr;
HANDLE hFile,hFileM;  int ic=0;   
hwt=GetDlgItem(hwc,IDC_EDIT1);    
hFile=CreateFile(s,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,   NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL);     
if(hFile==INVALID_HANDLE_VALUE)     
{     
MessageBox(hwc,"打开文件失败,请检查文件!","错误",MB_ICONSTOP); 
return;     

hFileM=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);   
if(hFileM==NULL)   

MessageBox(hwc,"创建文件映射失败!","错误",MB_ICONSTOP);
CloseHandle(hFile);     
return;  

ps=(char *)MapViewOfFile(hFileM,FILE_MAP_READ,0,0,0);   
pdher=(IMAGE_DOS_HEADER *)ps;  
if(pdher->e_magic!=IMAGE_DOS_SIGNATURE)   
{  
MessageBox(NULL,"不是有效的可执行文件!","错误",MB_ICONSTOP); 
goto err;  
}   
   ps+=pdher->e_lfanew;   
   pntHdr=(IMAGE_NT_HEADERS *)ps;   
   if(pntHdr->Signature!=IMAGE_NT_SIGNATURE)   
   {   
    MessageBox(NULL,"不是有效的PE文件!","PE错误",MB_ICONSTOP);   
     goto err;  
   }  
   ZeroMemory(uu,sizeof(uu));  
   wsprintf(uu,"File:%s 运行平台:0x%04X 节区数量:%d 文件属性:0x%04X 建议装入地址:0x%04X",s,pntHdr->FileHeader.Machine,   
    pntHdr->FileHeader.NumberOfSections,pntHdr->FileHeader.Characteristics,pntHdr->OptionalHeader.ImageBase);  
   ccR=0; 
SendMessage(hwt,EM_EXSETSEL,(WPARAM)0,(LPARAM)&sctr);  
SendMessage(hwt,EM_REPLACESEL,(WPARAM)FALSE,(LPARAM)"");   
SetWindowText(hwt,"");  
SetWindowText(hwt,uu);   
MessageBox(NULL,uu,"sail",MB_OK); 
   ps+=sizeof(IMAGE_NT_HEADERS);   
for(ic=0;icFileHeader.NumberOfSections;ic++)  
{  
psecHdr=(IMAGE_SECTION_HEADER*)ps;     
ZeroMemory(uu,sizeof(uu));    
wsprintf(uu,"节区名称:%s 节区大小:%08X 虚拟地址:%08X Raw_大小:%08X 节区属性:%08X",psecHdr->Name,     
psecHdr->Misc.VirtualSize,psecHdr->VirtualAddress,psecHdr->SizeOfRawData,psecHdr->Characteristics);  
MessageBox(NULL,uu,"SECTION",MB_OK);     ps+=sizeof(IMAGE_SECTION_HEADER);  

        err:
        UnmapViewOfFile(s);  
        CloseHandle(hFileM);  
        CloseHandle(hFile); 
    }

    LONG WINAPI _MyHand(struct _EXCEPTION_POINTERS* ExceptionInfo) 
    {  
    TCHAR ErrMsg[100];    
    ZeroMemory(ErrMsg,sizeof(ErrMsg));  
        wsprintf(ErrMsg,"异常发生位置:%d  异常代码:%08X 标志:%d EIP:%d  参数:%d",ExceptionInfo->ExceptionRecord->ExceptionAddress,
        ExceptionInfo->ExceptionRecord->ExceptionCode,ExceptionInfo->ExceptionRecord->ExceptionFlags     ,ExceptionInfo->ContextRecord->Eip,ExceptionInfo->ExceptionRecord->NumberParameters);   
        MessageBox(NULL,ErrMsg,"错误信息",MB_OK);   
        ExceptionInfo->ContextRecord->Eip=(DWORD)_safe;   
       return EXCEPTION_CONTINUE_EXECUTION; 
   }

   void _safe(void) 
   { 
    MessageBox(NULL,"发生错误程序退出!","异常处理",MB_OK);
    ExitProcess(1); 
   }