Skip to content

Instantly share code, notes, and snippets.

@themactep
Last active July 10, 2024 08:24
Show Gist options
  • Save themactep/237d98ce45b9fe71d794b20edaa15baa to your computer and use it in GitHub Desktop.
Save themactep/237d98ce45b9fe71d794b20edaa15baa to your computer and use it in GitHub Desktop.
Repack firmware with a blank root password.
#!/bin/bash
#
# Embedded Linux root hijacker
#
# This script repacks firmware replacing existing root password with a blank password.
# Tested on HiSilicon and Ingenic firmware dumps from NOR SPI flash chips.
# Use at your own risk.
#
# Paul Philppov <[email protected]>
# 2023-11-21: Initial release
# 2023-11-25: Handle hexadecimal values in mtdparts
# 2024-01-26: Use the last found copy of mtdparts
# 2024-02-14: Enable disabled console
# 2024-05-14: Fix false-positive matches
# 2024-07-08: Start telnet
# 2024-07-10: Refactor and colorize output
if [ -z "$1" ]; then
echo "Usage: $0 <stock firmware dump>"
exit 1
fi
echo_c() {
echo -e "\e[38;5;$1m$2\e[0m"
}
die() {
echo_c 124 "Error! $1"
exit 1
}
run() {
echo_c 94 "$1"
eval $1
}
say() {
echo_c 70 "\n$1"
}
full_binary_file="$1"
bootcmd=$(strings "$full_binary_file" | grep -E "mtdparts=\w+_sfc:" | tail -1)
root_part_num=$(echo $bootcmd | sed -E "s/(.*)(root=)/\\2/" | cut -d ' ' -f 1 | cut -d '=' -f 2 | sed -E "s/.*(.)/\\1/")
offset_bytes=0
say "looking for mtd partitions"
mtdparts=$(echo $bootcmd | sed -E "s/(.*)(mtdparts=)/\\2/" | cut -d ' ' -f 1 | cut -d: -f2)
say "Found this: $mtdparts"
for p in ${mtdparts//,/ }; do
p_size=$(echo $p | cut -d '(' -f 1)
if [ "-" = "$p_size" ]; then
p_size_bytes=""
elif [ "0x" = "${p_size:0:2}" ]; then
## convert hex values
p_size_bytes=$(( $p_size ))
else
p_size_value=$(echo $p_size | sed -E 's/[^0-9]//g')
p_size_unit=$(echo $p_size | sed -E 's/[0-9]+//')
if [ "k" = "${p_size_unit,,}" ]; then
p_size_bytes=$(( p_size_value * 1024 ))
elif [ "m" = "${p_size_unit,,}" ]; then
p_size_bytes=$(( p_size_value * 1024 * 1024 ))
else
p_size_bytes=$p_size_value
fi
fi
printf "%-14s\toffset: %8d\tsize: %8d\n" $p $offset_bytes $p_size_bytes
if [ "$n" = "$root_part_num" ]; then
echo "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
rootfs_file=rootfs.bin
rootfs_offset=$offset_bytes
rootfs_size=$p_size_bytes
fi
offset_bytes=$(( offset_bytes + p_size_bytes ))
n=$(( n + 1 ))
done
say "extract rootfs partition from full dump: $rootfs_size bytes at offset $rootfs_offset"
run "dd if=$full_binary_file bs=1 skip=$rootfs_offset count=$rootfs_size of=$rootfs_file status=progress"
say "unpack rootfs partition"
run "unsquashfs $rootfs_file || die Unable to unpack rootfs!"
say "replace password"
run "echo \"root::0:0:root:/root:/bin/sh\" > $(find squashfs-root -name passwd | grep etc)"
say "enable console"
run "sed -i 's/^#console:/console:/' $(find squashfs-root -name inittab | grep etc)"
say "activate telnet"
run "echo 'telnetd' >> $(find squashfs-root -name rcS)"
say "repack rootfs partition"
new_rootfs_file="${rootfs_file}-patched"
run "mksquashfs squashfs-root $new_rootfs_file -comp xz"
say "make sure new rootfs fits the partition"
new_rootfs_size=$(stat -c %s "$new_rootfs_file")
[ $new_rootfs_size -gt $rootfs_size ] && die "repacked file is larger than available partition!"
say "echo make a patched copy of full binary"
new_full_binary_file="${full_binary_file}-patched"
run "cp $full_binary_file $new_full_binary_file"
say "assemble new firmware"
tmp_file=$(mktemp)
run "dd if=/dev/zero bs=$rootfs_size count=1 | tr '\000' '\377' > $tmp_file"
run "dd if=$tmp_file bs=1 seek=$rootfs_offset count=$rootfs_size of=$new_full_binary_file conv=notrunc status=progress"
run "dd if=$new_rootfs_file bs=1 seek=$rootfs_offset count=$new_rootfs_size of=$new_full_binary_file conv=notrunc status=progress"
say "clean up the mess"
run "rm -rf squashfs-root"
run "rm -rf $rootfs_file"
run "rm -rf $new_rootfs_file"
run "rm -f $tmp_file"
say "Done!"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment