Với các ngôn ngữ máy ảo dựa trên mã byte như Java, VB.NET, C #, ActionScript 3.0, v.v., đôi khi bạn nghe thấy việc dễ dàng tải xuống một số trình dịch ngược từ Internet, chạy mã byte qua nó một lần thông thường, đến với một cái gì đó không quá xa mã nguồn ban đầu trong vài giây. Giả sử loại ngôn ngữ này đặc biệt dễ bị tổn thương.
Gần đây tôi đã bắt đầu tự hỏi tại sao bạn không nghe nhiều hơn về điều này liên quan đến mã nhị phân gốc, khi bạn ít nhất biết ngôn ngữ đó được viết bằng ngôn ngữ nào (và do đó, ngôn ngữ nào sẽ cố dịch ngược). Trong một thời gian dài, tôi đã hình dung ra điều đó chỉ vì ngôn ngữ máy bản địa quá điên rồ và phức tạp hơn so với mã byte thông thường.
Nhưng mã byte trông như thế nào? Nó trông như thế này:
1000: 2A 40 F0 14
1001: 2A 50 F1 27
1002: 4F 00 F0 F1
1003: C9 00 00 F2
Và mã máy gốc trông như thế nào (trong hex)? Nó, tất nhiên, trông như thế này:
1000: 2A 40 F0 14
1001: 2A 50 F1 27
1002: 4F 00 F0 F1
1003: C9 00 00 F2
Và các hướng dẫn đến từ một khung tâm trí hơi giống nhau:
1000: mov EAX, 20
1001: mov EBX, loc1
1002: mul EAX, EBX
1003: push ECX
Vì vậy, đưa ra ngôn ngữ để cố gắng dịch ngược một số nhị phân nguyên gốc thành C ++, có gì khó khăn về nó? Hai ý tưởng duy nhất nảy ra trong đầu là 1) nó thực sự phức tạp hơn nhiều so với mã byte, hoặc 2) một điều gì đó về thực tế là các hệ điều hành có xu hướng phân trang chương trình và phân tán các phần của chúng gây ra quá nhiều vấn đề. Nếu một trong những khả năng đó là chính xác, xin vui lòng giải thích. Nhưng dù bằng cách nào, tại sao bạn không bao giờ nghe về điều này về cơ bản?
GHI CHÚ
Tôi sắp chấp nhận một trong những câu trả lời, nhưng tôi muốn đề cập đến điều gì đó trước tiên. Hầu hết mọi người đều đề cập đến thực tế là các đoạn mã nguồn gốc khác nhau có thể ánh xạ tới cùng một mã máy; Tên biến cục bộ bị mất, bạn không biết loại vòng lặp ban đầu được sử dụng, v.v.
Tuy nhiên, những ví dụ như hai thứ vừa được nhắc đến là một thứ tầm thường trong mắt tôi. Một số câu trả lời mặc dù có xu hướng nói rằng sự khác biệt giữa mã máy và nguồn ban đầu mạnh hơn nhiều so với thứ tầm thường này.
Nhưng ví dụ, khi nói đến những thứ như tên biến cục bộ và loại vòng lặp, mã byte cũng mất thông tin này (ít nhất là đối với ActionScript 3.0). Tôi đã kéo những thứ đó trở lại thông qua một trình dịch ngược trước đó và tôi không thực sự quan tâm liệu một biến được gọi là strMyLocalString:String
hay loc1
. Tôi vẫn có thể nhìn vào phạm vi nhỏ, cục bộ đó và xem nó được sử dụng như thế nào mà không gặp nhiều rắc rối. Và một for
vòng lặp là khá chính xác như mộtwhile
vòng lặp, nếu bạn nghĩ về nó. Ngoài ra, ngay cả khi tôi sẽ chạy nguồn thông qua irFuscator (không giống như safeSWF, không làm gì nhiều ngoài việc chỉ ngẫu nhiên hóa tên biến và tên hàm thành viên), có vẻ như bạn chỉ có thể bắt đầu cô lập một số biến và hàm nhất định trong các lớp nhỏ hơn, hình tìm hiểu cách họ được sử dụng, gán tên của riêng bạn cho họ và làm việc từ đó.
Để điều này trở thành một vấn đề lớn, mã máy sẽ cần phải mất nhiều thông tin hơn thế, và một số câu trả lời đi sâu vào vấn đề này.