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


Tôi muốn hỏi rằng loại mã hóa nào được sử dụng để tạo tệp thực thi linux, ví dụ: hexadecemal, nhị phân hoặc bất kỳ 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 tin thực thi này không?

Dưới đâ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ì?


13
2017-09-08 07:34


gốc


Mặc dù nó sẽ không giúp bạn có được nhiều thứ trở lại, đáng chú ý là strings chương trình lọc có thể rất hữu ích trong việc xác định một 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 độ dài được chỉ định trong tệp nhị phân và xem các thông báo trong chương trình đôi khi cho bạn biết rất nhiều về nó là và làm. - Joe
Có thể / một phần trùng lặp? stackoverflow.com/questions/193896/whats-a-good-c-decompiler - arielf


Các câu trả lời:


Nó 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ư bless có thể làm cho những thay đổi tinh tế hơn) nhưng bạn thực sự cần biết bạn đang làm gì. Nó có khả năng chỉ tốt cho việc thay đổi chuỗi.

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

objdump -d helloworld | less

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

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

Bạn không thể chuyển mã được biên dịch trở lại nguyên mã nguồn.

Lấy làm tiếc. Đó là một phép chuyển đổi một chiều mất thông tin (bình luận, định dạng, khái niệm thuật toán có thể đọc được, vv), đượ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 sao cho không thể hiểu được bất cứ điều gì, nhưng là 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 của riêng nó.


29
2017-09-08 08:00



Bạn có thể cho tôi biết làm thế nào để đảo ngược kỹ sư nó và lấy lại số tiền tối đa của mã coz Tôi đã mất nguồn - redchief
Xem chỉnh sửa gần đây của tôi. Không có trở lại nguồn gốc. Với rất nhiều việc học tập và rất 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 là vô giá trị) và dễ dàng hơn để viết lại từ đầu. - Oli♦
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à, tình cờ, chỉ có cách đáng tin cậy để lấy lại một cái gì đó tương tự như mã nguồn ban đầu. - Michael Kjörling
Không hoàn toàn không đồng ý với đoạn cuối, chỉ là một lưu ý phụ: một số trình dịch ngược IME tạo một công việc tuyệt vời để khôi phục lại cấu trúc mã chính xác (tất nhiên là khi bạn nói bình luận, định dạng, tên biểu tượng ...). Nếu bạn không viết chương trình ở vị trí đầu tiên thì mã nguồn đã phục hồi có thể vẫn không hiểu được, tuy nhiên tôi nghĩ rằng đó là một tùy chọn tuyệt vời để khôi phục (ít nhất 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 nó) thực sự dễ hiểu, tùy thuộc vào mã cụ thể và về việc bạn có may mắn không) - kos
Đó là tất cả những gì EULA trong thế giới phần mềm sở hữu độc quyền nói rằng bạn không được phép làm - đảo ngược kỹ thuật / tháo gỡ. Chúng bao gồm các mệnh đề như thế này bởi vì nó có thể làm được - nhưng chắc chắn không dễ dàng! Nhưng như @ MichaelKjörling nói, cách tốt nhất để có được những điều trở lại là từ nhiều cấp độ sao lưu cho bất cứ điều gì bạn quan tâm. - Joe


Tôi không có đủ điểm danh tiếng để nhận xét nên đây là câu trả lời:

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

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, nó chỉ đơn giản là không thể.

Thực thi nhị phân được tạo ra với trình biên dịch, không tin bất cứ điều gì được nêu trên trang này, chỉ cần đọc hướng dẫn của trình biên dịch chính xác đó. Sau đó, bạn có thể thêm vào đây, 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 được đảo ngược như một tổng thể, nhưng chỉ có thể được phân tích những gì tác giả gốc có thể đã dự định và được viết.


7
2017-09-08 14:30





Đây có lẽ là 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ó với 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, điều này là không có ý tưởng tốt và bạn có thể đã phá hủy nó.


3
2017-09-08 07:48





Như Oli đã chỉ ra đã có trong câu trả lời của mình, bạn không thể có được mã nguồn ban đầu của một tập tin thực thi.

Trong quá trình biên soạn mã nguồn (biên dịch dự định như trong sự 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), nhiều thông tin bị mất.

Bộ tiền xử lý C, cho một, sẽ làm như sau (trong số những thứ khác):

  • Giải thích, thực hiện và loại bỏ các chỉ thị tiền xử lý (# các câu lệnh)
  • Xóa nhận xét
  • 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ới 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 của một assembly chỉ là một sự chuyển đổi đơn giản của các lệnh assembly thành các lệnh nhị phân dựa trên một bảng các điều chỉnh; một lệnh nhị phân đơn luôn luôn được nhận dạng và có thể 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ó sự điều chỉnh 1: 1 với hướng dẫn C; việc biên soạn mã nguồn C là thường không chỉ đơn giản là chuyển đổi các lệnh C thành các lệnh lắp ráp dựa trên một bảng các sự điều chỉnh, thực ra nó thường ngược lại; thường một lệnh C được chuyển đổi thành nhiều hướng dẫn lắp ráp nhiều (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 biết được và có thể hoàn nguyên về một lệnh C;

Có những công cụ được gọi là các trình giải mã có mục đích là cố gắng hoàn nguyên một tệp thực thi thành một mã nguồn tương đương với hàm; tuy nhiên kết quả thường là một cái gì đó xa từ mã nguồn ban đầu (và thường cũng không thể giải nén);

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 tin thực thi và giải mã nó thành một mã nguồn một lần nữa, đây là nhiều hay ít 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;
}

Như dự đoán:

  • Các chỉ thị tiền xử lý bị thiếu
  • Nhận xét bị thiếu (ngoài // address: 0x80483fb, đã được thêm bởi trình giải mã)
  • Thiếu khoảng trống không cần thiết (ngoài các dòng mới và các bảng, đã được thêm bởi trình biên dịch ngược)

Đây cũng là một kết quả khá tốt; nó không phải là hiếm để có đượ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 thực sự ban đầu*.

* Tuy nhiên, tùy thuộc vào thực thi và về vận may của bạn, bạn có thể có thể nhận được một cái gì đó bằng cách sử dụng một bộ giải mã.


3
2017-09-09 16:29





Các tệp 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ị tệp thi hành nhị phân trong 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 mà sẽ làm bạn). Nếu bạn muốn "chuyển đổi nó trở về dạng ban đầu của nó", bạn phải sử dụng một trình dịch ngược thích hợp xem bài đăng này, ví dụ:, mặc dù điều đó sẽ cung cấp cho bạn mã khá khó đọc chứ không phải mã gốc mà nó được biên dịch từ đó. Nếu nó không phải là một nhị phân biên dịch nó sẽ là một số loại kịch bản thực thi, mà nên dễ dàng đọc được trong bất kỳ trình soạn thảo văn bản. Những gì bạn cho chúng tôi thấy ở đây có lẽ là một tệp thực thi được biên dịch. ELF có nghĩa là "định dạng thực thi và liên kết" là định dạng nhị phân phổ biến trên các hệ thống Linux / Unix. Có khả năng trích xuất các phần chuỗi có thể đọc được từ các tệp nhị phân bằng cách sử dụng strings path/to/executable, nếu đây là những gì bạn cần.


2
2017-09-08 08:00



Tôi đã cố gắng để đảo ngược kỹ sư nó với packer upx nhưng không làm việc và cũng với bài viết bạn đã đề nghị. Vì vậy, xin vui lòng cho tôi biết nếu có một cách khác. - redchief
Rất tiếc, nhưng tôi không thể nói cho bạn biết gì hơn những gì được viết trong bài viết tuyệt vời của @ Oli. - Hinz