Skip to content

Commit b7e76b9

Browse files
committed
Release v4.3.0: Massive Power Boost & Code Organization
1 parent fbaaa0f commit b7e76b9

9 files changed

Lines changed: 223 additions & 238 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
.PHONY: build clean
22

33
APP_NAME=netscope
4-
VERSION=4.1.1
4+
VERSION=4.3.0
55

66
build:
77
go build -ldflags "-s -w -X main.version=${VERSION}" -o ${APP_NAME} *.go

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
# NetScope (v4.1.1)
1+
# NetScope (v4.3.0)
22
Formerly known as Lucas Kit, UltraDNS, and SiteStress.
33

4-
NetScope is an all-in-one DNS and HTTP analytical engine, combining advanced network enumeration capabilities with Layer 7 volumetric stress testing functionalities.
4+
NetScope is an all-in-one DNS and HTTP discovery engine, combining advanced network enumeration capabilities with Layer 7 volumetric stress testing functionalities.
55

66
**Author**: Lucas Mangroelal | [lucasmangroelal.nl](https://lucasmangroelal.nl)
77

88
## Features
99
- **DNS Enumeration (`-inf`, `-whois`, `-subs`)**: Perform comprehensive DNS mapping, Certificate Transparency log parsing, and Mail Security (SPF, DKIM, DMARC) validation.
1010
- **Web Analytics (`-http`, `-tls`, `-headers`, `-ports`, `-paths`)**: Scan web infrastructures for missing security headers, open administrative ports, sensitive configuration paths, permissive CORS, insecure cookies, and more.
11+
- **Discovery & Analyser (`-dir`, `-params`, `-cms`)**: Discover hidden directories, files, and parameters. Perform deep CMS & Plugin analysis for WordPress, Joomla, and more.
12+
- **Powerful L7 Stress Testing (`-t`, `-c`, `-level`)**: Multi-threaded HTTP/HTTPS volumetric stress tester with randomized Referrers, User-Agents, and Cache-Bypassing logic to assess CDN resilience.
1113
- **Bot Detection (`-crawlers`)**: Verify if robots.txt properly mitigates AI aggregator/spider indexing.
12-
- **L7 Stress Testing (`-t`, `-c`, `-level`)**: Multi-threaded HTTP/HTTPS volumetric stress tester meant for assessing CDN mitigations and load balancer configurations.
1314

1415
## Installation
1516

discovery_wizard.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
)
7+
8+
func runDiscoveryWizard(o options) {
9+
fmt.Println("Welkom bij de NetScope Discovery Wizard!")
10+
fmt.Println("Ik help je om snel de juiste scan-instellingen te kiezen.")
11+
12+
// Step 1: Target Domain
13+
domainLabel := "Op welk domein wil je de analyse uitvoeren?"
14+
domainExpl := "Het domein is het adres van de website (bijv. example.com). Voer de naam in zonder http:// of https://."
15+
domainChatGPT := "Ik ben bezig met een security-analyse van mijn eigen omgeving. Hoe identificeer ik het hoofddomein van een webserver voor technische scouting?"
16+
17+
for o.domain == "" {
18+
o.domain = promptInput(domainLabel, domainExpl, domainChatGPT)
19+
if o.domain == "" {
20+
fmt.Println("[!] Oeps! Je moet wel een domein opgeven om verder te gaan.")
21+
}
22+
}
23+
o.domain = normalizeDomain(o.domain)
24+
25+
// Step 2: Discovery Mode Selection
26+
discoveryOptions := []string{
27+
"Basis Scan (DNS, Security Headers, WHOIS)",
28+
"Directory & File Discovery (Bestandsscan)",
29+
"Parameter Discovery (Verborgen parameters)",
30+
"CMS & Plugin Analysis (WordPress/Joomla)",
31+
"Full Discovery (Alles hierboven)",
32+
}
33+
34+
choice := promptMenu("Welke analyse-modus wil je starten?", discoveryOptions)
35+
36+
switch choice {
37+
case 0:
38+
o.inf = true
39+
o.headersCheck = true
40+
o.whois = true
41+
case 1:
42+
o.dirCheck = true
43+
case 2:
44+
o.paramsCheck = true
45+
case 3:
46+
o.cmsCheck = true
47+
case 4:
48+
o.inf = true
49+
o.dirCheck = true
50+
o.paramsCheck = true
51+
o.cmsCheck = true
52+
o.headersCheck = true
53+
}
54+
55+
// Step 3: Final Confirmation
56+
fmt.Printf("\n--- Configuratie Compleet ---\n")
57+
fmt.Printf("Doelwit: %s\n", o.domain)
58+
fmt.Printf("Modus: %s\n", discoveryOptions[choice])
59+
60+
confirm := promptInput("Alles naar wens? (druk op Enter om te starten, of 'n' om te stoppen)", "", "")
61+
if confirm == "n" || confirm == "N" {
62+
fmt.Println("Analyse afgebroken. Tot de volgende keer!")
63+
os.Exit(0)
64+
}
65+
66+
fmt.Println("\n🚀 We gaan beginnen! NetScope modules worden geladen...")
67+
runUnifiedAnalysis(o)
68+
}

main.go

Lines changed: 13 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,11 @@ import (
44
"flag"
55
"fmt"
66
"os"
7-
"runtime"
87
"strings"
98
"time"
109
)
1110

12-
const version = "4.1.1"
13-
14-
func printBanner() {
15-
banner := `
16-
_ __ __ _____
17-
/ | / /__ / /_/ ___/_________ ____ ___
18-
/ |/ / _ \/ __/\__ \/ ___/ __ \/ __ \/ _ \
19-
/ /| / __/ /_ ___/ / /__/ /_/ / /_/ / __/
20-
/_/ |_/\___/\__//____/\___/\____/ .___/\___/
21-
/_/
22-
`
23-
fmt.Println(banner)
24-
fmt.Println("NetScope is made by Lucas Mangroelal | lucasmangroelal.nl")
25-
fmt.Printf("Version: %s | Platform: %s/%s\n", version, runtime.GOOS, runtime.GOARCH)
26-
fmt.Println("💡 [TIP]: Gebruik '-brute -cms' voor de ultieme aanval op WordPress sites!")
27-
fmt.Println("")
28-
}
11+
const version = "4.3.0"
2912

3013
type options struct {
3114
domain string
@@ -70,9 +53,6 @@ type options struct {
7053
dirCheck bool
7154
paramsCheck bool
7255
cmsCheck bool
73-
bruteCheck bool
74-
wordlist string
75-
username string
7656

7757
// Stress Test Flags
7858
measure bool
@@ -139,10 +119,7 @@ func main() {
139119
// Vulnerability & SecLists
140120
flag.BoolVar(&o.dirCheck, "dir", false, "Uitgebreide Directory & File Busting (SecLists)")
141121
flag.BoolVar(&o.paramsCheck, "params", false, "Verborgen Parameter Discovery fuzzing")
142-
flag.BoolVar(&o.cmsCheck, "cms", false, "CMS Vulnerability Scanner (WordPress, Joomla, etc)")
143-
flag.BoolVar(&o.bruteCheck, "brute", false, "Credential Brute-Forcing (SecLists)")
144-
flag.StringVar(&o.wordlist, "w", "", "Eigen lokale wordlist gebruiken (overschrijft SecLists download)")
145-
flag.StringVar(&o.username, "u", "", "Gebruikersnaam voor credential brute-forcing")
122+
flag.BoolVar(&o.cmsCheck, "cms", false, "CMS Discovery Scanner (WordPress, Joomla, etc)")
146123

147124
// Stress Test
148125
flag.BoolVar(&o.measure, "measure", false, "Meet de bereikbaarheid/latency van de site")
@@ -153,7 +130,7 @@ func main() {
153130
flag.BoolVar(&o.noKeepAlive, "no-keepalive", false, "Schakel Keep-Alive uit bij stress test (verzadigt sockets sneller)")
154131

155132
flag.Usage = func() {
156-
printBanner()
133+
printBanner(version)
157134
fmt.Fprintf(os.Stderr, "Gebruik: netscope -d <domein> [flags]\n\n")
158135

159136
printBoxedSection("🎯 ALGEMEEN & DOELWIT", []flagHelp{
@@ -190,13 +167,10 @@ func main() {
190167
{"-crawlers", "Controleer of de applicatie data-scraping door AI (LLM Bot) blokkeert"},
191168
})
192169

193-
printBoxedSection("🔥 VULNERABILITY & BRUTE-FORCING", []flagHelp{
170+
printBoxedSection("🔍 DISCOVERY & ANALYSE", []flagHelp{
194171
{"-dir", "Uitgebreide Directory & File Busting (downloadt SecLists)"},
195172
{"-params", "Verborgen Parameter Discovery (Fuzzing)"},
196-
{"-cms", "Agressieve CMS kwetsbaarhedenscan (WP/Joomla)"},
197-
{"-brute", "Credential Brute-Forcing op Login Portalen"},
198-
{"-w", "Optioneel: Geef een eigen wordlist pad op (/pad/naar/lijst.txt)"},
199-
{"-u", "Optioneel: Geef de target gebruikersnaam op (admin)"},
173+
{"-cms", "Agressieve CMS & Plugin discovery (WP/Joomla)"},
200174
})
201175

202176
printBoxedSection("⚡ CAPACITEITS & L7 STRESS TEST", []flagHelp{
@@ -218,7 +192,7 @@ func main() {
218192
flag.Parse()
219193

220194
if o.version {
221-
printBanner()
195+
printBanner(version)
222196
os.Exit(0)
223197
}
224198

@@ -228,28 +202,29 @@ func main() {
228202
}
229203

230204
if o.update {
231-
printBanner()
205+
printBanner(version)
232206
runAutoUpdate()
233207
os.Exit(0)
234208
}
235209

236210
if o.check {
237-
printBanner()
211+
printBanner(version)
238212
runCheckUpdate()
239213
os.Exit(0)
240214
}
241215

242216
if o.domain == "" {
243-
flag.Usage()
244-
os.Exit(2)
217+
runDiscoveryWizard(o)
218+
return
245219
}
246220

247221
if !o.jsonOut {
248-
printBanner()
222+
printBanner(version)
249223
}
250224

251225
if o.attackMinutes > 0 {
252-
runAttackOrchestrator(o)
226+
applyLevelSettings(&o)
227+
runAttack([]string{o.domain}, o)
253228
return
254229
}
255230

@@ -263,7 +238,3 @@ func normalizeDomain(d string) string {
263238
d = strings.TrimSuffix(d, "/")
264239
return strings.TrimSuffix(d, ".")
265240
}
266-
267-
func runAttackOrchestrator(o options) {
268-
fmt.Println("Attack starting... (Placeholder)")
269-
}

run_unified.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ func runUnifiedAnalysis(o options) {
3434
runWebAnalysis(o)
3535
}
3636

37-
// Vulnerability & Brute-Force routing
38-
runVuln := false
39-
if o.dirCheck || o.paramsCheck || o.cmsCheck || o.bruteCheck {
40-
runVuln = true
37+
// Vulnerability & Discovery routing
38+
runDiscovery := false
39+
if o.dirCheck || o.paramsCheck || o.cmsCheck {
40+
runDiscovery = true
4141
}
42-
if runVuln {
43-
fmt.Println("\n🔥 [MODULE: VULNERABILITY & BRUTE-FORCING]")
42+
if runDiscovery {
43+
fmt.Println("\n🔍 [MODULE: VULNERABILITY & DISCOVERY]")
4444
runVulnAnalysis(o)
4545
}
4646

scripts/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/bash
22

33
APP_NAME="netscope"
4-
VERSION="4.1.1"
4+
VERSION="4.3.0"
55

66
echo "Building $APP_NAME v$VERSION..."
77

stress_analysis.go

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package main
22

33
import (
4-
"fmt"
5-
"math/rand"
6-
"net/http"
7-
"sync"
8-
"sync/atomic"
9-
"time"
4+
"fmt"
5+
"io"
6+
"math/rand"
7+
"net/http"
8+
"net/url"
9+
"sync"
10+
"sync/atomic"
11+
"time"
1012
)
1113

1214
var userAgents = []string{
@@ -21,6 +23,19 @@ func getRandomUserAgent() string {
2123
return userAgents[rand.Intn(len(userAgents))]
2224
}
2325

26+
var referrers = []string{
27+
"https://www.google.com/",
28+
"https://www.bing.com/",
29+
"https://www.facebook.com/",
30+
"https://twitter.com/",
31+
"https://www.linkedin.com/",
32+
"https://duckduckgo.com/",
33+
}
34+
35+
func getRandomReferrer() string {
36+
return referrers[rand.Intn(len(referrers))]
37+
}
38+
2439
type domainStats struct {
2540
domain string
2641
targetURL string
@@ -49,16 +64,26 @@ func applyLevelSettings(o *options) {
4964
}
5065

5166
switch o.level {
52-
case 1: o.concurrency = 50
53-
case 2: o.concurrency = 150
54-
case 3: o.concurrency = 300
55-
case 4: o.concurrency = 750
56-
case 5: o.concurrency = 1500
57-
case 6: o.concurrency = 3000
58-
case 7: o.concurrency = 5000
59-
case 8: o.concurrency = 8000
60-
case 9: o.concurrency = 12000
61-
case 10: o.concurrency = 20000
67+
case 1:
68+
o.concurrency = 100
69+
case 2:
70+
o.concurrency = 500
71+
case 3:
72+
o.concurrency = 1500
73+
case 4:
74+
o.concurrency = 3000
75+
case 5:
76+
o.concurrency = 7000
77+
case 6:
78+
o.concurrency = 12000
79+
case 7:
80+
o.concurrency = 18000
81+
case 8:
82+
o.concurrency = 25000
83+
case 9:
84+
o.concurrency = 35000
85+
case 10:
86+
o.concurrency = 50000
6287
}
6388

6489
fmt.Printf("🎚️ Power Level: %d -> %d Workers\n", o.level, o.concurrency)
@@ -93,9 +118,12 @@ func runAttack(domains []string, o options) {
93118
}
94119

95120
client := &http.Client{
96-
Timeout: 5 * time.Second,
121+
Timeout: 10 * time.Second,
97122
Transport: &http.Transport{
98-
DisableKeepAlives: o.noKeepAlive,
123+
DisableKeepAlives: o.noKeepAlive,
124+
MaxIdleConns: o.concurrency * 2,
125+
MaxIdleConnsPerHost: o.concurrency * 2,
126+
IdleConnTimeout: 10 * time.Second,
99127
},
100128
}
101129

@@ -124,7 +152,7 @@ func runAttack(domains []string, o options) {
124152

125153
fmt.Printf(" %s -> %s\n", s.domain, downStr)
126154
fmt.Printf(" Reqs: %d (Success: %d, Fail: %d)\n",
127-
atomic.LoadInt64(&s.totalRequests),
155+
atomic.LoadInt64(&s.totalRequests),
128156
atomic.LoadInt64(&s.successRequests),
129157
atomic.LoadInt64(&s.failedRequests))
130158
s.mu.Unlock()
@@ -137,17 +165,29 @@ atomic.LoadInt64(&s.totalRequests),
137165

138166
func worker(client *http.Client, targetURL string, s *domainStats, deadline time.Time) {
139167
for time.Now().Before(deadline) {
140-
req, _ := http.NewRequest("GET", targetURL, nil)
168+
// Random Cache-Bypass
169+
cb := fmt.Sprintf("%d", rand.Int63())
170+
u, _ := url.Parse(targetURL)
171+
q := u.Query()
172+
q.Set("cb", cb)
173+
u.RawQuery = q.Encode()
174+
175+
req, _ := http.NewRequest("GET", u.String(), nil)
141176
req.Header.Set("User-Agent", getRandomUserAgent())
177+
req.Header.Set("Referer", getRandomReferrer())
178+
req.Header.Set("Cache-Control", "no-cache")
142179

143180
atomic.AddInt64(&s.totalRequests, 1)
144181
resp, err := client.Do(req)
145182
if err != nil {
146183
atomic.AddInt64(&s.failedRequests, 1)
147184
} else {
185+
// Fast body discard
186+
io.Copy(io.Discard, resp.Body)
148187
resp.Body.Close()
188+
149189
if resp.StatusCode >= 500 {
150-
atomic.AddInt64(&s.failedRequests, 1) // Server errors count as fail
190+
atomic.AddInt64(&s.failedRequests, 1)
151191
} else {
152192
atomic.AddInt64(&s.successRequests, 1)
153193
}

0 commit comments

Comments
 (0)