Chuỗi mã hóa runtime
Hôm nay chúng ta sẽ tìm hiểu cơ bản về chuỗi mã hóa runtime, tại sao cần mã hóa chuỗi và học cách tạo ra chuỗi mã hóa của riêng mình.
Trong bài viết này bạn sẽ hiểu và học được:
- Mã hóa và giải mã runtime là gì
- Tại sao bạn cần mã hóa chuỗi của mình
- Xem cách bất kỳ ai cũng có thể xem dữ liệu nhạy cảm của bạn
- Tạo mã hóa tùy chỉnh của riêng mình
Mã hóa và giải mã runtime là gì
Đây là dữ liệu được mã hóa và/hoặc giải mã trong quá trình thực thi chương trình (phần mềm, ứng dụng). Dữ liệu có thể là bất kỳ loại nào: khối bộ nhớ, lưu lượng mạng, chuỗi, v.v.
Một trong những phương pháp phổ biến nhất được sử dụng cho mục đích này là làm rối mã (cơ bản). Các cơ chế khác (nâng cao) bao gồm biến đổi/ảo hóa mã biên dịch.
Hôm nay chúng ta sẽ tập trung vào cơ chế sử dụng làm rối XOR .
Tại sao phải mã hóa chuỗi?
Ngay khi bạn chạy phần mềm, mọi thứ đều hiển thị trong bộ nhớ. Điều này cũng áp dụng cho người dùng cuối, nghĩa là họ có thể nhìn thấy mọi thứ.
Một trong những điều đầu tiên kẻ tấn công sẽ làm là tìm kiếm chuỗi bên trong phần mềm của bạn. Điều này sẽ cho phép họ hiểu mọi thứ về phần mềm của bạn với nỗ lực tối thiểu.
Nếu bạn đang lưu trữ dữ liệu nhạy cảm (như mật khẩu hoặc giấy phép), điều quan trọng là không lưu trữ chúng dưới dạng văn bản thuần. Lưu trữ chúng dưới dạng văn bản thuần sẽ giúp kẻ tấn công dễ dàng hơn.
Có nhiều cách để phân tích phần mềm của bạn. Các phương pháp phổ biến và nổi tiếng nhất là phân tích tĩnh và phân tích runtime.
Hãy xem một ví dụ đơn giản sử dụng ứng dụng console:
Hãy biên dịch ở chế độ Release (để tránh thông tin debug). Tiếp tục và kiểm tra phân tích tĩnh và phân tích runtime.
Kiểm tra phân tích tĩnh
Trong phân tích tĩnh, phần mềm không cần phải chạy. Vậy nên, hãy mở mẫu trong Ghidra .
Từ ảnh chụp màn hình bên dưới, bạn có thể thấy mẫu được biên dịch mà không có thông tin debug:
Nếu tìm kiếm chuỗi, bạn có thể thấy tất cả thông tin nhạy cảm của chúng ta đều hiển thị:
Sau khi đánh dấu chuỗi, bạn có thể mở trình xem trình dịch ngược và xem toàn bộ mã liên quan:
Khá buồn phải không? 😕 Hãy tưởng tượng bạn đã làm việc trên phần mềm tuyệt vời của mình hàng tháng trời và sẵn sàng bán nó.
Tôi nghĩ phần còn lại đã tự giải thích, nhưng tôi chắc bạn đã nắm được ý chính.
Điều còn buồn hơn là việc này đơn giản đến mức một đứa trẻ mười hai tuổi cũng có thể làm được. (và một số thực sự làm vậy)
Kiểm tra phân tích runtime
Trong phân tích runtime, phần mềm phải đang chạy. Điều này có nghĩa là chúng ta cần sử dụng phần mềm để mở tiến trình và đọc nó (thường là trình gỡ lỗi).
Tuy nhiên, trình gỡ lỗi không thực sự cần thiết cho mục đích này. Chúng ta chỉ cần tải xuống một công cụ miễn phí như Process Hacker và mở tiến trình:
Khá đơn giản phải không? Và hãy nhớ rằng chúng ta thậm chí chưa gắn trình gỡ lỗi. Một người có kỹ năng và quyết tâm sẽ sử dụng trình gỡ lỗi.
Khi gắn trình gỡ lỗi, bạn sẽ thấy nhiều thứ hơn, nhưng cuộc thảo luận đó sẽ dành cho ngày khác.
Tạo chuỗi mã hóa runtime
Có nhiều cách để đạt được điều này:
- Sử dụng phần mềm bên thứ ba như VMProtect , Themida .
- Mã hóa chuỗi lúc biên dịch như xorstr .
- Sử dụng phương pháp tùy chỉnh
2 lựa chọn đầu tiên có thể không phù hợp với nhu cầu của bạn. Có nhiều ưu và nhược điểm cho mỗi lựa chọn, mà chúng ta sẽ không thảo luận lúc này.
Một điều bạn cần hiểu là sự phổ biến đồng nghĩa với rủi ro. Khi bạn sử dụng những thứ tìm được ngẫu nhiên trên Google, ai đó đã biết về nó rồi.
Hầu hết mọi người đã phát triển một công cụ chống lại công cụ của bạn. Đó là cách mọi thứ vận hành. Họ làm vì thách thức, hoặc để đánh cắp công trình của bạn, nhưng họ vẫn làm.
Với điều đó trong đầu, bạn cần đi theo hướng tùy chỉnh. Bạn có thể tạo mã hóa chuỗi riêng từ cấp cơ bản đến nâng cao.
Kế hoạch
- Tạo giải pháp dễ sử dụng
- Giữ chuỗi luôn được mã hóa
- Chỉ giải mã khi cần
- Đặt chuỗi ở vị trí ngẫu nhiên (tùy chọn - chưa đề cập)
- Hủy chuỗi sau khi sử dụng (tùy chọn - chưa đề cập)
Giải pháp
Bắt đầu bằng cách định nghĩa các chuỗi từng cái một dưới dạng mảng:
Mảng có thể chứa số lượng chuỗi không giới hạn với giới hạn độ dài là 256.
Tôi biết đây là một công việc khó khăn, đặc biệt nếu chuỗi của bạn dài. Đây chỉ là cho mục đích minh họa và sau này chúng ta sẽ tạo giải pháp thực tế hơn.
Ý tưởng là mã hóa từng ký tự của chuỗi. Tôi sẽ sử dụng mã hóa XOR đơn giản cho việc này.
Dưới đây bạn có thể thấy ví dụ về cách hoạt động:
Đoạn trên không có gì phức tạp, đơn giản và trực tiếp nhưng khá mạnh mẽ. Bạn có thể sử dụng nó trong ứng dụng console.
Sau khi biên dịch và chạy, kết quả là các byte không thể đọc được bằng mắt thường:
Vậy là xong, phần mềm nhỏ của bạn để tạo chuỗi mã hóa runtime. 😏
Kết quả
Đã đến lúc đưa giải pháp vào thực tế. Hãy tạo một mẫu khác cho mục đích này và thêm mã của chúng ta:
Lưu ý 2 điều quan trọng:
- Tôi đã cố tình để lại một số chuỗi dưới dạng văn bản thuần để cho thấy sự khác biệt
- Hàm giải mã cần độ dài (sẽ thảo luận sau)
Hãy biên dịch đoạn trên ở chế độ Release và chạy. Mẫu mới hoạt động bình thường:
Nếu mở mẫu mới trong IDA (hoặc Ghidra), các chuỗi đã mã hóa không hiển thị:
Tôi đã đề cập rằng có một số chuỗi được cố tình để ở dạng văn bản thuần trong mẫu này. Lý do là chúng ta có thể theo dõi chúng để xem mã:
Tôi đã phải cuộn xuống để đến được đoạn văn bản trong hình ảnh phía trên. Bạn có thể thấy mã đã biên dịch khác biệt đến mức nào.
Chúng ta đã giải quyết vấn đề phân tích tĩnh, hãy chuyển sang runtime.
Hãy mở nó trong Process Hacker:
Tuyệt vời! Chúng ta cũng đã giải quyết vấn đề phân tích runtime 😎
Tìm hiểu thêm về chuỗi mã hóa
Ví dụ trên không thực sự thực tế. Định nghĩa từng chuỗi thủ công là một công việc cực nhọc, cũng như việc chỉ định độ dài chuỗi mỗi lần.
Lý tưởng nhất chúng ta cần:
- Đọc tệp văn bản cho các chuỗi
- Ghi các chuỗi kết quả vào tệp văn bản
- Thêm chuỗi thoát vào chuỗi để tránh chỉ định độ dài mỗi lần.
- Thêm XOR phức tạp hơn hoặc bất kỳ phương pháp nào khác (tùy chọn)
- Đặt chuỗi ở vị trí ngẫu nhiên (tùy chọn)
Tôi đã chuẩn bị một giải pháp tuyệt vời để bạn thử nghiệm. Bạn có thể kiểm tra mọi thứ được viết trong bài viết này và cũng có công cụ riêng sẵn sàng sử dụng để tạo chuỗi mã hóa runtime.
Bao gồm 4 dự án:
- RuntimeStringEcryptor đọc chuỗi từ tệp văn bản, mã hóa chúng rồi ghi vào tệp văn bản khác.
- Sample là ứng dụng console đơn giản được sử dụng để minh họa với IDA.
- SampleEncryptedStrings là ứng dụng console đơn giản với chuỗi đã mã hóa để minh họa với IDA.
- SimpleRuntimeStringEncryption là sân chơi ban đầu nơi bạn có thể kiểm tra phương pháp này.
Lưu ý:
- Nếu bạn không thêm chuỗi thoát, quá trình giải mã sẽ không biết khi nào cần “dừng”. Kết quả sẽ là dữ liệu không đọc được/null cho đến khi đạt kích thước mảng đã định nghĩa.
- Đảm bảo thay đổi các khóa XOR mà tôi đã sử dụng trong ví dụ.
- Tránh sử dụng cùng một từ nhiều lần. Chúng sẽ tạo ra các byte giống nhau và có nguy cơ bị phát hiện.
Tải xuống
Để tải xuống giải pháp sẵn sàng sử dụng, hãy cân nhắc ủng hộ blog này 😘
Bình luận