Skip to content

Commit 6b7b51c

Browse files
authored
Merge pull request #7 from h0tak88r/develop
Develop
2 parents 78a5cda + 8bfea83 commit 6b7b51c

13 files changed

Lines changed: 328 additions & 138 deletions

README.md

Lines changed: 70 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,31 @@ AutoAR is a comprehensive, modular security automation toolkit designed for bug
3434
- **File Sharing**: Automatic result file uploads
3535
- **Slash Commands**: Easy-to-use Discord commands
3636
- **Progress Tracking**: Real-time scan status updates
37+
- **Configurable Threading**: All tools support custom thread counts for optimal performance
3738

3839
### 🗄️ **Database Support**
3940
- **PostgreSQL Integration**: Full database support for results storage
4041
- **SQLite Fallback**: Lightweight database option
4142
- **Data Export**: Easy data export and analysis
4243
- **Result Management**: Organized result storage and retrieval
4344

45+
### **Performance & Threading**
46+
- **Configurable Threading**: All scanning tools support custom thread counts (default: 100)
47+
- **Parallel Processing**: Optimized for multi-core systems with concurrent operations
48+
- **Resource Management**: Intelligent thread allocation based on tool capabilities
49+
- **Performance Tuning**: Easy adjustment of thread counts via Discord commands or CLI flags
50+
51+
**Supported Tools with Threading:**
52+
- **Subdomain Enumeration**: Subfinder with configurable thread pools
53+
- **Live Host Detection**: Httpx with parallel HTTP probing
54+
- **Vulnerability Scanning**: Nuclei with concurrent template execution
55+
- **Port Scanning**: Naabu with high-speed parallel port discovery
56+
- **XSS Detection**: Dalfox with concurrent payload testing
57+
- **SQL Injection Testing**: SQLMap with Interlace for parallel testing
58+
- **Technology Detection**: Httpx with parallel technology fingerprinting
59+
- **URL Collection**: Urlfinder and JSFinder with concurrent crawling
60+
- **Backup File Discovery**: Fuzzuli with parallel backup file enumeration
61+
4462
## 🚀 Quick Start
4563

4664
### Docker Compose (Recommended)
@@ -119,18 +137,18 @@ python discord_bot.py
119137
Once the bot is running, use these slash commands in Discord:
120138

121139
#### Basic Reconnaissance
122-
- `/subdomains domain:example.com` - Enumerate subdomains
123-
- `/livehosts domain:example.com` - Find live hosts
140+
- `/subdomains domain:example.com [threads:100]` - Enumerate subdomains
141+
- `/livehosts domain:example.com [threads:100]` - Find live hosts
124142
- `/cnames domain:example.com` - Extract CNAME records
125-
- `/urls domain:example.com` - Collect URLs
126-
- `/tech domain:example.com` - Detect technologies
143+
- `/urls domain:example.com [threads:100]` - Collect URLs
144+
- `/tech domain:example.com [threads:100]` - Detect technologies
127145

128146
#### Vulnerability Scanning
129-
- `/nuclei domain:example.com` - Run Nuclei scans
147+
- `/nuclei domain:example.com [threads:100]` - Run Nuclei scans
130148
- `/wpdepconf domain:example.com` - WordPress plugin confusion
131-
- `/dalfox domain:example.com` - XSS detection
132-
- `/sqlmap domain:example.com` - SQL injection testing
133-
- `/backup domain:example.com` - Backup file discovery
149+
- `/dalfox domain:example.com [threads:100]` - XSS detection
150+
- `/sqlmap domain:example.com [threads:100]` - SQL injection testing
151+
- `/backup_scan domain:example.com [threads:100] [full:false]` - Backup file discovery
134152

135153
#### Specialized Scans
136154
- `/js domain:example.com` - JavaScript analysis
@@ -139,7 +157,7 @@ Once the bot is running, use these slash commands in Discord:
139157
- `/github-wordlist org:company` - Generate wordlists from GitHub org
140158
- `/s3 bucket:example-bucket` - S3 bucket scanning
141159
- `/dns domain:example.com` - DNS takeover detection
142-
- `/ports domain:example.com` - Port scanning
160+
- `/ports domain:example.com [threads:100]` - Port scanning
143161

144162
#### GitHub Reconnaissance
145163
- `/github scan repo:microsoft/PowerShell` - Scan specific repository for secrets
@@ -159,17 +177,20 @@ Access the container and use the CLI directly:
159177
# Enter the container
160178
docker exec -it autoar-bot bash
161179

162-
# Basic reconnaissance
163-
/app/main.sh subdomains get -d example.com
164-
/app/main.sh livehosts get -d example.com
180+
# Basic reconnaissance (with threading)
181+
/app/main.sh subdomains get -d example.com -t 100
182+
/app/main.sh livehosts get -d example.com -t 100
165183
/app/main.sh cnames get -d example.com
166-
/app/main.sh urls collect -d example.com
167-
168-
# Vulnerability scanning
169-
/app/main.sh nuclei run -d example.com
184+
/app/main.sh urls collect -d example.com -t 100
185+
/app/main.sh tech detect -d example.com -t 100
186+
187+
# Vulnerability scanning (with threading)
188+
/app/main.sh nuclei run -d example.com -t 100
189+
/app/main.sh dalfox run -d example.com -t 100
190+
/app/main.sh sqlmap run -d example.com -t 100
191+
/app/main.sh ports scan -d example.com -t 100
192+
/app/main.sh backup scan -d example.com -t 100 --full
170193
/app/main.sh wpDepConf scan -d example.com
171-
/app/main.sh dalfox run -d example.com
172-
/app/main.sh sqlmap run -d example.com
173194

174195
# Specialized scans
175196
/app/main.sh js scan -d example.com
@@ -274,6 +295,37 @@ GITHUB_TOKEN=your_github_personal_access_token
274295
- `read:org` - Read organization membership
275296
- `read:user` - Read user profile information
276297

298+
## ⚡ Threading Configuration
299+
300+
AutoAR supports configurable threading across all scanning tools for optimal performance:
301+
302+
### Discord Commands
303+
All Discord commands support optional `threads` parameter (default: 100):
304+
```
305+
/subdomains domain:example.com threads:200
306+
/nuclei domain:example.com threads:50
307+
/ports domain:example.com threads:500
308+
```
309+
310+
### CLI Commands
311+
All CLI commands support `-t` or `--threads` flag:
312+
```bash
313+
# High-performance scanning
314+
./modules/subdomains.sh get -d example.com -t 200
315+
./modules/nuclei.sh run -d example.com -t 50
316+
./modules/ports.sh scan -d example.com -t 500
317+
318+
# Conservative scanning (lower resource usage)
319+
./modules/subdomains.sh get -d example.com -t 25
320+
./modules/nuclei.sh run -d example.com -t 10
321+
```
322+
323+
### Performance Guidelines
324+
- **High-end systems**: 200-500 threads for maximum speed
325+
- **Standard systems**: 100 threads (default) for balanced performance
326+
- **Resource-constrained**: 25-50 threads to avoid overwhelming the system
327+
- **Network-limited**: Lower thread counts to avoid rate limiting
328+
277329
## 🔧 Configuration
278330

279331
### Environment Variables

discord_bot.py

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -447,25 +447,29 @@ async def github_wordlist(self, interaction: discord.Interaction, org: str,
447447
@app_commands.command(name="backup_scan", description="Discover backup files using Fuzzuli")
448448
@app_commands.describe(
449449
domain="Target domain to scan for backup files",
450-
threads="Number of threads (default: 10)",
451-
delay="Delay between requests in ms (default: 100)"
450+
threads="Number of threads (default: 100)",
451+
delay="Delay between requests in ms (default: 100)",
452+
full="Run full backup scan on all subdomains (default: False)"
452453
)
453454
async def backup_scan(self, interaction: discord.Interaction, domain: str,
454-
threads: int = 10, delay: int = 100):
455+
threads: int = 100, delay: int = 100, full: bool = False):
455456
"""Discover backup files using Fuzzuli."""
456457
scan_id = f"backup_{int(time.time())}"
457458

458459
command = [AUTOAR_SCRIPT_PATH, "backup", "scan", "-d", domain, "-t", str(threads), "--delay", str(delay)]
460+
if full:
461+
command.append("--full")
459462

463+
scan_type = 'backup_full' if full else 'backup'
460464
active_scans[scan_id] = {
461-
'type': 'backup',
465+
'type': scan_type,
462466
'target': domain,
463467
'status': 'running',
464468
'start_time': datetime.now(),
465469
'interaction': interaction
466470
}
467471

468-
embed = self.create_scan_embed('backup', domain, 'running')
472+
embed = self.create_scan_embed(scan_type, domain, 'running')
469473
await interaction.response.send_message(embed=embed)
470474

471475
# Run scan in background
@@ -588,10 +592,13 @@ async def scan_status(self, interaction: discord.Interaction):
588592
await interaction.response.send_message(embed=embed)
589593

590594
@app_commands.command(name="subdomains", description="Enumerate subdomains")
591-
@app_commands.describe(domain="The domain to enumerate")
592-
async def subdomains_cmd(self, interaction: discord.Interaction, domain: str):
595+
@app_commands.describe(
596+
domain="The domain to enumerate",
597+
threads="Number of threads for subfinder (default: 100)"
598+
)
599+
async def subdomains_cmd(self, interaction: discord.Interaction, domain: str, threads: int = 100):
593600
scan_id = f"subdomains_{int(time.time())}"
594-
command = [AUTOAR_SCRIPT_PATH, "subdomains", "get", "-d", domain]
601+
command = [AUTOAR_SCRIPT_PATH, "subdomains", "get", "-d", domain, "-t", str(threads)]
595602
active_scans[scan_id] = { 'type': 'subdomains', 'target': domain, 'status': 'running', 'start_time': datetime.now(), 'interaction': interaction }
596603
embed = self.create_scan_embed("Subdomains", domain, "running")
597604
await interaction.response.send_message(embed=embed)
@@ -608,20 +615,26 @@ async def cnames_cmd(self, interaction: discord.Interaction, domain: str):
608615
asyncio.create_task(self._run_scan_background(scan_id, command))
609616

610617
@app_commands.command(name="livehosts", description="Filter live hosts from subdomains")
611-
@app_commands.describe(domain="The domain")
612-
async def livehosts_cmd(self, interaction: discord.Interaction, domain: str):
618+
@app_commands.describe(
619+
domain="The domain",
620+
threads="Number of threads for httpx (default: 100)"
621+
)
622+
async def livehosts_cmd(self, interaction: discord.Interaction, domain: str, threads: int = 100):
613623
scan_id = f"live_{int(time.time())}"
614-
command = [AUTOAR_SCRIPT_PATH, "livehosts", "get", "-d", domain]
624+
command = [AUTOAR_SCRIPT_PATH, "livehosts", "get", "-d", domain, "-t", str(threads)]
615625
active_scans[scan_id] = { 'type': 'live', 'target': domain, 'status': 'running', 'start_time': datetime.now(), 'interaction': interaction }
616626
embed = self.create_scan_embed("Live Hosts", domain, "running")
617627
await interaction.response.send_message(embed=embed)
618628
asyncio.create_task(self._run_scan_background(scan_id, command))
619629

620630
@app_commands.command(name="urls", description="Collect URLs and JS URLs")
621-
@app_commands.describe(domain="The domain")
622-
async def urls_cmd(self, interaction: discord.Interaction, domain: str):
631+
@app_commands.describe(
632+
domain="The domain",
633+
threads="Number of threads for urlfinder and jsfinder (default: 100)"
634+
)
635+
async def urls_cmd(self, interaction: discord.Interaction, domain: str, threads: int = 100):
623636
scan_id = f"urls_{int(time.time())}"
624-
command = [AUTOAR_SCRIPT_PATH, "urls", "collect", "-d", domain]
637+
command = [AUTOAR_SCRIPT_PATH, "urls", "collect", "-d", domain, "-t", str(threads)]
625638
active_scans[scan_id] = { 'type': 'urls', 'target': domain, 'status': 'running', 'start_time': datetime.now(), 'interaction': interaction }
626639
embed = self.create_scan_embed("URLs", domain, "running")
627640
await interaction.response.send_message(embed=embed)
@@ -640,30 +653,39 @@ async def reflection_cmd(self, interaction: discord.Interaction, domain: str):
640653
asyncio.create_task(self._run_scan_background(scan_id, command))
641654

642655
@app_commands.command(name="nuclei", description="Run nuclei templates on live subdomains")
643-
@app_commands.describe(domain="The domain")
644-
async def nuclei_cmd(self, interaction: discord.Interaction, domain: str):
656+
@app_commands.describe(
657+
domain="The domain",
658+
threads="Number of threads for nuclei (default: 100)"
659+
)
660+
async def nuclei_cmd(self, interaction: discord.Interaction, domain: str, threads: int = 100):
645661
scan_id = f"nuclei_{int(time.time())}"
646-
command = [AUTOAR_SCRIPT_PATH, "nuclei", "run", "-d", domain]
662+
command = [AUTOAR_SCRIPT_PATH, "nuclei", "run", "-d", domain, "-t", str(threads)]
647663
active_scans[scan_id] = { 'type': 'nuclei', 'target': domain, 'status': 'running', 'start_time': datetime.now(), 'interaction': interaction }
648664
embed = self.create_scan_embed("Nuclei", domain, "running")
649665
await interaction.response.send_message(embed=embed)
650666
asyncio.create_task(self._run_scan_background(scan_id, command))
651667

