This commit is contained in:
yincong
2025-12-04 16:44:49 +08:00
parent b7db572f3c
commit 0bd0e86c99
2 changed files with 224 additions and 3 deletions
Regular → Executable
+115 -3
View File
@@ -1,5 +1,117 @@
#!/bin/zsh
# ==============================================================================
# Diaphora & IDA Pro 自动化批处理脚本
# ==============================================================================
# --- 配置区 (Configuration) ---
# 1. 存放所有 .a 文件的**源目录** (The directory containing all .a files)
# !!! 请将此路径替换为您的实际目录 !!!
A_FILES_SOURCE_DIR="/Users/yincong/go/src/github.com/yincongcyincong/mars/mars/cmake_build/OSX/Darwin.out/"
# 2. 存放 .o 文件提取、以及最终 .i64/.sqlite 结果的**工作目录**
# 建议使用 /tmp,脚本运行完毕后可以手动删除此目录。
WORK_DIR="/tmp/diaphora_batch_$(date +%s)"
# 3. IDA Pro 可执行文件路径 (基于您提供的路径)
IDA_EXECUTABLE="/Applications/IDA Professional 9.1.app/Contents/MacOS/ida"
# 4. Diaphora 脚本路径 (基于您提供的路径)
DIAPHORA_SCRIPT="/Users/yincong/go/src/github.com/yincongcyincong/diaphora/diaphora.py"
# --- 脚本执行 (Script Execution) ---
echo "--- Diaphora 自动化分析开始 ---"
echo "源目录: ${A_FILES_SOURCE_DIR}"
echo "工作目录: ${WORK_DIR}"
# 路径检查
if [ ! -x "${IDA_EXECUTABLE}" ]; then
echo "错误: 找不到 IDA 可执行文件或无执行权限: ${IDA_EXECUTABLE}" >&2
exit 1
fi
if [ ! -f "${DIAPHORA_SCRIPT}" ]; then
echo "错误: 找不到 Diaphora 脚本: ${DIAPHORA_SCRIPT}" >&2
exit 1
fi
# 创建工作目录
mkdir -p "${WORK_DIR}" || { echo "错误: 无法创建工作目录 ${WORK_DIR}" >&2; exit 1; }
export DIAPHORA_EXPORT_FILE=/Users/yincong/go/src/github.com/yincongcyincong/weixin-macos/diaphora/database.sqlite
export DIAPHORA_AUTO=1
/Applications/IDA\ Professional\ 9.1.app/Contents/MacOS/ida -A -B -L/tmp/ida.txt -S/Users/yincong/go/src/github.com/yincongcyincong/diaphora/diaphora.py /Users/yincong/go/src/github.com/yincongcyincong/mars/mars/cmake_build/OSX/Darwin.out/mars.framework/mars
# 1. 循环查找所有 .a 文件
find "${A_FILES_SOURCE_DIR}" -name "*.a" -print0 | while IFS= read -r -d $'\0' archive_file; do
# 提取 .a 文件名作为前缀 (例如: libmars)
archive_base=$(basename "${archive_file}" .a)
# 为当前 .a 文件创建一个专门的提取子目录
EXTRACTION_DIR="${WORK_DIR}/${archive_base}_o_files"
mkdir -p "${EXTRACTION_DIR}"
echo ""
echo ">>> 处理归档文件: ${archive_file}"
# 切换到提取目录并使用 'ar -x' 提取所有 .o 文件
(
cd "${EXTRACTION_DIR}" || exit 1
echo " -> 正在提取 .o 文件到: ${EXTRACTION_DIR}"
# 使用 ar -x 提取所有目标文件
ar -x "${archive_file}"
)
if [ $? -ne 0 ]; then
echo " -> 警告: 提取 ${archive_file} 失败,跳过。"
continue
fi
# 2. 循环处理所有提取出来的 .o 文件
# 使用 find 确保只处理当前目录下的 .o 文件 (maxdepth 1)
find "${EXTRACTION_DIR}" -maxdepth 1 -name "*.o" -print0 | while IFS= read -r -d $'\0' object_file; do
# 提取 .o 文件名 (例如: tcpclient_fsm.cc)
object_base=$(basename "${object_file}" .o)
# 构造唯一的输出文件名,以防止不同 .o 文件覆盖彼此的结果
OUTPUT_BASE="${archive_base}__${object_base}"
IDA_IDB_PATH="${WORK_DIR}/${OUTPUT_BASE}.i64"
DIAPHORA_SQLITE_PATH="${WORK_DIR}/${OUTPUT_BASE}.sqlite"
IDA_LOG_PATH="${WORK_DIR}/${OUTPUT_BASE}.log"
echo " -> 正在分析 .o 文件: ${object_file}"
echo " 输出 IDB: ${IDA_IDB_PATH}"
echo " 输出 SQLite: ${DIAPHORA_SQLITE_PATH}"
# 配置 Diaphora 环境变量
export DIAPHORA_EXPORT_FILE="${DIAPHORA_SQLITE_PATH}"
export DIAPHORA_AUTO=1
# 执行 IDA Pro 无头模式命令
"${IDA_EXECUTABLE}" -A -B \
-o"${IDA_IDB_PATH}" \
-L"${IDA_LOG_PATH}" \
-S"${DIAPHORA_SCRIPT}" \
"${object_file}"
if [ $? -ne 0 ]; then
echo " !!! 警告: IDA Pro 分析 ${object_base}.o 失败 (请检查 ${IDA_LOG_PATH})"
else
echo " <<< 分析成功: ${DIAPHORA_SQLITE_PATH} 已生成"
fi
# 清除环境变量,确保下次循环是干净的
unset DIAPHORA_EXPORT_FILE
unset DIAPHORA_AUTO
done
# 可选:删除提取出的 .o 文件以节省空间
# rm -rf "${EXTRACTION_DIR}"
done
echo ""
echo "--- 所有归档文件处理完毕 ---"
echo "分析结果 (IDB/SQLITE/LOG) 位于目录: ${WORK_DIR}"
+109
View File
@@ -0,0 +1,109 @@
#!/bin/zsh
# --- 配置区 ---
# 1. 存放所有源 SQLite 文件的目录
WORK_DIR="/tmp/diaphora_batch_1764836774/"
# 2. 最终合并生成的主数据库文件名
MASTER_DB_NAME="diaphora_merged_results.sqlite"
# 排除 SQLite 内部使用的特殊表
IGNORED_TABLES="(sqlite_sequence|android_metadata)"
# ------------------------------------------------------------------------------
echo "--- SQLite 数据库批量合并开始 ---"
echo "工作目录: ${WORK_DIR}"
echo "主数据库: ${MASTER_DB_NAME}"
echo "--------------------------------------"
# 查找所有源文件(排除目标主文件自身)
source_files=$(find "$WORK_DIR" -maxdepth 1 -name "*.sqlite" -not -name "$MASTER_DB_NAME" | sort)
if [ -z "$source_files" ]; then
echo "⚠️ 警告: 未找到任何源数据库文件 (.sqlite)。"
exit 0
fi
# 确保主数据库文件存在 (如果不存在则创建)
if [ ! -f "$MASTER_DB_NAME" ]; then
echo "-> 主数据库文件不存在,正在创建: ${MASTER_DB_NAME}"
sqlite3 "$MASTER_DB_NAME" "VACUUM;"
fi
# 尝试从第一个源数据库中获取所有表名 (用于定义结构和合并)
FIRST_SOURCE=$(echo "$source_files" | head -n 1)
# 使用 sqlite3 的 .tables 命令和一些文本处理来获取表名列表
TABLES=$(sqlite3 "$FIRST_SOURCE" ".tables" | tr ' ' '\n' | grep -v '^$' | sort | uniq | grep -vE "$IGNORED_TABLES")
if [ -z "$TABLES" ]; then
echo "❌ 错误: 无法从第一个源数据库 (${FIRST_SOURCE}) 中获取可合并的表名。" >&2
exit 1
fi
echo "找到以下需要合并的表: ${TABLES}"
echo "--------------------------------------"
## 🛠️ 关键步骤 1: 复制表结构到主数据库
echo ">>> 正在从 ${FIRST_SOURCE} 复制表结构到 ${MASTER_DB_NAME}..."
# 附加第一个源数据库,用于结构复制
sqlite3 "$MASTER_DB_NAME" "ATTACH DATABASE '$FIRST_SOURCE' AS source;"
# 循环创建表结构
for table_name in $TABLES; do
echo " -> 确保表结构存在: ${table_name}"
# 使用双引号 \"...\" 包裹表名,防止关键字冲突
sqlite3 "$MASTER_DB_NAME" "
CREATE TABLE IF NOT EXISTS \"${table_name}\" AS
SELECT * FROM source.\"${table_name}\" LIMIT 0;
"
done
# 分离数据库
sqlite3 "$MASTER_DB_NAME" "DETACH DATABASE source;"
echo "<<< 表结构复制完成"
echo "--------------------------------------"
## 💾 关键步骤 2: 循环合并数据 (已修复连接问题)
for source_db in $source_files; do
SOURCE_BASE=$(basename "$source_db")
echo ">>> 正在合并源数据库: ${SOURCE_BASE}"
# 1. 构建完整的 SQL 批处理命令 (包含 ATTACH)
# 这样所有操作都在同一个 sqlite3 进程中执行
SQL_BATCH_COMMAND="ATTACH DATABASE '$source_db' AS source;"
# 2. 循环插入数据
for table_name in $TABLES; do
# 使用双引号 \"...\" 包裹表名,防止关键字冲突
SQL_BATCH_COMMAND="${SQL_BATCH_COMMAND} INSERT OR IGNORE INTO \"${table_name}\" SELECT * FROM source.\"${table_name}\";"
done
# 3. 添加分离命令(在同一批次执行)
SQL_BATCH_COMMAND="${SQL_BATCH_COMMAND} DETACH DATABASE source;"
echo " -> 正在执行数据插入批处理..."
# 4. 集中执行所有命令 (ATTACH, INSERTS, DETACH)
sqlite3 -batch --bail "$MASTER_DB_NAME" "$SQL_BATCH_COMMAND"
if [ $? -ne 0 ]; then
echo "❌ 错误: 数据插入过程中发生错误,停止合并。" >&2
# 此时 DETACH 应该已在批处理中被执行,但如果 ATTACH 失败,DETACH 也会失败。
# 我们已经停止脚本,不再需要额外的清理 DETACH。
exit 1
fi
echo "<<< ${SOURCE_BASE} 合并完成"
echo "--------------------------------------"
done
echo "🎉 所有数据库已成功合并到 ${MASTER_DB_NAME}"
echo "--- 合并脚本结束 ---"