題:
如何為現有的二進制可執行文件添加功能?
asheeshr
2013-03-23 18:55:13 UTC
view on stackexchange narkive permalink

我想向現有的二進製文件添加一些功能。二進製文件是使用 gcc 創建的。

  • 即使我足夠了解程序的功能,我還是需要首先對二進製文件進行反編譯嗎?
  • 我應該如何添加必要的代碼?
  • 我需要任何工具來做到這一點嗎?
適用於Windows,Linux等平台?
您要添加什麼功能?因為這取決於不同的方法。例如,要使GUI自動化,您可以使用另一種技術,例如更改數據庫引擎。
HTTP://stack overflow.com/questions/4309771/disassembling-modifying-安定-太狠-reassembling-啊-Linux-executable
八 答案:
Ed McMan
2013-03-23 20:47:41 UTC
view on stackexchange narkive permalink

您可以通過多種方法進行此操作。

  1. 動態檢測

    諸如 PIN Valgrind DynamoRIO允許您動態更改程序的行為。例如,您可以在特定地址添加對新函數的調用,攔截庫調用並對其進行更改,等等。

    缺點是動態檢測通常具有高開銷。

  2. 靜態檢測

    您也可以嘗試靜態修改程序以添加所需的行為。挑戰之一是您經常需要弄混可執行文件格式。為此,存在一些工具,例如 ERESI項目中的 elfsh ,但是我發現它們有故障並且難以使用。

    另一種靜態策略檢測是為了“重新編譯”。您可以通過反編譯程序,修改源代碼並重新編譯來實現。從理論上講,您也可以使用 BAP之類的工具將程序提升為IL,進行修改,然後使用LLVM重新編譯。但是,當前版本可能還不夠成熟。

  3. 動態加載

    您可以使用 LD_PRELOAD 覆蓋功能將被動態鏈接。當您想更改庫函數的行為時,這是一個不錯的選擇。自然,它不適用於靜態鏈接的二進製文件或靜態函數。

  4. 二進制修補程序

    您通常可以使用十六進制編輯器。例如,如果您要跳過一個函數調用或分支,則通常可以用 nop 指令替換它。如果您需要添加大量新代碼,則可能需要使用 ERESI項目中的 elfsh 之類的內容來幫助您調整二進製文件的大小。

  5. ol>
Gilles 'SO- stop being evil'
2013-03-23 19:53:18 UTC
view on stackexchange narkive permalink

通常,您可以通過仔細地鉤入程序來更改其行為。是否可以通過這種方式添加所需的功能取決於程序的構造方式。如果該程序以一個主要可執行文件和幾個庫的形式出現,將有幫助。

您可以通過首先使用 LD_PRELOAD鏈接自己的庫,來掛接該程序對共享庫的任何調用。 。編寫一個定義函數 foo 的庫,並在啟動時將環境變量 LD_PRELOAD 設置為已編譯( .so )庫的路徑程序:然後該程序將調用您的 foo 而不是它想要的。您可以通過使用 dlsym()獲取指向其替換的原始 foo 函數。

以下是一些示例和教程:

一些使用 LD_PRELOAD 的程序示例:

LD_PRELOAD 的局限性在於,您只能攔截在運行時解析的函數調用(動態鏈接)。如果要攔截內部呼叫,則必須採用較重的技術(在磁盤上或使用 ptrace 在內存中修改可執行文件)。

Michael Anderson
2013-03-23 22:06:39 UTC
view on stackexchange narkive permalink

我想在現有的二進製文件中添加一些功能。

因此,通常,這四個更大的問題適用於修改Executeable:

提出的第一個基本問題:程序是否警惕代碼修改(自我檢查,反調試技巧,複製保護...)?

如果這樣:

  1. 是否甚至可以輕鬆地刪除/繞開這些保護措施(例如,拆箱,如果已包裝的話)
  2. 是否值得這樣做?
  3. ol>

    第二個問題是:
    您能找出使用哪個編譯器/語言生成可執行文件嗎?

    更多詳細信息會更好,但是大多數基本結構( if 和其他控制結構)在各種編譯器上的映射應非常相似。

    這與先前關於RE-Stackexchange的問題

    第三個問題是:
    如何實現用戶界面(CLI,Win32-Window控件,自定義...)?

    如果已知:
    您能否找出常見的HLL構造(菜單,下拉菜單,複選框等)與要修改的二手編譯器/語言的映射?

    第四個最大的問題是:
    如何在程序中創建所需的功能?

    從本質上講,這可能需要很多反向操作

    中心點:如何利用現有的內部API達到目標,而又不會破壞Stuff(例如CRTL + Z,版本控制,恢復)功能)?

  • 現有數據結構(及其之間的關係?)
  • 現有功能(參數,參數格式等)
    • 它是做什麼的?
    • 它還能做什麼?
    • 它真正起什麼作用?
    • ...
  • 現有過程(=程序在內部如何進行,逐步實現相似的功能)
    • 調用什麼函數,按什麼順序?
    • 使用了哪些數據結構?
  • 特徵/程序的位置在哪裡(數據,例如主繪畫區域,以及它在內部如何關聯?)
  • 尋找(如果它涉及所需的功能):
    • 日記
    • 恢復功能
    • 版本控制
  • 如何處理與所需功能相關的元數據(例如,快門速度,f-Stops等)。

示例項目: b>

  • 在圖形程序中構建一種新型繪畫工具(不帶plugin-API)。
  • 擴展程序的plugin-API。
  • 在沒有程序的程序中構建插件API。
  • 為文件添加新的保存/導出格式(如果無法將輸出格式轉換為所需格式,或者導出的f中缺少關鍵信息
  • 添加新的導入格式(如果無法將輸入格式轉換為可導入格式,或者某些信息未正確導入)。
  • 使用顏色搜索和替換工具(在選擇中或在整個圖片中)擴展Mspaint
  • 向程序添加代理支持/基本代理驗證。
  • 添加(新增),命令行切換到顯示新功能/現有功能的程序。
  • 添加用於遠程過程調用的API,以在外部管理程序的操作。
  • 添加腳本支持自動執行經常重複的操作(如果沒有插件/腳本API的話)或支持批處理。

關於包裝的代碼&反編譯器: 我不會談論與VM /解釋器(Py2Exe,Java 2 Exe,...)打包在一起或使用已安裝的代碼(JVM,C#)打包的其他語言的包裝代碼。在某些情況下,有相當不錯的反編譯器。成功進行反編譯後,它幾乎可以歸結為克服“代碼混淆”(如果有的話)。

關於C / C ++-反編譯器:
我不能談論C / C ++-Decompilers,儘管可以歸結為盡力而為的HLL-Remapping(對於Decompiler沒得到的東西)和Code-Deobfuscation(如果它是在沒有符號的情況下編譯的),前提是在可執行文件中沒有進一步的保護。 p>

有關HLL映射的建議:
本質上,該問題的很大一部分涉及的“ HLL映射”(高級語言映射(在機器代碼中))和的修改。這些結構在相應的機器代碼中。

我在此處(binary-auditing.com)上找到了一個非常好的可下載的入門課程,該課程使用“ IDA Free”。

Ange
2013-03-26 12:49:26 UTC
view on stackexchange narkive permalink

(略微過時,但正如之前在本線程中未提到的那樣)

很久以前,我花了幾個月的時間來擴展僅包含二進製文件的軟件。

  • 我使用IDA進行分析,並使用SoftICE進行實時調試。如果您可以在操作碼/字節碼級別理解目標,則無需進行反編譯。
  • 然後,因為它是x86 PE二進製文件,所以我使用了Tasm和Iczelion的代碼段創建器 >:它不再是一個著名的工具,但是它允許透明地使用Tasm並重新註入代碼,以及進行PE轉換等。

    它在EntryPoint上添加了代碼,所以我手動製作了自己的補丁,然後跳到原始的EntryPoint。

現在有點老套了-這些天我可能會注入DLL-但它確實起作用了。

並且至少,它通過ASM給予您完全控制,同時通過自動修補來保持可維護性。

Andrew
2013-03-23 19:30:43 UTC
view on stackexchange narkive permalink

您不需要反編譯二進製文件。如果您了解要進行哪些更改,並且僅通過修改二進製文件或其依賴項就可以進行更改,則只需在磁盤或內存中進行這些更改即可。

關於如何實現修改本身,您有幾種選擇。

您可以使用LD_PRELOAD使鏈接器在二進製文件運行之前加載共享對象。然後,您根本不需要修改磁盤上的二進製文件。這是valgrind的工作方式,它作為共享對象加載,然後開始動態二進制檢測。

您可以使用 valgrind。 Valgrind將允許您動態地重新編寫程序並任意修改其行為。 Valgrind是一個動態的二進制檢測程序,允許其工具在執行時編輯該程序。如果您只想更改程序行為,則可能會起作用,但是valgrind也會導致全局變慢,並且如果您想修補和重新分發程序,則可能不理想。

您還可以使用 elfsh / eresi之類的工具將新代碼插入程序。這些工具應注意將代碼插入與ELF程序標頭之類的東西有關的行為。您可以在Google上搜索“ ELF感染器”的概念,在該概念中,注入的代碼將成為新程序的入口點,執行某些操作,然後跳轉到舊程序的入口點。

0xC0000022L
2013-04-07 03:19:50 UTC
view on stackexchange narkive permalink

在Windows上執行此操作

儘管此問題集中在Linux上,我個人將使用其他答案中概述的簡單的 LD_PRELOAD 方法,但Windows知道類似的機制,實際上,它在最近的一段時間內已經被濫用(另請參見下面的替代方法)。我用那種方法“破解”了一個加密狗系統。事實證明,該方法是最近才發現的,方法是將DLL放在遠程共享上,然後導航到共享,例如媒體播放器,這將導致媒體播放器加載遠程DLL而不是本地版本。這是設計使然。現在更改它會破壞成百上千的應用程序。

這已經由Microsoft 以某些方式解決,儘管唯一真正的解決方案是在應用程序端正確實現。但是自從Windows 2000成為第一個基於NT平台的消費者操作系統以來,即使我們不得不處理NT安全,許多開發人員甚至都沒有掌握NT安全。

它與您的工作有什麼關係?

添加功能不一定意味著您在磁盤上修補了可執行文件。您還可以在內存中執行此操作。

如何利用它?

只要應用程序使用DL​​L,並且您可以使用 Dependency Walker告訴加載順序 h> a>或在調試器下,您可以選擇它導入的DLL之一併替換(在其當前位置),或在加載順序中將另一個DLL放置在現有DLL之前的路徑中。

另一種方法是更改​​導入的DLL的名稱。在極少數情況下(例如眾所周知的DLL),這是加載備用DLL的唯一可行方法,在某些特殊情況下仍可能失敗。

限制

如果所用的DLL位於DLL搜索順序的第一個位置,則必須從字面上替換磁盤上的文件,除非您如上所述重命名了導入。

實現

只有很少幾個導出符號的DLL可以使用手動方法。最簡單的方法是從DLL創建模塊定義文件,然後從該文件創建僅具有函數轉發器的DLL。這樣,您放置的DLL將已經加載,並且只需通過調用即可。

但是,這種方法對於導出的變量(相對於函數)將失敗。

這是一個簡單的方法我基於 pefile 編寫的Python腳本,它是在StackOverflow上的另一個答案

  import osimport sysimport redef main(pename):從pefile導入PE打印“ Parsing%s”%pename pe = PE(pename)modname = os.path.basename(pename)libname = re.sub(r“(?i)^。*?( [^ \\ /] +)\。(?: dll | exe | sys | ocx)$“,r” \ 1.lib“,modname)defname = libname.replace(”。lib“,” .def“)打印“為%s編寫模塊定義文件%s”%(defname,modname)f = open(defname,“ w”)#希望它拋出,這裡沒有復雜的錯誤處理f.write(“庫%s \ n \ n“%modname)f.write(” EXPORTS \ n“)numexp = 0,用於pe.DIRECTORY_ENTRY_EXPORT.symbols:if exp.name:numexp + = 1 f.write(” \ t%s \ n“%exp .name)打印“寫%帶有%d導出的s“%(defname,numexp)打印” \ n \ n使用此命令創建導出lib:\ n \ tlib / def:%s / out:%s“%(defname,libname)如果__name__ == '__main__':如果len(sys.argv)!= 2:sys.stderr.write(“ ERROR:\ n \ t語法:fakelib <dllfile> \ n”)sys.exit(1)sys.exit(main(sys.argv [1])) 

您可以對其進行調整以創建功能轉發器,而不是使用導出名稱的簡單模塊定義。

因此您可以將代碼穿梭到目標應用程序中並從那裡運行的方法。

替代方法

已經提到了儀器和掛鉤。 Detours(彎路)是經常被提及的示例,該鉤子出於大多數實際目的而使用了不方便的EULA。請參閱有關這種方法的現有答案。

您還可以使用 AppInit_DLL 註冊表值儘早插入DLL。或者,您可以編寫一個帶有調試器循環的啟動器,並使用 Image File Execution Options 使目標首先啟動調試器。調試器還可以影響DLL的加載,也可以方便地在可執行文件和DLL之間的邊界處攔截(方便地)調用。當您在Process Explorer中選擇選項時,將替換Task Manager。


您將注意到如何將這些方法歸類為 Ed McMan在其答案中提到的。但是,我將其留給讀者練習:)

jyz
2013-03-23 20:36:48 UTC
view on stackexchange narkive permalink

我在Windows上使用Notepad.exe完成了此操作。我想添加一個頂級菜單項來打開calc.exe只是為了好玩(我知道您的問題被標記為Linux和gcc編譯器,但是想法可能是相同的。)

所以我使用了 Resource Hacker工具添加Calc菜單,並在 Immunity Debugger上打開notepad.exe,在代碼中尋找一些空間,以便放置 WinExec shellcode。最初我沒有更改可執行文件,我不得不查看內存中的程序以找到一些空間,可以在其中粘貼我的彙編指令而不會導致記事本崩潰。

一旦我找到足夠的空間(通過更改原始代碼,消除了一些不需要的彙編指令甚至優化它們)我在 XVI Hex Editor上打開了notepad.exe,並蒐索了在Immunity上運行的操作碼。我的意思是,調試器正在運行一些操作碼,對嗎?我只是搜索了一系列操作碼,以確保我位於要更改的軟件的正確位置,並用我的shellcode(現在不是彙編代碼,而是“已編譯”的彙編-機器代碼)對其進行了封裝再次:我知道您的問題被標記為Linux和gcc編譯器,但也許有人可以指出Linux中的一些工具來實現與Windows相同的功能。這個想法可能是相同的。

Peter Teoh
2014-11-15 13:38:19 UTC
view on stackexchange narkive permalink

“ ptrace()”是Giles偶然提到的。但是我認為它本身應該值得一整節。 “ ptrace()”是OS提供的系統調用API(Linux和所有UNIX都有,Windows也是如此),以對另一個進程施加調試控制。當您使用PTRACE_ATTACH(作為ptrace()的一部分)附加到另一個進程時,內核將完全暫停運行該進程的CPU,從而允許您對進程的任何部分進行更改:CPU,任何寄存器,該部分的任何部分進程內存等。這就是動態內聯掛鉤的工作方式。 (附加ptrace(),修改內存中的二進製文件,然後附加ptrace())。據我所知,對另一個進程的所有動態修改都必須使用ptrace(),因為這是內核提供的唯一機制,可以通過系統調用來保證系統調用的完整性。 utrace()彈出了,因此理論上也可以進行內聯掛鉤:

http://landley.net/kdocs/ols/2007/ols2007v1-pages-215-224.pdf

對於內核掛鉤,有許多方法:syscall,中斷和內聯掛鉤。這是用於中斷掛鉤的:

http://mammon.github.io/Text/linux_hooker.txt



該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 3.0許可。
Loading...