aboutsummaryrefslogblamecommitdiff
path: root/scream/winscn.go
blob: 05d0f3f9fbbc757788fa4853dcba354d2396947e (plain) (tree)







































































































































































































































                                                                                                                                                                              
package scream

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"sync"
	"time"
)

// StartPscan start port scanning tcp or udp (or both)
func StartPscan(host string, timeout time.Duration, gt int64, portstruct ...PortType) []PoutComming {
	infop := []byte{0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x20, 0x45, 0x6E, 0x67, 0x69, 0x6E, 0x65, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x00}
	resportscan := []PoutComming{}
	scanreslock := sync.Mutex{}
	dummg := sync.WaitGroup{}
	semap := NewWeighted(gt)
	pscantcpfunc := func(ip string, port int, pscansig string, timeout time.Duration) {
		conn, err := net.DialTimeout(pscansig, fmt.Sprintf("%s:%d", ip, port), timeout)
		if err != nil {
			scanreslock.Lock()
			resportscan = append(resportscan, PoutComming{Stat: "close", Number: port, Ptype: pscansig})
			scanreslock.Unlock()
			return
		}
		defer conn.Close()
		scanreslock.Lock()
		resportscan = append(resportscan, PoutComming{Stat: "open", Number: port, Ptype: pscansig})
		scanreslock.Unlock()
	}

	pscanudpfunc := func(ip string, port int, pscansig string, timeout time.Duration) {
		conn, err := net.DialTimeout(pscansig, fmt.Sprintf("%s:%d", ip, port), timeout)
		if err != nil {
			scanreslock.Lock()
			resportscan = append(resportscan, PoutComming{Stat: "close", Number: port, Ptype: pscansig})
			scanreslock.Unlock()
			return
		}
		defer conn.Close()
		// so for scanning udp ports we have to say something to server and wait for response,
		// its pretty sucks

		// here we write infop payload on udp connection
		_, err = conn.Write(infop)
		if err != nil {
			// in case something goes wrong ...
			scanreslock.Lock()
			resportscan = append(resportscan, PoutComming{Stat: "close", Number: port, Ptype: pscansig})
			scanreslock.Unlock()
			return
		}
		// buffer
		buffer := make([]byte, 1500)
		conn.SetReadDeadline(time.Now().Add(timeout))
		n, err := conn.Read(buffer)
		if err != nil {
			scanreslock.Lock()
			resportscan = append(resportscan, PoutComming{Stat: "close", Number: port, Ptype: pscansig})
			scanreslock.Unlock()
			return
		}
		// check for any response
		if buffer == nil || n == 0 {
			scanreslock.Lock()
			resportscan = append(resportscan, PoutComming{Stat: "close", Number: port, Ptype: pscansig})
			scanreslock.Unlock()
			return
		}
		scanreslock.Lock()
		resportscan = append(resportscan, PoutComming{Stat: "open", Number: port, Ptype: pscansig})
		scanreslock.Unlock()

	}

	for _, port := range portstruct {
		semap.Acquire(context.TODO(), 1)
		dummg.Add(1)
		go func(port PortType) {
			defer semap.Release(1)
			defer dummg.Done()
			if port.Tp == "TCP" {
				pscantcpfunc(host, port.Nm, "tcp", timeout)
				return
			}
			if port.Tp == "UDP" {
				pscanudpfunc(host, port.Nm, "udp", timeout)
				return
			}
			pscantcpfunc(host, port.Nm, "tcp", timeout)
			pscanudpfunc(host, port.Nm, "udp", timeout)
		}(port)
	}
	dummg.Wait()
	return resportscan
}

// DetectWeb return webserver name and an error
func DetectWeb(addr string, port int) (string, error) {
	sndreq := http.Client{
		Timeout: 3 * time.Second,
	}
	resp, err := sndreq.Get(fmt.Sprintf("http://%v:%v", addr, port))
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	return resp.Header.Values("Server")[0], nil

}

// ScanResults implement CustomScanTCP and CustomScanUDP
type ScanResults interface {
	PortInfo() string
	SigPort() string
	StatInfo() (bool, int)
}

// CustomScanTCP struct type for tcp scan
type CustomScanTCP struct {
	OK bool
	NM int
}

// CustomScanUDP struct type for udp scan
type CustomScanUDP struct {
	OK bool
	NM int
}

// CustomPscan start port scanning tcp or udp (or both) for port mapper tool
func CustomPscan(host string, timeout time.Duration, gt int64, rgscan []int, udpmsg []byte, contype bool, ch chan<- ScanResults) {
	dummg := sync.WaitGroup{}
	semap := NewWeighted(gt)
	defer func() {
		dummg.Wait()
		close(ch)
	}()
	pscantcpfunc := func(ip string, port int, pscansig string, timeout time.Duration) {
		conn, err := net.DialTimeout(pscansig, fmt.Sprintf("%s:%d", ip, port), timeout)
		if err != nil {
			ch <- CustomScanTCP{OK: false, NM: port}
			return
		}
		defer conn.Close()
		ch <- CustomScanTCP{OK: true, NM: port}

	}

	pscanudpfunc := func(ip string, port int, pscansig string, timeout time.Duration) {
		conn, err := net.DialTimeout(pscansig, fmt.Sprintf("%s:%d", ip, port), timeout)
		if err != nil {
			ch <- CustomScanUDP{OK: false, NM: port}
			return
		}
		defer conn.Close()
		// so for scanning udp ports we have to say something to server and wait for response,
		// its pretty sucks

		// here we write infop payload on udp connection
		_, err = conn.Write(udpmsg)
		if err != nil {
			// in case something goes wrong ...
			ch <- CustomScanUDP{OK: false, NM: port}
			return
		}
		// buffer
		buffer := make([]byte, 1500)
		conn.SetReadDeadline(time.Now().Add(timeout))
		n, err := conn.Read(buffer)
		if err != nil {
			ch <- CustomScanUDP{OK: false, NM: port}
			return
		}
		// check for any response
		if buffer == nil || n == 0 {
			ch <- CustomScanUDP{OK: false, NM: port}
			return
		}
		ch <- CustomScanUDP{OK: true, NM: port}

	}

	if !contype {
		for _, port := range rgscan {
			if signal, _ := semap.AcquireSnix(context.TODO(), 1); signal != 0 {
				return
			}
			dummg.Add(1)
			go func(port int) {
				defer semap.Release(1)
				defer dummg.Done()
				pscantcpfunc(host, port, "tcp", timeout)
			}(port)
		}
	} else {
		for _, port := range rgscan {
			if signal, _ := semap.AcquireSnix(context.TODO(), 1); signal != 0 {
				return
			}
			dummg.Add(1)
			go func(port int) {
				defer semap.Release(1)
				defer dummg.Done()
				pscanudpfunc(host, port, "udp", timeout)
			}(port)
		}
	}
	dummg.Wait()

}

// SigPort return port protocol type
func (CustomScanTCP) SigPort() string {
	return "tcp"
}

// SigPort return port protocol type
func (CustomScanUDP) SigPort() string {
	return "udp"
}

// StatInfo returns stat and port number
func (p CustomScanTCP) StatInfo() (bool, int) {
	return p.OK, p.NM
}

// StatInfo returns stat and port number
func (p CustomScanUDP) StatInfo() (bool, int) {
	return p.OK, p.NM
}

Snix LLC Git Repository Holder Copyright(C) 2022 All Rights Reserved Email To Snix.IR