1. 程式人生 > 其它 >記憶體載入PE檔案的一個問題

記憶體載入PE檔案的一個問題

  工作中碰到一個問題,需要把一個遠控工具放到磁碟上,讀取到記憶體中載入PE程式。

  使用github中的載入PE檔案程式RunPeMemory32位程式直接載入遠控工具是沒有問題的,為了隱蔽性,需要寫一個服務dll,然後有Windows服務主程式svchost.exe來載入服務dll,在服務dll程式碼中載入遠控工具PE檔案。

  這種方法實踐不可行,猜測是遠控工具是由golang寫的,與svchost.exe中某些庫不相容,導致無法執行。

  只能換一種方法,在服務dll中再次啟動一個svchost.exe程式,傳入特定的命令列引數,方便之後識別,需要下面幾個步驟:

  1. 呼叫CreateProcessA/W函式啟動svchost.exe程式時掛起程序

  2. 使用程序注入技術,呼叫VirtualAllocEx在目標程序空間中申請空間,存放服務dll的絕對路徑,使用程序注入呼叫LoadLibraryA/W傳入dll地址,獲取執行緒返回值得到模組地址

  3. 獲取服務dll的匯出函式的地址,服務dll除了ServiceMain函式還有一個匯出函式,通過解析PE檔案獲取匯出函式的相對偏移,加上上一步獲取到的基地址

  4. 使用執行緒注入技術呼叫匯出函式,在匯出函式中識別命令列引數,記憶體載入遠控PE檔案即可。

  也可以不使用遠端注入技術,使用跨程序寫入shellcode:

  1. 掛起程序後,獲取主執行緒的執行緒上下檔案環境,獲取到EIP暫存器指向地址之後,修改EIP所在地址的記憶體頁面屬性,改為可讀可寫。

  2. 檢視掛起的svchost程序,看到記憶體模組只有ntdll模組,跨程序寫入shellcode,如載入kernel32.dll、再載入目標dll,需要使用到ntdll中的載入dll函式。

  3. 目標dll載入後,再呼叫匯出函式。

  這兩種方法對比的話,第二種方法需要寫入shellcode,相容性不好,需要寫x86和x67兩套shellcode,第一種相容性更好。