




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、使用VC自己動(dòng)手編寫(xiě)加殼程序閱讀對(duì)象:想寫(xiě)殼的新手。高手掠過(guò),本文僅限于寫(xiě)殼入門(mén)?;疽螅毫私釼C+6.0基本使用方法;了解PE格式,不熟悉的地方能夠通過(guò)查閱資料弄懂;(1)生成界面,完成文件操作主要內(nèi)容:生成界面,完成打開(kāi)文件對(duì)話框。首先說(shuō)一下寫(xiě)作原因。最初學(xué)習(xí)加殼技術(shù),網(wǎng)上確實(shí)能找到一些源代碼,但90%的沒(méi)有注釋?zhuān)院芏啻a都看不懂。即使某個(gè)函數(shù)大體功能知道,但其中的小細(xì)節(jié)由于沒(méi)有注釋?zhuān)膊恢雷髡叩挠猛臼鞘裁?,所以這一過(guò)程相當(dāng)痛苦。當(dāng)時(shí)對(duì)于我來(lái)說(shuō),一個(gè)簡(jiǎn)單的加殼程序也是相當(dāng)復(fù)雜。有時(shí)候想修改他們的程序,但程序結(jié)構(gòu)牽一發(fā)而動(dòng)全身,不得不放棄。有些程序前面90%的代碼都在做鋪墊和打基礎(chǔ),
2、而最后的10%是合并功能,往往我們?cè)诜治銮懊娴?0%中的20%就沒(méi)有耐心了,因?yàn)殇亯|太多,讓我們感覺(jué)沒(méi)有成就感,感覺(jué)不到那么多代碼是干嘛的。所以本文在寫(xiě)作時(shí),每一部分都會(huì)實(shí)實(shí)在在的實(shí)現(xiàn)一部分功能,讓我們有些成就感,這樣才有興趣。寫(xiě)此文是給像我一樣想寫(xiě)殼卻無(wú)從下手的人一個(gè)參考。不過(guò)本人現(xiàn)在也是研究階段,能力有限,文章一方面是總結(jié)一下自己,另一方面也希望和大家多多交流。殼的理論我就不多說(shuō)了。一開(kāi)始就說(shuō)一大堆理論同樣會(huì)使學(xué)習(xí)失去興趣,我就喜歡邊動(dòng)手邊理論。開(kāi)始吧。打開(kāi)VC+6.0,新建工程,工程名稱(chēng)“PEPackef,選擇“MFCAppWizard(exe)”,下一步,選擇基于對(duì)話框的應(yīng)用程序。在對(duì)
3、話框中刪除默認(rèn)的確定”、取消”按鈕,還有默認(rèn)的文本信息。如下圖所示:然后按F7組建(編譯)程序,可以從IDE的提示窗口中看到是否生成成功,按CTRL+F5程序是能夠正常運(yùn)行的,不過(guò)是一個(gè)什么都沒(méi)有的對(duì)話框?,F(xiàn)在我們要添加元素了。添加兩個(gè)組框、一個(gè)編輯框、三個(gè)按鈕、一個(gè)Rich編輯框?,F(xiàn)在修改其屬性。在對(duì)話框上點(diǎn)擊右鍵,選擇屬性”,打開(kāi)屬性對(duì)話框,在對(duì)話框的左上角有個(gè)像釘子一樣的圖標(biāo),點(diǎn)擊一下,這樣屬性對(duì)話框就會(huì)像釘子一樣保持可見(jiàn)了,我們就不需要每修改一個(gè)控件屬性的時(shí)候就點(diǎn)一下右鍵選擇了。修改屬性后的控件ID和標(biāo)題如下:控件類(lèi)型ID值標(biāo)題組框IDC_STATIC請(qǐng)選擇文件組框IDC_STATIC
4、文件處理信息按鈕IDCBUTTONOPENFILE選擇文件按鈕IDCBUTTONPACKING開(kāi)始加殼按鈕IDC_BUTTON_ABOUT關(guān)于本程序編輯框IDC_EDIT_FILEPATHNAME無(wú)Rich編輯框IDCRICHEDITPROCINFO無(wú)對(duì)話框IDD_PEPACKER_DIALOGPEPackerV1.0設(shè)置好的界面如下圖所示:IrlnrIIir,fiIiib1in)IihriritpiIi?Iii-iIitfi>IiifIihrII|liHfffflllM小品諳選擇空件-?:研選擇文件!_-:開(kāi)始加殼關(guān)于,程序:文件處理信息jRichEdiF現(xiàn)在按F7編譯,CTRL+F5
5、運(yùn)行一下,發(fā)現(xiàn)程序好沒(méi)有動(dòng)靜。什么反應(yīng)也沒(méi)有,如果把RichEdit刪除掉,再編譯,再運(yùn)行就可以。這個(gè)問(wèn)題是由于RichEidt沒(méi)有初始化引起的,微軟的說(shuō)法是要在APP的初始化函數(shù)中加入初始化函數(shù):AfxInitRichEdit()。那我們現(xiàn)在加入。在classview視圖中,展開(kāi)CPEPackerApp類(lèi),雙擊InitInstance()函數(shù),在AfxEnableControlContainer();后面添加代碼AfxInitRichEdit();,添加后的函數(shù)代碼如下:BOOLCPEPackerApp:InitInstance()AfxEnableControlContainer();Af
6、xInitRichEdit();/Standardinitialization/Ifyouarenotusingthesefeaturesandwishtoreducethesize/ofyourfinalexecutable,youshouldremovefromthefollowing/thespecificinitializationroutinesyoudonotneed.此時(shí)再F7編譯,CTRL+F5運(yùn)行,就可以看到程序正常運(yùn)行了。再修改一下對(duì)話框的屬性,右鍵,選擇屬性”后,在樣式”標(biāo)簽中,勾選上最小化框N",這樣對(duì)話框就可以最小化了。當(dāng)然你還可以選擇其它屬性。現(xiàn)在來(lái)添加成
7、員變量。在編輯框上點(diǎn)擊右鍵,選擇建立類(lèi)向?qū)А保蜷_(kāi)類(lèi)向?qū)?duì)話框,然后選擇"MemberVariables”標(biāo)簽。注意Project:里面是否是PEPacker,Classname:里面是否是CPEPackerDlg,然后在ControlIDs:里面找到IDC_EDIT_FILEPATHNAME,雙擊。或者點(diǎn)擊右邊的“AddVarible.按鈕,在"AddMemberVarible對(duì)話框中添加成員變量。變量名為"m_FilePathName”,Category選擇"Value:變量類(lèi)型選擇"CString:然后確定。用同樣的方法給控件IDC_RI
8、CHEDIT_PROCINFO添加成員變量。變量名為m_RichEditProcInfo,注意category選擇Control,變量類(lèi)型為CRichEditCtrl。最后確定。雙擊選擇文件”按鈕,彈出添加程序函數(shù)對(duì)話框,函數(shù)名你為:OnButtonOpenfile,我們確定即可,使用默認(rèn)的,當(dāng)然也可以修改。此時(shí)來(lái)到了PEPackerDlg.cpp文件中,界面默認(rèn)的位置是剛剛添加的函數(shù)編輯處。代碼如下:voidCPEPackerDlg:OnButtonOpenfile()/TODO:Addyourcontrolnotificationhandlercodehere此時(shí)在此函數(shù)中添加如下代碼:代
9、碼我會(huì)作注釋。voidCPEPackerDlg:OnButtonOpenfile()/TODO:Addyourcontrolnotificationhandlercodehere/設(shè)置文件過(guò)濾,默認(rèn)打開(kāi)哪些文件類(lèi)型,最后“|結(jié)束。charszFilter="可執(zhí)行文件(*.exe)|*.exe|全部文件(*.*)|*.*|"/通過(guò)查閱MSDN,了解CFileDialog中構(gòu)造函數(shù)的用法。/第一個(gè)參數(shù)為T(mén)RUE,表示打開(kāi)文件對(duì)話框;為FALSE,表示保存對(duì)話框。/其他詳細(xì)參數(shù)說(shuō)明見(jiàn)后面。CFileDialogdlg(TRUE,NULL,NULL,OFN_HIDEREADONL
10、Y|OFN_OVERWRITEPROMPT,szFilter,NULL);/通過(guò)模態(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.ReplaceSel(m_FilePathName);/用獲取的文件路
11、徑更新編輯框內(nèi)容。UpdateData(FALSE);添加完成后,本次功能結(jié)束。編譯運(yùn)行即可,運(yùn)行界面如下:PEPackerVI.0作者;天漏客http:/lilu.itasejPx請(qǐng)選擇文件消熏目臨時(shí)文件夾««|匚落舞需笑R開(kāi)始加殼J關(guān)于本程序1文件處理信息文件路徑:G消黑客臨時(shí)文件夾««其中CFileDialog類(lèi)的詳細(xì)說(shuō)明如下:CFileDialog文件選擇對(duì)話框的使用:首先構(gòu)造一個(gè)對(duì)象并提供相應(yīng)的參數(shù),構(gòu)造函數(shù)原型如下:CFileDialog:CFileDialog(BOOLbOpenFileDialog,LPCTSTRlpszDefExt=NU
12、LL,LPCTSTRlpszFileName=NULL,DWORDdwFlags=OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,LPCTSTRlpszFilter=NULL,CWnd*pParentWnd=NULL);參數(shù)意義如下:bOpenFileDialog為T(mén)RUE則顯示打開(kāi)對(duì)話框,為FALSE則顯示保存對(duì)話文件對(duì)話框。IpszDefExt指定默認(rèn)的文件擴(kuò)展名。IpszFileName指定默認(rèn)的文件名。dwFlags指明一些特定風(fēng)格。lpszFilter是最重要的一個(gè)參數(shù),它指明可供選擇的文件類(lèi)型和相應(yīng)的擴(kuò)展名。參數(shù)格式如:"ChartFiles(*
13、.xlc)|*.xlc|WorksheetFiles(*.xls)|*.xls|DataFiles(*.xlc;*.xls)|*.xlc;*.xls|AllFiles(*.*)|*.*|"|分隔,同種類(lèi)型文件的|分隔,末尾用|指明。在返回后可以利用下面的函數(shù)得到用戶選擇:得到完整的文件名,包括目錄名和擴(kuò)展名如:得到完整的文件名,包括擴(kuò)展名如:test1.txt得到完整的文件擴(kuò)展名,如:txt得到完整的文件名,不包括目錄名和擴(kuò)展名如:對(duì)于選擇了多個(gè)文件的情況得到第一個(gè)文件類(lèi)型說(shuō)明和擴(kuò)展名間用擴(kuò)展名間可以用;分割,每種文件類(lèi)型間用pParentWnd為父窗口指針。創(chuàng)建文件對(duì)話框可以使用D
14、oModal(),CStringCFileDialog:GetPathName()c:estest1.txtCStringCFileDialog:GetFileName()CStringCFileDialog:GetExtName()CStringCFileDialog:GetFileTitle()test1POSITIONCFileDialog:GetStartPosition()文件位置。CStringCFileDialog:GetNextPathName(POSITION&pos)對(duì)于選擇了多個(gè)文件的情況得到下一個(gè)文件位置,并同時(shí)返回當(dāng)前文件名。但必須已經(jīng)調(diào)用過(guò)POSITIONC
15、FileDialog:GetStartPosition()來(lái)得到最初的POSITION變量。(2)使用內(nèi)存映射生成文件主要內(nèi)容:打開(kāi)文件,使用內(nèi)存映射生成文件。本次要完成的任務(wù)是:點(diǎn)擊開(kāi)始加殼”按鈕,生成加殼后的文件,當(dāng)然這是假想加過(guò)殼,并沒(méi)有加殼。實(shí)際上就是將文件改名,復(fù)制成另外一個(gè)文件,但又不同于復(fù)制。因?yàn)槭窍葘⑽募?chuàng)建內(nèi)存映射,然后再通過(guò)映射指針寫(xiě)回文件。本次的界面效果:首先添加幾個(gè)和文件名相關(guān)的成員變量。在classview中,雙擊PEPackerDlg函數(shù),在類(lèi)的定義中申明成員變量:public:加殼后的文件名CStringm_FilePathNamePacked;/下面來(lái)添加開(kāi)始加
16、殼”按鈕的函數(shù)。在開(kāi)始加殼”按鈕上雙擊,將出現(xiàn)新建函數(shù)的提示,確定即可。也可以點(diǎn)擊工具欄上的查看”菜單,選擇建立類(lèi)向?qū)А?,選中“MessageMaps標(biāo)簽。Project:設(shè)置為PEPacker,Classname:設(shè)置為CPEPackerDlg,ObjectIDs選中IDC_BUTTON_PACKING,Messages:選中BN_CLICKED,然后點(diǎn)擊右邊的“AddFunction.按鈕,添加函數(shù)“OnButtonPacking即可。空的函數(shù)為:voidCPEPackerDlg:OnButtonPacking()/TODO:Addyourcontrolnotificationhandle
17、rcodehere現(xiàn)在在該函數(shù)中添加內(nèi)容。代碼部分我都做了注釋?zhuān)晕揖筒欢嗾f(shuō)了。voidCPEPackerDlg二OnButtonPacking()(/TODO:Addyourcontrolnotificationhandlercodehere文件句柄文件映射句柄創(chuàng)建映射的頭指針文件大小實(shí)際讀取字節(jié)HANDLEhFile;/HANDLEhMapping;/LPVOIDlpHeadBase;/DWORDdwFileSize;/DWORDdwBufferRead;/打開(kāi)文件hFile=CreateFile(m_FilePathName,GENERIC_READ,FILE_SHARE_READ,N
18、ULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);/如果文件打開(kāi)失敗,就彈出對(duì)話框,并返回。if(hFile=INVALID_HANDLE_VALUE)(MessageBox("打開(kāi)文件失敗!”,"錯(cuò)誤提示",MB_OK);return;/獲取文件大小dwFileSize=GetFileSize(hFile,NULL);/設(shè)定加殼后的文件名,我采取了一個(gè)偷懶的簡(jiǎn)單方法。/如果要嚴(yán)格做,需要獲取文件路徑,擴(kuò)展名等等。m_FilePathNamePacked=m_FilePathName.Left(m_FilePathName
19、.GetLength()-4)+”_packed.exe"/創(chuàng)建文件映射。如果對(duì)文件映射不了解,請(qǐng)自行查閱相關(guān)資料。hMapping=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);/如果創(chuàng)建映射失敗,彈出對(duì)話框,并關(guān)閉文件句柄,然后返回。if(hMapping=NULL)(MessageBox("創(chuàng)建文件映射失??!","錯(cuò)誤提示",MB_OK);CloseHandle(hFile);/關(guān)閉創(chuàng)建的文件句柄return;/將文件映射對(duì)象映射到當(dāng)前應(yīng)用程序的地址空間中l(wèi)pHeadBase=M
20、apViewOfFile(hMapping,FILE_MAP_READ,0,0,0);if(lpHeadBase=NULL)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_READ|FILE_SHARE_WRITE,NULL,CREAT
21、E_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);if(hFile=INVALID_HANDLE_VALUE)MessageBox("生成文件失敗!”,”錯(cuò)誤提示!",MB_OK);/寫(xiě)入文件if(!WriteFile(hFile,lpHeadBase,dwFileSize,&dwBufferRead,NULL)MessageBox("寫(xiě)入文件失敗!”,”錯(cuò)誤提示!",MB_OK);/卸載文件映射,關(guān)閉文件句柄UnmapViewOfFile(lpHeadBase);CloseHandle(hMapping);CloseHa
22、ndle(hFile);return;/卸載文件映射,關(guān)閉文件句柄UnmapViewOfFile(lpHeadBase);CloseHandle(hMapping);CloseHandle(hFile);/在編輯框中顯示信息m_RichEditProcInfo.ReplaceSel("文件加殼完成!rn");MessageBox("創(chuàng)建文件成功!”,"成功提示",MB_OK);)針對(duì)于上次還要修改的地方:打開(kāi)對(duì)話框資源,修改RichEdit的屬性,勾選多行”和自動(dòng)垂直滾動(dòng)”,去掉自動(dòng)水平滾動(dòng)”。在OnButtonOpenfile()函數(shù)中,在代
23、碼/替換編輯框最后的內(nèi)容,實(shí)際上就是在最后添加內(nèi)容。m_RichEditProcInfo.ReplaceSel("文件路徑:");m_RichEditProcInfo.ReplaceSel(m_FilePathName);的后面添加:m_RichEditProcInfo.ReplaceSel("rn");(3)檢測(cè)文件格式主要內(nèi)容:檢測(cè)文件格式(是否為PE格式的EXE文件)本次的主要內(nèi)容為檢測(cè)文件是否為PE格式,且是否為EXE文件。DLL等文件也是PE格式,但其加殼的一些數(shù)據(jù)處理方式不一樣,最明顯的一個(gè)差別就是DLL文件需要重定位。本系統(tǒng)現(xiàn)在暫時(shí)只處理E
24、XE可執(zhí)行文件。截圖效果:(在RichEdit中多了個(gè)文件格式提示)首先添加一個(gè)成員函數(shù):IsPe,用來(lái)判斷文件格式。如果滿足就返回TRUE,否則返回FALSE。在classview視圖中,找到CPEPackerDlg類(lèi),在其上面點(diǎn)擊右鍵,選擇"AddmemberFunction.,”函數(shù)類(lèi)型為BOOL,函數(shù)描述為IsPE(HANDLEhFile),Access為public,然后確定,編輯此函數(shù)。/檢測(cè)文件是否是PE可執(zhí)行文件格式BOOLCPEPackerDlg:IsPE(HANDLEhFile)WORDwTemp;/暫存讀取的字節(jié)DWORDdwBufferRead;/實(shí)際讀取的字
25、節(jié)數(shù)DWORDdwOffset;/PE頭偏移位置DWORDdwOEP;程序OEP/讀取MZ標(biāo)志SetFilePointer(hFile,0,NULL,FILE_BEGIN);ReadFile(hFile,&wTemp,2,&dwBufferRead,NULL);/因?yàn)槎M(jìn)制目標(biāo)文件反著順序存儲(chǔ),所以要反過(guò)來(lái)判斷。if(wTemp!='ZM')returnFALSE;/讀取PE頭位置SetFilePointer(hFile,0x3C,NULL,FILE_BEGIN);ReadFile(hFile,&dwOffset,4,&dwBufferRead,
26、NULL);/讀取PE頭信息SetFilePointer(hFile,dwOffset,NULL,FILE_BEGIN);ReadFile(hFile,&wTemp,2,&dwBufferRead,NULL);/判斷是否為PE,同樣要反著判斷。if(wTemp!='EP')returnFALSE;/獲取文件OEPSetFilePointer(hFile,dwOffset+0x28,NULL,FILE_BEGIN);ReadFile(hFile,&dwOEP,4,&dwBufferRead,NULL);/如果OEP為0。if(!dwOEP)retu
27、rnFALSE;/獲取文件特征,判斷是exe還是dll文件。SetFilePointer(hFile,dwOffset+0x16,NULL,FILE_BEGIN);ReadFile(hFile,&wTemp,2,&dwBufferRead,NULL);if(wTemp&0x2000!=0)returnFALSE;returnTRUE;CreateFile最后在OnButtonPacking函數(shù)中,運(yùn)用此函數(shù)。將此函數(shù)添加在打開(kāi)文件和創(chuàng)建映射之間。如果文件格式正確,就創(chuàng)建映射;否則,就返回。添加后的代碼為:/如果文件打開(kāi)失敗,就彈出對(duì)話框,并返回。if(hFile=INV
28、ALID_HANDLE_VALUE)MessageBox("打開(kāi)文件失?。 ?"錯(cuò)誤提示",MB_OK);return;)/第三次加的內(nèi)容/判斷文件格式if(!IsPE(hFile)(m_RichEditProcInfo.ReplaceSel("錯(cuò)誤提示:文件不是PE格式!r'n");MessageBox("文件不是PE可執(zhí)行文件","錯(cuò)誤提示!",MB_OK);return;)/獲取文件大小dwFileSize=GetFileSize(hFile,NULL);/設(shè)定加殼后的文件名,我采取了一個(gè)偷
29、懶的簡(jiǎn)單方法。/如果要嚴(yán)格做,需要獲取文件路徑,擴(kuò)展名等等。m_FilePathNamePacked=m_FilePathName.Left(m_FilePathName.GetLength()-4)+"_packed.exe"(3)通過(guò)分配虛擬內(nèi)存生成文件主要內(nèi)容:給文件分配虛擬內(nèi)存并載入內(nèi)存,然后輸出加殼后文件。將PE文件載入內(nèi)存后再操作有三種方法。第一是通過(guò)文件映射的基址,其內(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)的虛擬地址空間中。本
30、次內(nèi)容將使用第三種方式加載文件到內(nèi)存。由于PE文件在運(yùn)行時(shí),對(duì)文件中數(shù)據(jù)的讀取都是通過(guò)RVA(相對(duì)虛擬地址)進(jìn)行的,如果采用第一種或者第二種方式加載到內(nèi)存,那么當(dāng)讀取數(shù)據(jù)的時(shí)候,還需要將RVA轉(zhuǎn)換成Offset(文件偏移),這種轉(zhuǎn)換雖然說(shuō)不麻煩,但如果需要轉(zhuǎn)換的地方較多,有時(shí)也會(huì)出錯(cuò),所以本系統(tǒng)的加殼也將采用第二種方式加入到內(nèi)存。載入內(nèi)存用先通過(guò)VirtualAlloc函數(shù)分配虛擬內(nèi)存空間,然后通過(guò)ReadFile讀入到內(nèi)存。根據(jù)PE文件的加載機(jī)制,PE文件會(huì)按照區(qū)段進(jìn)行載入,每個(gè)區(qū)段的虛擬地址在區(qū)段表中都有說(shuō)明。最后的效果圖。首先添加兩個(gè)成員函數(shù):MemAlloc和MemAllocFree,
31、在classview視圖中的CPEPackerDlg類(lèi)上點(diǎn)擊右鍵,選擇"addmemberfunction.。函數(shù)類(lèi)型和說(shuō)明分別如下:BOOLMemAlloc(HANDLEhFile);分配內(nèi)存voidMemAllocFree();/釋放內(nèi)存然后再添加幾個(gè)成員變量,在classview視圖中的CPEPackerDlg類(lèi)上點(diǎn)擊右鍵,選擇"addmembervariables.”。變量類(lèi)型和名稱(chēng)如下,Access都選擇public。定義的都是指針類(lèi)型變量。LPVOIDPIMAGE_DOS_HEADERPIMAGE_NT_HEADERSPIMAGE_OPTIONAL_HEADER
32、PIMAGE_SECTION_HEADERlpVirtualtAlloc;/內(nèi)存分配指針pDosHeader;/DOS頭指針pNtHeader;/NT頭pOptionalHeader;/可選頭指針pSectionHeader;/區(qū)塊表指針此時(shí)我們把兩個(gè)編輯框的屬性設(shè)置為只讀。第一個(gè)編輯框設(shè)置為只讀后,獲取文件路徑時(shí)方便點(diǎn),如果用戶不是通過(guò)按鈕來(lái)選擇文件,而是手動(dòng)輸入文件路徑,那么就還需要一個(gè)判斷和獲取文件。所以為了省去這種麻煩,我們干脆設(shè)置為只讀算了。第二個(gè)編輯框本來(lái)只輸出信息,不需要修改,所以設(shè)置為只讀。設(shè)置方法。在資源視圖中打開(kāi)該對(duì)話框,然后在編輯框的屬性中選擇樣式”標(biāo)簽,最后面有個(gè)只讀”
33、復(fù)選框,勾上就行了。編寫(xiě)代碼。MemAlloc函數(shù)的代碼如下,我都做了注釋?zhuān)筒欢嗾f(shuō)了。/文件分配虛擬內(nèi)存BOOLCPEPackerDlg:MemAlloc(HANDLEhFile)DWORDdwSizeOfImage;/映像大小DWORDdwSizeOfHeaders;/文件頭大小DWORDdwBufferRead;/文件實(shí)際讀入大小DWORDdwOffset;/PE頭偏移charszBuffer512;/調(diào)試用DWORDdwNumOfSections;/區(qū)段表個(gè)數(shù)DWORDi;/獲取文件的映彳t大小,從PE頭中讀取。SetFilePointer(hFile,0x3C,NULL,FILE_B
34、EGIN);ReadFile(hFile,&dwOffset,4,&dwBufferRead,NULL);讀取PE頭位置SetFilePointer(hFile,dwOffset+0x50,NULL,FILE_BEGIN);ReadFile(hFile,&dwSizeOfImage,4,&dwBufferRead,NULL);/讀取文件映像大小SetFilePointer(hFile,dwOffset+0x54,NULL,FILE_BEGIN);讀取文件頭大小ReadFile(hFile,&dwSizeOfHeaders,4,&dwBufferR
35、ead,NULL);/sprintf(szBuffer,”文件頭:%lx,文件頭大?。?lx,文件映像大小:lxrn",dwOffset,dwSizeOfHeaders,dwSizeOfImage);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);/如
36、果分配失敗if(lpVirtualtAlloc=NULL)(returnFALSE;)/將文件讀入到內(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+(DWORD)pDosHeade
37、r);pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)(&pNtHeader->OptionalHeader);/IMAGE_FIRST_SECTION是VC下定義的一個(gè)宏,用來(lái)獲取區(qū)段表的頭指針pSectionHeader=IMAGE_FIRST_SECTION(pNtHeader);/然后分區(qū)塊進(jìn)行讀入dwNumOfSections=pNtHeader->FileHeader.NumberOfSections;for(i=0;i<dwnumofsections;i+)/將指針設(shè)定到每個(gè)區(qū)塊的開(kāi)始SetFilePointer(hFil
38、e,(pSectionHeader+i)->PointerToRawData,NULL,FILE_BEGIN);/根據(jù)每個(gè)區(qū)塊的原始大小讀入到相應(yīng)的虛擬地址中去。ReadFile(hFile,(LPVOID)(DWORD)lpVirtualtAlloc+(pSectionHeader+i)->VirtualAddress),(pSectionHeader+i)->SizeOfRawData,&dwBufferRead,NULL);</dwnumofsections;i+)returnTRUE;第二個(gè)函數(shù),MemAllocFree主要是釋放分配的內(nèi)存。voidCP
39、EPackerDlg:MemAllocFree()/釋放分配的虛擬內(nèi)存VirtualFree(lpVirtualtAlloc,0,MEM_DECOMMIT);VirtualFree(lpVirtualtA110c,0,MEM_RELEASE);)最后在主函數(shù)OnButtonPacking中調(diào)用分配函數(shù),及釋放函數(shù)。/第三次加的內(nèi)容/判斷文件格式if(!IsPE(hFile)m_RichEditProcInfo.ReplaceSel("錯(cuò)誤提示:文件不是PE格式!r'n");MessageBox("文件不是PE可執(zhí)行文件","錯(cuò)誤提示!&
40、quot;,MB_OK);return;)/第四次內(nèi)容。分配內(nèi)存,并載入內(nèi)存/if(!MemAlloc(hFile)m_RichEditProcInfo.ReplaceSel("錯(cuò)誤提示:文件加載到內(nèi)存失敗!rn");MessageBox("文件加載到內(nèi)存失??!","錯(cuò)誤提示!",MB_OK);return;)/獲取文件大小dwFileSize=GetFileSize(hFile,NULL);/設(shè)定加殼后的文件名,我采取了一個(gè)偷懶的簡(jiǎn)單方法。/文件寫(xiě)入完畢后,釋放內(nèi)存MemAllocFree();/卸載文件映射,關(guān)閉文件句柄Unmap
41、ViewOfFile(lpHeadBase);CloseHandle(hMapping);CloseHandle(hFile);/在編輯框中顯示信息最后還要將寫(xiě)入函數(shù)的指針設(shè)置為內(nèi)存分配的句柄,代碼如下:/寫(xiě)入文件if(!WriteFile(hFile,IpVirtualtAlloc,dwFileSize,&dwBufferRead,NULL)(MessageBox("寫(xiě)入文件失敗!”,”錯(cuò)誤提示!",MB_OK);/卸載文件映射,關(guān)閉文件句柄CloseHandle(hFile);return;最后編譯,運(yùn)行,即可。如有問(wèn)題,請(qǐng)對(duì)照發(fā)布的源代碼。為了優(yōu)化函數(shù),把第2
42、次內(nèi)容所使用的文件映射相關(guān)的內(nèi)容都刪除掉。刪除后的按鈕事件代碼如下:voidCPEPackerDlg:OnButtonPacking()(/TODO:AddyourcontrolnotificationhandlercodehereHANDLEhFile;/文件句柄DWORDdwFileSize;/文件大小DWORDdwBufferRead;/實(shí)際讀取字節(jié)/打開(kāi)文件hFile=CreateFile(m_FilePathName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);/如果文件打開(kāi)失
43、敗,就彈出對(duì)話框,并返回。if(hFile=INVALID_HANDLE_VALUE)(MessageBox("打開(kāi)文件失??!”,"錯(cuò)誤提示",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)存/if(!MemAlloc(hFile)m_Ri
44、chEditProcInfo.ReplaceSel("錯(cuò)誤提示:文件加載到內(nèi)存失敗!rn");MessageBox("文件加載到內(nèi)存失敗!","錯(cuò)誤提示!",MB_OK);return;/獲取文件大小dwFileSize=GetFileSize(hFile,NULL);/設(shè)定加殼后的文件名,我采取了一個(gè)偷懶的簡(jiǎn)單方法。/如果要嚴(yán)格做,需要獲取文件路徑,擴(kuò)展名等等。m_FilePathNamePacked=m_FilePathName.Left(m_FilePathName.GetLength()-4)+"_packed.ex
45、e"CloseHandle(hFile);/創(chuàng)建加殼后的文件句柄hFile=CreateFile(m_FilePathNamePacked,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);if(hFile=INVALID_HANDLE_VALUE)MessageBox("生成文件失敗!”,"錯(cuò)誤提示!",MB_OK);/寫(xiě)入文件if(!WriteFile(hFile,lpVirtualtAl
46、loc,dwFileSize,&dwBufferRead,NULL)MessageBox("寫(xiě)入文件失敗!”,”錯(cuò)誤提示!",MB_OK);/卸載文件映射,關(guān)閉文件句柄CloseHandle(hFile);return;)/文件寫(xiě)入完畢后,釋放內(nèi)存MemAllocFree();/卸載文件映射,關(guān)閉文件句柄CloseHandle(hFile);/在編輯框中顯示信息m_RichEditProcInfo.ReplaceSel("文件加殼完成!rn");MessageBox("創(chuàng)建文件成功!”,"成功提示",MB_OK);)
47、(4)給程序添加一個(gè)區(qū)段主要內(nèi)容:添加一個(gè)新的文件區(qū)段,用來(lái)存放殼代碼,并用8來(lái)填充區(qū)段。本次內(nèi)容將添加一個(gè)新的區(qū)段到原PE文件中,一般加殼程序都會(huì)添加一個(gè)新的區(qū)段用來(lái)存放殼代碼(這只是一般情況)。然后修改添加區(qū)段后的文件的入口點(diǎn),讓程序從添加的殼代碼段開(kāi)始運(yùn)行。本次內(nèi)容只添加區(qū)段,不修改程序入口點(diǎn)。添加區(qū)段的主要有三個(gè)步驟。第一,是修改PE文件頭信息。增加一個(gè)區(qū)段后,要修改NT頭中的區(qū)段表個(gè)數(shù)成員,修改可選頭的文件鏡像大小成員。第二,獲取要添加的區(qū)段的存放位置和大小,包括文件偏移位置和大小、文件相對(duì)虛擬地址和虛擬大小第三,就是將文件寫(xiě)入到文件末尾。添加區(qū)段后的區(qū)段表對(duì)比圖如下:PF區(qū)段表對(duì)比
48、碩士畢業(yè)設(shè)計(jì)特別做區(qū)段表名VAddressVSueROffsstRSizeFlags.text00001000000040000000100000004000E000002000305000000010000000500000001000C0000040,idata000060000000100000006000000010004000004G,rsrc0000700000005000oootnooo0000500040000040.reloc(MJQOCOOOoooooriaoooocooo00口口OFIEE2000Q40rid立隹OOOODOOD00001003OOOODOOOODOOOC
49、OOCD0Q0D40加殼后區(qū)段表名VAddressVSireOffsetFlags,text00001000000040000000100000004000E0000020.data0005000ooooioao0000500000001000C0000040.id&ta0000600000001000000060000000100040000040.rsrcooooraooooao5oaoooooTooa0000500040000040,relccOQQOCQOOOOOQOTieOOOQCCOODODOOF1宣E2000040.idata2oooonooo00001000OOODDC
50、OOODOOOCOOCObatXMO.bugskyOOODEOOO00001000ooooncoo000(X)10040000020首先添加三個(gè)成員函數(shù),如下:BOOLMakePacking(HANDLEhFile);/生成加殼后的文件voidMakeShell(HANDLEhFile);/生成殼代碼段voidEditHeader();/修改文件頭信息再添加兩個(gè)成員變量,public型。LPVOIDlpVirtualShell;/殼虛擬內(nèi)存指針DWORDSizeOfShell;/殼代碼的的大小DWORDSizeOfImage;/文件鏡像大小MakeShell函數(shù)功能是生成殼代碼數(shù)據(jù),先暫時(shí)用0
51、填充該數(shù)據(jù)段。其功能代碼如下:/生成殼代碼段voidCPEPackerDlg:MakeShell(HANDLEhFile)/殼代碼段中暫定為用8填充SizeOfShell=0x100;/大小暫時(shí)定為256字節(jié)lpVirtualShell=VirtualA110c(NULL,SizeOfShell,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);memset(lpVirtualShell,8,SizeOfShell);修改PE頭,主要是修改區(qū)段表個(gè)數(shù)和鏡像大小。修改PE文件頭信息,主要是區(qū)塊個(gè)數(shù)和鏡像大小voidCPEPackerDlg:EditHeader()(D
52、WORDdwNumOfSections;/區(qū)塊個(gè)數(shù)DWORDdwFileAlign;/文件粒度(文件對(duì)齊大小)DWORDdwSectionAlign;/塊粒度(內(nèi)存對(duì)齊大?。〥WORDdwAlignLastSection;/最后一個(gè)區(qū)段按內(nèi)存對(duì)齊后的大小LPVOIDlpShellSecTab;/殼區(qū)段表指針I(yè)MAGE_SECTION_HEADERSectionHeaderOfShell;/殼代碼段的區(qū)塊表信息/以下為修改區(qū)段表信息功能,主要是增加殼區(qū)段表/初始化區(qū)段表結(jié)構(gòu)memset(&SectionHeaderOfShell,0,sizeof(SectionHeaderOfShell
53、);/獲取對(duì)齊大小數(shù)據(jù)dwFileAlign=pOptionalHeader->FileAlignment;dwSectionAlign=pOptionalHeader->SectionAlignment;/獲取區(qū)塊表個(gè)數(shù)dwNumOfSections=pNtHeader->FileHeader.NumberOfSections;/設(shè)定殼的區(qū)塊表信息SectionHeaderOfShell.Misc.PhysicalAddress=SizeOfShell;/原始大小/在文件中對(duì)齊后的大小,除以文件粒度,如果余數(shù)為零,就直接使用;否則,就擴(kuò)充對(duì)齊。SectionHeaderOf
54、Shell.SizeOfRawData=(SizeOfShell%dwFileAlign)?(dwFileAlign*(SizeOfShell/dwFileAlign+1):SizeOfShell;/區(qū)塊特征SectionHeaderOfShell.Characteristics=IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;區(qū)塊名稱(chēng)重定位偏移重定位表數(shù)目行號(hào)表偏移行號(hào)表中行號(hào)數(shù)目memcpy(&SectionHeaderOfShell.Name,".bugsky",7);/SectionH
55、eaderOfShell.PointerToRelocations=0;/SectionHeaderOfShell.NumberOfRelocations=0;/SectionHeaderOfShell.PointerToLinenumbers=0;/SectionHeaderOfShell.NumberOfLinenumbers=0;/對(duì)齊最后一個(gè)區(qū)段后的塊大小,來(lái)計(jì)算殼區(qū)段的虛擬地址。if(pSectionHeader+dwNumOfSections-1)->SizeOfRawData%dwSectionAlign)dwAlignLastSection=dwSectionAlign*(pSe
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 個(gè)人自助循環(huán)貸款合同范本
- 東莞抵押合同范本
- 申報(bào)課題書(shū)怎么寫(xiě)
- 畜牧課題申報(bào)書(shū)范文
- 原材料海外采購(gòu)合同范本
- 課題申報(bào)書(shū)樣板
- 光伏承建合同范本
- 公程合同范本
- 申報(bào)書(shū)課題設(shè)計(jì)論證
- 全面提升國(guó)際化水平的實(shí)施方案
- 英語(yǔ)板書(shū)設(shè)計(jì)(課件)
- 三年級(jí)勞動(dòng)課1ppt
- 大數(shù)據(jù)在金融領(lǐng)域的應(yīng)用方案
- 建筑裝飾設(shè)計(jì)收費(fèi)標(biāo)準(zhǔn)
- 智能中臺(tái)數(shù)據(jù)底座解決方案
- 《財(cái)政與金融》課程教學(xué)大綱
- 《國(guó)際稅收》教案
- 傳統(tǒng)體育養(yǎng)生概論
- 電力建設(shè)工程預(yù)算定額2006版
- 公益性崗位保潔員保證書(shū)
- 行政許可執(zhí)法案卷自評(píng)表
評(píng)論
0/150
提交評(píng)論