Coding is a way of life

Code Repeats, Humans Compete

How to build a PWN environment on Mac

Posted at # Mac # PWN
  1. Download UTM and install it. You can use command
brew install --cask utm
  1. 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"