#!/bin/bash # Converts little endian 4-byte unsigned integer given as spaced hex string # into decimal number (e.g. "00 D0 4C 00" -> 5033984) hex2dec() { # ATTENTION, 'strtonum' is gawk-specific, other awk versions like mawk # probably do not know it. echo "$1" | gawk '{ printf "%d\n", strtonum("0x" $4 $3 $2 $1) }' } extract_exe_start() { echo -e "Extracting executabel first part ..." exe_length=$kernel_start_at #echo "exe_length:$exe_length" output_file="$output_dir/exe_start" echo " exe_start, start @ 0, length: $exe_length" dd if="$input_file" of="$output_file" ibs=$exe_length obs=8192 count=1 2> /dev/null } extract_exe_end() { echo -e "Extracting executabel end part ..." act_size=`ls -l "$input_file" | sed -e 's/[^0-9]/#/g' | sed -e 's/#\+[0-9]\+#\+\([0-9]\+\).*/\1/'` offs=$((bootloder_start_at + bsize)) esize=$((act_size - offs)) output_file="$output_dir/exe_end" echo " exe_end, start @ $offs, length: $esize, end @ $act_size" ( dd of="/dev/null" ibs=$offs obs=8192 count=1 2> /dev/null && dd of="$output_file" ibs=$esize obs=8192 count=1 2> /dev/null ) < "$input_file" } extract_bootloader() { echo -e "Extracting bootloader (urlader.image) ..." output_file="$output_dir/urlader.image" act_end=$((bootloder_start_at + bsize)) echo " urlader.image, start @ $bootloder_start_at, length: $bsize, end @ $act_end" ( dd of="/dev/null" ibs=$bootloder_start_at obs=8192 count=1 2> /dev/null && dd of="$output_file" ibs=$bsize obs=8192 count=1 2> /dev/null ) < "$input_file" grep -iq 'entering passive mode' "$output_file" \ && grep -iq 'ftp server ready' "$output_file" \ && echo " file is a possible bootloader candidate" } extract_kernel_plus_mid() { echo -e "Extracting root kernel (kernel.image) ..." dd_count=$((kernel_end - kernel_start_at)) output_file="$output_dir/kernel.image" echo " kernel.image, start @ ${kernel_start_at}, length: $dd_count, end @ $kernel_end" ( dd of="/dev/null" ibs=$kernel_start_at obs=8192 count=1 2> /dev/null && dd of="$output_file" ibs=$dd_count obs=8192 count=1 2> /dev/null ) < "$input_file" output_file="$output_dir/exe_mid" echo " exe_mid, start @ $kernel_end, length: $psize, end @ $bootloder_start_at " ( dd of="/dev/null" ibs=$kernel_end obs=8192 count=1 2> /dev/null && dd of="$output_file" ibs=$psize obs=8192 count=1 2> /dev/null ) < "$input_file" #dd if="$output_file" bs=1 count=16 2> /dev/null | tr -d '[:alpha:]' | sed 's/-\.//' | sed 's/-//' OldRversion="$(dd if=$output_dir/exe_mid bs=1 count=32 2> /dev/null)" #get it directly OldRversion="$(echo $OldRversion | sed 's/\(.*[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/')" echo "Firmware version: $OldRversion" } # Extracts kernel.image candidates from input file, based on kernel and # SquashFS magic strings. # calculated from assumed length header field is close enough to subsequent # SquashFS start offset. # firmwares, but currently no other image types. ## did not work correctly, looks like it works again but is 6 byte shorter extract_kernel_image() { echo -e "Extracting kernel.image ..." kernel_lines="$(tools/hexgrep "$KERNEL_MAGIC" "$input_file")" #echo "kernel magic line: $kernel_lines" kernel_offs=($(echo "$kernel_lines" | sed 's/:.*//')) #echo "kernel offset: $kernel_offs" squashfs_lines="$(tools/hexgrep "$SQUASHFS_MAGIC" "$input_file")" #echo "squashfs magic line: $squashfs_lines" squashfs_offs=($(echo "$squashfs_lines" | sed 's/:.*//')) #echo "squashfs offset: $squashfs_offs" #echo -n "squashfs length in hex: " #echo "$squashfs_lines" | sed -r 's/^[0-9]+:.{24}(.*)/\1/' squashfs_length=($(hex2dec "$(echo "$squashfs_lines" | sed -r 's/^[0-9]+:.{24}(.*)/\1/')")) #echo "squashfs length in decimal: $squashfs_length" #ls -l "$input_file" act_size=`ls -l "$input_file" | sed -e 's/[^0-9]/#/g' | sed -e 's/#\+[0-9]\+#\+\([0-9]\+\).*/\1/'` #echo "File sizes: $act_size" dd_count=$((squashfs_offs - kernel_offs + squashfs_length)) ##older firmwaews used to have zerro bytes added #dd_count=$((((squashfs_offs - kernel_offs + squashfs_length) | 0xFFF)+1)) #echo "File sizes: $dd_count" output_file="$output_dir/kernel.image" echo " kernel.image, start @ ${kernel_offs}, SquashFS @ ${squashfs_offs}, length: $dd_count, end @ $act_size" ( dd of="/dev/null" ibs=$kernel_offs obs=8192 count=1 2> /dev/null && dd of="$output_file" ibs=$dd_count obs=8192 count=1 2> /dev/null ) < "$input_file" } # No exit 0 is used as incudefile