Get bin info.py
From Attie's Wiki
(Difference between revisions)
m (indentation!) |
m (now operates with .rodata sections that are not aligned to a 16-byte boundary...) |
||
Line 8: | Line 8: | ||
CROSS_COMPILE="" | CROSS_COMPILE="" | ||
fi | fi | ||
− | + | ||
FILE=$1; shift | FILE=$1; shift | ||
SYMBOL=$1; shift | SYMBOL=$1; shift | ||
− | + | ||
if [ ! -e ${FILE} ]; then | if [ ! -e ${FILE} ]; then | ||
echo "File '${FILE}' does not exist..." >&2 | echo "File '${FILE}' does not exist..." >&2 | ||
exit 1 | exit 1 | ||
fi | fi | ||
− | + | ||
# get the symbol information | # get the symbol information | ||
SYM_INFO=$(${CROSS_COMPILE}readelf ${FILE} --syms | grep "${SYMBOL}\$" || true) | SYM_INFO=$(${CROSS_COMPILE}readelf ${FILE} --syms | grep "${SYMBOL}\$" || true) | ||
Line 23: | Line 23: | ||
exit 1 | exit 1 | ||
fi | fi | ||
− | + | ||
# validate the symbols (it may have been present in more than one symbol table) | # validate the symbols (it may have been present in more than one symbol table) | ||
echo "${SYM_INFO}" | awk 'BEGIN{a=-1}{v=strtonum("0x"$2); if (a==-1) a=v; else if (a!=v) exit(1)}' || ( | echo "${SYM_INFO}" | awk 'BEGIN{a=-1}{v=strtonum("0x"$2); if (a==-1) a=v; else if (a!=v) exit(1)}' || ( | ||
Line 42: | Line 42: | ||
# get the number of 16-byte rows that this symbol spans | # get the number of 16-byte rows that this symbol spans | ||
− | SYM_ROWS_SPANNED=$(echo "${SYM_INFO}" | awk '{v=strtonum($3); printf("%d", (v | + | SYM_ROWS_SPANNED=$(echo "${SYM_INFO}" | awk '{v=strtonum($3); printf("%d", ((v - (v % 16)) / 16))}') |
+ | |||
+ | # get the section's full data | ||
+ | SECTION_DATA=$(${CROSS_COMPILE}readelf ${FILE} --hex-dump .rodata | tail -n +3 | head -n -1) | ||
+ | |||
+ | # get the alignment of the .rodata section with respect to the 16-byte boundary that we're working with | ||
+ | SECTION_ALIGNMENT=$(echo "${SECTION_DATA}" 2>/dev/null | head -n 1 | awk '{v=strtonum($1); printf("%d", (v % 16))}') | ||
+ | |||
+ | # adjust the symbol's aligned offset with the section's alignment | ||
+ | SYM_OFFSET_REALIGNED=$(echo "${SYM_OFFSET_ALIGNED} ${SECTION_ALIGNMENT}" | awk '{o=strtonum($1); a=strtonum($2); printf("0x%08x", o + a)}') | ||
# get the rows for the interesting region of the file | # get the rows for the interesting region of the file | ||
− | REGION_DATA=$(${CROSS_COMPILE}readelf ${FILE} --hex-dump .rodata | grep "${ | + | REGION_DATA=$(${CROSS_COMPILE}readelf ${FILE} --hex-dump .rodata | grep "${SYM_OFFSET_REALIGNED}" -A${SYM_ROWS_SPANNED} | cut -b14-48 | tr -d ' \n') |
# snip out the symbol's data | # snip out the symbol's data |
Revision as of 16:21, 15 October 2015
This script helps you extract the data associated with a symbol in a binary. Remember that the output here will not necessarily be correctly ordered (see Endianness).
#!/bin/bash -eu if [ -z ${CROSS_COMPILE+x} ]; then CROSS_COMPILE="" fi FILE=$1; shift SYMBOL=$1; shift if [ ! -e ${FILE} ]; then echo "File '${FILE}' does not exist..." >&2 exit 1 fi # get the symbol information SYM_INFO=$(${CROSS_COMPILE}readelf ${FILE} --syms | grep "${SYMBOL}\$" || true) if [ "${SYM_INFO}" == "" ]; then echo "Symbol '${SYMBOL}' does not exist..." >&2 exit 1 fi # validate the symbols (it may have been present in more than one symbol table) echo "${SYM_INFO}" | awk 'BEGIN{a=-1}{v=strtonum("0x"$2); if (a==-1) a=v; else if (a!=v) exit(1)}' || ( echo "Symbol '${SYMBOL}' has conflicting definitions..." >&2 echo "${SYM_INFO}" >&2 exit 1 ) SYM_INFO=$(echo "${SYM_INFO}" | head -n 1) # get the offset of the symbol's data (in hex), rounded down to the closes 16-byte boundary SYM_OFFSET_ALIGNED=$(echo "${SYM_INFO}" | awk '{v=strtonum("0x"$2); printf("0x%08x", v - (v % 16))}') # get the offset of the symbol's data (in decomal), into this 16-byte aligned data SYM_OFFSET_INTO_ALIGNED_DATA=$(echo "${SYM_INFO}" | awk '{v=strtonum("0x"$2); printf("%d", (v % 16) * 2)}') # get the size of the symbol's data (in decimal), as nibbles / hex digits SYM_SIZE_IN_NIBBLES=$(echo "${SYM_INFO}" | awk '{v=strtonum($3); printf "%d",v * 2}') # get the number of 16-byte rows that this symbol spans SYM_ROWS_SPANNED=$(echo "${SYM_INFO}" | awk '{v=strtonum($3); printf("%d", ((v - (v % 16)) / 16))}') # get the section's full data SECTION_DATA=$(${CROSS_COMPILE}readelf ${FILE} --hex-dump .rodata | tail -n +3 | head -n -1) # get the alignment of the .rodata section with respect to the 16-byte boundary that we're working with SECTION_ALIGNMENT=$(echo "${SECTION_DATA}" 2>/dev/null | head -n 1 | awk '{v=strtonum($1); printf("%d", (v % 16))}') # adjust the symbol's aligned offset with the section's alignment SYM_OFFSET_REALIGNED=$(echo "${SYM_OFFSET_ALIGNED} ${SECTION_ALIGNMENT}" | awk '{o=strtonum($1); a=strtonum($2); printf("0x%08x", o + a)}') # get the rows for the interesting region of the file REGION_DATA=$(${CROSS_COMPILE}readelf ${FILE} --hex-dump .rodata | grep "${SYM_OFFSET_REALIGNED}" -A${SYM_ROWS_SPANNED} | cut -b14-48 | tr -d ' \n') # snip out the symbol's data DATA=$(echo -n "${REGION_DATA}" | cut -b $((SYM_OFFSET_INTO_ALIGNED_DATA + 1))-$((SYM_OFFSET_INTO_ALIGNED_DATA + SYM_SIZE_IN_NIBBLES))) # print out the symbol's data... ## ... as hex digits #echo ${DATA} ## ... as raw binary data echo -n ${DATA} | sed -e "s/.\{2\}/&\n/g" | awk -b '{printf "%c", strtonum("0x"$0)}' ## ... rendered by hexdump #echo -n ${DATA} | sed -e "s/.\{2\}/&\n/g" | awk -b '{printf "%c", strtonum("0x"$0)}' | hexdump -C ## ... a nul-terminated C string (without the nul) #echo -n ${DATA} | sed -e "s/.\{2\}/&\n/g" | awk -b '{v=strtonum("0x"$0); if (v==0) exit(0); printf "%c", v}'
Example Usage
cat <<EOF | gcc -x c - -o eg const char my_data[] = "test string"; void main(void) {} EOF ./get_bin_info.sh eg my_data