Last active
June 14, 2026 19:36
-
-
Save hed0rah/a6e16941b73b7182ad7c71699aaf4869 to your computer and use it in GitHub Desktop.
hand rolled namespace container
This file contains hidden or 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
| #!/usr/bin/env bash | |
| # | |
| # hovercraft.sh - Build an ultra-stripped BusyBox from scratch, | |
| # populate a minimal rootfs, and pivot into an isolated namespace. | |
| # | |
| set -euo pipefail | |
| ROOT="${1:-/tmp/handroll-rootfs}" | |
| HOSTNAME_IN="earth" | |
| CR=$'\r' | |
| if [[ $EUID -ne 0 ]]; then | |
| echo "must run as root (sudo)" >&2 | |
| exit 1 | |
| fi | |
| # --------------------------------------------------------------------------- | |
| # 1. Fetch and compile an ultra-stripped static BusyBox | |
| # --------------------------------------------------------------------------- | |
| echo "[*] Downloading BusyBox source via OpenSSL..." | |
| openssl s_client -connect busybox.net:443 -quiet 2>/dev/null <<EOF | sed '1,/^\r$/d' > busybox-1.38.0.tar.bz2 | |
| GET /downloads/busybox-1.38.0.tar.bz2 HTTP/1.1${CR} | |
| Host: busybox.net${CR} | |
| Connection: close${CR} | |
| ${CR} | |
| EOF | |
| echo "[*] Extracting source..." | |
| tar -xjf busybox-1.38.0.tar.bz2 | |
| cd busybox-1.38.0 | |
| echo "[*] Configuring minimal applet profile..." | |
| make allnoconfig | |
| for applet in ASH SH_IS_ASH LS CAT ECHO PWD \ | |
| MOUNT UMOUNT HOSTNAME IFCONFIG ROUTE \ | |
| MKDIR LN INIT HALT REBOOT POWEROFF; do | |
| sed -i "s/# CONFIG_$applet is not set/CONFIG_$applet=y/" .config | |
| done | |
| sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config | |
| sed -i 's/# CONFIG_STRIP is not set/CONFIG_STRIP=y/' .config | |
| sed -i 's/# CONFIG_BUILD_OPTIMIZED_FOR_SIZE is not set/CONFIG_BUILD_OPTIMIZED_FOR_SIZE=y/' .config | |
| make silentoldconfig | |
| make -j"$(nproc)" | |
| BUSYBOX="$(pwd)/busybox" | |
| cd .. | |
| # --------------------------------------------------------------------------- | |
| # 2. Directory skeleton creation | |
| # --------------------------------------------------------------------------- | |
| echo "[*] building rootfs skeleton at $ROOT" | |
| rm -rf "$ROOT" | |
| mkdir -p "$ROOT"/{bin,sbin,etc,proc,sys,dev,tmp,root,run,var,usr/bin,usr/sbin,home} | |
| mkdir -p "$ROOT"/dev/{pts,shm} | |
| mkdir -p "$ROOT"/var/{log,tmp} | |
| mkdir -p "$ROOT"/.oldroot | |
| chmod 1777 "$ROOT"/tmp "$ROOT"/var/tmp "$ROOT"/dev/shm | |
| # --------------------------------------------------------------------------- | |
| # 3. Populate applet symlinks | |
| # --------------------------------------------------------------------------- | |
| echo "[*] installing busybox and applet symlinks" | |
| cp "$BUSYBOX" "$ROOT/bin/busybox" | |
| chmod 755 "$ROOT/bin/busybox" | |
| while read -r applet; do | |
| [[ -z "$applet" ]] && continue | |
| ln -sf busybox "$ROOT/bin/$applet" | |
| done < <("$ROOT/bin/busybox" --list 2>/dev/null) | |
| ln -sf busybox "$ROOT/bin/sh" | |
| for s in init halt reboot poweroff ip ifconfig route; do | |
| ln -sf ../bin/busybox "$ROOT/sbin/$s" 2>/dev/null || true | |
| done | |
| # --------------------------------------------------------------------------- | |
| # 4. /etc account database setup | |
| # --------------------------------------------------------------------------- | |
| echo "[*] writing accounts database" | |
| cat > "$ROOT/etc/passwd" <<'EOF' | |
| root:x:0:0:root:/root:/bin/sh | |
| daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin | |
| bin:x:2:2:bin:/bin:/usr/sbin/nologin | |
| sys:x:3:3:sys:/dev:/usr/sbin/nologin | |
| sync:x:4:65534:sync:/bin:/bin/sync | |
| games:x:5:60:games:/usr/games:/usr/sbin/nologin | |
| man:x:6:12:man:/var/cache/man:/usr/sbin/nologin | |
| lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin | |
| mail:x:8:8:mail:/var/mail:/usr/sbin/nologin | |
| news:x:9:9:news:/var/spool/news:/usr/sbin/nologin | |
| uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin | |
| proxy:x:13:13:proxy:/bin:/usr/sbin/nologin | |
| www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin | |
| backup:x:34:34:backup:/var/backups:/usr/sbin/nologin | |
| list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin | |
| irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin | |
| nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin | |
| EOF | |
| cat > "$ROOT/etc/group" <<'EOF' | |
| root:x:0: | |
| daemon:x:1: | |
| bin:x:2: | |
| sys:x:3: | |
| adm:x:4: | |
| tty:x:5: | |
| disk:x:6: | |
| lp:x:7: | |
| mail:x:8: | |
| news:x:9: | |
| uucp:x:10: | |
| man:x:12: | |
| proxy:x:13: | |
| kmem:x:15: | |
| dialout:x:20: | |
| fax:x:21: | |
| voice:x:22: | |
| cdrom:x:24: | |
| floppy:x:25: | |
| tape:x:26: | |
| sudo:x:27: | |
| audio:x:29: | |
| games:x:60: | |
| users:x:100: | |
| www-data:x:33: | |
| backup:x:34: | |
| list:x:38: | |
| irc:x:39: | |
| nogroup:x:65534: | |
| EOF | |
| # --------------------------------------------------------------------------- | |
| # 5. Hostname & Network Configuration | |
| # --------------------------------------------------------------------------- | |
| echo "[*] writing minimal network configs" | |
| echo "$HOSTNAME_IN" > "$ROOT/etc/hostname" | |
| cat > "$ROOT/etc/hosts" <<EOF | |
| 127.0.0.1 localhost | |
| ::1 localhost ip6-localhost ip6-loopback | |
| 127.1.1.1 $HOSTNAME_IN | |
| EOF | |
| # --------------------------------------------------------------------------- | |
| # 6. The Execution Payload (Runs INSIDE the new namespaces) | |
| # --------------------------------------------------------------------------- | |
| cat > "$ROOT/rc.container" <<'EOF' | |
| #!/bin/sh | |
| set -eu | |
| mount -t proc proc /proc | |
| mount -t sysfs sysfs /sys | |
| mount -t devtmpfs devtmpfs /dev 2>/dev/null || mount -t tmpfs devtmpfs /dev | |
| mkdir -p /dev/pts /dev/shm | |
| mount -t devpts devpts /dev/pts | |
| mount -t tmpfs shm /dev/shm | |
| ifconfig lo 127.0.0.1 up | |
| export PATH=/bin:/sbin:/usr/bin:/usr/sbin | |
| export HOME=/root | |
| export TERM=xterm-256color | |
| # Fix terminal environment and inject raw colors for the screenshot | |
| alias ls='ls --color=auto' | |
| export PS1='\[\033[38;5;36m\]04:20:00 \[\033[38;5;36m\]earth\[\033[38;5;202m\]☠\[\033[38;5;36m\][\w]\[\033[38;5;202m\] # \[\033[0m\]' | |
| echo "====================================================" | |
| echo " Welcome to the Panopticon. Everyone is Root. " | |
| echo "====================================================" | |
| exec /bin/sh | |
| EOF | |
| chmod +x "$ROOT/rc.container" | |
| # --------------------------------------------------------------------------- | |
| # 7. Unshare, Pivot, and Execute | |
| # --------------------------------------------------------------------------- | |
| echo "[*] launching container via unshare + pivot_root..." | |
| unshare -m -u -i -p -f bash -c " | |
| mount --bind '$ROOT' '$ROOT' | |
| cd '$ROOT' | |
| pivot_root . .oldroot | |
| umount -l /.oldroot | |
| hostname '$HOSTNAME_IN' | |
| exec /rc.container | |
| " |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment