#!/bin/bash # Extract function fingerprints from ELF binaries # Outputs JSON array with function name, offset, size, and hashes set -euo pipefail DIR="${1:-.}" extract_functions_from_binary() { local binary="$1" # Skip non-ELF files file "$binary" 2>/dev/null | grep -q "ELF" || return 0 # Get function symbols with objdump objdump -t "$binary" 2>/dev/null | \ awk '/\.text.*[0-9a-f]+.*F/ { gsub(/\*.*\*/, "", $1) if ($5 != "" && length($4) > 0) { size = strtonum("0x" $4) if (size >= 16) { print $1, $4, $NF } } }' | while read -r offset size name; do # Skip compiler-generated symbols case "$name" in __*|_GLOBAL_*|.plt*|.text*|frame_dummy|register_tm_clones|deregister_tm_clones|_start|_init|_fini) continue ;; esac # Convert hex size dec_size=$((16#$size)) # Compute hash of function bytes local hash=$(objdump -d --start-address="0x$offset" --stop-address="$((16#$offset + dec_size))" "$binary" 2>/dev/null | \ grep -E "^[[:space:]]*[0-9a-f]+:" | \ awk '{for(i=2;i<=NF;i++){if($i~/^[0-9a-f]{2}$/){printf "%s", $i}}}' | \ sha256sum | cut -d' ' -f1) [ -n "$hash" ] || hash="unknown" printf '{"name":"%s","offset":"0x%s","size":%d,"hash":"%s"}\n' \ "$name" "$offset" "$dec_size" "$hash" done } # Output JSON array echo "[" first=true find "$DIR" -type f \( -executable -o -name "*.so" -o -name "*.so.*" \) 2>/dev/null | while read -r binary; do file "$binary" 2>/dev/null | grep -q "ELF" || continue extract_functions_from_binary "$binary" | while read -r json; do [ -z "$json" ] && continue if [ "$first" = "true" ]; then first=false echo "$json" else echo ",$json" fi done done echo "]"