变态重口极致另类在线-波多久久夜色精品国产-波多野结衣在线观看一区-波多野结衣在线观看一区二区-污污的网站免费阅读-污污视频网址

東坡下載:內容最豐富最安全的下載站!

首頁IT技術軟件教程 → 利用pe添加節(jié)的方法添加代碼 實現(xiàn)簡單的加殼

利用pe添加節(jié)的方法添加代碼 實現(xiàn)簡單的加殼

相關文章發(fā)表評論 來源:本站原創(chuàng)時間:2014/2/20 19:08:20字體大小:A-A+

更多

作者:不詳點擊:589次評論:0次標簽: Speccy

利用pe添加節(jié)的方法添加代碼 實現(xiàn)簡單的加殼

大致流程如下

要達到的目的是 添加一個新節(jié) 在新節(jié)中添加自己的代碼 讓程序運行時 先運行自己的代碼

而自己的代碼就是為了解開之前對程序進行的加密執(zhí)行完后 再繼續(xù)運行原程序的路線。




詳細步驟

第一步

先寫程序將 采用文件映射的方法將待修改的exe加載進來 獲取所有我們需要的信息
CreateFile    CreateFileMapping  MapViewOfFile(返回 文件基地址 Pimage)
GetFileSize(用于修改文件大小)

第二步

初始化pe頭信息 DOS=PIMAGE_DOS_HEADER(Pimage); 其他初始化略
驗證pe的有效性 MZ 和 PE

第三步

開始加節(jié) 因為后邊要修改eop所在的節(jié)的內容
所以先將此節(jié)的屬性設置為 可讀可寫  IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE
(此處很關鍵 自己修改的事飛秋 結果修改完后一直不能運行 卡了很長時間 切記)

加節(jié)

1

找到最后一節(jié)的地址
PIMAGE_SECTION_HEADER lastsec = SECTION+(FILE->NumberOfSections-1);
  確定新加節(jié)的地址
PIMAGE_SECTION_HEADER newsec = lastsec+1;
  節(jié)表數(shù)目加1
FILE->NumberOfSections++;
驗證一下 在節(jié)表頭最后 到 第一個節(jié)內容開始 有沒有40個字節(jié)
(一般都有  沒有考慮不夠的情況)
驗證方法(主要明白SizeOfHeaders的真實含義)

NEWSIZE 計算的是 (dos + dos stub ) + nt +  新加節(jié)后的節(jié)表頭總大小(純粹大小 未對齊)
DWORD NEWSIZE = (DOS->e_lfanew)+sizeof(IMAGE_OPTIONAL_HEADER32)+sizeof(IMAGE_SECTION_HEADER)*NumberOfSections;
(不要忘記 dos stub  直接用(sizeof(IMAGE_DOS_HEADER))盡管沒有神馬影響 但是事實 必須這樣計算)

讓它跟原SizeOfHeaders比較
SizeOfHeaders是  dos+dos stub+nt+所有節(jié)表頭總大小(對齊后的)       可以用作第一個節(jié)內容的開始位置

2
大小滿足之后  對新加節(jié)的所有屬性進行初始化(UP函數(shù)是 用來對齊的 參數(shù) 1 大小 2 對齊粒度)

memcpy(newsec->Name,".NewSec",8);

newsec->Misc.VirtualSize=實際大小(size); 節(jié)內容的實際大小  SizeOfRawData 用到

newsec->SizeOfRawData=Up(size,pe.OPTION->FileAlignment); 文件中的大小

newsec->VirtualAddress 在內存中的RVA 重要 可以利用上一個節(jié)的數(shù)據(jù)得到

DWORD last =Up((lastsec->SizeOfRawData),pe.OPTION->SectionAlignment)+lastsec->VirtualAddress;
DWORD last =Up((LastSec->Misc.VirtualSize),pe.OPTION->SectionAlignment)+lastsec->VirtualAddress;

兩個last 相等 因為 SizeOfRawData 是Misc.VirtualSize按文件對齊得到的
文件對齊粒度512 內存對齊粒度4096 所以肯定相等
不過為了準確 采用后者
其實這個last 也就是 pe文件 載入內存后 經過SectionAlignment對齊后 的 總大小 SizeOfImage

newsec->PointerToRawData=lastsec->PointerToRawData+lastsec->SizeOfRawData;  同理
newsec->Characteristics=IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; 可讀可寫

其他屬性沒有什么影響 故均設置為0  到此 初始化完畢

3

需要修改的其他地方的參數(shù)
a (必須)文件在磁盤上的總大小 即第一步中的GetFileSize返回的值 再加上一頁的大小4096
  用于CreateFileMapping創(chuàng)建文件映射對象函數(shù) 把大小設置為修改后的大小 即 加上4096后的值
b (必須)文件映射內存后的總大小
   OPTION->SizeOfImage+=Up(size,pe.OPTION->SectionAlignment);
c (不必須的)
   pe.DATA[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size=0;
   pe.DATA[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress=0;
   pe.OPTION->SizeOfCode+=Up(size,pe.OPTION->SectionAlignment);
   pe.OPTION->SizeOfInitializedData+=Up(size,pe.OPTION->SectionAlignment);

4 至此加節(jié)成功

第四步

取反
因為是對 eop所在節(jié)的內容取反 所以要找到 eop 所在節(jié)
方法 獲取eop= OPTION->AddressOfEntryPoint 然后循環(huán)遍歷各個節(jié)表頭的起始地址 進行比較
for (int i=0; i<FILE->NumberOfSections; i++)
{
PIMAGE_SECTION_HEADER sec = PIMAGE_SECTION_HEADER(SECTION+i);
if (eop>=sec->VirtualAddress   &&    eop<=(sec->VirtualAddress+sec->SizeOfRawData))
{return sec;}
}
找到所在節(jié)后  是要對在磁盤上此節(jié)的內容 進行修改 所以獲取
PVOID address = sec->PointerToRawData+image; //文件的地址
DWORD lenth   = sec->SizeOfRawData;          //文件的大小

取反函數(shù)
void  _stdcall QF(PVOID address,DWORD len)
{
DWORD i=0;
PBYTE buf=(PBYTE)address;
for ( i=0; i<len; i++)
{buf[i]=~buf[i];}
}
函數(shù)中有一個關鍵字 _stdcall  作用是 函數(shù)執(zhí)行完后 自己跳轉到之前壓棧的地址 用于返回eop使用

好了 取反結束了 此時 磁盤上的 exe文件已經被 破壞 接下來是 解密

第五步

解密 比較復雜

首先說一下思路
解密其實是 exe在執(zhí)行后 先執(zhí)行自己的解密算法 在跳轉回去 繼續(xù)自己的程序
所以解密 就是當exe文件執(zhí)行時 先執(zhí)行自己的代碼 即將已取反加密的節(jié)再取反 即可正常運行
記住是當exe文件執(zhí)行的時候所以 需要獲得當 exe文件加載進去后的 內存地址才行(重要)
并不是說將磁盤上的文件再改回來 這樣想是錯的 再怎么說文件執(zhí)行了 再對它進行修改 肯定是不行的

獲得了待解密的節(jié)首地址 和 大小 此時解密函數(shù)參數(shù)已經解決了 接下來要做的 是讓程序運行的時候 先執(zhí)行自己的代碼
也就是先執(zhí)行自己的這個解密算法函數(shù)  一個函數(shù)運行的步驟是 先將參數(shù)從右到左依次入棧 再將代碼入棧 而我們還需要
執(zhí)行完后 再跳轉回原eop入口地址 所以再將原eop入口地址入棧 待函數(shù)執(zhí)行完后 返回到這個地址 怎么返回的? 這就用到
關鍵字 _stdcall   它的作用是  由被調的函數(shù)清除堆棧 它的反匯編是 ret 8 ;兩個字節(jié)的大小
(在這個程序中不用它也可以 用是最安全 省心的 至于原因 強哥解釋了 我沒太搞明白)

接下來就開始copy應該copy的內容到新加節(jié)的內容中

參數(shù)入棧 需要自己寫機器語言(因為是執(zhí)行自己的函數(shù)所以自己調) 利用結構體 形成語句 然后再copy到新加節(jié)的開始
當執(zhí)行新加節(jié)的內容時 先執(zhí)行自己做的這個解密函數(shù)(參數(shù)入棧  原eop入棧 代碼入棧 ret 8)

1 獲得copy的首地址 即 新加節(jié)的文件地址
  PBYTE begin=(RVATORAW(newsec->VirtualAddress)+image);


再將 參數(shù)入棧的機器碼構成結構體 直接copy機器碼到新加節(jié)中

2 從右到左 copy參數(shù) 即先copy 節(jié)的長度length

先對之前自己做的結構體進行初始化
MOV_EBX.address=secofeop->SizeOfRawData;        //所在節(jié)的length
MOV_EAX.address=secofeop->VirtualAddress+pe.OPTION->ImageBase; //所在節(jié)的起始地址 va+400000
PUSH_OLD_EOP.address=pe.OPTION->AddressOfEntryPoint+pe.OPTION->ImageBase; //原eop+400000

再copy到新加節(jié)的內容中
memcpy(begin,&MOV_EBX,sizeof(mov_eax));                 //所在節(jié)的length
memcpy(begin+sizeof(mov_eax),&MOV_EAX,sizeof(mov_eax)); //所在節(jié)的起始地址 va+400000
memcpy(begin+sizeof(mov_eax)*2,&PUSH_OLD_EOP,sizeof(push_old_eop)); //原eop+400000

DWORD lenofcode=(DWORD)end_qf-(DWORD)start_qf;
//其中 start_qf  和  end_qf 是取反函數(shù)的首地址和末地址 用來計算代碼的長度 注意最后還得加上末地址后邊的幾個字節(jié)(重要)
//兩個數(shù)值是自己寫好程序后 調試程序時 手動找出來的 不知道怎么動態(tài)獲得 待大牛看后 指點迷津
//計算一下代碼需要的內存長度 再加上至少有返回的指令的長度 此時即為2
//多了也沒事 自動填充為 CC

memcpy(begin+sizeof(mov_eax)*2+sizeof(push_old_eop),(PVOID)start_qf,lenofcode+2);  //

重要一步 修改eop入口點地址為新加節(jié)的rva

OPTION->AddressOfEntryPoint=newsec->VirtualAddress;  //修改入口點地址到新加節(jié)的rva

此時解密也結束了

第六步

收尾工作

首先了解一點知識 摘在網絡

為了提高速度,系統(tǒng)將文件的數(shù)據(jù)頁面進行高速緩存,并且在對文件的映射視圖進行操作時不立即更新文件的磁盤映像。如果需要確保你的更新被寫入磁盤,可以強制系統(tǒng)將修改過的數(shù)據(jù)的一部分或全部重新寫入磁盤映像中,方法是調用F l u s h Vi e w O f F i l e函數(shù):
BOOL FlushViewOfFile(
  PVOID pvAddress,
  SIZE_T dwNumberOfBytesToFlush);
第一個參數(shù)是包含在內存映射文件中的視圖的一個字節(jié)的地址。該函數(shù)將你在這里傳遞的地址圓整為一個頁面邊界值。第二個參數(shù)用于指明你想要刷新的字節(jié)數(shù)。系統(tǒng)將把這個數(shù)字向上圓整,使得字節(jié)總數(shù)是頁面的整數(shù)。

1 "對文件的映射視圖進行操作時不立即更新文件的磁盤映像" 那么何時更新?我程序正常退出前一定會更新吧?如果程序意外結束(比如電腦死機)那是不是就可能無法將更改寫入磁盤?
1、在UnmapViewOfFile、CloseHandle和系統(tǒng)回收物理內存的時候寫入磁盤。
當進程結束時(包括正常和異常),系統(tǒng)會自動關閉該進程打開的所有Handle,所以會寫入磁盤。除非是內核代碼異常,導致死機,這時才可能沒有寫入。

2 是不是只要程序不意外結束,我們就沒使用FlushViewOfFile的必要?否則請問在什么情況下有必要使用它?
2、FlushViewOfFile是為了實現(xiàn)程序自己控制寫入磁盤而提供的,當你真正遇到這種需求的時候才能體會到它的價值。


本程序實現(xiàn)的代碼如下
BOOL success = FlushViewOfFile(Pimage,FileSize);  //將寫入文件映射緩沖區(qū)的所有數(shù)據(jù)都刷新到磁盤
if (!success)
{return false;}
success = UnmapViewOfFile(Pimage); //在當前應用程序的內存地址空間解除對一個文件映射對象的映射
      //lpBaseAddress Long,指定要解除映射的一個文件映射的基準地址。這個地址是早先用MapViewOfFile函數(shù)獲得的
CloseHandle(hMap);
return true;

擴展知識

相關評論

閱讀本文后您有什么感想? 已有 人給出評價!

  • 2791 喜歡喜歡
  • 2101 頂
  • 800 難過難過
  • 1219 囧
  • 4049 圍觀圍觀
  • 5602 無聊無聊
熱門評論
最新評論
發(fā)表評論 查看所有評論(0)
昵稱:
表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
字數(shù): 0/500 (您的評論需要經過審核才能顯示)
主站蜘蛛池模板: 亚洲欧美精品中文字幕 | 成年美女黄网色大观看全 | 日本三级精品 | 久久精品18 | 日本国产精品 | 亚洲免费观看 | 欧美手机在线视频 | 免费日皮视频 | 欧美精品在线播放 | 成年人免费在线 | 日韩黄色影片 | 国产大片免费观看中文字幕 | 久久精品国产亚洲综合色 | 色狠狠综合网 | 五月天激情婷婷大综合 | 成人高辣h视频一区二区在线观看 | 国产精品福利小视频 | 亚洲伦理一区二区 | 国产在线爱做人成小视频 | 中国一及黄色片 | 丁香五香天堂网卡 | 成人免费在线看片 | 99在线视频精品费观看视 | 国产日韩欧美综合 | 国产人成精品 | 中文字幕日韩精品一区口 | 中文字幕 视频一区 | 男女免费观看视频 | 永久免费看毛片 | 在线成h人视频网站免费观看 | 国产成人网 | 国产一区二区免费播放 | 亚洲欧美日韩综合在线 | 亚洲无线码在线一区观看 | 免费在线一级片 | 国产精品亚洲专区在线观看 | 亚洲成a人片在线观看中 | 国产一区三区二区中文在线 | 久久久久久精 | 欧美日韩一级视频 | 欧美日韩中文字幕在线观看 |