Android Pentest - Part 2 - Giải mã

Ở bài blog Android Pentest https://duonghaonika.github.io/2025/09/15/android-pentest/ đã xong phần dựng môi trường & bypass SSL Pinning. Tuy nhiên response trả về có dữ liệu được mã hóa. Mục đích của blog này là tìm cách giải mã phần dữ liệu được mã hóa này để phục vụ mục đích pentest.

Tại sao các ứng dụng mobile hay mã hóa dữ liệu?

Môi trường không tin cậy

  • Web: Trình duyệt là một môi trường được chuẩn hóa và kiểm soát khá chặt chẽ. Khi bạn dùng HTTPS, trình duyệt đảm bảo mã hóa từ máy khách đến máy chủ.
  • Mobile: Ứng dụng chạy trên thiết bị của người dùng, nơi người dùng có quyền kiểm soát hoàn toàn (đặc biệt là nếu thiết bị đã Root/Jailbreak). Nhà phát triển coi thiết bị của người dùng là “môi trường không tin cậy”. Họ mã hóa payload để làm khó các công cụ phân tích (như Frida, Burp Suite) ngay cả khi bạn đã sở hữu thiết bị.

Chống lại các công cụ Proxy (Anti-MITM)

  • Web Pentest: Bạn cài chứng chỉ CA của Burp Suite vào trình duyệt -> Trình duyệt tin tưởng Burp -> Bạn thấy toàn bộ request/response dưới dạng Plaintext.
  • Mobile Pentest: Ngay cả khi bạn bypass được SSL Pinning và cài chứng chỉ Burp vào điện thoại, nếu ứng dụng có mã hóa payload (body của request), bạn sẽ chỉ thấy một chuỗi ký tự vô nghĩa (ví dụ: Base64, Hex) trong Burp Suite. Mục đích để ngăn chặn attacker (hoặc pentester) dễ dàng nhìn thấy cấu trúc dữ liệu, tham số để thực hiện các đòn tấn công như SQL Injection hay IDOR.

Đảm bảo tính toàn vẹn

Ngoài việc mã hóa, mobile app thường đi kèm cơ chế Ký (Signing) request. Ví dụ: App sẽ tạo ra một chuỗi hash dựa trên body + timestamp + secret_key. Nếu bạn chặn request lại bằng Burp Suite và sửa amount: 100 thành amount: 1000, server sẽ từ chối request đó vì chữ ký sai. Điều này khó thực hiện hiệu quả trên Web vì secret_key trên Web rất dễ bị lộ, trong khi trên Mobile, key có thể được giấu sâu trong Native Library hoặc được làm rối.

Cách để giải mã

Nếu bạn có source code app mobile thì quá ngon, chỉ việc đọc source code tìm chỗ xử lý giải mã response. Còn không thì sử dụng công cụ JADX để decompile file apk của ứng dụng.

Sau đó tìm code xử lý giải mã response.

Note:: Mỗi ứng dụng có thể sử dùng cách mã hóa/giải mã khác nhau. Ở đây mình chỉ làm với 1 app bất kỳ, các app khác sẽ khác.

Với JADX

Với source code

1
2
String decryptResponse = HttpHelper.decryptResponse(response,
mApplication.getObjectGiDo().getToken());

Như vậy ta cần xem qua hàm decryptResponse của HttpHelper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static String decryptResponse(String input, String key) {
if (TextUtils.isEmpty(input)) {
return null;
}
try {
JSONObject jsonObject = new JSONObject(input);
if (jsonObject.optInt("code", -1) == 200 || jsonObject.optInt("code", -1) == 202 || jsonObject.optInt("code", -1) == 203 || jsonObject.optInt("code", -1) == 204) {
return XXTEACrypt.decryptBase64StringToString(jsonObject.optString("data"), key);
}
} catch (Exception e) {
Log.e(TAG, "Exception", e);
}
return null;
}

–> Sử dụng thuật toán mã hóa đối xứng XXTEA, bây giờ ta cần tìm nốt key.

Lần mò theo 7749 các class và hàm, mình đã tìm được vị trí lấy token. Đây là getMethod lấy token của một model

1
2
3
public String getToken() {
return token;
}

-> Khả năng token được lưu trong database trên thiết bị. Tiếp tục tìm các file .db trong folder databases của ứng dụng. Pull các file này về máy và mở bằng DB Browser (SQLite).

Thành công tìm được token. Bây giờ đã có thuật toán + key (token). Thực hiện code giải mã nào (Vibe Coding with Claude ^^) ~~

Giải mã thành công!