使用VC自己動(dòng)手編寫加殼程序_第1頁
使用VC自己動(dòng)手編寫加殼程序_第2頁
使用VC自己動(dòng)手編寫加殼程序_第3頁
使用VC自己動(dòng)手編寫加殼程序_第4頁
使用VC自己動(dòng)手編寫加殼程序_第5頁
已閱讀5頁,還剩24頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、使用VC自己動(dòng)手編寫加殼程序閱讀對(duì)象:想寫殼的新手。高手掠過,本文僅限于寫殼入門。基本要求:了解VC+6.0基本使用方法;了解PE格式,不熟悉的地方能夠通過查閱資料弄懂;(1) 生成界面,完成文件操作主要內(nèi)容:生成界面,完成打開文件對(duì)話框。首先說一下寫作原因。最初學(xué)習(xí)加殼技術(shù),網(wǎng)上確實(shí)能找到一些源代碼,但90%的沒有注釋,所以很多代碼都看不懂。即使某個(gè)函數(shù)大體功能知道,但其中的小細(xì)節(jié)由于沒有注釋,也不知道作者的用途是什么,所以這一過程相當(dāng)痛苦。當(dāng)時(shí)對(duì)于我來說,一個(gè)簡單的加殼程序也是相當(dāng)復(fù)雜。有時(shí)候想修改他們的程序,但程序結(jié)構(gòu)牽一發(fā)而動(dòng)全身,不得不放棄。有些程序前面90%的代碼都在做鋪墊和打基礎(chǔ)

2、,而最后的10%是合并功能,往往我們?cè)诜治銮懊娴?0%中的20%就沒有耐心了,因?yàn)殇亯|太多,讓我們感覺沒有成就感,感覺不到那么多代碼是干嘛的。所以本文在寫作時(shí),每一部分都會(huì)實(shí)實(shí)在在的實(shí)現(xiàn)一部分功能,讓我們有些成就感,這樣才有興趣。寫此文是給像我一樣想寫殼卻無從下手的人一個(gè)參考。不過本人現(xiàn)在也是研究階段,能力有限,文章一方面是總結(jié)一下自己,另一方面也希望和大家多多交流。殼的理論我就不多說了。一開始就說一大堆理論同樣會(huì)使學(xué)習(xí)失去興趣,我就喜歡邊動(dòng)手邊理論。開始吧。打開VC+6.0,新建工程,工程名稱“PEPacker”,選擇“MFC AppWizard(exe)”,下一步,選擇基于對(duì)話框的應(yīng)用程序

3、。在對(duì)話框中刪除默認(rèn)的“確定”、“取消”按鈕,還有默認(rèn)的文本信息。如下圖所示: 然后按F7組建(編譯)程序,可以從IDE的提示窗口中看到是否生成成功,按CTRL+F5程序是能夠正常運(yùn)行的,不過是一個(gè)什么都沒有的對(duì)話框?,F(xiàn)在我們要添加元素了。添加兩個(gè)組框、一個(gè)編輯框、三個(gè)按鈕、一個(gè)Rich編輯框?,F(xiàn)在修改其屬性。在對(duì)話框上點(diǎn)擊右鍵,選擇“屬性”,打開屬性對(duì)話框,在對(duì)話框的左上角有個(gè)像釘子一樣的圖標(biāo),點(diǎn)擊一下,這樣屬性對(duì)話框就會(huì)像釘子一樣保持可見了,我們就不需要每修改一個(gè)控件屬性的時(shí)候就點(diǎn)一下右鍵選擇了。修改屬性后的控件ID和標(biāo)題如下: 控件類型ID值 標(biāo)題 

4、; 組框 IDC_STATIC 請(qǐng)選擇文件 組框 IDC_STATIC 文件處理信息 按鈕 IDC_BUTTON_OPENFILE 選擇文件 按鈕 IDC_BUTTON_PACKING 開始加殼 按鈕 IDC_BUTTON_ABOUT 關(guān)于本程序 編輯框 IDC_EDIT_FILEPATHNAME 無 Rich編輯框 IDC_RICHEDIT_PROCINFO 無 對(duì)話框

5、60;IDD_PEPACKER_DIALOG PEPacker V1.0 設(shè)置好的界面如下圖所示:現(xiàn)在按F7編譯,CTRL+F5運(yùn)行一下,發(fā)現(xiàn)程序好沒有動(dòng)靜。什么反應(yīng)也沒有,如果把RichEdit刪除掉,再編譯,再運(yùn)行就可以。這個(gè)問題是由于RichEidt沒有初始化引起的,微軟的說法是要在APP的初始化函數(shù)中加入初始化函數(shù):AfxInitRichEdit()。那我們現(xiàn)在加入。在classview視圖中,展開CPEPackerApp類,雙擊InitInstance()函數(shù),在AfxEnableControlContainer();后面添加代碼 AfxInitRichEdit(

6、);,添加后的函數(shù)代碼如下:BOOL CPEPackerApp:InitInstance() AfxEnableControlContainer(); AfxInitRichEdit(); / Standard initialization / If you are not using these features and wish to reduce the size /  of your final executable, you should remove from the following /  the

7、specific initialization routines you do not need.此時(shí)再F7編譯,CTRL+F5運(yùn)行,就可以看到程序正常運(yùn)行了。再修改一下對(duì)話框的屬性,右鍵,選擇“屬性”后,在“樣式”標(biāo)簽中,勾選上“最小化框N”,這樣對(duì)話框就可以最小化了。當(dāng)然你還可以選擇其它屬性?,F(xiàn)在來添加成員變量。在編輯框上點(diǎn)擊右鍵,選擇“建立類向?qū)А保蜷_類向?qū)?duì)話框,然后選擇“Member Variables”標(biāo)簽。注意Project:里面是否是PEPacker,Class name:里面是否是CPEPackerDlg,然后在Control IDs:里面找到IDC_EDIT_FILEPA

8、THNAME,雙擊?;蛘唿c(diǎn)擊右邊的“Add Varible.”按鈕,在“Add Member Varible”對(duì)話框中添加成員變量。變量名為"m_FilePathName”,Category選擇"Value”,變量類型選擇"CString”,然后確定。用同樣的方法給控件IDC_RICHEDIT_PROCINFO添加成員變量。變量名為m_RichEditProcInfo,注意category選擇Control,變量類型為CRichEditCtrl。最后確定。雙擊“選擇文件”按鈕,彈出添加程序函數(shù)對(duì)話框,函數(shù)名你為:OnButtonOpenfile,我們確定即可,使用

9、默認(rèn)的,當(dāng)然也可以修改。此時(shí)來到了PEPackerDlg.cpp文件中,界面默認(rèn)的位置是剛剛添加的函數(shù)編輯處。代碼如下:void CPEPackerDlg:OnButtonOpenfile()  / TODO: Add your control notification handler code here  此時(shí)在此函數(shù)中添加如下代碼:代碼我會(huì)作注釋。void CPEPackerDlg:OnButtonOpenfile()   / TODO: Add your control notification handler cod

10、e here /設(shè)置文件過濾,默認(rèn)打開哪些文件類型,最后“|”結(jié)束。 char szFilter="可執(zhí)行文件(*.exe)|*.exe|全部文件(*.*)|*.*|" /通過查閱MSDN,了解CFileDialog中構(gòu)造函數(shù)的用法。 /第一個(gè)參數(shù)為TRUE,表示打開文件對(duì)話框;為FALSE,表示保存對(duì)話框。 /其他詳細(xì)參數(shù)說明見后面。 CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter,NULL); /

11、通過模態(tài)對(duì)話框顯示文件對(duì)話框 if (dlg.DoModal()=IDOK)   /獲取文件路徑  m_FilePathName=dlg.GetPathName(); /設(shè)置RICHEDIT內(nèi)容 /將指針設(shè)置到編輯框最后 m_RichEditProcInfo.SetSel(-1,-1); /替換編輯框最后的內(nèi)容,實(shí)際上就是在最后添加內(nèi)容。 m_RichEditProcInfo.ReplaceSel("文件路徑:"); m_RichEditProcInfo.

12、ReplaceSel(m_FilePathName); /用獲取的文件路徑更新編輯框內(nèi)容。 UpdateData(FALSE); 添加完成后,本次功能結(jié)束。編譯運(yùn)行即可,運(yùn)行界面如下:其中CFileDialog類的詳細(xì)說明如下:CFileDialog文件選擇對(duì)話框的使用:首先構(gòu)造一個(gè)對(duì)象并提供相應(yīng)的參數(shù),構(gòu)造函數(shù)原型如下: CFileDialog:CFileDialog( BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR&

13、#160;lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL );參數(shù)意義如下: bOpenFileDialog 為TRUE則顯示打開對(duì)話框,為FALSE則顯示保存對(duì)話文件對(duì)話框。 lpszDef

14、Ext 指定默認(rèn)的文件擴(kuò)展名。 lpszFileName 指定默認(rèn)的文件名。 dwFlags 指明一些特定風(fēng)格。 lpszFilter 是最重要的一個(gè)參數(shù),它指明可供選擇的文件類型和相應(yīng)的擴(kuò)展名。參數(shù)格式如: "Chart Files (*.xlc)|*.xlc|Worksheet Files (*.xls)|*.xls|Data Files (*.xlc;*.xls)|*.xlc; *.xls|All Files 

15、(*.*)|*.*|"文件類型說明和擴(kuò)展名間用 | 分隔,同種類型文件的擴(kuò)展名間可以用  分割,每種文件類型間用 | 分隔,末尾用 | 指明。 pParentWnd 為父窗口指針。 創(chuàng)建文件對(duì)話框可以使用DoModal(),在返回后可以利用下面的函數(shù)得到用戶選擇: CString CFileDialog:GetPathName( ) 得到完整的文件名,包括目錄名和擴(kuò)展名如:c: est est1.txt C

16、String CFileDialog:GetFileName( ) 得到完整的文件名,包括擴(kuò)展名如:test1.txt CString CFileDialog:GetExtName( ) 得到完整的文件擴(kuò)展名,如:txt CString CFileDialog:GetFileTitle ( ) 得到完整的文件名,不包括目錄名和擴(kuò)展名如:test1 POSITION CFileDialog:GetStartPosition( ) 對(duì)于選擇

17、了多個(gè)文件的情況得到第一個(gè)文件位置。 CString CFileDialog:GetNextPathName( POSITION& pos ) 對(duì)于選擇了多個(gè)文件的情況得到下一個(gè)文件位置,并同時(shí)返回當(dāng)前文件名。但必須已經(jīng)調(diào)用過POSITION CFileDialog:GetStartPosition( )來得到最初的POSITION變量。 (2) 使用內(nèi)存映射生成文件主要內(nèi)容:打開文件,使用內(nèi)存映射生成文件。本次要完成的任務(wù)是:點(diǎn)擊“開始加殼”按鈕,生成加殼后的文件,當(dāng)然這是假想加過殼,并沒有加殼

18、。實(shí)際上就是將文件改名,復(fù)制成另外一個(gè)文件,但又不同于復(fù)制。因?yàn)槭窍葘⑽募?chuàng)建內(nèi)存映射,然后再通過映射指針寫回文件。本次的界面效果:首先添加幾個(gè)和文件名相關(guān)的成員變量。在classview中,雙擊PEPackerDlg函數(shù),在類的定義中申明成員變量:public: CString m_FilePathNamePacked; /加殼后的文件名下面來添加“開始加殼”按鈕的函數(shù)。在“開始加殼”按鈕上雙擊,將出現(xiàn)新建函數(shù)的提示,確定即可。也可以點(diǎn)擊工具欄上的“查看”菜單,選擇“建立類向?qū)А?,選中“Message Maps”標(biāo)簽。Project:設(shè)置為PEPacker,Cl

19、ass name:設(shè)置為CPEPackerDlg,Object IDs選中IDC_BUTTON_PACKING,Messages:選中BN_CLICKED,然后點(diǎn)擊右邊的“Add Function.”按鈕,添加函數(shù)“OnButtonPacking”即可??盏暮瘮?shù)為:void CPEPackerDlg:OnButtonPacking()  / TODO: Add your control notification handler code here 現(xiàn)在在該函數(shù)中添加內(nèi)容。代碼部分我都做了注釋,所以我就不多說了。void CPEPackerDlg:OnButtonP

20、acking()  / TODO: Add your control notification handler code here HANDLE hFile; /文件句柄 HANDLE hMapping; /文件映射句柄 LPVOID lpHeadBase; /創(chuàng)建映射的頭指針 DWORD dwFileSize; /文件大小 DWORD dwBufferRead; /實(shí)際讀取字節(jié) /打開文件 hFile=CreateFile(

21、m_FilePathName,GENERIC_READ,FILE_SHARE_READ,NULL,  OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); /如果文件打開失敗,就彈出對(duì)話框,并返回。 if (hFile=INVALID_HANDLE_VALUE)   MessageBox("打開文件失??!","錯(cuò)誤提示",MB_OK);  return;  /獲取文件大小 dwFileSize=GetFi

22、leSize(hFile,NULL); /設(shè)定加殼后的文件名,我采取了一個(gè)偷懶的簡單方法。 /如果要嚴(yán)格做,需要獲取文件路徑,擴(kuò)展名等等。 m_FilePathNamePacked=m_FilePathName.Left(m_FilePathName.GetLength()-4)+"_packed.exe" /創(chuàng)建文件映射。如果對(duì)文件映射不了解,請(qǐng)自行查閱相關(guān)資料。 hMapping=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL); /如果創(chuàng)建映射失敗,彈出

