免费体验120秒视频_榴莲榴莲榴莲榴莲官网_2021国产麻豆剧果冻传媒入口_一二三四视频社区在线
東坡下載:內容最豐富最安全的下載站!

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

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

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

更多

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

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

大致流程如下

要達到的目的是 添加一個新節(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é)表數目加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函數是 用來對齊的 參數 1 大小 2 對齊粒度)

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

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

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

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

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

需要修改的其他地方的參數
a (必須)文件在磁盤上的總大小 即第一步中的GetFileSize返回的值 再加上一頁的大小4096
  用于CreateFileMapping創(chuàng)建文件映射對象函數 把大小設置為修改后的大小 即 加上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;          //文件的大小

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

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

第五步

解密 比較復雜

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

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

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

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

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


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

2 從右到左 copy參數 即先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 是取反函數的首地址和末地址 用來計算代碼的長度 注意最后還得加上末地址后邊的幾個字節(jié)(重要)
//兩個數值是自己寫好程序后 調試程序時 手動找出來的 不知道怎么動態(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

此時解密也結束了

第六步

收尾工作

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

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

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

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


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

擴展知識

相關評論

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

  • 2791 喜歡喜歡
  • 2101 頂
  • 800 難過難過
  • 1219 囧
  • 4049 圍觀圍觀
  • 5602 無聊無聊
熱門評論
最新評論
發(fā)表評論 查看所有評論(0)
昵稱:
表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
字數: 0/500 (您的評論需要經過審核才能顯示)
免费体验120秒视频_榴莲榴莲榴莲榴莲官网_2021国产麻豆剧果冻传媒入口_一二三四视频社区在线
主站蜘蛛池模板: 欧美国产日本| 国产美女19p爽一下| 午夜小福利| 美女的尿口免费看软件| 波多野结衣xxxxx在线播放| 亚洲熟妇中文字幕五十中出 | 巨龙征母全文王雪琴笔趣阁| 失禁h啪肉尿出来高h男男视频| 亚洲伊人久久精品| 国产精品一区不卡| 欧美日韩国产综合在线| 亚洲综合在线成人一区| 啊轻点灬大ji巴太粗太长了欧美| 亚洲精品在线播放视频| 青青国产在线| 做暧暧小视频全集免费 | 中文字幕视频在线观看| 欧美综合自拍亚洲综合图| 中国一级毛片视频| 免费国产综合视频在线看| 天天操美女逼| 国产精品美女视频| 久久公开视频| 91女神疯狂娇喘3p之夜| 俺也去第四色| 天天看天天射| 韩国精品福利一区二区三区| 久久久久久久人妻无码中文字幕爆| 亚洲国产成人久久综合一区| 久久久久亚洲av成人网| 亚洲国产精品久久久天堂| 亚洲一区爱区精品无码| 欧美18videos极品massage| 国产伦精品一区二区三区四区 | 欧美性白人极品hd| 丰满多毛的陰户视频| 欧美寡妇XXXX黑人猛交| 亚洲国产精品xo在线观看| 豪妇荡乳1一5| 蜜柚在线观看免费高清| 特级片网站|