0
0
Lập trình
Sơn Tùng Lê
Sơn Tùng Lê103931498422911686980

Phân Tích và Mã Hóa Traffic Của Ứng Dụng Android: Hướng Dẫn Chi Tiết

Đăng vào 3 ngày trước

• 4 phút đọc

Giới Thiệu

Khi tiến hành kiểm thử xâm nhập (pentest) cho một số ứng dụng Android, bạn có thể gặp phải tình trạng traffic giữa thiết bị Android và server bị mã hóa. Để sửa đổi request nhằm mục đích kiểm thử, việc hiểu rõ cũng như tái hiện cơ chế mã hóa và giải mã là điều cần thiết. Bài viết này sẽ hướng dẫn bạn từng bước cụ thể để đạt được mục tiêu này.

Cài Đặt Công Cụ

Để bắt đầu, bạn cần cài đặt một số công cụ như emulator (mà mình sử dụng là WSA của Windows), jadx và frida. Bạn có thể tham khảo các bài viết sau để biết chi tiết cách cài đặt:

Ứng Dụng Mẫu

Mình sẽ sử dụng một ứng dụng Android có chức năng đăng nhập (tên ứng dụng sẽ được che đậy để tránh rắc rối pháp lý). Sau khi sử dụng Proxydroid để chuyển hướng traffic sang Burp và thực hiện đăng nhập với email abc@example.com và mật khẩu 123456, ta nhận được traffic như sau:

Copy
Du22azpzkVjMk0l0Emtcv1S8xnawAf+zMFcnvJaNhnC7ejCWD3pdDPHJeP5N1dFhon/EFHIuZO3NpGNLn2tDmwvPElDD2BG+zGAPgwQ3Ct8=

Dữ liệu này đã được mã hóa và sau đó encode bằng base64. Tiếp theo, khi xem xét một số API, mặc dù server trả về dữ liệu dưới dạng JSON, nhưng nội dung cũng không phải là văn bản rõ ràng:

Copy
{"code":0,"data":{"info":"rLrUWFNS+npD4GybX979A02j5M6nJI9wy0i3unlQ9MvGnq85XXwNWqOPvqVclKQUDYTeC2sOiV2w5DwqfzRMgjLNribJEFmiyxQPsgw+mGo="}}

Hãy cùng tìm hiểu cách ứng dụng này mã hóa dữ liệu.

Phân Tích Ứng Dụng Android

Trước hết, có một số điểm cần lưu ý:

  • Để đảm bảo hiệu suất, phương pháp mã hóa thường sử dụng mã hóa đối xứng, phổ biến nhất là AES, thay vì mã hóa bất đối xứng (như RSA).
  • Khi mã hóa giữa client và server (và server cũng trả về dữ liệu mã hóa), có khả năng cao là phía client sẽ có key để giải mã.

Chúng ta sẽ sử dụng jadx để decompile ứng dụng. Bắt đầu bằng cách tìm kiếm từ khóa aes, và ngay lập tức thấy nhiều kết quả khả quan.

Chú ý đến đoạn mã sau trong class getAESCipher:

java Copy
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");

Đây là đoạn mã khởi tạo instance cho quá trình mã hóa và giải mã AES. Khi kiểm tra nơi gọi hàm getAESCipher, chúng ta chỉ thấy nó được gọi một lần, và đó là những xử lý liên quan đến mã hóa và giải mã file chứ không phải traffic trên server.

Quay trở lại tìm kiếm, ấn vào Load more để xem tất cả kết quả. Chúng ta tìm thấy những hàm khác như trong class DecodeUtils, nơi có:

  • NativeUtil.getInstance().aesDecryptWithKey
  • NativeUtil.getInstance().aesEncryptWithKey

Khi vào class NativeUtil, chúng ta chỉ thấy danh sách các hàm mà không có mã nguồn, vì các hàm này được viết bằng ngôn ngữ native và không phải Java.

Phần mã hóa này sẽ nằm trong thư viện lib + alg. Đổi đuôi file .apk thành .zip và giải nén, tìm đến thư mục lib > arm64-v8a và bạn sẽ thấy file libalg.so (cũng có cả file debug của thư viện này).

Sử Dụng Frida

Để hiểu sâu về quá trình mã hóa, bạn cần reverse engineering file .so đã đề cập. Tuy nhiên, nếu bạn chỉ muốn thao tác với những request trong Burp, bạn có thể dùng Frida để hook.

Nhấp chuột phải vào tên hàm và chọn copy as frida snippet (f) như hình dưới đây:

Sau đó, sao chép và dán vào file hook.js, tạo thành file với mục tiêu là log ra các tham số và kết quả của các hàm mã hóa/giải mã:

Chạy frida-server trên thiết bị và sử dụng lệnh sau để spawn và hook ứng dụng:

Copy
frida -U -l hook.js -f com.redacted

Thực hiện đăng nhập lại trên ứng dụng, bạn sẽ thấy output trên console với tham số và kết quả mã hóa:

BINGO! Bạn cũng có thể chỉnh sửa mã để gọi hàm aesEncryptWithKey với tham số tùy ý.

Phân Tích Thư Viện Native

Nếu chỉ dừng lại ở đây vẫn chưa đủ để thao tác trên Burp, bạn cần đi sâu hơn. Mở IDA và tải file libalg.so:

Nhờ đã biết tên các hàm khi gọi từ Java, bạn có thể tìm được các hàm tương ứng. Việc còn lại chỉ là đọc mã để tìm key.

Chú ý hàm getKey có truyền vào một tham số kiểu unsigned int, đây sẽ là index của key sử dụng (vì ứng dụng có nhiều key mã hóa cho các chức năng khác nhau). Để lấy key này, bạn chỉ cần tuân thủ các bước reverse đơn giản.

Nếu gặp khó khăn, hãy thử hỏi ChatGPT nhé!

Sau khi có key và phương pháp mã hóa dữ liệu, bạn có thể tái hiện quá trình giải mã bằng CyberChef như sau:

Với dữ liệu lúc đầu: Du22azpzkVjMk0l0Emtcv1S8xnawAf+zMFcnvJaNhnC7ejCWD3pdDPHJeP5N1dFhon/EFHIuZO3NpGNLn2tDmwvPElDD2BG+zGAPgwQ3Ct8=, bạn sẽ giải mã thành công. Tại đây, bạn có thể sử dụng Hackvertor để viết một custom tag cho phép tùy ý chỉnh sửa dữ liệu gửi lên trong Burp. Để biết chi tiết, bạn có thể tham khảo bài viết khác của mình về cách biến đổi payload trong Burp Suite nhanh chóng và dễ dàng hơn.

Kết Luận

Giống như mã hóa trên web, việc đọc mã Java rất quan trọng trong pentesting Android. Đôi khi, bạn cũng cần hiểu cả mã assembly.

P/S: Chúc mọi người một năm mới tràn đầy thành công và gặp nhiều bug thú vị để kiểm thử!
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào