Như Oli đã chỉ ra trong câu trả lời của anh ấy, bạn không thể lấy mã nguồn ban đầu của một tệp thực thi.
Trong quá trình biên dịch mã nguồn (việc biên dịch nhằm mục đích chấp nhận rộng hơn điển hình của nó, do đó toàn bộ quá trình "biến đổi" mã nguồn thành một tệp thực thi), rất nhiều thông tin bị mất.
Bộ tiền xử lý C, đối với một, sẽ làm như sau (trong số những thứ khác):
- Giải thích, thực thi và loại bỏ các chỉ thị (
#
câu lệnh) tiền xử lý
- Xóa bình luận
- Xóa khoảng trắng không cần thiết
Mặt khác, những gì không bị mất trong quá trình biên dịch mã nguồn về mặt kỹ thuật có thể hoàn nguyên về mã nguồn tương đương về mặt chức năng.
Điều này là do:
- Hướng dẫn nhị phân có độ chính xác 1: 1 với hướng dẫn lắp ráp; việc lắp ráp mã nguồn lắp ráp chỉ là một sự chuyển đổi đơn thuần của các hướng dẫn lắp ráp thành các hướng dẫn nhị phân dựa trên một bảng các điều kiện cần thiết; một lệnh nhị phân duy nhất luôn có thể nhận dạng và hoàn nguyên thành một lệnh lắp ráp đơn ;
- Hướng dẫn lắp ráp không có độ chính xác 1: 1 với hướng dẫn C; việc biên dịch mã nguồn C thường không chỉ là sự chuyển đổi đơn thuần các hướng dẫn C thành các hướng dẫn lắp ráp dựa trên một bảng các điều kiện cần thiết, trên thực tế, nó thường ngược lại; thông thường một lệnh C được chuyển đổi thành nhiều lệnh (thường khác nhau dựa trên trình biên dịch); tuy nhiên, các mẫu của nhiều hướng dẫn lắp ráp thường có thể nhận dạng và hoàn nguyên theo một lệnh C ;
Có những công cụ được gọi là trình dịch ngược có mục đích là cố gắng hoàn nguyên mã thực thi thành mã nguồn tương đương về chức năng; tuy nhiên, kết quả thường là một cái gì đó khác xa với mã nguồn ban đầu (và thường không thể biên dịch được);
Hãy xem xét chương trình này:
#include <stdio.h>
#define MESSAGE "Literal strings will be recovered" // This preprocessor directive won't be recovered
/*
This comment and the comment above won't be recovered
*/
int main(int argc, char* argv[]) {
printf(MESSAGE);
return 0;
}
Bằng cách biên dịch nó thành một tệp thực thi và dịch ngược lại thành mã nguồn, đây ít nhiều là những gì bạn thường lấy lại (trong trường hợp cụ thể này tôi đã sử dụng gcc
/ Boomerang ):
// address: 0x80483fb
int main(int argc, char **argv, char **envp) {
printf("Literal strings will be recovered");
return 0;
}
Theo dự đoán:
- Chỉ thị tiền xử lý bị thiếu
- Nhận xét bị thiếu (ngoài
// address: 0x80483fb
, đã được thêm vào bởi trình dịch ngược)
- Khoảng trắng không cần thiết bị thiếu (ngoài các dòng mới và bảng, đã được thêm vào bởi trình dịch ngược)
Đây cũng là một kết quả khá tốt; Không hiếm khi nhận được hướng dẫn lắp ráp nội tuyến vào mã:
asm("assembly_instruction");
__asm__("assembly_instruction");
Điểm mấu chốt là (như đã chỉ ra trong các câu trả lời khác): bạn không thể có được nguồn gốc của một tệp thực thi *.
* Tuy nhiên, tùy thuộc vào khả năng thực thi và vào vận may của bạn, bạn có thể có được thứ gì đó bằng cách sử dụng trình dịch ngược.
strings
chương trình lọc có thể rất hữu ích trong việc xác định chương trình nhị phân cụ thể là gì hoặc vì nó sẽ in tất cả các chuỗi văn bản được nhúng dài hơn một độ dài được chỉ định trong một tập tin nhị phân và nhìn vào các thông điệp trong một chương trình đôi khi cho bạn biết rất nhiều về những gì nó đang và làm.