Skip to content

Commit 9086936

Browse files
committed
up
1 parent 661ed95 commit 9086936

File tree

4 files changed

+232
-8
lines changed

4 files changed

+232
-8
lines changed
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
package discovery
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net"
7+
"time"
8+
9+
"golang.org/x/net/icmp"
10+
"golang.org/x/net/ipv4"
11+
)
12+
13+
// DiscoveryResult armazena o resultado da descoberta de um host
14+
type DiscoveryResult struct {
15+
IP string
16+
Alive bool
17+
Method string
18+
}
19+
20+
// RunDiscovery executa descoberta em uma rede no formato CIDR usando método "icmp" ou "tcp"
21+
// Agora aceita portaTCP como parâmetro, caso o método seja "tcp"
22+
func RunDiscovery(ctx context.Context, cidr string, method string, timeout time.Duration, tcpPort int) ([]DiscoveryResult, error) {
23+
ips, err := ExpandCIDR(cidr)
24+
if err != nil {
25+
return nil, fmt.Errorf("CIDR inválido: %v", err)
26+
}
27+
28+
results := DiscoverHostsConcurrently(ctx, ips, method, timeout, tcpPort)
29+
return results, nil
30+
}
31+
32+
// PingICMP envia um pacote ICMP Echo Request para um IP
33+
func PingICMP(ip string, timeout time.Duration) bool {
34+
c, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
35+
if err != nil {
36+
return false // Sem permissão para socket raw
37+
}
38+
defer c.Close()
39+
40+
msg := icmp.Message{
41+
Type: ipv4.ICMPTypeEcho,
42+
Code: 0,
43+
Body: &icmp.Echo{
44+
ID: 1234,
45+
Seq: 1,
46+
Data: []byte("HELLO-PING"),
47+
},
48+
}
49+
msgBytes, err := msg.Marshal(nil)
50+
if err != nil {
51+
return false
52+
}
53+
54+
dst, err := net.ResolveIPAddr("ip4", ip)
55+
if err != nil {
56+
return false
57+
}
58+
59+
if _, err := c.WriteTo(msgBytes, dst); err != nil {
60+
return false
61+
}
62+
63+
c.SetReadDeadline(time.Now().Add(timeout))
64+
65+
buf := make([]byte, 1500)
66+
n, _, err := c.ReadFrom(buf)
67+
if err != nil {
68+
return false
69+
}
70+
71+
rm, err := icmp.ParseMessage(1, buf[:n])
72+
if err != nil {
73+
return false
74+
}
75+
76+
return rm.Type == ipv4.ICMPTypeEchoReply
77+
}
78+
79+
// PingTCP tenta conectar em uma porta TCP
80+
func PingTCP(ip string, port int, timeout time.Duration) bool {
81+
addr := fmt.Sprintf("%s:%d", ip, port)
82+
conn, err := net.DialTimeout("tcp", addr, timeout)
83+
if err != nil {
84+
return false
85+
}
86+
conn.Close()
87+
return true
88+
}
89+
90+
// ExpandCIDR retorna todos os IPs dentro de um CIDR
91+
func ExpandCIDR(cidr string) ([]string, error) {
92+
ip, ipnet, err := net.ParseCIDR(cidr)
93+
if err != nil {
94+
return nil, err
95+
}
96+
97+
var ips []string
98+
for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); incIP(ip) {
99+
ipCopy := make(net.IP, len(ip))
100+
copy(ipCopy, ip)
101+
ips = append(ips, ipCopy.String())
102+
}
103+
104+
// Remove endereço de rede e broadcast
105+
if len(ips) > 2 {
106+
return ips[1 : len(ips)-1], nil
107+
}
108+
return ips, nil
109+
}
110+
111+
// incIP incrementa o IP
112+
func incIP(ip net.IP) {
113+
for j := len(ip) - 1; j >= 0; j-- {
114+
ip[j]++
115+
if ip[j] > 0 {
116+
break
117+
}
118+
}
119+
}
120+
121+
// DiscoverHostsConcurrently faz a varredura concorrente
122+
func DiscoverHostsConcurrently(ctx context.Context, ips []string, method string, timeout time.Duration, tcpPort int) []DiscoveryResult {
123+
results := make([]DiscoveryResult, 0, len(ips))
124+
resultsChan := make(chan DiscoveryResult, len(ips))
125+
126+
for _, ip := range ips {
127+
go func(ip string) {
128+
alive := false
129+
130+
if method == "icmp" {
131+
alive = PingICMP(ip, timeout)
132+
} else if method == "tcp" {
133+
alive = PingTCP(ip, tcpPort, timeout)
134+
}
135+
136+
resultsChan <- DiscoveryResult{
137+
IP: ip,
138+
Alive: alive,
139+
Method: method,
140+
}
141+
}(ip)
142+
}
143+
144+
for i := 0; i < len(ips); i++ {
145+
select {
146+
case res := <-resultsChan:
147+
if res.Alive {
148+
results = append(results, res)
149+
}
150+
case <-ctx.Done():
151+
return results
152+
}
153+
}
154+
155+
return results
156+
}

Valkan/Internal/ui/terminal.go

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"time"
1212

1313
"github.com/Vyzer9/Valkan/Valkan/Internal/detection"
14+
"github.com/Vyzer9/Valkan/Valkan/Internal/discovery" // importe o discovery aqui
1415
"github.com/Vyzer9/Valkan/Valkan/Internal/plugins"
1516
"github.com/Vyzer9/Valkan/Valkan/Internal/scanner"
1617
)
@@ -92,8 +93,9 @@ func ShowMenu() {
9293
fmt.Println()
9394
fmt.Println(Yellow + Bold + "Menu:" + Reset)
9495
fmt.Println(Yellow + "1) Scanner" + Reset)
95-
fmt.Println(Yellow + "2) Help" + Reset)
96-
fmt.Println(Yellow + "3) Sair" + Reset)
96+
fmt.Println(Yellow + "2) Discovery" + Reset)
97+
fmt.Println(Yellow + "3) Help" + Reset)
98+
fmt.Println(Yellow + "4) Sair" + Reset)
9799
fmt.Print(Reset + "Escolha uma opção: " + Reset)
98100

99101
input, _ := reader.ReadString('\n')
@@ -196,9 +198,63 @@ func ShowMenu() {
196198
}
197199

198200
case "2":
199-
showHelp()
201+
fmt.Println(Yellow + "Iniciando Discovery..." + Reset)
202+
203+
reader := bufio.NewReader(os.Stdin)
204+
205+
// Pedir CIDR para o usuário
206+
fmt.Print("Digite a rede no formato CIDR (ex: 192.168.1.0/24): ")
207+
cidr, _ := reader.ReadString('\n')
208+
cidr = strings.TrimSpace(cidr)
209+
if cidr == "" {
210+
fmt.Println(Red + "CIDR inválido." + Reset)
211+
continue
212+
}
213+
214+
// Pedir método
215+
fmt.Print("Digite o método (icmp/tcp): ")
216+
method, _ := reader.ReadString('\n')
217+
method = strings.TrimSpace(method)
218+
if method != "icmp" && method != "tcp" {
219+
fmt.Println(Red + "Método inválido." + Reset)
220+
continue
221+
}
222+
223+
// Se método for TCP, pedir porta
224+
tcpPort := 80 // valor padrão
225+
if method == "tcp" {
226+
fmt.Print("Digite a porta TCP para testar (ex: 80): ")
227+
portInput, _ := reader.ReadString('\n')
228+
portInput = strings.TrimSpace(portInput)
229+
_, err := fmt.Sscanf(portInput, "%d", &tcpPort)
230+
if err != nil || tcpPort <= 0 || tcpPort > 65535 {
231+
fmt.Println(Red + "Porta inválida." + Reset)
232+
continue
233+
}
234+
}
235+
236+
ctx := context.Background()
237+
timeout := 2 * time.Second
238+
239+
// Agora com tcpPort como argumento
240+
results, err := discovery.RunDiscovery(ctx, cidr, method, timeout, tcpPort)
241+
if err != nil {
242+
fmt.Println(Red + "Erro ao executar discovery: " + err.Error() + Reset)
243+
} else {
244+
if len(results) == 0 {
245+
fmt.Println(Yellow + "Nenhum host ativo encontrado." + Reset)
246+
} else {
247+
fmt.Println(Green + "Resultados do Discovery:" + Reset)
248+
for _, res := range results {
249+
fmt.Printf("IP: %s, Vivo: %t, Método: %s\n", res.IP, res.Alive, res.Method)
250+
}
251+
}
252+
}
200253

201254
case "3":
255+
showHelp()
256+
257+
case "4":
202258
fmt.Println("Saindo...")
203259
return
204260

@@ -241,10 +297,13 @@ func showHelp() {
241297
- Busca portas abertas e tenta identificar serviços (apenas TCP).
242298
- Salva resultados em arquivo "resultados_scan.txt".
243299
244-
2) Help
300+
2) Discovery
301+
- Executa uma varredura de descoberta na rede (ex: ping sweep, hosts ativos).
302+
303+
3) Help
245304
- Mostra este menu de ajuda.
246305
247-
3) Sair
306+
4) Sair
248307
- Fecha o programa.
249308
250309
Dicas:

go.mod

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ require (
1414
github.com/rivo/uniseg v0.4.7 // indirect
1515
github.com/spf13/cobra v1.10.1 // indirect
1616
github.com/spf13/pflag v1.0.9 // indirect
17-
golang.org/x/sys v0.29.0 // indirect
18-
golang.org/x/term v0.28.0 // indirect
19-
golang.org/x/text v0.21.0 // indirect
17+
golang.org/x/net v0.44.0 // indirect
18+
golang.org/x/sys v0.36.0 // indirect
19+
golang.org/x/term v0.35.0 // indirect
20+
golang.org/x/text v0.29.0 // indirect
2021
)

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
4444
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
4545
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
4646
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
47+
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
48+
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
4749
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
4850
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
4951
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -63,6 +65,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
6365
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
6466
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
6567
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
68+
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
69+
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
6670
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
6771
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
6872
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -73,6 +77,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
7377
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
7478
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
7579
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
80+
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
81+
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
7682
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
7783
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
7884
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
@@ -83,6 +89,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
8389
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
8490
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
8591
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
92+
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
93+
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
8694
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
8795
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
8896
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=

0 commit comments

Comments
 (0)