objdump 是 Linux 中功能强大的 二进制文件分析工具,用于反汇编、查看目标文件结构和调试信息。它是 GNU Binutils 工具集的一部分。
📦 基本语法
bash
objdump [选项] 文件...
🎯 主要功能
- 反汇编:将二进制代码转换为汇编语言
- 文件头分析:查看 ELF 文件头信息
- 段/节信息:显示二进制文件的各个段/节
- 符号表查看:显示函数和变量符号
- 重定位信息:查看重定位条目
- 调试信息:显示 DWARF 调试信息
💡 常用选项分类
1. 反汇编相关
bash
# 反汇编可执行代码段
objdump -d 可执行文件
# 反汇编所有段(包括数据段)
objdump -D 可执行文件
# 反汇编特定函数
objdump -d 可执行文件 | grep -A 20 "函数名>"
# 显示源代码与汇编混合(需要 -g 编译)
objdump -S 可执行文件
# 反汇编特定地址范围
objdump -d --start-address=0x400000 --stop-address=0x400100 可执行文件
2. 文件结构分析
bash
# 显示文件头信息
objdump -f 可执行文件
# 显示段/节头信息
objdump -h 可执行文件
# 显示所有头信息(详细)
objdump -x 可执行文件
# 显示程序头(段头)
objdump -p 可执行文件
# 显示节头
objdump -t 可执行文件
3. 符号和重定位
bash
# 显示符号表
objdump -t 可执行文件
# 显示动态符号表
objdump -T 可执行文件
# 显示重定位信息
objdump -r 可执行文件
# 显示动态重定位信息
objdump -R 可执行文件
4. 内容查看
bash
# 显示所有段的内容(十六进制)
objdump -s 可执行文件
# 显示特定段的内容
objdump -s -j .text 可执行文件
# 显示文件头魔数
objdump -p 可执行文件 | grep -i magic
5. 调试信息
bash
# 显示 DWARF 调试信息
objdump -g 可执行文件
# 显示行号信息
objdump -l 可执行文件
# 显示所有调试信息
objdump -W 可执行文件
⚡ 实际应用示例
示例 1:基本反汇编分析
bash
#!/bin/bash
# 基本反汇编分析脚本
FILE="$1"
if [[ -z "$FILE" ]] || [[ ! -f "$FILE" ]]; then
echo "用法: $0 <可执行文件>"
exit 1
fi
echo "=== 文件分析: $FILE ==="
echo ""
# 1. 检查文件类型
echo "1. 文件类型:"
file "$FILE"
echo ""
# 2. 显示文件头信息
echo "2. 文件头信息:"
objdump -f "$FILE"
echo ""
# 3. 显示段头信息
echo "3. 段头信息:"
objdump -h "$FILE" | head -20
echo ""
# 4. 显示符号表(前20行)
echo "4. 符号表(前20行):"
objdump -t "$FILE" | head -20
echo ""
# 5. 反汇编 main 函数
echo "5. 反汇编 main 函数:"
if objdump -t "$FILE" | grep -q " main$"; then
MAIN_ADDR=$(objdump -t "$FILE" | grep " main$" | awk '{print $1}')
echo "main 函数地址: 0x$MAIN_ADDR"
echo ""
objdump -d --start-address="0x$MAIN_ADDR" "$FILE" | head -50
else
echo "未找到 main 函数"
fi
示例 2:函数调用分析
bash
#!/bin/bash
# 函数调用关系分析
FILE="$1"
FUNC="$2"
if [[ -z "$FILE" ]] || [[ ! -f "$FILE" ]]; then
echo "用法: $0 <可执行文件> [函数名]"
exit 1
fi
echo "=== 函数分析: $FILE ==="
echo ""
# 获取所有函数
echo "1. 所有函数列表:"
objdump -t "$FILE" | grep "F .text" | awk '{print $NF}' | sort
echo ""
# 如果指定了函数名,分析该函数
if [[ -n "$FUNC" ]]; then
echo "2. 分析函数: $FUNC"
echo "----------------------------------------"
# 查找函数地址
FUNC_ADDR=$(objdump -t "$FILE" | grep " $FUNC$" | awk '{print $1}')
if [[ -n "$FUNC_ADDR" ]]; then
echo "函数地址: 0x$FUNC_ADDR"
echo ""
# 反汇编该函数
echo "反汇编代码:"
objdump -d --start-address="0x$FUNC_ADDR" "$FILE" | head -100
# 查找函数调用
echo ""
echo "函数调用关系:"
echo "调用的函数:"
objdump -d --start-address="0x$FUNC_ADDR" "$FILE" | \
grep -E "callq|call" | \
grep -v "plt" | \
awk '{print $NF}' | \
sort | uniq
echo ""
echo "被调用位置:"
objdump -d "$FILE" | \
grep -B2 "call.*$FUNC" | \
grep -E "^ [0-9a-f]+:" | \
awk '{print $1, $2}'
else
echo "未找到函数: $FUNC"
fi
fi
# 显示导入/导出函数
echo ""
echo "3. 动态符号表(导入函数):"
objdump -T "$FILE" | grep "UND" | awk '{print $NF}' | sort | head -20
echo ""
echo "4. 导出函数:"
objdump -T "$FILE" | grep "DF .text" | awk '{print $NF}' | sort | head -20
示例 3:二进制文件比较
bash
#!/bin/bash
# 比较两个二进制文件的差异
FILE1="$1"
FILE2="$2"
if [[ -z "$FILE1" ]] || [[ -z "$FILE2" ]] || [[ ! -f "$FILE1" ]] || [[ ! -f "$FILE2" ]]; then
echo "用法: $0 <文件1> <文件2>"
exit 1
fi
echo "=== 二进制文件比较 ==="
echo "文件1: $FILE1"
echo "文件2: $FILE2"
echo ""
# 1. 文件基本信息比较
echo "1. 文件基本信息:"
echo "----------------------------------------"
echo "文件1:"
file "$FILE1"
echo "大小: $(stat -c%s "$FILE1") 字节"
echo ""
echo "文件2:"
file "$FILE2"
echo "大小: $(stat -c%s "$FILE2") 字节"
echo ""
# 2. 文件头比较
echo "2. 文件头差异:"
echo "----------------------------------------"
diff <(objdump -f "$FILE1") <(objdump -f "$FILE2")
echo ""
# 3. 段头比较
echo "3. 段头信息差异:"
echo "----------------------------------------"
diff <(objdump -h "$FILE1") <(objdump -h "$FILE2")
echo ""
# 4. 符号表比较
echo "4. 符号表差异:"
echo "----------------------------------------"
diff <(objdump -t "$FILE1" | sort) <(objdump -t "$FILE2" | sort) | head -50
echo ""
# 5. 反汇编代码比较(仅比较 .text 段)
echo "5. .text 段反汇编差异(前50行):"
echo "----------------------------------------"
TEXT1=$(objdump -d -j .text "$FILE1" 2>/dev/null)
TEXT2=$(objdump -d -j .text "$FILE2" 2>/dev/null)
if [[ -n "$TEXT1" ]] && [[ -n "$TEXT2" ]]; then
diff <(echo "$TEXT1") <(echo "$TEXT2") | head -50
else
echo "无法获取 .text 段信息"
fi
示例 4:安全分析 - 检查保护机制
bash
#!/bin/bash
# 检查二进制文件的安全保护机制
FILE="$1"
if [[ -z "$FILE" ]] || [[ ! -f "$FILE" ]]; then
echo "用法: $0 <可执行文件>"
exit 1
fi
echo "=== 安全分析: $FILE ==="
echo "分析时间: $(date)"
echo ""
# 1. 检查文件类型和保护位
echo "1. 文件属性和保护位:"
ls -la "$FILE"
echo ""
file "$FILE"
echo ""
# 2. 检查 RELRO(重定位只读)
echo "2. RELRO 保护:"
readelf -d "$FILE" 2>/dev/null | grep -E "(BIND_NOW|FLAGS)"
if readelf -d "$FILE" 2>/dev/null | grep -q "BIND_NOW"; then
echo "✅ FULL RELRO: 启用"
elif readelf -l "$FILE" 2>/dev/null | grep -q "GNU_RELRO"; then
echo "⚠️ PARTIAL RELRO: 启用"
else
echo "❌ RELRO: 禁用"
fi
echo ""
# 3. 检查栈保护(Stack Canary)
echo "3. 栈保护(Stack Canary):"
if objdump -d "$FILE" 2>/dev/null | grep -q "__stack_chk_fail"; then
echo "✅ 栈保护: 启用"
else
echo "❌ 栈保护: 禁用"
fi
echo ""
# 4. 检查 NX(不可执行栈)
echo "4. NX(不可执行栈):"
if readelf -l "$FILE" 2>/dev/null | grep -q "GNU_STACK"; then
STACK_PERM=$(readelf -l "$FILE" 2>/dev/null | grep "GNU_STACK" | awk '{print $6}')
if [[ "$STACK_PERM" == "RW" ]]; then
echo "✅ NX: 启用(栈不可执行)"
elif [[ "$STACK_PERM" == "RWE" ]]; then
echo "❌ NX: 禁用(栈可执行)"
else
echo "⚠️ NX: 未知权限 ($STACK_PERM)"
fi
else
echo "⚠️ 无法确定 NX 状态"
fi
echo ""
# 5. 检查 PIE(位置无关可执行文件)
echo "5. PIE(位置无关可执行文件):"
FILE_TYPE=$(file "$FILE")
if echo "$FILE_TYPE" | grep -q "shared object"; then
echo "✅ PIE: 启用(动态链接)"
elif echo "$FILE_TYPE" | grep -q "ELF.*executable.*dynamically linked"; then
# 检查是否有 .plt.got 节
if readelf -S "$FILE" 2>/dev/null | grep -q "\.plt\.got"; then
echo "✅ PIE: 启用"
else
echo "⚠️ PIE: 可能启用"
fi
else
echo "❌ PIE: 禁用(静态地址)"
fi
echo ""
# 6. 检查 RPATH/RUNPATH
echo "6. RPATH/RUNPATH 检查:"
readelf -d "$FILE" 2>/dev/null | grep -E "(RPATH|RUNPATH)"
if readelf -d "$FILE" 2>/dev/null | grep -q "RPATH"; then
echo "⚠️ 存在 RPATH(可能不安全)"
elif readelf -d "$FILE" 2>/dev/null | grep -q "RUNPATH"; then
echo "⚠️ 存在 RUNPATH"
else
echo "✅ 无 RPATH/RUNPATH"
fi
echo ""
# 7. 检查动态符号表
echo "7. 动态符号表(前20个函数):"
objdump -T "$FILE" 2>/dev/null | grep "DF .text" | head -20 | awk '{print $NF}'
echo ""
# 8. 检查字符串
echo "8. 可疑字符串(前20个):"
strings "$FILE" | grep -E "(pass|key|secret|token|admin|root)" | head -20
echo ""
echo "=== 安全建议 ==="
echo "1. 确保启用所有保护机制(RELRO、Stack Canary、NX、PIE)"
echo "2. 移除不必要的 RPATH/RUNPATH"
echo "3. 使用 strip 移除调试符号(生产环境)"
echo "4. 定期使用 checksec 工具检查"
示例 5:库依赖分析
bash
#!/bin/bash
# 分析二进制文件的库依赖
FILE="$1"
if [[ -z "$FILE" ]] || [[ ! -f "$FILE" ]]; then
echo "用法: $0 <可执行文件>"
exit 1
fi
echo "=== 库依赖分析: $FILE ==="
echo ""
# 1. 使用 ldd 查看动态依赖
echo "1. 动态库依赖(ldd):"
echo "----------------------------------------"
if ldd "$FILE" 2>/dev/null; then
echo ""
else
echo "不是动态链接的可执行文件"
fi
# 2. 使用 objdump 查看动态段
echo "2. 动态段信息(objdump -p):"
echo "----------------------------------------"
objdump -p "$FILE" | grep -A50 "Dynamic Section"
echo ""
# 3. 查看 NEEDED 库
echo "3. 需要的共享库:"
echo "----------------------------------------"
objdump -p "$FILE" | grep "NEEDED" | sort
echo ""
# 4. 查看库搜索路径
echo "4. 库搜索路径:"
echo "----------------------------------------"
objdump -p "$FILE" | grep -E "(RPATH|RUNPATH)"
echo ""
# 5. 查看符号版本
echo "5. 符号版本信息:"
echo "----------------------------------------"
objdump -p "$FILE" | grep -A20 "Version References"
echo ""
# 6. 检查未定义符号
echo "6. 未定义符号(需要动态解析):"
echo "----------------------------------------"
objdump -T "$FILE" | grep "UND" | head -20
echo ""
# 7. 生成依赖图(简单文本版)
echo "7. 依赖关系图:"
echo "----------------------------------------"
echo "$FILE"
LIBRARIES=$(objdump -p "$FILE" | grep "NEEDED" | awk '{print $2}')
for lib in $LIBRARIES; do
echo " └── $lib"
# 尝试查找库的进一步依赖
LIB_PATH=$(ldd "$FILE" 2>/dev/null | grep "$lib" | awk '{print $3}')
if [[ -f "$LIB_PATH" ]]; then
SUB_LIBS=$(objdump -p "$LIB_PATH" 2>/dev/null | grep "NEEDED" | awk '{print $2}' | head -3)
for sub_lib in $SUB_LIBS; do
echo " └── $sub_lib"
done
if [[ $(echo "$SUB_LIBS" | wc -l) -gt 3 ]]; then
echo " └── ..."
fi
fi
done
🔧 高级用法和技巧
1. 结合其他工具使用
bash
#!/bin/bash
# 综合二进制分析工具链
FILE="$1"
echo "=== 综合二进制分析 ==="
echo "文件: $FILE"
echo ""
# 1. 使用 file 确定文件类型
echo "1. 文件类型:"
file "$FILE"
echo ""
# 2. 使用 readelf 查看 ELF 结构
echo "2. ELF 文件头:"
readelf -h "$FILE"
echo ""
# 3. 使用 objdump 反汇编
echo "3. 反汇编 main 函数:"
MAIN_ADDR=$(objdump -t "$FILE" | grep " main$" | awk '{print $1}' 2>/dev/null)
if [[ -n "$MAIN_ADDR" ]]; then
objdump -d --start-address="0x$MAIN_ADDR" --stop-address="0x$(printf '%x' $((0x$MAIN_ADDR + 200)))" "$FILE"
fi
echo ""
# 4. 使用 nm 查看符号
echo "4. 符号表(nm):"
nm "$FILE" 2>/dev/null | head -20
echo ""
# 5. 使用 strings 查看字符串
echo "5. 可打印字符串:"
strings "$FILE" | head -20
echo ""
# 6. 使用 ldd 查看依赖
echo "6. 动态库依赖:"
ldd "$FILE" 2>/dev/null | head -10
echo ""
# 7. 使用 strip 移除符号(演示)
echo "7. 文件大小对比:"
ORIG_SIZE=$(stat -c%s "$FILE")
echo "原始大小: $ORIG_SIZE 字节"
# 创建副本并 strip
cp "$FILE" "${FILE}.stripped"
strip "${FILE}.stripped" 2>/dev/null
STRIPPED_SIZE=$(stat -c%s "${FILE}.stripped")
echo "去除符号后: $STRIPPED_SIZE 字节"
echo "节省空间: $((ORIG_SIZE - STRIPPED_SIZE)) 字节"
# 清理
rm -f "${FILE}.stripped"
2. 反汇编特定架构
bash
# 指定架构反汇编
objdump -d -m i386 可执行文件 # 32位 x86
objdump -d -m i386:x86-64 可执行文件 # x86-64
objdump -d -m arm 可执行文件 # ARM
objdump -d -m aarch64 可执行文件 # ARM64
objdump -d -m powerpc 可执行文件 # PowerPC
objdump -d -m mips 可执行文件 # MIPS
# 指定字节序
objdump -d -EB 可执行文件 # 大端序
objdump -d -EL 可执行文件 # 小端序
# 指定指令集
objdump -d -M att 可执行文件 # AT&T 语法(默认)
objdump -d -M intel 可执行文件 # Intel 语法
3. 输出格式控制
bash
# 控制反汇编输出
objdump -d --no-show-raw-insn 可执行文件 # 不显示机器码
objdump -d --prefix-addresses 可执行文件 # 每行显示地址
objdump -d --visualize-jumps 可执行文件 # 可视化跳转
objdump -d --disassemble-zeroes 可执行文件 # 反汇编零字节
# 控制符号显示
objdump -d --demangle 可执行文件 # 解码 C++ 符号
objdump -d --no-demangle 可执行文件 # 不解码符号
# 输出到文件
objdump -d 可执行文件 > 反汇编.txt
objdump -d 可执行文件 | grep -A5 "main>" > main函数.txt
🛠️ 故障排查和调试
1. 常见问题解决
bash
# 问题1: 不是可执行文件
# 错误: objdump: 文件格式无法识别
# 解决: 检查文件类型
file 文件名
# 确保是 ELF 可执行文件或目标文件
# 问题2: 权限不足
# 错误: objdump: 无法打开文件
# 解决: 使用 sudo 或检查文件权限
sudo objdump -d 文件名
# 或
chmod +r 文件名
# 问题3: 架构不匹配
# 错误: 文件格式无法识别或架构不匹配
# 解决: 指定正确的架构
objdump -d -m i386:x86-64 文件名
# 问题4: 缺少调试信息
# 现象: 反汇编时没有源代码
# 解决: 编译时添加 -g 选项
gcc -g -o 程序 源文件.c
# 问题5: 剥离了符号表
# 现象: 看不到函数名
# 解决: 使用未剥离符号的文件
# 编译时不要使用 -s 或 strip 命令
2. 调试示例:分析崩溃的核心转储
bash
#!/bin/bash
# 分析核心转储文件
CORE_FILE="$1"
EXECUTABLE="$2"
if [[ -z "$CORE_FILE" ]] || [[ ! -f "$CORE_FILE" ]]; then
echo "用法: $0 <核心转储文件> [可执行文件]"
exit 1
fi
echo "=== 核心转储分析 ==="
echo "核心文件: $CORE_FILE"
echo ""
# 1. 确定可执行文件
if [[ -z "$EXECUTABLE" ]]; then
EXECUTABLE=$(file "$CORE_FILE" | grep -o "from '.*'" | sed "s/from '//;s/'//")
if [[ -z "$EXECUTABLE" ]]; then
echo "请指定可执行文件: $0 $CORE_FILE <可执行文件>"
exit 1
fi
fi
echo "可执行文件: $EXECUTABLE"
echo ""
# 2. 使用 gdb 获取回溯
echo "1. GDB 回溯:"
echo "----------------------------------------"
gdb -q "$EXECUTABLE" "$CORE_FILE" -ex "bt" -ex "quit" 2>/dev/null
echo ""
# 3. 使用 objdump 分析崩溃点
echo "2. 崩溃点附近的代码:"
echo "----------------------------------------"
# 获取程序计数器值
PC_VALUE=$(gdb -q "$EXECUTABLE" "$CORE_FILE" -ex "info reg rip" -ex "quit" 2>/dev/null | grep "rip" | awk '{print $2}')
if [[ -n "$PC_VALUE" ]]; then
echo "程序计数器 (RIP): $PC_VALUE"
echo ""
# 转换为十进制
PC_DEC=$((16#${PC_VALUE#0x}))
# 计算范围(前后 100 字节)
START=$((PC_DEC - 100))
END=$((PC_DEC + 100))
# 反汇编该区域
echo "反汇编崩溃点附近代码:"
objdump -d --start-address="0x$(printf '%x' $START)" \
--stop-address="0x$(printf '%x' $END)" \
"$EXECUTABLE" 2>/dev/null || echo "无法反汇编该地址范围"
else
echo "无法获取程序计数器值"
fi
echo ""
# 4. 检查栈信息
echo "3. 栈信息:"
echo "----------------------------------------"
gdb -q "$EXECUTABLE" "$CORE_FILE" -ex "info stack" -ex "quit" 2>/dev/null
echo ""
# 5. 检查寄存器
echo "4. 寄存器状态:"
echo "----------------------------------------"
gdb -q "$EXECUTABLE" "$CORE_FILE" -ex "info registers" -ex "quit" 2>/dev/null | head -20
📊 实用脚本集合
1. 二进制文件信息提取脚本
bash
#!/bin/bash
# 提取二进制文件信息的工具脚本
FILE="$1"
OUTPUT_DIR="${2:-./analysis_output}"
if [[ -z "$FILE" ]] || [[ ! -f "$FILE" ]]; then
echo "用法: $0 <二进制文件> [输出目录]"
exit 1
fi
mkdir -p "$OUTPUT_DIR"
BASENAME=$(basename "$FILE")
echo "分析文件: $FILE"
echo "输出目录: $OUTPUT_DIR"
echo ""
# 1. 基本信息
echo "提取基本信息..."
file "$FILE" > "$OUTPUT_DIR/${BASENAME}.info.txt"
# 2. 文件头
echo "提取文件头..."
objdump -f "$FILE" > "$OUTPUT_DIR/${BASENAME}.headers.txt"
objdump -h "$FILE" >> "$OUTPUT_DIR/${BASENAME}.headers.txt"
# 3. 符号表
echo "提取符号表..."
objdump -t "$FILE" > "$OUTPUT_DIR/${BASENAME}.symbols.txt"
objdump -T "$FILE" > "$OUTPUT_DIR/${BASENAME}.dynamic_symbols.txt"
# 4. 反汇编
echo "反汇编代码..."
objdump -d "$FILE" > "$OUTPUT_DIR/${BASENAME}.disassembly.txt"
# 5. 段内容
echo "提取段内容..."
objdump -s "$FILE" > "$OUTPUT_DIR/${BASENAME}.sections.txt"
# 6. 字符串
echo "提取字符串..."
strings "$FILE" > "$OUTPUT_DIR/${BASENAME}.strings.txt"
# 7. 依赖库
echo "提取依赖库..."
ldd "$FILE" 2>/dev/null > "$OUTPUT_DIR/${BASENAME}.dependencies.txt"
objdump -p "$FILE" | grep "NEEDED" > "$OUTPUT_DIR/${BASENAME}.needed_libs.txt"
# 8. 重定位信息
echo "提取重定位信息..."
objdump -r "$FILE" > "$OUTPUT_DIR/${BASENAME}.relocations.txt"
objdump -R "$FILE" > "$OUTPUT_DIR/${BASENAME}.dynamic_relocations.txt"
# 9. 生成报告
echo "生成分析报告..."
cat > "$OUTPUT_DIR/${BASENAME}.report.md" << EOF
# 二进制文件分析报告
## 文件信息
- 文件名: $BASENAME
- 分析时间: $(date)
- 文件类型: $(file "$FILE")
## 基本信息
\`\`\`
$(head -20 "$OUTPUT_DIR/${BASENAME}.info.txt")
\`\`\`
## 符号统计
- 总符号数: $(wc -l < "$OUTPUT_DIR/${BASENAME}.symbols.txt")
- 动态符号数: $(wc -l < "$OUTPUT_DIR/${BASENAME}.dynamic_symbols.txt")
## 段信息
\`\`\`
$(head -30 "$OUTPUT_DIR/${BASENAME}.headers.txt")
\`\`\`
## 依赖库
\`\`\`
$(cat "$OUTPUT_DIR/${BASENAME}.dependencies.txt")
\`\`\`
## 分析文件列表
1. \`${BASENAME}.info.txt\` - 文件基本信息
2. \`${BASENAME}.headers.txt\` - 文件头信息
3. \`${BASENAME}.symbols.txt\` - 符号表
4. \`${BASENAME}.disassembly.txt\` - 反汇编代码
5. \`${BASENAME}.strings.txt\` - 可打印字符串
6. \`${BASENAME}.dependencies.txt\` - 依赖库
7. \`${BASENAME}.relocations.txt\` - 重定位信息
EOF
echo "分析完成!"
echo "报告文件: $OUTPUT_DIR/${BASENAME}.report.md"
ls -la "$OUTPUT_DIR/${BASENAME}."*
2. 恶意软件分析快速检查
bash
#!/bin/bash
# 恶意软件分析快速检查
FILE="$1"
if [[ -z "$FILE" ]] || [[ ! -f "$FILE" ]]; then
echo "用法: $0 <可疑文件>"
exit 1
fi
echo "=== 恶意软件快速分析 ==="
echo "文件: $FILE"
echo "MD5: $(md5sum "$FILE" | awk '{print $1}')"
echo "SHA256: $(sha256sum "$FILE" | awk '{print $1}')"
echo ""
# 1. 文件基本信息
echo "1. 文件基本信息:"
echo "----------------------------------------"
file "$FILE"
stat "$FILE"
echo ""
# 2. 检查是否加壳
echo "2. 加壳检测:"
echo "----------------------------------------"
strings "$FILE" | head -5
echo ""
echo "熵值分析:"
entropy=$(cat "$FILE" | ent | grep "Entropy" | awk '{print $3}')
echo "熵值: $entropy"
if (( $(echo "$entropy > 7.5" | bc -l) )); then
echo "⚠️ 高熵值,可能加壳或加密"
else
echo "✅ 熵值正常"
fi
echo ""
# 3. 检查可疑导入函数
echo "3. 可疑导入函数:"
echo "----------------------------------------"
objdump -T "$FILE" 2>/dev/null | grep "UND" | awk '{print $NF}' | \
grep -E -i "(execve|system|popen|socket|connect|listen|accept|bind|send|recv|CreateProcess|WinExec|ShellExecute|URLDownloadToFile|GetProcAddress|LoadLibrary)" | \
sort | uniq
echo ""
# 4. 检查可疑字符串
echo "4. 可疑字符串:"
echo "----------------------------------------"
strings "$FILE" | \
grep -E -i "(http://|https://|ftp://|www\.|\.com|\.net|\.org|\.ru|\.cn|pass|key|secret|admin|root|exploit|hack|backdoor|malware|virus|trojan|botnet|cmd\.exe|/bin/sh|/bin/bash)" | \
head -20
echo ""
# 5. 检查节区名称
echo "5. 可疑节区名称:"
echo "----------------------------------------"
objdump -h "$FILE" 2>/dev/null | grep -E "\.(text|data|bss|rodata)" | head -10
objdump -h "$FILE" 2>/dev/null | grep -v -E "\.(text|data|bss|rodata|comment|note|debug)" | head -10
echo ""
# 6. 检查入口点
echo "6. 入口点分析:"
echo "----------------------------------------"
ENTRY_POINT=$(objdump -f "$FILE" 2>/dev/null | grep "start address" | awk '{print $NF}')
if [[ -n "$ENTRY_POINT" ]]; then
echo "入口点地址: $ENTRY_POINT"
# 反汇编入口点附近代码
ENTRY_HEX=${ENTRY_POINT#0x}
ENTRY_DEC=$((16#$ENTRY_HEX))
START=$((ENTRY_DEC - 50))
END=$((ENTRY_DEC + 50))
objdump -d --start-address="0x$(printf '%x' $START)" \
--stop-address="0x$(printf '%x' $END)" \
"$FILE" 2>/dev/null | head -20
else
echo "无法获取入口点"
fi
echo ""
echo "=== 建议 ==="
echo "1. 在隔离环境中运行此文件"
echo "2. 使用 VirusTotal 在线扫描"
echo "3. 使用 strace/ltrace 监控系统调用"
echo "4. 使用 gdb 动态分析"
echo "5. 检查网络连接行为"
📚 总结
objdump 常用命令速查表
| 命令 | 功能 | 示例 |
|---|---|---|
objdump -d |
反汇编代码段 | objdump -d program |
objdump -D |
反汇编所有段 | objdump -D program |
objdump -h |
显示段头 | objdump -h program |
objdump -t |
显示符号表 | objdump -t program |
objdump -T |
显示动态符号表 | objdump -T program |
objdump -r |
显示重定位信息 | objdump -r program |
objdump -s |
显示段内容 | objdump -s program |
objdump -S |
显示源码和汇编 | objdump -S program |
objdump -f |
显示文件头 | objdump -f program |
objdump -p |
显示程序头 | objdump -p program |
objdump -x |
显示所有头信息 | objdump -x program |
最佳实践建议
- 结合使用 :
objdump与readelf、nm、strings、ldd等工具结合使用 - 调试版本 :分析时使用带调试信息的版本(
-g编译) - 架构匹配:确保使用正确的架构选项分析跨平台二进制文件
- 输出重定向:将反汇编结果保存到文件以便分析
- 脚本自动化:编写脚本自动化常见分析任务
- 安全分析 :结合安全工具(如
checksec)进行安全评估
objdump 是二进制分析的基础工具,掌握它可以深入理解程序内部结构,对于调试、逆向工程和安全分析都至关重要。