使用 dd 修補二進製文件
我已經多次閱讀這句話(下面),最近一次是在這裡
dd
,並且一直對如何使用更新檔來修補任何東西感到困惑,更不用說編譯器了:30 年前我在學校使用的 Unix 系統在 RAM 和磁碟空間方面非常有限。尤其是
/usr/tmp
文件系統很小,當有人試圖編譯一個大程序時,就會出現問題。當然,無論如何,學生不應該寫“大程序”。大型程序通常是從“某處”複製的原始碼。我們中的許多人復製/usr/bin/cc
到/home/<myname>/cc
,並**用於dd
修補二進製文件以使用/tmp
而不是/usr/tmp
**更大的 。當然,這只會讓問題變得更糟——這些副本佔用的磁碟空間在當時確實很重要,現在/tmp
經常被填滿,甚至阻止其他使用者編輯他們的文件。在他們發現發生了什麼之後,系統管理員做了一個chmod go-r /bin/* /usr/bin/*
它“修復”了問題,並刪除了我們所有的 C 編譯器副本。(強調我的)
手冊頁沒有說明任何關於修補的
dd
內容,而且無論如何也不認為它可以重新用於執行此操作。二進製文件真的可以打更新檔
dd
嗎?這有什麼歷史意義嗎?
讓我們試試看。這是一個簡單的 C 程序:
#include <stdio.h> int main(int argc, char **argv) { puts("/usr/tmp"); }
我們將把它建構成
test
:$ cc -o test test.c
如果我們執行它,它會列印“/usr/tmp”。
讓我們找出“
/usr/tmp
”在二進製文件中的位置:$ strings -t d test | grep /usr/tmp 1460 /usr/tmp
-t d
將十進制的偏移量列印到它找到的每個字元串的文件中。現在讓我們創建一個只有“
/tmp\0
”的臨時文件:$ printf "/tmp\x00" > tmp
所以現在我們有了二進製文件,我們知道要更改的字元串在哪裡,並且我們有一個包含替換字元串的文件。
現在我們可以使用
dd
:$ dd if=tmp of=test obs=1 seek=1460 conv=notrunc
tmp
這從(我們的“ ”文件)讀取數據/tmp\0
,將其寫入我們的二進製文件,使用 1 字節大小的輸出塊,在寫入任何內容之前跳到我們之前找到的偏移量,並且在完成後明確不截斷文件。我們可以執行打更新檔的執行檔:
$ ./test /tmp
程序列印出的字元串文字已更改,因此它現在包含“
/tmp\0tmp\0
”,但字元串函式在看到第一個空字節後立即停止。這種修補只允許使字元串更短或相同長度,而不是更長,但它足以滿足這些目的。所以我們不僅可以使用 來修補東西
dd
,而且我們剛剛完成了它。