No Result
View All Result
HungTNT.Dev Blog
  • Trang chủ
  • Tech
    • Tin công nghệ
    • Linux
    • Windows
    • Network
  • Life
  • Photography
  • Trang chủ
  • Tech
    • Tin công nghệ
    • Linux
    • Windows
    • Network
  • Life
  • Photography
No Result
View All Result
HungTNT.Dev Blog
No Result
View All Result

Hành trình giải mã Zalo – Phần 1: Backup

Hưng Trần by Hưng Trần
23/08/2026
10
VIEWS
ShareShareShare

Disclaimer 01: Bài viết không cung cấp hướng dẫn trực tiếp hay công cụ để thực hiện lại hành động để đảm bảo tuân thủ các điều khoản sử dụng của Zalo. Đây chỉ là một dự án nghiên cứu cá nhân không nhằm mục đích thương mại.

Disclaimer 02: Nếu có anh/chị/em nào ở Zalo cảm thấy bài viết này không nên được công khai, xin ping mình ở [email protected]

Đề bài

Mình có một người bạn làm kinh doanh, hàng ngày chat với rất nhiều khách hàng, trong đó hỏi thăm có, giới thiệu sản phẩm cũng có, mà chốt đơn cũng có. Ti tỉ thứ nằm cùng một cái ứng dụng Zalo. Bạn nào dùng Zalo chắc cũng hiểu, tính năng tìm kiếm yêu cầu phải chính xác từ khóa, mà làm sao có thể tìm nổi với một kho dữ liệu qua năm tháng như vậy. Bạn nhờ tới mình.

Mình nghĩ đến việc lấy toàn bộ lịch sử chat của Zalo ra, sau đó sẽ đưa tất cả vào một database, và cho một mô hình LLM học cục database này, sau đó bạn mình chỉ cần hỏi những câu ví dụ như: “Năm 2026 tôi đã chốt bao nhiêu đơn hàng với anh A?” hay “Tổng doanh thu trên tất cả đơn hàng của sản phẩm B là bao nhiêu?” thì AI sẽ ngay lập tức trả lời và cung cấp reference để dễ dàng tổng hợp.

Nghĩ là làm, mình bắt tay vào việc tìm cách lấy lịch sử chat của Zalo. Cuộc vui bắt đầu.

Chương 1: Xuất… dữ liệu

Zalo có tính năng Xuất và Nhập dữ liệu, khi dùng tính năng Xuất dữ liệu thì chúng ta sẽ nhận được một file nén có định dạng backup_zalo_dd_mm_yyyy.zl.zip. File này tuy có phần mở rộng là .zip nhưng thực ra nó không phải là file zip chuẩn (không có ứng dụng nén nào đọc được file này).

Đây là một file data đã được Zalo mã hóa và chỉ có thể dùng tính năng Nhập dữ liệu của Zalo sử dụng. Từ đó, mình quyết định tìm cách để giải mã file backup này.

 

Chương 2: Dịch ngược

Muốn giải mã thì phải biết cách nó mã hóa, mình nghĩ ngay đến việc mò vào mã nguồn của Zalo để xem. Zalo là một ứng dụng Electron nên khá đơn giản để tìm hiểu.

Mình đã tải file cài đặt của Zalo về, giải nén file exe để lấy file asar và sau đó tiếp tục bung file asar để lấy phần mã xử lý bên trong.

Dĩ nhiên, nó đã được minify nên gần như không đọc được nếu chỉ dùng sức người bình thường. Tuy nhiên, với sức mạnh của AI, mình cũng đã dịch ngược lại được cục mã nguồn này và có thể đọc được để tìm thuật toán ẩn sau quá trình xuất dữ liệu :))

Chương 3: Truy vết

Sau khi có được mã nguồn đã qua format, mình bắt đầu quá trình tìm hiểu công đoạn xuất file.

Đầu tiên, mình xác định được function tạo file mã hóa này có tên là achiveBackupFile nằm trong file compact-app-preload.js, và Zalo xử lý việc tạo file backup như thế này:

