68 lines
2.0 KiB
Bash
68 lines
2.0 KiB
Bash
#!/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 "]"
|