652668
@app_commands.command(name="tech", description="Detect technologies on live hosts")
653-
@app_commands.describe(domain="The domain")
654-
async def tech_cmd(self, interaction: discord.Interaction, domain: str):
669+
@app_commands.describe(
670+
domain="The domain",
671+
threads="Number of threads for httpx (default: 100)"
672+
)
673+
async def tech_cmd(self, interaction: discord.Interaction, domain: str, threads: int = 100):
655674
scan_id = f"tech_{int(time.time())}"
656-
command = [AUTOAR_SCRIPT_PATH, "tech", "detect", "-d", domain]
675+
command = [AUTOAR_SCRIPT_PATH, "tech", "detect", "-d", domain, "-t", str(threads)]
657676
active_scans[scan_id] = { 'type': 'tech', 'target': domain, 'status': 'running', 'start_time': datetime.now(), 'interaction': interaction }
658677
embed = self.create_scan_embed("Tech Detect", domain, "running")
659678
await interaction.response.send_message(embed=embed)
660679
asyncio.create_task(self._run_scan_background(scan_id, command))
661680

662681
@app_commands.command(name="ports", description="Run port scan (naabu) on live hosts")
663-
@app_commands.describe(domain="The domain")
664-
async def ports_cmd(self, interaction: discord.Interaction, domain: str):
682+
@app_commands.describe(
683+
domain="The domain",
684+
threads="Number of threads for naabu (default: 100)"
685+
)
686+
async def ports_cmd(self, interaction: discord.Interaction, domain: str, threads: int = 100):
665687
scan_id = f"ports_{int(time.time())}"
666-
command = [AUTOAR_SCRIPT_PATH, "ports", "scan", "-d", domain]
688+
command = [AUTOAR_SCRIPT_PATH, "ports", "scan", "-d", domain, "-t", str(threads)]
667689
active_scans[scan_id] = { 'type': 'ports', 'target': domain, 'status': 'running', 'start_time': datetime.now(), 'interaction': interaction }
668690
embed = self.create_scan_embed("Ports", domain, "running")
669691
await interaction.response.send_message(embed=embed)
@@ -680,20 +702,26 @@ async def gf_cmd(self, interaction: discord.Interaction, domain: str):
680702
asyncio.create_task(self._run_scan_background(scan_id, command))
681703

682704
@app_commands.command(name="sqlmap", description="Run SQLMap on GF SQLi results")
683-
@app_commands.describe(domain="The domain")
684-
async def sqlmap_cmd(self, interaction: discord.Interaction, domain: str):
705+
@app_commands.describe(
706+
domain="The domain",
707+
threads="Number of threads for sqlmap (default: 100)"
708+
)
709+
async def sqlmap_cmd(self, interaction: discord.Interaction, domain: str, threads: int = 100):
685710
scan_id = f"sqlmap_{int(time.time())}"
686-
command = [AUTOAR_SCRIPT_PATH, "sqlmap", "run", "-d", domain]
711+
command = [AUTOAR_SCRIPT_PATH, "sqlmap", "run", "-d", domain, "-t", str(threads)]
687712
active_scans[scan_id] = { 'type': 'sqlmap', 'target': domain, 'status': 'running', 'start_time': datetime.now(), 'interaction': interaction }
688713
embed = self.create_scan_embed("SQLMap", domain, "running")
689714
await interaction.response.send_message(embed=embed)
690715
asyncio.create_task(self._run_scan_background(scan_id, command))
691716

692717
@app_commands.command(name="dalfox", description="Run Dalfox XSS scan")
693-
@app_commands.describe(domain="The domain")
694-
async def dalfox_cmd(self, interaction: discord.Interaction, domain: str):
718+
@app_commands.describe(
719+
domain="The domain",
720+
threads="Number of threads for dalfox (default: 100)"
721+
)
722+
async def dalfox_cmd(self, interaction: discord.Interaction, domain: str, threads: int = 100):
695723
scan_id = f"dalfox_{int(time.time())}"
696-
command = [AUTOAR_SCRIPT_PATH, "dalfox", "run", "-d", domain]
724+
command = [AUTOAR_SCRIPT_PATH, "dalfox", "run", "-d", domain, "-t", str(threads)]
697725
active_scans[scan_id] = { 'type': 'dalfox', 'target': domain, 'status': 'running', 'start_time': datetime.now(), 'interaction': interaction }
698726
embed = self.create_scan_embed("Dalfox", domain, "running")
699727
await interaction.response.send_message(embed=embed)
@@ -865,7 +893,10 @@ async def _run_scan_background(self, scan_id: str, command: list):
865893
elif any(cmd in command for cmd in ['github-wordlist']):
866894
timeout = 900 # 15 minutes for GitHub wordlist generation
867895
elif any(cmd in command for cmd in ['backup']):
868-
timeout = 600 # 10 minutes for backup scans
896+
if '--full' in command:
897+
timeout = 1200 # 20 minutes for full backup scans (includes subdomain collection)
898+
else:
899+
timeout = 600 # 10 minutes for regular backup scans
869900
elif any(cmd in command for cmd in ['depconfusion']):
870901
timeout = 1200 # 20 minutes for dependency confusion scans
871902
elif any(cmd in command for cmd in ['live-depconfusion']):

0 commit comments

Comments
 (0)