Skip to content

Instantly share code, notes, and snippets.

@socram8888
Created July 13, 2015 15:05
Show Gist options
  • Save socram8888/03c5da015e0f9ce83ee5 to your computer and use it in GitHub Desktop.
Save socram8888/03c5da015e0f9ce83ee5 to your computer and use it in GitHub Desktop.
3DS NATIVE_FIRM unpacker
#!/bin/bash -e
odbin() {
od --output-duplicates --address=none --endian=little $*
}
rdu32() {
odbin --format d4 --skip-bytes "$2" --read-bytes 4 "$1" | tr -c -d [:digit:]
}
rdu32hex() {
printf 0x%08X $(rdu32 "$1" "$2")
}
rdhex() {
odbin --format x1 --skip-bytes "$2" --read-bytes "$3" "$1" | tr -c -d [:xdigit:]
}
if [ $# != 2 ]; then
echo "Usage: $0 firm.bin outdir" 2>&1
exit 1
fi
FIRM="$1"
OUTDIR="$2"
if [ ! -f "$FIRM" ]; then
echo "Firmware file not found"
exit 2
fi
if [ ! -d "$OUTDIR" ]; then
mkdir "$OUTDIR"
fi
MAGIC=$(rdu32hex "$FIRM" 0x000)
echo "FIRM magic: $MAGIC"
if [ $MAGIC != 0x4D524946 ]; then
echo "Invalid magic (expected 0x4D524946)"
exit 3
fi
ARM11EP=$(rdu32hex "$FIRM" 0x008)
echo "ARM11 entry point: $ARM11EP"
ARM9EP=$(rdu32hex "$FIRM" 0x00C)
echo "ARM9 entry point: $ARM9EP"
echo
for SECID in 0 1 2 3; do
echo "Section $SECID:"
SECBASE=$((0x040 + $SECID * 0x30))
SECOFF=$(rdu32hex "$FIRM" $(($SECBASE + 0x000)))
echo " - File offset: $SECOFF"
SECADDR=$(rdu32hex "$FIRM" $(($SECBASE + 0x004)))
echo " - Load address: $SECADDR"
SECSIZE=$(rdu32 "$FIRM" $(($SECBASE + 0x008)))
echo " - Size: $SECSIZE"
if [ $SECSIZE -eq 0 ]; then
continue
fi
SECTYPE=$(rdu32 "$FIRM" $(($SECBASE + 0x00C)))
echo -n " - Type: $SECTYPE "
case $SECTYPE in
0)
echo "(ARM9)"
;;
1)
echo "(ARM11)"
;;
*)
echo "(unknown)"
esac
SECSHA=$(rdhex "$FIRM" $(($SECBASE + 0x010)) 32)
echo " - SHA256: $SECSHA"
SECFILE="$OUTDIR/sec$SECID.bin"
dd if="$FIRM" of="$SECFILE" skip=$(($SECOFF)) count=$SECSIZE iflag=count_bytes,skip_bytes status=none
echo "$SECSHA *$SECFILE" | sha256sum --check --quiet
echo
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment