Loại chuyển đổi mã được sử dụng trong các tệp thi hành Linux


13

Tôi muốn hỏi rằng loại mã hóa nào được sử dụng để tạo các tệp thực thi linux, ví dụ hexadecemal, binary hoặc bất cứ thứ gì khác. nó được chuyển đổi như thế nào? Có cách nào để lấy lại mã gốc từ tệp thực thi này không?

Đây là một chút mã tôi có:

ELF���������>�����%|�����@�������������������@�8��@���������������������@�������@�����7<�����7<������� ������������������f�����f���������������������� ������[�UPX!L
h�h�8����������?�E�h=��ڊ̓�N�    4���9ISloB�q�w�]ȉ.��,ς��Q䝦����#e��-�N����/�b,���d<��'��-E��6E�s�/�U���ly�V�Y2]"a��S�.�hU�|�S�J�I�2���X}
�G0�;���5d�$���.)

nó có nghĩa là gì?


Mặc dù nó sẽ không giúp bạn lấy lại được bất cứ thứ gì, nhưng điều đáng chú ý là stringschươ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.
Joe

Câu trả lời:


29

Đó là nhị phân. Mã nguồn đã được biên dịch. Bạn có thể xem nó trong một trình soạn thảo (một trình soạn thảo hex như blesscó thể tạo ra những thay đổi tinh tế hơn) nhưng bạn thực sự cần phải biết những gì bạn đang làm. Nó chỉ có thể tốt để thực hiện thay đổi chuỗi.

Đối với bất cứ điều gì khó khăn hơn, bạn có thể bắt đầu đảo ngược kỹ thuật nhị phân thành mã lắp ráp . Đây thường được coi là ngôn ngữ máy tính có thể phân tích cú pháp ở mức thấp nhất.

objdump -d helloworld | less

Nhưng nó cũng sẽ bao gồm rất nhiều trình biên dịch vô nghĩa. Ví dụ, nếu bạn biên dịch đơn giản nhấthelloworld.cpp với G ++ và sau objdumpđó, bạn kết thúc với 226 dòng (208 tước) của yuck. Bạn có thể viết một "thế giới xin chào" chỉ trong 15 dòng lắp ráp , biên dịch nó và objdumpnó vẫn phát triển thành 166 dòng (tước).

Nếu bạn đủ giỏi với lắp ráp, điều này có thể cung cấp cho bạn đủ quyền truy cập để hiểu những gì đang xảy ra và thậm chí cho phép bạn thay đổi nó ... Nhưng để trả lời câu hỏi ban đầu của bạn:

Bạn không thể biến mã được biên dịch trở lại thành mã nguồn ban đầu .

Lấy làm tiếc. Đó là một phép biến đổi một chiều làm mất thông tin (nhận xét, định dạng, khái niệm thuật toán có thể đọc được, v.v.), được liên kết tĩnh với những thứ khác và thường được tối ưu hóa theo cách khiến nó không thể hiểu được với bất kỳ ai trừ những lập trình viên giỏi nhất và dày dạn nhất.

Để cung cấp cho bạn ý tưởng về quy mô của vấn đề, toàn bộ ý tưởng về phần mềm kỹ thuật đảo ngược có trang web Stack Exchange riêng .


Bạn có thể cho tôi biết làm thế nào để tôi đảo ngược kỹ sư và lấy lại số lượng mã tối đa vì tôi đã mất nguồn
redchief

7
Xem chỉnh sửa gần đây của tôi. Không có trở lại nguồn ban đầu. Với rất nhiều học hỏi và nhiều thời gian, bạn có thể viết lại nguồn dựa trên mã lắp ráp đã tháo rời, nhưng trong hầu hết các trường hợp, nó sẽ rẻ hơn (trừ khi thời gian của bạn không có giá trị) và dễ dàng hơn để viết lại từ đầu.
Oli

1
Cách lấy lại số lượng mã tối đa là khôi phục bản sao lưu gần đây nhất. Đó cũng là cách tình cờ duy nhất để lấy lại một cái gì đó giống với mã nguồn ban đầu.
CVn

1
Hoàn toàn không đồng ý với đoạn cuối cùng, chỉ là một lưu ý phụ: một số trình dịch ngược IME tạo ra một công việc tuyệt vời trong việc khôi phục cấu trúc mã chính xác (tất nhiên ngoài những gì bạn đã nói, định dạng, tên biểu tượng ...). Nếu bạn không viết chương trình ở nơi đầu tiên, mã nguồn được khôi phục có thể vẫn không thể hiểu được, tuy nhiên tôi nghĩ đó là một lựa chọn tuyệt vời để khôi phục (ít nhất là một phần) mã nguồn bị mất / mã nguồn không xác định (ít nhất là một phần của mã nguồn thực sự dễ hiểu, tùy thuộc vào mã cụ thể và vào việc bạn có may mắn không)
kos

1
Đó là điều mà tất cả các EULA trong thế giới phần mềm độc quyền nói rằng bạn không được phép làm - kỹ thuật đảo ngược / tháo gỡ. Chúng bao gồm các mệnh đề như thế này vì có thể làm được - nhưng chắc chắn không dễ! Nhưng như @ MichaelKjorling nói, cách tốt nhất để lấy lại mọi thứ là từ nhiều cấp độ sao lưu cho bất cứ điều gì bạn quan tâm.
Joe

7

Tôi không đủ điểm danh tiếng cho một bình luận vì vậy đó là một câu trả lời:

Không, không thể chuyển đổi "trở lại". Bạn đề cập đến upx packer, bạn đã bao giờ đọc hướng dẫn sử dụng upx chưa?

Nếu bạn bị mất nguồn hoặc không có quyền truy cập vào mã của người khác không quan trọng ở đây, điều đó đơn giản là không thể.

Tệp thực thi nhị phân được tạo ra với trình biên dịch, đừng tin bất cứ điều gì được nêu trên trang web này, chỉ cần đọc hướng dẫn của chính xác trình biên dịch đó. Sau đó, bạn có thể thêm vào đây, bằng ngôn ngữ mà mã gốc được viết, trình biên dịch nào đã được sử dụng và sau đó bạn có thể lưu ý rằng các bước này (tiền xử lý, biên dịch, liên kết, có thể đóng gói) không bị đảo ngược toàn bộ, nhưng chỉ có thể được phân tích những gì tác giả ban đầu có thể có ý định và viết.


3

Đây có lẽ là một tệp nhị phân (Tệp ELF) như được mô tả độc đáo ở đây:

https://en.wikipedia.org/wiki/Executable_and_Linkable_Format

Nếu bạn đã thay đổi nó bằng một trình soạn thảo văn bản bình thường và lưu các thay đổi của bạn, thì đây không phải là ý kiến ​​hay và bạn có thể đã phá hủy nó.


3

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 thể có được thứ gì đó bằng cách sử dụng trình dịch ngược.


2

Thực thi thường là nhị phân nếu bạn đang nói về các chương trình được biên dịch. Bạn có thể tìm thêm thông tin bằng cách sử dụng file path/to/executable. Bạn có thể hiển thị các tệp thực thi nhị phân theo hệ thập lục phân bằng cách sử dụng ví dụ hexdump -C path/to/executable | less(bất cứ điều gì tốt sẽ làm cho bạn). Nếu bạn muốn "chuyển đổi nó trở lại dạng ban đầu", bạn phải sử dụng một trình dịch ngược phù hợp , nếu đây là thứ bạn cần. xem bài đăng này, ví dụ , mặc dù điều đó sẽ cung cấp cho bạn mã khá khó đọc không phải là bản gốc được biên dịch từ đó. Nếu nó không phải là một tệp nhị phân được biên dịch, nó sẽ là một loại tập lệnh thực thi, có thể dễ đọc trong bất kỳ trình soạn thảo văn bản nào. Những gì bạn chỉ cho chúng tôi ở đây có lẽ là một biên dịch thực thi. ELF có nghĩa là "Định dạng liên kết và thực thi" là định dạng nhị phân phổ biến trên các hệ thống Linux / Unix. Cóstrings path/to/executable


Tôi đã cố gắng đảo ngược nó với trình đóng gói upx nhưng không hoạt động và cũng với bài đăng mà bạn đề xuất. Vì vậy, xin vui lòng cho tôi biết nếu có một cách khác.
redchief

Rất xin lỗi, nhưng tôi không thể nói với bạn nhiều hơn những gì được viết trong bài viết xuất sắc của @ Oli's.
Hinz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.