Get bin info.py

From Attie's Wiki
(Difference between revisions)
Jump to: navigation, search
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 * 16) - 1)}')
+
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 "${SYM_OFFSET_ALIGNED}" -A${SYM_ROWS_SPANNED} | cut -b14-48 | tr -d ' \n')
+
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
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox