How to build a PWN environment on Mac
- Download UTM and install it. You can use command
brew install --cask utm
- Download the image form https://releases.ubuntu.com/22.04/ and install it.
Then install gdb server by running the command
sudo apt install gdbserver
if you wan to debug some executable file for 32 bit, then you must run the command:
sudo dpkg --add-architecture i386
sudo apt update
sudo apt install libc6:i386 libncurses5:i386 libstdc++6:i386
After the environment setup, you could use
gdbserver :1234 ./test
on the ubuntu machine, and on the mac you can running command
gdb ./test \
-ex "target extended-remote 192.168.64.13:1234"
replace the ip adress and port
on the mac, you type
gdb ./pwn101-1644307211706.pwn101 \
-ex "target extended-remote gdbserver.local:1234" \
-ex "set remote exec-file /home/gdb/pwn101-1644307211706.pwn101" \
-ex "break main"
PS: the target extended-remote 192.168.64.13:1234
must be the first line, or it won’t affect.
you also can use pwndbg to run the debugger on the mac.
if you wan to disable ASLR, you can use
sudo sysctl -w kernel.randomize_va_space=0
for temporarily disable it, or permanently disalbe ASLR.
echo "kernel.randomize_va_space = 0" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
if you want to access this machine via domain service, like gdbserver.local
, you need to install avahi-daemin
sudo apt install avahi-daemon
sudo systemctl enable avahi-daemon
sudo systemctl start avahi-daemon
This is a script, it would automatically upload the file which you want to debug to the remote server.
you can save it as rdbg
at /usr/local/bin/
, and use it like
rdb pwn_test --host gdbserver.local --port 1234
#!/usr/bin/env bash
# Usage:
# ./debug.sh <local-path-to-binary> [--host <remote-host>] [--port <port>]
# Example:
# ./debug.sh ./vuln --host gdbserver.local --port 1234
set -e
# ====== Argument Parsing ======
if [ $# -lt 1 ]; then
echo "Usage: $0 <local-path-to-binary> [--host <remote-host>] [--port <port>]"
exit 1
fi
# Default values
REMOTE_USER="dbg"
REMOTE_HOST="gdbserver.local"
PORT=1234
# Extract the first non-flag argument as the local file
LOCAL_FILE=""
POSITIONAL_ARGS=()
for ((i=1; i<=$#; i++)); do
arg="${!i}"
case "$arg" in
--host)
((i++))
REMOTE_HOST="${!i}"
;;
--port)
((i++))
PORT="${!i}"
;;
--help|-h)
echo "Usage: $0 <local-path-to-binary> [--host <remote-host>] [--port <port>]"
exit 0
;;
-*)
echo "Unknown option: $arg"
exit 1
;;
*)
if [ -z "$LOCAL_FILE" ]; then
LOCAL_FILE="$arg"
else
POSITIONAL_ARGS+=("$arg")
fi
;;
esac
done
# Validate local file
if [ ! -f "$LOCAL_FILE" ]; then
echo "Error: File '$LOCAL_FILE' not found."
exit 1
fi
# Remote path
REMOTE_DIR="/home/$REMOTE_USER/pwn"
FILENAME=$(basename "$LOCAL_FILE")
# Upload
# Calculate local file hash
LOCAL_HASH=$(sha256sum "$LOCAL_FILE" | cut -d ' ' -f1)
# Get remote file hash (if exists)
REMOTE_HASH=$(ssh "$REMOTE_USER@$REMOTE_HOST" "sha256sum '$REMOTE_DIR/$FILENAME' 2>/dev/null | cut -d ' ' -f1 || true")
if [ "$LOCAL_HASH" == "$REMOTE_HASH" ]; then
echo "[✓] Remote file is identical to local file. Skipping upload."
else
echo "[*] Uploading updated file to $REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR ..."
scp "$LOCAL_FILE" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/"
fi
# Start pwndbg
echo "[*] Starting GDB with remote target $REMOTE_HOST:$PORT ..."
pwndbg -ex "file $LOCAL_FILE" \
-ex "target extended-remote ${REMOTE_HOST}:${PORT}" \
-ex "set remote exec-file $REMOTE_DIR/$FILENAME" \
-ex "break main"