Kỹ sư đảo ngược ứng dụng Android để 'bẻ khóa' dữ liệu board game Hitster
Một lập trình viên đã dành 18 giờ để dịch ngược ứng dụng Android của board game Hitster, giải mã file dữ liệu mã hóa AES để lấy danh sách bài hát — rồi phát hiện ra toàn bộ dữ liệu đó thực ra được công khai trên một URL không hề được bảo vệ.

Kỹ sư đảo ngược ứng dụng Android để "bẻ khóa" dữ liệu board game Hitster
Một lập trình viên nhận được món quà là board game Hitster — trò chơi đoán tên bài hát và năm phát hành. Vì ứng dụng đi kèm yêu cầu gói đăng ký Spotify hoặc Apple Music, anh quyết định dịch ngược file APK Android để tự lấy dữ liệu. Điều thú vị nhất nằm ở cái kết: sau 18 giờ giải mã, toàn bộ dữ liệu hóa ra lại nằm công khai trên một URL chẳng hề được bảo vệ.
Minh họa mã nguồn và quá trình phân tích ứng dụng
Cách board game Hitster vận hành
Mỗi thẻ trong Hitster có hai mặt. Mặt trước in tên ca sĩ hoặc ban nhạc, năm phát hành và tên bài hát. Mặt sau là một mã QR — quét mã này sẽ mở ra một URL chứa hai thông tin trong đường dẫn: khu vực phát hành của bộ game (ví dụ DE cho Đức) và ID thẻ.
Ứng dụng sau đó đối chiếu ID thẻ với một bảng ánh xạ để phát bài hát tương ứng qua Spotify hoặc Apple Music. Vì mỗi khu vực có bộ thẻ khác nhau, chỉ riêng ID là chưa đủ để xác định bài hát: thẻ số 1 ở Anh có thể là "Wet Dream", nhưng ở Đức lại là "Tage wie diese".
Bước đầu: lấy APK và dịch ngược
Tác giả tải file APK từ một trang chia sẻ APK khá "mờ ám", sau đó dùng công cụ jadx để dịch ngược sang mã Java. Lục lọi một lúc, anh tìm thấy vài file JSON trong thư mục res/raw, trong đó có gameset_database_4.json với nội dung trông như đã bị mã hóa.
Bước đầu tiên là nhận diện định dạng: file này thực chất chỉ được mã hóa Base64. Giải mã xong vẫn không đọc được gì, nên phán đoán tiếp theo là nội dung đã được mã hóa bằng AES.
Manh mối nằm ngay trong mã nguồn
Vì chưa từng dịch ngược ứng dụng Android, tác giả chỉ đơn giản tìm kiếm toàn cục từ khóa "AES" — và may mắn thay, toàn bộ quy trình giải mã hiện ra trong file k43.java. Logic gồm ba bước rõ ràng:
- Giải mã Base64 chuỗi đầu vào, sau đó kiểm tra dữ liệu phải dài tối thiểu 28 byte.
- 12 byte đầu tiên là IV (vector khởi tạo) cho chế độ GCM, phần còn lại là bản mã.
- Khóa AES 256-bit không được lưu sẵn mà được sinh ra bằng cách băm SHA-256 chuỗi gồm
(độ dài dữ liệu − 28)ghép với một chuỗi bí mật cố định trong ứng dụng.
Điểm đáng chú ý: khóa phụ thuộc vào chính độ dài của dữ liệu mã hóa, nên không thể dùng lại khóa cho file khác. Dù vậy, đây vẫn là kiểu "bảo mật" khá hời hợt vì toàn bộ thuật toán nằm ngay trong APK.
Viết lại công cụ giải mã bằng Rust
Sau khi hiểu cơ chế, tác giả viết lại quy trình bằng Rust với các thư viện base64, sha2 và aes-gcm: đọc file, giải mã Base64, tách IV, băm khóa, rồi giải mã bằng AES-256-GCM. Kết quả là một file văn bản khoảng 31.000 dòng chứa ánh xạ từ ID thẻ sang track Spotify, track Apple Music cùng mã ISRC, bao phủ nhiều khu vực khác nhau.
Anh cũng được Mr.Corrupt trong cộng đồng Discord ngôn ngữ Rust hỗ trợ trong quá trình này.
"Chúng tôi đã dành khoảng 18 giờ để đuổi theo một file mà cuối cùng chẳng hề là bí mật gì cả."
Cú "twist": dữ liệu vốn đã công khai
Sau khi lục lọi mã nguồn thêm một chút, nhóm tác giả nhận ra toàn bộ công sức trên là không cần thiết. Nếu tìm kiếm các URL HTTPS trước, họ sẽ thấy ngay địa chỉ https://hitster.jumboplay.com/hitster-assets/.
Chỉ cần thử thêm một chút, đường dẫn https://hitster.jumboplay.com/hitster-assets/gameset_database.json trả về nguyên bộ dữ liệu — không hề mã hóa.
Bài học cho lập trình viên Việt Nam
Câu chuyện này là lời nhắc nhở quen thuộc nhưng luôn đáng nhắc lại với các đội phát triển phần mềm, kể cả ở Việt Nam:
- Mã hóa dữ liệu trong ứng dụng di động không phải là bảo mật thực sự. Bất kỳ ai cũng có thể tải APK và dịch ngược, đặc biệt khi khóa được sinh từ những hằng số nằm ngay trong mã.
- Đừng để lộ endpoint công khai ngoài ý muốn. Một thư mục asset không được kiểm soát truy cập có thể vô hiệu hóa toàn bộ nỗ lực che giấu dữ liệu.
- Thử cách đơn giản trước khi lao vào cách phức tạp. Như chính tác giả thừa nhận, chỉ cần tìm URL trước là mọi chuyện đã kết thúc trong vài phút.
Với người dùng cuối, câu chuyện cũng mang tính thực tế: các board game "lai" ứng dụng ngày càng phổ biến, và việc phụ thuộc vào gói đăng ký dịch vụ nhạc là rào cản không nhỏ — nhất là ở những thị trường mà người chơi chưa quen trả phí định kỳ.
Mã QR trên thẻ game là chìa khóa dẫn tới dữ liệu bài hát


