init pro_sdk
This commit is contained in:
208
tools/extract_blowfish_key.sh
Normal file
208
tools/extract_blowfish_key.sh
Normal file
@@ -0,0 +1,208 @@
|
||||
#!/bin/bash
|
||||
# Blowfish密钥提取脚本 - 在树莓派上以root运行
|
||||
# 用法: sudo bash extract_blowfish_key.sh [PID]
|
||||
#
|
||||
# 安全保证:
|
||||
# - 只读取内存,不修改任何寄存器或内存
|
||||
# - GDB attach时间最短化 (<30秒)
|
||||
# - 自动detach,即使中途异常
|
||||
|
||||
set -e
|
||||
|
||||
PID=${1:-$(pgrep -f Legged_sport | head -1)}
|
||||
OUTDIR=/tmp/blowfish_dump_$$
|
||||
mkdir -p $OUTDIR
|
||||
|
||||
if [ -z "$PID" ]; then
|
||||
echo "❌ 找不到 Legged_sport 进程"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查PID存在
|
||||
if [ ! -d "/proc/$PID" ]; then
|
||||
echo "❌ PID $PID 不存在"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "============================================"
|
||||
echo "🐕 Blowfish密钥提取"
|
||||
echo "============================================"
|
||||
echo "PID: $PID"
|
||||
echo "输出: $OUTDIR"
|
||||
echo ""
|
||||
|
||||
# 检查当前狗的状态 (通过/tmp下的状态文件,如果有的话)
|
||||
# 提示用户确认安全状态
|
||||
echo "⚠️ 确认狗的状态:"
|
||||
echo " - 趴下(damping)或在脚架上"
|
||||
echo " - 当前是高级模式 (未在执行运动指令)"
|
||||
echo ""
|
||||
read -p "确认安全状态? (yes/no): " confirm
|
||||
if [ "$confirm" != "yes" ]; then
|
||||
echo "❌ 用户取消"
|
||||
rm -rf $OUTDIR
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ===== 第1步: 保存进程内存映射 =====
|
||||
echo ""
|
||||
echo "[1/5] 保存进程内存映射..."
|
||||
cat /proc/$PID/maps > $OUTDIR/maps.txt
|
||||
echo " ✅ /proc/$PID/maps -> $OUTDIR/maps.txt"
|
||||
|
||||
# 找出代码段范围 (anonymous r-x 段,是UPX解压后的代码)
|
||||
ANON_RX=$(awk '/r-xp/ && !/\// {print $1}' $OUTDIR/maps.txt | head -1)
|
||||
if [ -n "$ANON_RX" ]; then
|
||||
ANON_RX_START=$(echo $ANON_RX | cut -d- -f1)
|
||||
ANON_RX_END=$(echo $ANON_RX | cut -d- -f2)
|
||||
echo " 📌 匿名代码段(UPX解压): 0x$ANON_RX_START - 0x$ANON_RX_END"
|
||||
fi
|
||||
|
||||
# 找堆段
|
||||
HEAP=$(awk '/\[heap\]/ {print $1}' $OUTDIR/maps.txt | head -1)
|
||||
if [ -n "$HEAP" ]; then
|
||||
HEAP_START=$(echo $HEAP | cut -d- -f1)
|
||||
HEAP_END=$(echo $HEAP | cut -d- -f2)
|
||||
echo " 📌 堆: 0x$HEAP_START - 0x$HEAP_END"
|
||||
fi
|
||||
|
||||
# ===== 第2步: 准备GDB脚本 (只读,不修改) =====
|
||||
echo ""
|
||||
echo "[2/5] 生成GDB脚本..."
|
||||
|
||||
cat > $OUTDIR/gdb_script.gdb <<'GDBSCRIPT'
|
||||
# GDB脚本: 只读模式提取Blowfish密钥
|
||||
# 严格规定: 不修改任何寄存器、不写入任何内存、不调用任何函数
|
||||
|
||||
set pagination off
|
||||
set print pretty on
|
||||
set logging redirect on
|
||||
set logging overwrite on
|
||||
|
||||
# 1. 进程基本信息
|
||||
printf "=== 进程信息 ===\n"
|
||||
info proc mappings
|
||||
|
||||
printf "\n=== 寄存器状态 ===\n"
|
||||
info registers
|
||||
|
||||
printf "\n=== 调用栈 ===\n"
|
||||
bt 5
|
||||
|
||||
# 2. 不设断点,只dump关键内存
|
||||
|
||||
# 完成
|
||||
printf "\n=== 完成,准备detach ===\n"
|
||||
GDBSCRIPT
|
||||
|
||||
echo " ✅ $OUTDIR/gdb_script.gdb"
|
||||
|
||||
# ===== 第3步: GDB attach (最短时间) =====
|
||||
echo ""
|
||||
echo "[3/5] GDB attach (目标<5秒)..."
|
||||
|
||||
START_TS=$(date +%s)
|
||||
|
||||
# 用-batch模式,自动执行后立即退出
|
||||
timeout 30 gdb -batch \
|
||||
-p $PID \
|
||||
-x $OUTDIR/gdb_script.gdb \
|
||||
> $OUTDIR/gdb_output.txt 2>&1
|
||||
|
||||
END_TS=$(date +%s)
|
||||
ELAPSED=$((END_TS - START_TS))
|
||||
echo " ✅ GDB完成,耗时 ${ELAPSED}s"
|
||||
|
||||
# 检查狗是否还在线
|
||||
if ! kill -0 $PID 2>/dev/null; then
|
||||
echo " ⚠️ 警告: Legged_sport进程消失!"
|
||||
fi
|
||||
|
||||
# ===== 第4步: dump堆内存 (用/proc/PID/mem直接读取,比GDB快) =====
|
||||
echo ""
|
||||
echo "[4/5] 直接读取堆内存 (不用GDB)..."
|
||||
|
||||
if [ -n "$HEAP_START" ]; then
|
||||
HEAP_SIZE=$((0x$HEAP_END - 0x$HEAP_START))
|
||||
HEAP_OFFSET=$((0x$HEAP_START))
|
||||
echo " 读取堆 ${HEAP_SIZE} 字节..."
|
||||
|
||||
# 用dd直接从/proc/$PID/mem读 (bs=65536大块读取,比bs=1快1000x)
|
||||
dd if=/proc/$PID/mem of=$OUTDIR/heap.bin \
|
||||
bs=65536 count=$HEAP_SIZE skip=$HEAP_OFFSET \
|
||||
iflag=skip_bytes,count_bytes 2>/dev/null || \
|
||||
echo " ⚠️ /proc/mem读取失败,可能需要ptrace"
|
||||
|
||||
if [ -f $OUTDIR/heap.bin ]; then
|
||||
HEAPACTUAL=$(stat -c%s $OUTDIR/heap.bin)
|
||||
echo " ✅ heap.bin ($HEAPACTUAL 字节)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 也dump匿名代码段 (UPX解压后的代码,含运行时S-box)
|
||||
if [ -n "$ANON_RX_START" ]; then
|
||||
RX_SIZE=$((0x$ANON_RX_END - 0x$ANON_RX_START))
|
||||
RX_OFFSET=$((0x$ANON_RX_START))
|
||||
echo " 读取匿名代码段 ${RX_SIZE} 字节..."
|
||||
|
||||
dd if=/proc/$PID/mem of=$OUTDIR/anon_code.bin \
|
||||
bs=65536 count=$RX_SIZE skip=$RX_OFFSET \
|
||||
iflag=skip_bytes,count_bytes 2>/dev/null
|
||||
|
||||
if [ -f $OUTDIR/anon_code.bin ]; then
|
||||
CODEACTUAL=$(stat -c%s $OUTDIR/anon_code.bin)
|
||||
echo " ✅ anon_code.bin ($CODEACTUAL 字节)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 也dump所有匿名rw段 (含运行时S-box和P-array)
|
||||
echo " 读取所有匿名rw段..."
|
||||
RW_COUNT=0
|
||||
awk '/rw-p/ && !/\// && !/\[stack\]/ && !/\[vvar\]/ {print $1}' $OUTDIR/maps.txt | while read range; do
|
||||
START=$(echo $range | cut -d- -f1)
|
||||
END=$(echo $range | cut -d- -f2)
|
||||
SIZE=$((0x$END - 0x$START))
|
||||
OFFSET=$((0x$START))
|
||||
|
||||
# 只dump合理大小的段 (1KB - 64MB)
|
||||
if [ $SIZE -gt 1024 ] && [ $SIZE -lt 67108864 ]; then
|
||||
OUTFILE=$OUTDIR/rw_${START}.bin
|
||||
dd if=/proc/$PID/mem of=$OUTFILE \
|
||||
bs=65536 count=$SIZE skip=$OFFSET \
|
||||
iflag=skip_bytes,count_bytes 2>/dev/null
|
||||
|
||||
if [ -f $OUTFILE ] && [ -s $OUTFILE ]; then
|
||||
echo " rw_${START}.bin ($SIZE 字节)"
|
||||
RW_COUNT=$((RW_COUNT + 1))
|
||||
else
|
||||
rm -f $OUTFILE
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# ===== 第5步: 打包 =====
|
||||
echo ""
|
||||
echo "[5/5] 打包输出..."
|
||||
cd /tmp
|
||||
TARBALL=blowfish_dump_$(date +%Y%m%d_%H%M%S).tar.gz
|
||||
tar czf $TARBALL -C $OUTDIR .
|
||||
mv $TARBALL /tmp/blowfish_dump.tar.gz
|
||||
echo " ✅ /tmp/blowfish_dump.tar.gz ($(stat -c%s /tmp/blowfish_dump.tar.gz) 字节)"
|
||||
|
||||
# 检查狗是否还在线
|
||||
echo ""
|
||||
if kill -0 $PID 2>/dev/null; then
|
||||
echo "✅ Legged_sport仍在运行 (PID $PID)"
|
||||
else
|
||||
echo "❌ Legged_sport已退出!"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "完成!"
|
||||
echo "============================================"
|
||||
echo "数据位置: /tmp/blowfish_dump.tar.gz"
|
||||
echo "中间文件: $OUTDIR/"
|
||||
echo ""
|
||||
echo "从Mac拉取:"
|
||||
echo " scp pi@192.168.123.161:/tmp/blowfish_dump.tar.gz ./data/lowlevel_captures/"
|
||||
Reference in New Issue
Block a user