– Các file data local trên thiết bị của người dùng đều được mã hóa.

– Dữ liệu (các file database, media, v.v.) khi thực hiện backup sẽ được giải mã, sau đó được đưa vào một luộng archive để đóng gói dạng tarball.

– Luồng archive này được pipe thẳng qua một luồng cipher (Zalo sử dụng Node.js stream để thực hiện đóng gói và mã hóa đồng thời), luồng cipher này sẽ mã hóa từng byte dữ liệu đi qua nó.

– Output sau khi đi qua luồng cipher được ghi ra một file tạm có đuôi .ztemp đặt ngay tại thư mục output được người dùng chọn khi thực hiện xuất file.

– Khi hoàn tất, file .ztemp được đổi tên thành backup_zalo_dd_mm_yyyy.zl.zip

let e = archiveStream;
r.cipher && (e = e.pipe(r.cipher)); // Pipe qua bộ mã hóa AES
r.progress && (e = e.pipe(r.progress));
e.pipe(fileWriteStream); // Ghi ra đĩa

 

Tiếp tục dò theo code, mình tìm được cơ chế mã hóa mà archive stream sử dụng:

– Zalo sử dụng thuật toán AES-256-CBC để mã hóa. Khóa mã hóa (Key) và Vector khởi tạo (Initialization Vector – IV) được tạo ra từ một mật khẩu nào đó mà mình chưa tìm được (cái này xử lý sau).

– Cơ chế tạo Key và IV được làm như sau

// e = Password from somewhere
static getCipherKey(e) {
return crypto.createHash("sha256").update(e).digest();
}

static getFormattedIv(e) {
const t = "zie" + e.slice(0, 13);
return Buffer.from(t); // Return IV 16 bytes
}

Giải thích dễ hiểu thì sẽ là

– Zalo tạo ra 1 key từ password bằng cách băm nó với SHA256

– Tương tự, Zalo tính ra IV bằng cách ghép chuỗi “zie” với 13 ký tự đầu tiên của password (không băm)

– Sau khi có được key và IV rồi thì chạy mã hóa AES-256 với những thứ vừa tính ra được.

Như vậy, muốn giải mã được file dữ liệu sau khi xuất ra thì cần phải làm ngược lại với lúc mã hóa, cụ thể là:

– Tính Key = SHA256(password)

– Tính IV = (“zie” + password).substring(0, 16) (cắt lấy 16 byte đầu)

– Đọc file backup .zl.zip, dùng thuật toán AES-256-CBC với Key và IV đã tính được để giải mã (Decrypt), xử lý mỗi lần 1 block nhỏ thôi cho nhẹ vì file backup nặng hàng chục GB ko load hết lên RAM nổi.  Việc decrypt mình sử dụng thư viện cryptography có sẵn của Python.

– Lưu output ra một file mới dạng tar. Lúc này toàn bộ data đã ở trước mắt.

Phần còn lại của câu chuyện bây giờ sẽ là: tìm được mật khẩu mà Zalo đã sử dụng.

 

Chương 4: Tìm khóa

Đi đến đây rồi, chỉ cần tìm ra được password thì bài toán xem như đã được giải xong.

Với việc đăng nhập Zalo sử dụng QR, password để mã hóa sẽ không thể là mật khẩu tài khoản người dùng (vì người dùng không nhập). Vả lại, dù có đi nữa thì cũng ko ứng dụng nào lại đi lưu password của người dùng ở dạng clear để dùng lại sau này cả, việc này sẽ vi phạm nghiêm trọng nguyên tắc về security.

Nhìn vào thuật toán mã hóa, Initialization Vector yêu cầu chính xác 16 ký tự, trong đó 3 ký tự “zie” là cố định, vậy mật khẩu còn lại sẽ phải là một chuỗi gì đó và phải đảm bảo có 13 ký tự trở lên.

Lúc này mình nghĩ đến 2 thứ: User ID hoặc Device ID

