Last active
February 15, 2024 00:42
-
-
Save themactep/237d98ce45b9fe71d794b20edaa15baa to your computer and use it in GitHub Desktop.
Repack firmware with a blank root password.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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