一.手動新增節添加代碼
1.當預備條件都滿足,節表結尾沒有相關數據時:
現在我們將ipmsg.exe用winhex打開,在節的最后新增一個節用于存放我們要增加的數據
注意:飛鴿的文件對齊和內存對齊是一致的
先判斷節表末尾到第一個節之間是否夠80字節:可選PE頭中SizeOfHeaders值為0x1000,標準PE頭中SizeOfOptionalHeader獲取可選pe頭的大小值為0xE0,NumberOfSections獲取節的數量為0x4,DOS頭中e_lfanew獲取NT的地址為0xE0,PE簽名大小0x04,標準PE頭大小0x14,通過0x1000 - (0xE0 + 0x4 + 0x14 + 0xE0 + 0x4 * 0x28)= 0xD88獲取節表到節之間的空白區大小,因為0xD88 > 0x50,所以可以存下新增節表。在實際操作中,我們肉眼便可判斷空間是否足夠
我們將.text節表(注意是第一個節表)的40字節復制一份到節表末尾地址0x278:選中.text40字節復制,再選中0x278到后面40字節數據粘貼,這樣我們就把.text節表內容復制一份添加到節表末尾作為新節表的40字節
注:winhex中write是覆蓋選中數據,paste是插入
接著為了滿足Windows格式要求將新增節后面的40字節數據改為0
修改PE標準頭中的NumberOfSections值為4 + 1 = 5
先看一下文件對齊和內存對齊都是0x1000,所以我們新增的節大小為了方便后面修改可以設定為0x1000字節大小,這已經足夠存放我們想要添加的代碼了。(如果文件對齊和內存對齊不一樣,那可以選擇兩個的最小公倍數,方便后面的修改)
接著修改可選PE頭中SizeOfImage值:由于我們想要新增節的大小為0x1000(考慮了內存對齊),所以將SizeOfImage + 0x1000即可,0x3D000 + 0x1000 = 0x3E000
然后修改節表中的字段:
Name:名字改為.tttt 2E 74 74 74 74
Misc.VirtualSize:直接寫0x1000,即內存中對齊前的長度
VirtualAddress:0x30000 + 0x4000 + 0x4000 + 0x4000 + 0x4000 = 0x3D000 第一個節的VirtualAddress時0x300000,一共四個節,每個節對齊后是0x4000大小,加起來就是0xD0000
SizeOfRawData:0x1000
PointerToRawData:0x2C000 + 0xD000 = 0x39000
屬性值不用變,因為復制的.text節表已經滿足了可執行的屬性
現在我們要在文件第四個節末添加新節,選中節末最后一個數據,右鍵–edit–paste zero bytes–輸入新節的大小十進制大小4096,將其初始化為0
新增節后我們將要添加的代碼加到新節中,這里就使用前兩節應用的shellcode,就是運行飛鴿后先彈一個框,再正常運行,但是此時還要計算一下E8和E9后面的值:
E8后面的值:X = 0x77D36476 - (0x400000 + 0x3D000 + 0x8 + 0x5) = 0x778F9469 注意0x77D36476為MessageBoxA API地址
E9后面的值:X = 0x400000 + 0x1D26F - (0x400000 + 0x3D000 + 0xD + 0x5) = 0xFFFE025D
所以將完整的代碼(硬編碼)添加到新節中:
最后將OEP的值改為0x3D000
保存,運行后發現先彈框再正常打開程序,成功
2.節表結尾有數據整體上移的情況
我們打開記事本復件notepad_test.exe,找到節表末,發現這里有一些我們不認識的數據,而且是緊挨著節表的,所以這種情況下我們沒法在節表末新增節表
此時我們發現DOS頭結尾到PE簽名之間是垃圾數據,如果將PE簽名一直到節表末之間的所有數據整體上緊挨著DOS頭后面,接著將e_lfanew字段值改為0x40,此時節表末便空出來了0xE8 - 0x40 = 0xA8字節內存,足夠存放80字節,即兩個節表大小了
選中0xE8到0x258的全部數據復制,從0x40開始write覆蓋0x258 - 0xE8 = 0x170字節數據,接著將此時節表末尾多空出來的數據改為0,再修改e_lfanew的值為0x40即可。此時0x1B0到0x258之間就空出來了0xA8字節,在這里新增節即可
后面新增節的過程與條件都滿足時一模一樣,不再演示
二.代碼實現新增一個節,并添加代碼
三.編程實現擴大最后一個節,并添加代碼
?3.整體上移后空間還不夠,擴大最后一個節
如果整體上移覆蓋DOS Stub后空間還不夠兩節表寬度,那么就要采用擴大最后一個節的方式。注意不要擴大其他的節,因為如果不是最后一個節擴大的話,其他的節擴大會造成其下面的全部節的數據偏等等諸多問題
需要修改SizeOfImage,比如我想擴大500字節,那么要滿足內存對齊,所以SizeOfImage應該 + 0x1000,這里為了方便后面的修改,直接就按照內存對齊來擴大,所以擴大0x1000字節即可
接著就是修改最后一個節表的屬性:
VirtualAddress和PointerToRawData的值都不用改變
VirtualSize:SizeOfImage - VirtualAddress + Ex,再內存對齊(這里為了方便,Ex可以直接選文件對齊粒度和內存對齊粒度的最小公倍數,這樣就不用再考慮內存對齊了),就是最后注入shellcode時不好判斷Ex+原來空白區大小是否足夠存下shellcode了,不過可以直接在Ex區域注入shellcode即可,不用考慮原來此節的空白區
SizeOfRawData:因為文件對齊一般都為0x200或0x1000,這里直接等于VirtualSize即可(因為VirtualSize此時肯定即是0x200的整數倍,也是0x1000的整數倍)
因為擴大節的目的是為了添加shellcode,所以還要看最后一個節的屬性是否可執行
此時就可以在最后一個節的末尾到結束這之間添加代碼了