Cả 2 đều là chuỗi số khá dài đáp ứng được cho yêu cầu làm password, tuy nhiên mình nghĩ khả năng Zalo dùng nó là rất thấp, vì những lý do:

– Nếu dùng User ID thì khả thi, nhưng Zalo đã dựng nên một hàng rào mã hóa kỹ lưỡng nên không lý do gì lại dùng một chiếc chìa khóa đơn giản như vậy.

– Nếu dùng Device ID thì sẽ khiến cho file bị gắn chặt với thiết bị dùng để backup, hoặc Zalo sẽ phải lưu trữ từng Device ID để có thể Import về sau. Nhưng mình đã kiểm tra thì có thể import được, và không thấy Zalo có thực hiện gởi thông tin gì ngược lên hệ thống khi backup, vậy chắc chắn là không phải device ID. Từ đó mình cũng có thể loại bỏ luôn trường hợp Zalo tạo password ngẫu nhiên và lưu trữ thông qua máy chủ Zalo.

Để kiểm chứng suy nghĩ, mình thử dùng cả 2 làm password thì đều tạch.

Lúc này. có thể kết luận Zalo đang sử dụng mật khẩu dựa trên một thuật toán hoặc cơ chế gì đó có thể đảm bảo điều kiện lấy được / tính toán ra được trên một thiết bị khác.

Lúc này, thay vì tiếp tục đào sâu thêm vào mã nguồn để tìm hiểu, mình quay về cách truyền thống, dùng Debug mode :))

Zalo là một ứng dụng Electron, nhưng đã chặn mở DevTools ở UI, tuy nhiêm vẫn có thể sử dụng cờ –remote debugging-port để bật debug ở một port khác, sau đó sử dụng DevTools từ đây.

Vì đã xác định được fuction xuất file có tên là achiveBackupFile, mình tạo 1 breakpoint để tạm dừng Zalo ngay khi gọi hàm này và lúc đó mình có thể kiểm tra bộ nhớ xem nó đã truyền gì vào.

Từ mã nguồn, mình biết được rằng hàm này khi chạy nhận biến this.uin để làm password. Vậy công việc bây giờ là show cái biến này ra thôi. Hẹ hẹ. Sau đó cứ cho nó tiếp tục xuất file.

Và…

Đến đây thì file đã được giải mã thành công, phần tiếp theo là xử lý nội dung chat dạng CSV và Media, và nó là một câu chuyện dài kỳ khác :))

Hành trình đến đây đã tạm xong, nhưng vẫn chưa dừng lại, mình sẽ còn quay lại với Phần 2: Giải mã trực tiếp database local của Zalo.

Previous Post

Protected: Hướng dẫn giải mã Zalo Backup

Next Post

Hành trình giải mã Zalo – Phần 2: Database

Bài liên quan

Hành trình giải mã Zalo – Phần 2: Database
Tech

Hành trình giải mã Zalo – Phần 2: Database

23/08/2026
Protected: Hướng dẫn giải mã Zalo Backup
Tech

Protected: Hướng dẫn giải mã Zalo Backup

23/08/2026
Hướng dẫn cài đặt Docker và Docker Compose trên Linux
Linux

Hướng dẫn cài đặt Docker và Docker Compose trên Linux

04/06/2022
Linux

Mở nhiều port SSH cùng lúc trên Linux

09/11/2021
Ví dụ về một Job Description tồi ngành IT
Life

Ví dụ về một Job Description tồi ngành IT

18/08/2026
Lỗi SSL trên Cyberpanel từ tháng 6/2021
Linux

Lỗi SSL trên Cyberpanel từ tháng 6/2021

25/06/2021
Next Post
Hành trình giải mã Zalo – Phần 2: Database

Hành trình giải mã Zalo – Phần 2: Database

HungTNT

© HungTNT - Tập làm văn

Chuyên mục

  • Tech
  • Photography
  • Life

Follow

No Result
View All Result
  • Frontpage
  • Life
  • Linux
  • Network
  • News
  • Photography
  • Tech
  • Windows

© HungTNT - Tập làm văn