23、對(duì)話框,并關(guān)閉文件句柄,然后返回。 if (hMapping=NULL)   MessageBox("創(chuàng)建文件映射失?。?quot;,"錯(cuò)誤提示",MB_OK);  CloseHandle(hFile); /關(guān)閉創(chuàng)建的文件句柄  return;  /將文件映射對(duì)象映射到當(dāng)前應(yīng)用程序的地址空間中 lpHeadBase=MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0); if (lpHeadBase=N

24、ULL)   MessageBox("文件映射地址失??!","錯(cuò)誤提示",MB_OK);  CloseHandle(hMapping); /關(guān)閉映射句柄  CloseHandle(hFile);  /關(guān)閉文件句柄  return;  /創(chuàng)建加殼后的文件句柄 hFile=CreateFile(m_FilePathNamePacked,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_

25、READ|FILE_SHARE_WRITE,  NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); if (hFile=INVALID_HANDLE_VALUE)   MessageBox("生成文件失??!","錯(cuò)誤提示!",MB_OK);  /寫入文件 if (!WriteFile(hFile,lpHeadBase,dwFileSize,&dwBufferRead,NULL)   M

26、essageBox("寫入文件失??!","錯(cuò)誤提示!",MB_OK);  /卸載文件映射,關(guān)閉文件句柄  UnmapViewOfFile(lpHeadBase);  CloseHandle(hMapping);  CloseHandle(hFile);  return;  /卸載文件映射,關(guān)閉文件句柄 UnmapViewOfFile(lpHeadBase); CloseHandle(hMapping); C

27、loseHandle(hFile); /在編輯框中顯示信息 m_RichEditProcInfo.ReplaceSel("文件加殼完成!rn");  MessageBox("創(chuàng)建文件成功!","成功提示",MB_OK); 針對(duì)于上次還要修改的地方:打開對(duì)話框資源,修改RichEdit的屬性,勾選“多行”和“自動(dòng)垂直滾動(dòng)”,去掉“自動(dòng)水平滾動(dòng)”。在OnButtonOpenfile() 函數(shù)中,在代碼 /替換編輯框最后的內(nèi)容,實(shí)際上就是在最后添加內(nèi)容。 m_RichEd

28、itProcInfo.ReplaceSel("文件路徑:"); m_RichEditProcInfo.ReplaceSel(m_FilePathName);的后面添加: m_RichEditProcInfo.ReplaceSel("rn");(3)檢測文件格式主要內(nèi)容:檢測文件格式(是否為PE格式的EXE文件)本次的主要內(nèi)容為檢測文件是否為PE格式,且是否為EXE文件。DLL等文件也是PE格式,但其加殼的一些數(shù)據(jù)處理方式不一樣,最明顯的一個(gè)差別就是DLL文件需要重定位。本系統(tǒng)現(xiàn)在暫時(shí)只處理EXE可執(zhí)行文件。截圖效果:(在RichEdi

29、t中多了個(gè)文件格式提示) 首先添加一個(gè)成員函數(shù):IsPe,用來判斷文件格式。如果滿足就返回TRUE,否則返回FALSE。在classview視圖中,找到CPEPackerDlg類,在其上面點(diǎn)擊右鍵,選擇“Add member Function.” ,函數(shù)類型為BOOL,函數(shù)描述為IsPE(HANDLE hFile),Access為public,然后確定,編輯此函數(shù)。/檢測文件是否是PE可執(zhí)行文件格式BOOL CPEPackerDlg:IsPE(HANDLE hFile) WORD wTemp; /暫存讀取的字節(jié) DWORD 

30、dwBufferRead; /實(shí)際讀取的字節(jié)數(shù) DWORD dwOffset; /PE頭偏移位置 DWORD dwOEP;  /程序OEP /讀取MZ標(biāo)志 SetFilePointer(hFile,0,NULL,FILE_BEGIN); ReadFile(hFile,&wTemp,2,&dwBufferRead,NULL); /因?yàn)槎M(jìn)制目標(biāo)文件反著順序存儲(chǔ),所以要反過來判斷。 if (wTemp!='ZM')  

31、 return FALSE;  /讀取PE頭位置 SetFilePointer(hFile,0x3C,NULL,FILE_BEGIN); ReadFile(hFile,&dwOffset,4,&dwBufferRead,NULL); /讀取PE頭信息 SetFilePointer(hFile,dwOffset,NULL,FILE_BEGIN); ReadFile(hFile,&wTemp,2,&dwBufferRead,NULL); /判斷是否為PE,同樣要反著判斷。

32、60;if (wTemp!='EP')   return FALSE;  /獲取文件OEP SetFilePointer(hFile,dwOffset+0x28,NULL,FILE_BEGIN); ReadFile(hFile,&dwOEP,4,&dwBufferRead,NULL); /如果OEP為0。 if (!dwOEP)   return FALSE;  /獲取文件特征,判斷是exe還是dll文件。 Set

33、FilePointer(hFile,dwOffset+0x16,NULL,FILE_BEGIN); ReadFile(hFile,&wTemp,2,&dwBufferRead,NULL); if (wTemp & 0x2000 !=0)   return FALSE;  return TRUE;最后在OnButtonPacking函數(shù)中,運(yùn)用此函數(shù)。將此函數(shù)添加在打開文件CreateFile和創(chuàng)建映射之間。如果文件格式正確,就創(chuàng)建映射;否則,就返回。添加后的代碼為:  /如果文件打

34、開失敗,就彈出對(duì)話框,并返回。 if (hFile=INVALID_HANDLE_VALUE)   MessageBox("打開文件失?。?quot;,"錯(cuò)誤提示",MB_OK);  return; /第三次加的內(nèi)容/ /判斷文件格式 if (!IsPE(hFile)   m_RichEditProcInfo.ReplaceSel("錯(cuò)誤提示:文件不是PE格式!rn");  MessageBox("

35、;文件不是PE可執(zhí)行文件","錯(cuò)誤提示!",MB_OK);  return; / /獲取文件大小 dwFileSize=GetFileSize(hFile,NULL); /設(shè)定加殼后的文件名,我采取了一個(gè)偷懶的簡單方法。 /如果要嚴(yán)格做,需要獲取文件路徑,擴(kuò)展名等等。 m_FilePathNamePacked=m_FilePathName.Left(m_FilePathName.GetLength()-4)+"_packed.exe"(3) 通過分配虛擬內(nèi)存生成文件

36、主要內(nèi)容:給文件分配虛擬內(nèi)存并載入內(nèi)存,然后輸出加殼后文件。將PE文件載入內(nèi)存后再操作有三種方法。第一是通過文件映射的基址,其內(nèi)容在第二節(jié)中已經(jīng)應(yīng)用并實(shí)現(xiàn)。第二是獲取獲取文件大小,然后分配相應(yīng)大小的內(nèi)存。第三是模擬PE文件的加載機(jī)制,根據(jù)PE文件的鏡像大小分配相應(yīng)大小的內(nèi)存,然后將相應(yīng)的區(qū)塊載入到對(duì)應(yīng)的虛擬地址空間中。本次內(nèi)容將使用第三種方式加載文件到內(nèi)存。由于PE文件在運(yùn)行時(shí),對(duì)文件中數(shù)據(jù)的讀取都是通過RVA(相對(duì)虛擬地址)進(jìn)行的,如果采用第一種或者第二種方式加載到內(nèi)存,那么當(dāng)讀取數(shù)據(jù)的時(shí)候,還需要將RVA轉(zhuǎn)換成Offset(文件偏移),這種轉(zhuǎn)換雖然說不麻煩,但如果需要轉(zhuǎn)換的地方較多,有時(shí)也

37、會(huì)出錯(cuò),所以本系統(tǒng)的加殼也將采用第二種方式加入到內(nèi)存。載入內(nèi)存用先通過VirtualAlloc函數(shù)分配虛擬內(nèi)存空間,然后通過ReadFile讀入到內(nèi)存。根據(jù)PE文件的加載機(jī)制,PE文件會(huì)按照區(qū)段進(jìn)行載入,每個(gè)區(qū)段的虛擬地址在區(qū)段表中都有說明。最后的效果圖。首先添加兩個(gè)成員函數(shù):MemAlloc和MemAllocFree,在class view視圖中的CPEPackerDlg類上點(diǎn)擊右鍵,選擇“add member function.”。函數(shù)類型和說明分別如下: BOOL MemAlloc(HANDLE hFile);  /分配內(nèi)存 void MemAll

38、ocFree();  /釋放內(nèi)存然后再添加幾個(gè)成員變量,在class view視圖中的CPEPackerDlg類上點(diǎn)擊右鍵,選擇“add member variables.” 。變量類型和名稱如下,Access都選擇public。定義的都是指針類型變量。 LPVOID                         &

39、#160;                  lpVirtualtAlloc;  /內(nèi)存分配指針 PIMAGE_DOS_HEADER                    pDosHeader; /DOS頭指針

40、 PIMAGE_NT_HEADERS                     pNtHeader; /NT頭 PIMAGE_OPTIONAL_HEADER           pOptionalHeader; /可選頭指針 PIMAGE_SECTIO

41、N_HEADER             pSectionHeader;  /區(qū)塊表指針此時(shí)我們把兩個(gè)編輯框的屬性設(shè)置為只讀。第一個(gè)編輯框設(shè)置為只讀后,獲取文件路徑時(shí)方便點(diǎn),如果用戶不是通過按鈕來選擇文件,而是手動(dòng)輸入文件路徑,那么就還需要一個(gè)判斷和獲取文件。所以為了省去這種麻煩,我們干脆設(shè)置為只讀算了。第二個(gè)編輯框本來只輸出信息,不需要修改,所以設(shè)置為只讀。設(shè)置方法。在資源視圖中打開該對(duì)話框,然后在編輯框的屬性中選擇“樣式”標(biāo)簽,最后面有個(gè)“只讀”復(fù)選框

42、,勾上就行了。編寫代碼。MemAlloc函數(shù)的代碼如下,我都做了注釋,就不多說了。/文件分配虛擬內(nèi)存BOOL CPEPackerDlg:MemAlloc(HANDLE hFile) DWORD dwSizeOfImage; /映像大小 DWORD dwSizeOfHeaders; /文件頭大小 DWORD dwBufferRead; /文件實(shí)際讀入大小 DWORD dwOffset;  /PE頭偏移 char szBuffer512; 

43、/調(diào)試用 DWORD dwNumOfSections; /區(qū)段表個(gè)數(shù) DWORD i; /獲取文件的映像大小,從PE頭中讀取。 SetFilePointer(hFile,0x3C,NULL,FILE_BEGIN); ReadFile(hFile,&dwOffset,4,&dwBufferRead,NULL); /讀取PE頭位置 SetFilePointer(hFile,dwOffset+0x50,NULL,FILE_BEGIN); ReadFile(hFile,&

44、;dwSizeOfImage,4,&dwBufferRead,NULL);/讀取文件映像大小 SetFilePointer(hFile,dwOffset+0x54,NULL,FILE_BEGIN); ReadFile(hFile,&dwSizeOfHeaders,4,&dwBufferRead,NULL);/讀取文件頭大小 sprintf(szBuffer,"文件頭:%lx,文件頭大?。?lx,文件映像大?。?lxrn",  dwOffset,dwSizeOfHeaders,dwSizeOfImage

45、); m_RichEditProcInfo.ReplaceSel(szBuffer); /分配虛擬內(nèi)存 /MEM_RESERVE保留分配 /MEM_COMMIT表示提交分配 /申請(qǐng)內(nèi)存的同時(shí)提交分配,具體用法可以參考MSDN。 lpVirtualtAlloc=VirtualAlloc(NULL,dwSizeOfImage,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE); /如果分配失敗 if (lpVirtualtAlloc=NULL)   return

46、FALSE;  /將文件讀入到內(nèi)存中 /首先讀取文件頭 SetFilePointer(hFile,0,NULL,FILE_BEGIN); ReadFile(hFile,lpVirtualtAlloc,dwSizeOfHeaders,&dwBufferRead,NULL); /獲取PE文件頭相關(guān)指針 pDosHeader=(PIMAGE_DOS_HEADER)lpVirtualtAlloc; pNtHeader=(PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew+(DWOR

47、D)pDosHeader); pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)(&pNtHeader->OptionalHeader); /IMAGE_FIRST_SECTION是VC下定義的一個(gè)宏,用來獲取區(qū)段表的頭指針 pSectionHeader=IMAGE_FIRST_SECTION(pNtHeader); /然后分區(qū)塊進(jìn)行讀入 dwNumOfSections=pNtHeader->FileHeader.NumberOfSections; for (i=0;i<dwnu

48、mofsections;i+)   /將指針設(shè)定到每個(gè)區(qū)塊的開始  SetFilePointer(hFile,(pSectionHeader+i)->PointerToRawData,NULL,FILE_BEGIN);  /根據(jù)每個(gè)區(qū)塊的原始大小讀入到相應(yīng)的虛擬地址中去。  ReadFile(hFile,(LPVOID)(DWORD)lpVirtualtAlloc+(pSectionHeader+i)->VirtualAddress),(pSectionHeader+i)->SizeOf

49、RawData,&dwBufferRead,NULL); </dwnumofsections;i+) return TRUE;第二個(gè)函數(shù),MemAllocFree主要是釋放分配的內(nèi)存。void CPEPackerDlg:MemAllocFree() /釋放分配的虛擬內(nèi)存 VirtualFree(lpVirtualtAlloc,0,MEM_DECOMMIT); VirtualFree(lpVirtualtAlloc,0,MEM_RELEASE);最后在主函數(shù)OnButtonPacking中調(diào)用分配函數(shù),及釋放函數(shù)。 /第三

50、次加的內(nèi)容/ /判斷文件格式 if (!IsPE(hFile)   m_RichEditProcInfo.ReplaceSel("錯(cuò)誤提示:文件不是PE格式!rn");  MessageBox("文件不是PE可執(zhí)行文件","錯(cuò)誤提示!",MB_OK);  return;  /第四次內(nèi)容。分配內(nèi)存,并載入內(nèi)存/ if (!MemAlloc(hFile)   m_RichEditProcIn

51、fo.ReplaceSel("錯(cuò)誤提示:文件加載到內(nèi)存失??!rn");  MessageBox("文件加載到內(nèi)存失??!","錯(cuò)誤提示!",MB_OK);  return;  /獲取文件大小 dwFileSize=GetFileSize(hFile,NULL); /設(shè)定加殼后的文件名,我采取了一個(gè)偷懶的簡單方法。 /文件寫入完畢后,釋放內(nèi)存MemAllocFree(); /卸載文件映射,關(guān)閉文件句柄 UnmapViewOfFil

52、e(lpHeadBase); CloseHandle(hMapping); CloseHandle(hFile); /在編輯框中顯示信息最后還要將寫入函數(shù)的指針設(shè)置為內(nèi)存分配的句柄,代碼如下: /寫入文件 if (!WriteFile(hFile,lpVirtualtAlloc,dwFileSize,&dwBufferRead,NULL)   MessageBox("寫入文件失??!","錯(cuò)誤提示!",MB_OK);  /卸載文件映射,關(guān)閉文件句柄&

53、#160; CloseHandle(hFile);  return; 最后編譯,運(yùn)行,即可。如有問題,請(qǐng)對(duì)照發(fā)布的源代碼。為了優(yōu)化函數(shù),把第2次內(nèi)容所使用的文件映射相關(guān)的內(nèi)容都刪除掉。刪除后的按鈕事件代碼如下:void CPEPackerDlg:OnButtonPacking()  / TODO: Add your control notification handler code here HANDLE hFile; /文件句柄 DWORD dwFileSize; /文件大小

54、0;DWORD dwBufferRead; /實(shí)際讀取字節(jié) /打開文件 hFile=CreateFile(m_FilePathName,GENERIC_READ,FILE_SHARE_READ,NULL,  OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); /如果文件打開失敗,就彈出對(duì)話框,并返回。 if (hFile=INVALID_HANDLE_VALUE)   MessageBox("打開文件失敗!","錯(cuò)誤提示&

55、quot;,MB_OK);  return;  /第三次加的內(nèi)容/ /判斷文件格式 if (!IsPE(hFile)   m_RichEditProcInfo.ReplaceSel("錯(cuò)誤提示:文件不是PE格式!rn");  MessageBox("文件不是PE可執(zhí)行文件","錯(cuò)誤提示!",MB_OK);  return;  / /第四次內(nèi)容。分配內(nèi)存,并載入內(nèi)存/ 

56、if (!MemAlloc(hFile)   m_RichEditProcInfo.ReplaceSel("錯(cuò)誤提示:文件加載到內(nèi)存失??!rn");  MessageBox("文件加載到內(nèi)存失?。?quot;,"錯(cuò)誤提示!",MB_OK);  return;  /獲取文件大小 dwFileSize=GetFileSize(hFile,NULL); /設(shè)定加殼后的文件名,我采取了一個(gè)偷懶的簡單方法。 /如果要嚴(yán)格做,需要獲取文件

57、路徑,擴(kuò)展名等等。 m_FilePathNamePacked=m_FilePathName.Left(m_FilePathName.GetLength()-4)+"_packed.exe" CloseHandle(hFile); /創(chuàng)建加殼后的文件句柄 hFile=CreateFile(m_FilePathNamePacked,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,  NULL,CREATE_ALWAYS,FILE_ATTRIBUTE

58、_NORMAL,NULL); if (hFile=INVALID_HANDLE_VALUE)   MessageBox("生成文件失??!","錯(cuò)誤提示!",MB_OK);  /寫入文件 if (!WriteFile(hFile,lpVirtualtAlloc,dwFileSize,&dwBufferRead,NULL)   MessageBox("寫入文件失??!","錯(cuò)誤提示!",MB_OK); &

59、#160;/卸載文件映射,關(guān)閉文件句柄  CloseHandle(hFile);  return;  /文件寫入完畢后,釋放內(nèi)存 MemAllocFree(); /卸載文件映射,關(guān)閉文件句柄 CloseHandle(hFile); /在編輯框中顯示信息 m_RichEditProcInfo.ReplaceSel("文件加殼完成!rn");  MessageBox("創(chuàng)建文件成功!","成功提示",MB_OK

60、);(4) 給程序添加一個(gè)區(qū)段主要內(nèi)容:添加一個(gè)新的文件區(qū)段,用來存放殼代碼,并用8來填充區(qū)段。本次內(nèi)容將添加一個(gè)新的區(qū)段到原PE文件中,一般加殼程序都會(huì)添加一個(gè)新的區(qū)段用來存放殼代碼(這只是一般情況)。然后修改添加區(qū)段后的文件的入口點(diǎn),讓程序從添加的殼代碼段開始運(yùn)行。本次內(nèi)容只添加區(qū)段,不修改程序入口點(diǎn)。添加區(qū)段的主要有三個(gè)步驟。第一,是修改PE文件頭信息。增加一個(gè)區(qū)段后,要修改NT頭中的區(qū)段表個(gè)數(shù)成員,修改可選頭的文件鏡像大小成員。第二,獲取要添加的區(qū)段的存放位置和大小,包括文件偏移位置和大小、文件相對(duì)虛擬地址和虛擬大小第三,就是將文件寫入到文件末尾。添加區(qū)段后的區(qū)段表對(duì)比圖如下:首先添加

61、三個(gè)成員函數(shù),如下: BOOL MakePacking(HANDLE hFile);  /生成加殼后的文件 void MakeShell(HANDLE hFile);  /生成殼代碼段 void EditHeader();  /修改文件頭信息 再添加兩個(gè)成員變量,public型。 LPVOID lpVirtualShell;   /殼虛擬內(nèi)存指針 DWORD SizeOfShell; /殼代碼的的大小 DW

62、ORD SizeOfImage;  /文件鏡像大小MakeShell函數(shù)功能是生成殼代碼數(shù)據(jù),先暫時(shí)用0填充該數(shù)據(jù)段。其功能代碼如下:/生成殼代碼段void CPEPackerDlg:MakeShell(HANDLE hFile) /殼代碼段中暫定為用8填充 SizeOfShell=0x100; /大小暫時(shí)定為256字節(jié) lpVirtualShell=VirtualAlloc(NULL,SizeOfShell,MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE); memset(lpVi

63、rtualShell,8,SizeOfShell);修改PE頭,主要是修改區(qū)段表個(gè)數(shù)和鏡像大小。/修改PE文件頭信息,主要是區(qū)塊個(gè)數(shù)和鏡像大小void CPEPackerDlg:EditHeader() DWORD dwNumOfSections; /區(qū)塊個(gè)數(shù) DWORD dwFileAlign; /文件粒度(文件對(duì)齊大?。?#160;DWORD dwSectionAlign; /塊粒度(內(nèi)存對(duì)齊大?。?#160;DWORD dwAlignLastSection; /最后一個(gè)區(qū)段按內(nèi)存對(duì)齊后的大

64、小 LPVOID lpShellSecTab;  /殼區(qū)段表指針 IMAGE_SECTION_HEADER SectionHeaderOfShell; /殼代碼段的區(qū)塊表信息  /以下為修改區(qū)段表信息功能,主要是增加殼區(qū)段表/ /初始化區(qū)段表結(jié)構(gòu) memset(&SectionHeaderOfShell,0,sizeof(SectionHeaderOfShell); /獲取對(duì)齊大小數(shù)據(jù) dwFileAlign=pOptionalHeader->File

65、Alignment; dwSectionAlign=pOptionalHeader->SectionAlignment; /獲取區(qū)塊表個(gè)數(shù) dwNumOfSections=pNtHeader->FileHeader.NumberOfSections; /設(shè)定殼的區(qū)塊表信息 SectionHeaderOfShell.Misc.PhysicalAddress=SizeOfShell; /原始大小 /在文件中對(duì)齊后的大小,除以文件粒度,如果余數(shù)為零,就直接使用;否則,就擴(kuò)充對(duì)齊。 SectionHeaderO

66、fShell.SizeOfRawData=(SizeOfShell%dwFileAlign)?(dwFileAlign*(SizeOfShell/dwFileAlign+1):SizeOfShell;  /區(qū)塊特征 SectionHeaderOfShell.Characteristics=IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; memcpy(&SectionHeaderOfShell.Name,".bugsky",7);  

67、/區(qū)塊名稱 SectionHeaderOfShell.PointerToRelocations=0; /重定位偏移 SectionHeaderOfShell.NumberOfRelocations=0;  /重定位表數(shù)目 SectionHeaderOfShell.PointerToLinenumbers=0; /行號(hào)表偏移 SectionHeaderOfShell.NumberOfLinenumbers=0;  /行號(hào)表中行號(hào)數(shù)目   /對(duì)齊最后一個(gè)區(qū)段后的塊大小,來計(jì)算殼區(qū)段的虛擬地址。 if (pSectionHeader+dwNumOfSections-1)->SizeOfRawData % dwSectionAlign)   dwAlignLastSection=dwSectionAlign*(pSectionHeader+dwNumOfSections-1)->SizeOfRaw

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論