104 lines
4.5 KiB
Python
104 lines
4.5 KiB
Python
import os
|
|
import subprocess
|
|
import logging
|
|
import sqlite3
|
|
import shutil
|
|
|
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
|
|
|
def run_adb_command(command: str):
|
|
"""Chạy lệnh ADB shell và trả về kết quả"""
|
|
full_cmd = f"adb shell {command}"
|
|
try:
|
|
result = subprocess.run(full_cmd, shell=True, check=True, capture_output=True, text=True)
|
|
return result.stdout.strip()
|
|
except subprocess.CalledProcessError as e:
|
|
return None
|
|
|
|
def analyze_zalo():
|
|
logging.info("BẮT ĐẦU TRÍCH XUẤT DATABASE ZALO (PULL VỀ SERVER)")
|
|
# Đảm bảo kết nối
|
|
subprocess.run("adb connect 10.160.138.2:5555", shell=True, capture_output=True)
|
|
|
|
# Tạo thư mục chứa db
|
|
os.makedirs("zalo_dbs", exist_ok=True)
|
|
|
|
# Lấy danh sách các UID (thư mục) trong databases
|
|
zalo_db_path = "/data/data/com.zing.zalo/databases"
|
|
ls_output = run_adb_command(f"su -c 'ls -l {zalo_db_path}'")
|
|
|
|
if not ls_output:
|
|
logging.error("Không thể truy cập thư mục Zalo. Kiểm tra lại quyền Root.")
|
|
return
|
|
|
|
# Tìm các thư mục có tên là số (UID)
|
|
uid_folders = []
|
|
for line in ls_output.split('\n'):
|
|
if line.startswith('d'): # là thư mục
|
|
parts = line.split()
|
|
folder_name = parts[-1]
|
|
if folder_name.isdigit():
|
|
uid_folders.append(folder_name)
|
|
|
|
if not uid_folders:
|
|
logging.error("Không tìm thấy thư mục UID nào của Zalo!")
|
|
return
|
|
|
|
logging.info(f"Tìm thấy các thư mục tài khoản Zalo: {uid_folders}")
|
|
|
|
with open("zalo_schema_dump.txt", "w", encoding="utf-8") as f:
|
|
f.write("=== DUMP CẤU TRÚC DATABASE ZALO ===\n")
|
|
|
|
for uid in uid_folders:
|
|
logging.info(f"Đang xử lý tài khoản: {uid}")
|
|
# Liệt kê các file trong thư mục UID
|
|
files_in_uid = run_adb_command(f"su -c 'ls {zalo_db_path}/{uid}/'")
|
|
if not files_in_uid: continue
|
|
|
|
for db_file in files_in_uid.split('\n'):
|
|
db_file = db_file.strip()
|
|
if not db_file or not db_file.endswith('.db'): continue
|
|
|
|
logging.info(f"Phát hiện file DB: {db_file}")
|
|
|
|
# Copy file ra sdcard để có thể pull về
|
|
run_adb_command(f"su -c 'cp {zalo_db_path}/{uid}/{db_file} /sdcard/temp_zalo_{db_file}'")
|
|
run_adb_command(f"su -c 'chmod 666 /sdcard/temp_zalo_{db_file}'")
|
|
|
|
# Pull file về server
|
|
local_path = os.path.join("zalo_dbs", f"{uid}_{db_file}")
|
|
subprocess.run(f"adb pull /sdcard/temp_zalo_{db_file} {local_path}", shell=True, capture_output=True)
|
|
run_adb_command(f"su -c 'rm /sdcard/temp_zalo_{db_file}'") # Xóa file tạm
|
|
|
|
if os.path.exists(local_path):
|
|
logging.info(f"Đã kéo file về thành công: {local_path}. Đang phân tích...")
|
|
try:
|
|
conn = sqlite3.connect(local_path)
|
|
cursor = conn.cursor()
|
|
|
|
# Lấy danh sách các bảng
|
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
|
|
tables = cursor.fetchall()
|
|
|
|
if tables:
|
|
with open("zalo_schema_dump.txt", "a", encoding="utf-8") as f:
|
|
f.write(f"\n\n--- Cấu trúc file: {db_file} (Tài khoản {uid}) ---\n")
|
|
f.write(f"Danh sách bảng: {[t[0] for t in tables]}\n")
|
|
|
|
for table_tuple in tables:
|
|
table_name = table_tuple[0]
|
|
if "msg" in table_name.lower() or "chat" in table_name.lower() or "group" in table_name.lower():
|
|
cursor.execute(f"PRAGMA table_info({table_name});")
|
|
columns = cursor.fetchall()
|
|
f.write(f"\nBảng '{table_name}':\n")
|
|
for col in columns:
|
|
f.write(f" - {col[1]} ({col[2]})\n")
|
|
conn.close()
|
|
except Exception as e:
|
|
logging.warning(f"Lỗi khi đọc file SQLite {local_path}: {str(e)}")
|
|
|
|
logging.info("Hoàn tất! Hãy gửi cho tôi nội dung file zalo_schema_dump.txt để phân tích.")
|
|
|
|
if __name__ == "__main__":
|
|
analyze_zalo()
|