2

I'm trying to detect the bitness (32 or 64 bit) of an ELF binary in the bash shell of an android device.

I don't have file, objdump or readelf, which are the obvious answers on a real Linux system. Additionally, I don't have head, tail, sed, awk, grep or perl.

I've seen in the ELF header description that the e_ident[EI_CLASS] field of the binary header should contain a byte which describes the bitness. Maybe I could use that? But I'm having trouble teasing that byte out of the file with such a limited toolset.

kb0
  • 522
  • 3
  • 8

3 Answers3

2

Thanks to Charles Duffy's answer to How do I read first line using cat, I found a way to read only the bytes I needed out of the file:

$ # Read 5 bytes of the 'adb' binary.    
$ read -r -n 5 elf_header < /system/bin/adb; echo $elf_header | cat -v
^?ELF^A

If the 7th character of that output is "A", then the binary is 32-bit. If it's "B", then 64-bit.

Community
  • 1
  • 1
kb0
  • 522
  • 3
  • 8
1

https://en.wikipedia.org/wiki/Executable_and_Linkable_Format

head -c 20 ${executable} | tail -c 2 will get you the 2 bytes for e_machine. Then you can do further processing on that. Eg, x86 may be either 32-bit or 64-bit while x86-64 is 64-bit.

Alternatively, if you're specifically looking for the bitness of the ELF container (as opposed to the executable code), which implies the requirements of the code, you might try looking at e_ident[EI_CLASS]:

head -c 5 ${executable} | tail -c 1. If the byte is 0x01, it's 32 bit. If it's 0x02, it's 64 bit. If it's anything else, it's undefined at this time.

Edit: Recommended reading (hehe pun intended) describes the difference between -n and -N.

So without the use of head and tail, this would be better: read -r -N 5 elf_header < ${executable} && echo -n "${elf_header:4:1}"

At this point, the single character that was echoed to stdout would be "\\x1" for 32-bit and "\\x2" for 64-bit. In a more complete linux environment you can pass that through xxd to see a hex dump. You can check the bit with this 1-liner:

bitness32=$(printf "\\x1") && bitness64=$(printf "\\x2") && read -r -N 5 elf_header < ~/a.out && elf_bitness="${elf_header:4:1}" && { [[ "${bitness32}" == "${elf_bitness}" ]] && echo "32-bit"; } || { [[ "${bitness64}" == "${elf_bitness}" ]] && echo "64-bit"; } || { echo "???"; }

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
inetknght
  • 4,300
  • 1
  • 26
  • 52
  • This looks cleaner than the read solution, but I can't rely on my android shell having `head` and `tail`. – kb0 Apr 12 '16 at 23:43
1

Using printf and dd:

#!/bin/sh

elf32="$(printf "\177ELF\001")"
elf64="$(printf "\177ELF\002")"
header="$(dd bs=5 seek=0 count=1 "if=$1" 2> /dev/null)"

case "$header" in
    "$elf32") echo ELF32 ;;
    "$elf64") echo ELF64 ;;
    *)        exit 1 ;;
esac
ysdx
  • 8,889
  • 1
  • 38
  • 51