這是不雅觀的,所以我會對更好的想法感興趣,但這裏總結了我基本能夠完成的工作。
這是一個插入原始精靈填充的小引導負載的雙叉方法,然後mmap()是一個任意大的二進制blob來完成實際的工作。
第I部分:引導淨荷
基本上我插入在.ARM.exidx部分(這在代碼段的頂部加載)和.preinit_array部之間一些填充的代碼量小。這段代碼只是將另一個二進制blob和mmap()作爲只讀文件打開,並且在我希望安全的硬編碼虛擬地址中可執行。
爲了讓我插入的代碼作爲主要可執行文件的一部分加載,我必須修改elf文件中的加載段的大小,在這種情況下,它是第二個從0x54開始的phdr結構。 0x64(0x54 + 0x20)處的p_filesz和0x68(0x54 + 0x24)處的p_memsz都被改變了。
我還更改了elf頭在偏移地址0x18處的e_entry開始地址,指向我插入的代碼。我插入的代碼在完成設置後跳轉到舊的起始地址(實際上,它首先跳轉到較大有效負載中的第二階段設置,然後跳轉到原始地址)。
最後我改變了靜態鏈接的系統調用存根我想陷阱在較大載荷的加載地址指向我的替代品的功能,我的mmap()荷蘭國際集團在
第二部分:大有效載荷
這實現了所做的任何修改 - 在我的情況下,用滿足特定條件時記錄的函數替換系統調用。由於主要的可執行文件是靜態鏈接的,因此必須這樣做 - 或者更簡單的說,它不能使用C庫。相反,它使用匯編語言來發出基本I/O的系統調用。我意識到,沒有被加載爲可執行文件,我沒有持久化本地變量存儲,所以在啓動時,我mmap()一個匿名頁面來保存局部變量 - 大部分是我登錄的文件的fd和設備驅動程序fd的操作應該被記錄。
編譯這個部分有點不雅觀。我正在編譯彙編,其中-S切換到gcc,然後刪除所有節關鍵字。然後我通過gcc傳回來組裝並生成一個對象。我通過鏈接器指定我的第一個函數的名稱作爲入口點(-e)並使用通常的鏈接器腳本的定製來移除0x8000起始偏移量。但是由於標題還有一些偏移量,在這種情況下是128字節。保留修正我objcopy鏈接精靈的內容到一個二進制blob,dd自己128字節從/ dev /零,和貓到開始......
正如我所說...這是不雅的,所以我打開更好的想法
不一定爲我想要做的一切,我想要一個相當一般的方法。但是我可能有足夠的空間來編碼系統調用mmap()從外部文件中編譯一個可執行頁面,並編輯啓動代碼以跳轉到該頁面。 – 2011-04-22 18:37:26
爲什麼地球上你不重新編譯內核......? – 2011-04-22 22:19:30
@Turbo J這不是內核代碼。監控用戶代碼的內核對於無法從備用閃存位置引導內核的設備來說是非常激烈的,而且當精確內核的源還沒有被釋放時(如在設備開始之前應該已經完成的)銷售)。 – 2011-04-22 22:57:30