簡體   English   中英

從二進制文件獲取源代碼

[英]Obtaining source code from the binary

難道不可能從二進制文件中獲取源代碼嗎? 由於編譯是將高級語言(源代碼)轉換為低級語言(機器代碼)的過程,難道我們不能為了獲得源代碼而僅僅顛倒該過程嗎? 如果沒有,為什么?

假設我給您數字3 ,並告訴您我是通過將兩個數字相加得到的。 您能告訴我3是總和的兩個數字嗎? 這是不可能的,因為sum是單向函數-無法從其輸出中恢復其參數。 我可以從-5558獲得它,即使對於您 12仍然可以得出相同的答案。

編譯是相似的。 有無數個C ++程序可以生成任何特定的機器代碼輸出(或多或少)。

您當然可以顛倒編譯過程,並產生C或C ++代碼,這些代碼至少會導致具有相同語義(含義)的機器代碼,但可能不是逐字節相同的。 這樣的工具在不同程度上存在。

是的,這是可能的,但是由於必須丟失源代碼中的許多信息,因此您將獲得的代碼不會對原始源代碼的設計產生太多的了解。 對於任何規模很大的項目,您將獲得的代碼將執行相同的操作,但是對於人類來說幾乎是不可讀的。 這將是一些非常非常模糊的C / C ++。

為什么信息丟失? 因為高級語言的全部重要之處在於它們應該對人類有效 源代碼越高級且易於理解,它與完成編譯器時產生的機器代碼的差異就越大。 作為軟件設計師,您的主要目標是利用編譯器和其他代碼生成工具將高級思想和概念轉換為機器代碼。 兩者之間的差距越大,有關高級設計的更多信息就會丟失。

請記住,編譯器必須保留的唯一內容就是代碼的語義 (含義)。 只要看起來代碼在按照您的意圖執行操作,一切都很好。 例如,當現代編譯器根據某種度量標准進行“有意義”的操作時,它們可以預先執行部分代碼,並僅存儲操作結果。 假設整個程序的內容如下:

#include <iostream>
#include <cmath>
int main() {
  std::cout << sin(1)+cos(2) << std::endl;
  return 0;
}

假設使用Unix系統,則編譯器完全有權產生可執行兩個系統調用的機器代碼:對stdout的寫入(具有恆定的緩沖區)和退出。 反編譯此類代碼后,您可以獲得:

#include <unistd.h>
#include <cstdlib>
int main() {
  write(0, "0.425324\n", 9);
  exit(0);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM