Skip to content

Instantly share code, notes, and snippets.

@themactep
Last active February 15, 2024 00:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • 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 <paul@themactep.com>
# 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
if [ -z "$1" ]; then
echo "Usage: $0 <stock firmware dump>"
exit 1
fi
full_binary_file="$1"
bootcmd=$(strings "$full_binary_file" | grep 'mtdparts=' | 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
mtdparts=$(echo $bootcmd | sed -E "s/(.*)(mtdparts=)/\\2/" | cut -d ' ' -f 1 | cut -d: -f2)
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 found in Goke U-Boot
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
### extract rootfs partition from full dump
dd if="$full_binary_file" bs=1 skip=$rootfs_offset count=$rootfs_size of="$rootfs_file" status=progress
### unpack rootfs partition
unsquashfs "$rootfs_file"
### replace password
echo "root::0:0:root:/root:/bin/sh" > $(find squashfs-root -name passwd | grep etc)
### enable console
sed -i 's/^#console:/console:/' $(find squashfs-root -name inittab | grep etc)
### repack rootfs partition
new_rootfs_file="${rootfs_file}-patched"
mksquashfs squashfs-root "$new_rootfs_file" -comp xz
### make sure new rootfs fits the partition
new_rootfs_size=$(stat -c %s "$new_rootfs_file")
if [ $new_rootfs_size -gt $rootfs_size ]; then
echo "Repacked file is larger than available partition!"
exit 2
fi
### make a patched copy of full binary
new_full_binary_file="${full_binary_file}-patched"
cp "$full_binary_file" "$new_full_binary_file"
tmp_file=$(mktemp)
dd if=/dev/zero bs=$rootfs_size count=1 | tr '\000' '\377' > "$tmp_file"
dd if="$tmp_file" bs=1 seek=$rootfs_offset count=$rootfs_size of="$new_full_binary_file" conv=notrunc status=progress
dd if="$new_rootfs_file" bs=1 seek=$rootfs_offset count=$new_rootfs_size of="$new_full_binary_file" conv=notrunc status=progress
### clean up mess
rm -r squashfs-root
rm -r "$rootfs_file"
rm -r "$new_rootfs_file"
rm "$tmp_file"
echo "Done"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment