discovery
This commit is contained in:
commit
cec3e321f2
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
### Go template
|
||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, build with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
||||||
|
.glide/
|
||||||
|
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
bin/logs
|
6
bin/bridge_conf.xml
Normal file
6
bin/bridge_conf.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<conf version="1.0.0">
|
||||||
|
<url>http://localhost:8080/discoveryHistory</url>
|
||||||
|
<user>sa</user>
|
||||||
|
<password>qwe123</password>
|
||||||
|
<bodyType>application/json</bodyType>
|
||||||
|
</conf>
|
4
bin/collector.yaml
Normal file
4
bin/collector.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
central:
|
||||||
|
address: "http://localhost:9090"
|
||||||
|
port: 443
|
||||||
|
log_path: "./bin/log.xml"
|
33
bin/log.xml
Normal file
33
bin/log.xml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<seelog type="asynctimer" asyncinterval="1000">
|
||||||
|
<outputs>
|
||||||
|
|
||||||
|
<!-- Exclude global log settings -->
|
||||||
|
<!--<exceptions>-->
|
||||||
|
<!--<exception funcpattern="*seelog.main.test1*" minlevel="info"/>-->
|
||||||
|
<!--<exception funcpattern="*seelog.main.test2*" minlevel="debug"/>-->
|
||||||
|
<!--<exception filepattern="*main.go" minlevel="debug"/>-->
|
||||||
|
<!--</exceptions>-->
|
||||||
|
|
||||||
|
<filter levels="trace, debug">
|
||||||
|
<console formatid="dtLevelFmt" />
|
||||||
|
|
||||||
|
</filter>
|
||||||
|
<filter levels="info, warn">
|
||||||
|
<console formatid="iwLevelFmt" />
|
||||||
|
|
||||||
|
</filter>
|
||||||
|
<filter levels="error, critical">
|
||||||
|
<console formatid="ecLevelFmt" />
|
||||||
|
|
||||||
|
</filter>
|
||||||
|
<!--<console formatid="basic" />-->
|
||||||
|
<rollingfile formatid="basic" type="date" filename="./bin/logs/log" maxrolls="5" archiveexploded="true"
|
||||||
|
datepattern="02.01.2006" archivetype="zip" fullname="true" archivepath="./bin/logs/archives/"/>
|
||||||
|
</outputs>
|
||||||
|
<formats>
|
||||||
|
<format id="basic" format="%Date/%Time [%LEV] %File:%Line %Func()-%Msg%n"/>
|
||||||
|
<format id="dtLevelFmt" format="%EscM(34)%Date/%Time [%LEV] %File:%Line %Func()-%Msg%n"/>
|
||||||
|
<format id="iwLevelFmt" format="%EscM(35)%Date/%Time [%LEV] %File:%Line %Func()-%Msg%n"/>
|
||||||
|
<format id="ecLevelFmt" format="%EscM(31)%Date/%Time [%LEV] %File:%Line %Func()-%Msg%n"/>
|
||||||
|
</formats>
|
||||||
|
</seelog>
|
71
bin/scripts/ubuntu/of_collector
Normal file
71
bin/scripts/ubuntu/of_collector
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: overFlow
|
||||||
|
# Required-Start: $network
|
||||||
|
# Required-Stop: $network
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Short-Description: of-collector agent
|
||||||
|
# Description: overFlow Collector Agent
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
PROG="ofcollector"
|
||||||
|
PROG_PATH="/home/insanity/develop/overflow/overflow.collector/bin/"
|
||||||
|
PID_PATH="/var/run/"
|
||||||
|
FILE_SERVER=/var/run/of_server
|
||||||
|
|
||||||
|
start() {
|
||||||
|
if [ -e "$PID_PATH/$PROG.pid" ]; then
|
||||||
|
## Program is running, exit with error.
|
||||||
|
echo "$PROG is currently running!" 1>&2
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
$PROG_PATH/$PROG 2>&1 > /dev/null &
|
||||||
|
echo "$PROG started"
|
||||||
|
touch "$PID_PATH/$PROG.pid"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
sudo echo -n 'STOP' | netcat -U $FILE_SERVER
|
||||||
|
|
||||||
|
if [ -e "$PID_PATH/$PROG.pid" ]; then
|
||||||
|
## Program is running, so stop it
|
||||||
|
#killall $PROG
|
||||||
|
rm "$PID_PATH/$PROG.pid"
|
||||||
|
echo "$PROG stopped"
|
||||||
|
else
|
||||||
|
## Program is not running, exit with error.
|
||||||
|
echo "Error! $PROG not started!" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
status() {
|
||||||
|
sudo echo -n $1 | netcat -U $FILE_SERVER
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if [ "$(id -u)" != "0" ]; then
|
||||||
|
echo "This script must be run as root" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
reload|restart|force-reload)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status 'STATUS'
|
||||||
|
;;
|
||||||
|
**)
|
||||||
|
echo "Usage: $0 {start|stop|restart|status}" 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
51
bootstrap/bootstrap.go
Normal file
51
bootstrap/bootstrap.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
"git.loafle.net/overflow/discovery"
|
||||||
|
"git.loafle.net/overflow/discovery/conf"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
paramA := flag.String("conf", "/overflow/collector", "Config file path")
|
||||||
|
//paramB := flag.Int("b", 1, "int type param")
|
||||||
|
//paramC := flag.Bool("c", false, "bool type param")
|
||||||
|
flag.Parse()
|
||||||
|
//fmt.Println("Args: ", *paramA, *paramB, *paramC)
|
||||||
|
fmt.Println("Args: ", *paramA)
|
||||||
|
//if len(os.Args) < /* paramcount */ {
|
||||||
|
// flag.Usage()
|
||||||
|
// os.Exit(1)
|
||||||
|
//}
|
||||||
|
|
||||||
|
if err := conf.LoadConfig(*paramA); err != nil {
|
||||||
|
fmt.Printf("Error: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
|
|
||||||
|
defer log.Flush()
|
||||||
|
|
||||||
|
stop := make(chan bool, 1)
|
||||||
|
go handleShell(stop)
|
||||||
|
handleSignal(stop)
|
||||||
|
|
||||||
|
collector.Start()
|
||||||
|
|
||||||
|
if <-stop {
|
||||||
|
// Comes from shell cmd 'stop' or quit signals
|
||||||
|
stopHandleShell()
|
||||||
|
collector.Stop()
|
||||||
|
close(stop)
|
||||||
|
log.Flush()
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
76
bootstrap/shell.go
Normal file
76
bootstrap/shell.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const FILE_SERVER string = "/var/run/of_server"
|
||||||
|
|
||||||
|
var fd net.Conn
|
||||||
|
|
||||||
|
func handleShell(stop chan bool) {
|
||||||
|
|
||||||
|
//os.Stdout.Close()
|
||||||
|
//os.Stderr.Close()
|
||||||
|
//os.Stdin.Close()
|
||||||
|
|
||||||
|
if fi, _ := os.Stat(FILE_SERVER); fi != nil {
|
||||||
|
os.Remove(FILE_SERVER)
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := net.ListenUnix("unix", &net.UnixAddr{Name: FILE_SERVER, Net: "unix"})
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
l.Close()
|
||||||
|
os.Remove(FILE_SERVER)
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
fd, err = l.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
nr, err := fd.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data := string(buf[0:nr])
|
||||||
|
switch strings.ToUpper(data) {
|
||||||
|
case "STOP":
|
||||||
|
if fi, _ := os.Stat(FILE_SERVER); fi != nil {
|
||||||
|
os.Remove(FILE_SERVER)
|
||||||
|
}
|
||||||
|
stop <- true
|
||||||
|
case "STATUS":
|
||||||
|
fd.Write(status())
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
fd.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stopHandleShell() {
|
||||||
|
log.Info("Shell Handler stopped.")
|
||||||
|
|
||||||
|
if fi, _ := os.Stat(FILE_SERVER); fi != nil {
|
||||||
|
os.Remove(FILE_SERVER)
|
||||||
|
}
|
||||||
|
if fd != nil {
|
||||||
|
fd.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func status() []byte {
|
||||||
|
return []byte("STATUS OK\n")
|
||||||
|
}
|
53
bootstrap/signal.go
Normal file
53
bootstrap/signal.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func handleSignal(stop chan bool) {
|
||||||
|
sigs := make(chan os.Signal, 1)
|
||||||
|
|
||||||
|
signal.Notify(sigs,
|
||||||
|
os.Kill,
|
||||||
|
os.Interrupt,
|
||||||
|
syscall.SIGKILL,
|
||||||
|
syscall.SIGSTOP,
|
||||||
|
syscall.SIGHUP,
|
||||||
|
syscall.SIGINT,
|
||||||
|
syscall.SIGTERM,
|
||||||
|
syscall.SIGQUIT,
|
||||||
|
)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
s := <-sigs
|
||||||
|
switch s {
|
||||||
|
case os.Kill, os.Interrupt, syscall.SIGSTOP, syscall.SIGKILL, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT:
|
||||||
|
log.Infof("Signal received. [%s]", s)
|
||||||
|
stop <- true
|
||||||
|
default:
|
||||||
|
log.Infof("Signal received. [%s]", s)
|
||||||
|
stop <- true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
|
||||||
|
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
|
||||||
|
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
|
||||||
|
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
|
||||||
|
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
|
||||||
|
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
|
||||||
|
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
|
||||||
|
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
|
||||||
|
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
|
||||||
|
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
|
||||||
|
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
|
||||||
|
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
|
||||||
|
63) SIGRTMAX-1 64) SIGRTMAX
|
||||||
|
*/
|
68
collector.go
Normal file
68
collector.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types/timestamp"
|
||||||
|
"os/exec"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Collector struct {
|
||||||
|
stop chan bool `json:"-"`
|
||||||
|
|
||||||
|
ID int `json:"id,omitempty"`
|
||||||
|
ProductId string `json:"productId"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
ConfigPath string `json:"configPath"`
|
||||||
|
InstallDate timestamp.Timestamp `json:"installDate"`
|
||||||
|
UpdateDate timestamp.Timestamp `json:"updateDate"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var coll *Collector
|
||||||
|
var once sync.Once
|
||||||
|
|
||||||
|
func Start() *Collector {
|
||||||
|
|
||||||
|
once.Do(func() {
|
||||||
|
coll = &Collector{}
|
||||||
|
coll.info()
|
||||||
|
})
|
||||||
|
coll.start()
|
||||||
|
|
||||||
|
return coll
|
||||||
|
}
|
||||||
|
|
||||||
|
func Stop() {
|
||||||
|
log.Info("Collector has stopped.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Collector) start() {
|
||||||
|
go coll.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Collector) run() {
|
||||||
|
log.Info("Collector is now running.")
|
||||||
|
|
||||||
|
fin := make(chan bool, 1)
|
||||||
|
c.stop = make(chan bool)
|
||||||
|
|
||||||
|
discovery.Discover(fin)
|
||||||
|
|
||||||
|
if <-fin {
|
||||||
|
log.Info("Discovery has finished.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Collector) info() {
|
||||||
|
|
||||||
|
uuid, err := exec.Command("uuidgen").Output()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
c.ProductId = string(uuid)
|
||||||
|
c.Version = "1.0"
|
||||||
|
c.ConfigPath = "/root"
|
||||||
|
c.InstallDate = timestamp.Now()
|
||||||
|
c.UpdateDate = timestamp.Now()
|
||||||
|
}
|
72
collector_test.go
Normal file
72
collector_test.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types/timestamp"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTimeStampe(t *testing.T) {
|
||||||
|
|
||||||
|
aa := "1479186033399"
|
||||||
|
|
||||||
|
i, err := strconv.ParseInt(aa, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
tm := time.Unix(i/1000, 0)
|
||||||
|
fmt.Println(tm)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJPAInsert(t *testing.T) {
|
||||||
|
|
||||||
|
c := &Collector{}
|
||||||
|
c.Version = "2.0"
|
||||||
|
c.ConfigPath = "/root"
|
||||||
|
c.LicenseType = LICENSE1
|
||||||
|
c.ProductId = "6666"
|
||||||
|
c.InstallDate = timestamp.Now()
|
||||||
|
c.UpdateDate = timestamp.Now()
|
||||||
|
c.LicenseDueDate = timestamp.Date(2017, 12, 25)
|
||||||
|
|
||||||
|
b, err := json.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Post("http://localhost:8080/collector", "application/x-spring-data-verbose+json", bytes.NewBuffer(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJPASelect(t *testing.T) {
|
||||||
|
//res, err := http.Get("http://localhost:8080/collector/1")
|
||||||
|
res, err := http.Get("http://localhost:8080/collector/p/6666")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(res.Body)
|
||||||
|
res.Body.Close()
|
||||||
|
if len(body) <= 0 {
|
||||||
|
t.Error("not found.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var result Collector
|
||||||
|
json.Unmarshal(body, &result)
|
||||||
|
t.Log(result)
|
||||||
|
|
||||||
|
t.Log("ID : ", result.ID)
|
||||||
|
t.Log("productID : ", result.ProductId)
|
||||||
|
t.Log("version : ", result.Version)
|
||||||
|
}
|
27
communicate/communicate.go
Normal file
27
communicate/communicate.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package communicate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
//"git.loafle.net/overflow/central/client/events"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _c *communicator = nil
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
fmt.Println("init communicator")
|
||||||
|
//_c = NewCommunicator()
|
||||||
|
//_c.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetRootURL(url string) {
|
||||||
|
_c.RootURL = url
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRootURL() string {
|
||||||
|
return _c.RootURL
|
||||||
|
}
|
||||||
|
|
||||||
|
//func Send(e *events.Event) {
|
||||||
|
// _c.addEvent(e)
|
||||||
|
//}
|
83
communicate/communicate_test.go
Normal file
83
communicate/communicate_test.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package communicate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gopkg.in/gin-gonic/gin.v1"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"git.loafle.net/overflow/central/client/events"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCommunicatorInit(t *testing.T) {
|
||||||
|
assert.NotNil(t, _c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeGin() *gin.Engine {
|
||||||
|
r := gin.New()
|
||||||
|
api := r.Group("/_api")
|
||||||
|
{
|
||||||
|
collector := api.Group("/collector")
|
||||||
|
{
|
||||||
|
event := collector.Group("/event")
|
||||||
|
{
|
||||||
|
{
|
||||||
|
types := event.Group("/status")
|
||||||
|
{
|
||||||
|
types.POST("/:type", func(c *gin.Context) {
|
||||||
|
fmt.Println("called /_api/collector/event/status/:type")
|
||||||
|
var j events.Event
|
||||||
|
c.BindJSON(&j)
|
||||||
|
fmt.Println(j)
|
||||||
|
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSend(t *testing.T) {
|
||||||
|
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
}))
|
||||||
|
defer ts.Close()
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
e := events.NewEvent(events.CENTRAL_EVENT, events.CollectorInstallEvent{Version: "Test"})
|
||||||
|
Send(e)
|
||||||
|
// t.Log(e.GetResult())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRealSendByGin(t *testing.T) {
|
||||||
|
|
||||||
|
SetRootURL("http://localhost:8080")
|
||||||
|
|
||||||
|
e := events.NewEvent(events.CENTRAL_EVENT, events.NewInstallEvent("TestInstallEvent"))
|
||||||
|
data, _ := json.Marshal(&e)
|
||||||
|
|
||||||
|
var u events.URLMaker
|
||||||
|
u = e.Data.(events.URLMaker)
|
||||||
|
t.Log(GetRootURL() + u.GetUrl())
|
||||||
|
req := httptest.NewRequest("POST", u.GetUrl(), bytes.NewReader(data))
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
g := makeGin()
|
||||||
|
g.ServeHTTP(w, req)
|
||||||
|
|
||||||
|
if w.Code != http.StatusOK {
|
||||||
|
t.Errorf("Home page didn't return %v", http.StatusOK)
|
||||||
|
} else {
|
||||||
|
t.Log("OKOKOK")
|
||||||
|
data, _ := ioutil.ReadAll(w.Body)
|
||||||
|
t.Log(string(data))
|
||||||
|
}
|
||||||
|
}
|
52
communicate/communicator.go
Normal file
52
communicate/communicator.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package communicate
|
||||||
|
|
||||||
|
import (
|
||||||
|
//"bytes"
|
||||||
|
//"compress/gzip"
|
||||||
|
//"git.loafle.net/overflow/discovery/communicate/events"
|
||||||
|
//"git.loafle.net/overflow/central/client/events"
|
||||||
|
)
|
||||||
|
|
||||||
|
type communicator struct {
|
||||||
|
//Queue chan *events.Event
|
||||||
|
RootURL string
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//func NewCommunicator() *communicator {
|
||||||
|
// return &communicator{Queue: make(chan *events.Event, 10)}
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func (c *communicator) addEvent(e *events.Event) {
|
||||||
|
// c.Queue <- e
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func CompressDataGzip(data []byte) []byte {
|
||||||
|
// var b bytes.Buffer
|
||||||
|
// w := gzip.NewWriter(&b)
|
||||||
|
// w.Write(data)
|
||||||
|
// w.Close()
|
||||||
|
// return b.Bytes()
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func (c *communicator) start() {
|
||||||
|
// go func() {
|
||||||
|
// for e := range c.Queue {
|
||||||
|
// go func(event *events.Event) {
|
||||||
|
// // m := event.Data.(events.URLMaker)
|
||||||
|
// // data, _ := json.Marshal(event)
|
||||||
|
// //
|
||||||
|
// // // compress , accept-encoding : gzip
|
||||||
|
// // //res, err := http.Post(GetRootURL()+m.GetUrl(), "application/json", bytes.NewBuffer(CompressDataGzip(data)))
|
||||||
|
// // //res, err := http.Post(GetRootURL()+m.GetUrl(), "application/json", bytes.NewBuffer(data))
|
||||||
|
// //
|
||||||
|
// // // todo timeout,error
|
||||||
|
// // if err != nil {
|
||||||
|
// // return
|
||||||
|
// // }
|
||||||
|
// // if res.StatusCode != 200 && res.StatusCode != 201 {
|
||||||
|
// //
|
||||||
|
// // }
|
||||||
|
// }(e)
|
||||||
|
// }
|
||||||
|
// }()
|
||||||
|
//}
|
26
communicate/communicator_test.go
Normal file
26
communicate/communicator_test.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package communicate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"git.loafle.net/overflow/central/client/events"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types/timestamp"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEventCollector(t *testing.T) {
|
||||||
|
ev := events.Event{}
|
||||||
|
|
||||||
|
ev.EventType = "install"
|
||||||
|
ev.Time = timestamp.Now()
|
||||||
|
ev.Collector_id = "1111111"
|
||||||
|
ev.Data = events.CollectorInstallEvent{Version: "2.2"}
|
||||||
|
|
||||||
|
bb, _ := json.Marshal(ev)
|
||||||
|
|
||||||
|
//com := CompressTest(CompressDataGzip, UnCompressDataGzip, bb)
|
||||||
|
|
||||||
|
http.Post("http://localhost:9090/_api/collector/event/status/install", "application/json", bytes.NewBuffer(bb))
|
||||||
|
}
|
57
conf/conf.go
Normal file
57
conf/conf.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package conf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/cihub/seelog"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
"io/ioutil"
|
||||||
|
//"git.loafle.net/overflow/discovery/communicate"
|
||||||
|
//"git.loafle.net/overflow/overflow.collector_backup2/src/git.loafle.net/overflow/discovery/communicate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Central struct {
|
||||||
|
Address string
|
||||||
|
Port int
|
||||||
|
}
|
||||||
|
Log_Path string
|
||||||
|
}
|
||||||
|
|
||||||
|
var c Config
|
||||||
|
|
||||||
|
func LoadConfig(f string) error {
|
||||||
|
if len(f) <= 0 {
|
||||||
|
return errors.New("conf file path is nil")
|
||||||
|
}
|
||||||
|
c = Config{}
|
||||||
|
data, err := ioutil.ReadFile(f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = yaml.Unmarshal([]byte(data), &c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = loadLogConfig(c.Log_Path)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Log Config Load Error : ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println(c)
|
||||||
|
|
||||||
|
//communicate.SetRootURL(c.Central.Address)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadLogConfig(path string) error {
|
||||||
|
|
||||||
|
l, err := seelog.LoggerFromConfigAsFile(path)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error : ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
seelog.ReplaceLogger(l)
|
||||||
|
return err
|
||||||
|
}
|
1
core/device/hw/cpu.go
Normal file
1
core/device/hw/cpu.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package hw
|
1
core/device/hw/hdd.go
Normal file
1
core/device/hw/hdd.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package hw
|
1
core/device/hw/memory.go
Normal file
1
core/device/hw/memory.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package hw
|
10
core/device/hw/nic.go
Normal file
10
core/device/hw/nic.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package hw
|
||||||
|
|
||||||
|
type NIC struct {
|
||||||
|
Cidr int32
|
||||||
|
Dns [2]int64
|
||||||
|
Gateway int64
|
||||||
|
Iface string
|
||||||
|
Ip int64
|
||||||
|
Mac int64
|
||||||
|
}
|
6
core/device/sw/application.go
Normal file
6
core/device/sw/application.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package sw
|
||||||
|
|
||||||
|
type Application struct {
|
||||||
|
Name string
|
||||||
|
Version string
|
||||||
|
}
|
7
core/device/sw/os.go
Normal file
7
core/device/sw/os.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package sw
|
||||||
|
|
||||||
|
type OS struct {
|
||||||
|
Name string
|
||||||
|
Version string
|
||||||
|
DisplayName string
|
||||||
|
}
|
7
core/device/sw/process.go
Normal file
7
core/device/sw/process.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package sw
|
||||||
|
|
||||||
|
type Process struct {
|
||||||
|
Command string
|
||||||
|
Pid int
|
||||||
|
User string
|
||||||
|
}
|
5
core/net/host.go
Normal file
5
core/net/host.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package net
|
||||||
|
|
||||||
|
type Host struct {
|
||||||
|
Name string
|
||||||
|
}
|
6
core/net/port.go
Normal file
6
core/net/port.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package net
|
||||||
|
|
||||||
|
type Port struct {
|
||||||
|
Number int16
|
||||||
|
PortType string
|
||||||
|
}
|
6
core/net/service.go
Normal file
6
core/net/service.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package net
|
||||||
|
|
||||||
|
type Service struct {
|
||||||
|
CryptoType string
|
||||||
|
Name string
|
||||||
|
}
|
6
core/net/zone.go
Normal file
6
core/net/zone.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package net
|
||||||
|
|
||||||
|
type Zone struct {
|
||||||
|
Cidr int32
|
||||||
|
Ip int64
|
||||||
|
}
|
64
core/pcapwrapper/pcap.go
Normal file
64
core/pcapwrapper/pcap.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package pcap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var pcaps map[string]*PcapWrapper = nil
|
||||||
|
|
||||||
|
var m *sync.Mutex
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
pcaps = make(map[string]*PcapWrapper, 0)
|
||||||
|
m = new(sync.Mutex)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetInstance(zone *types.DiscoveryZone) (*PcapWrapper, error) {
|
||||||
|
m.Lock()
|
||||||
|
//
|
||||||
|
var p *PcapWrapper
|
||||||
|
var ok bool
|
||||||
|
p, ok = pcaps[zone.CidrStr()]
|
||||||
|
if !ok {
|
||||||
|
p, err := newPcapWrapper(zone)
|
||||||
|
if err != nil {
|
||||||
|
m.Unlock()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pcaps[zone.CidrStr()] = p
|
||||||
|
m.Unlock()
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
m.Unlock()
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Release(zone *types.DiscoveryZone) {
|
||||||
|
|
||||||
|
m.Lock()
|
||||||
|
|
||||||
|
p, ok := pcaps[zone.CidrStr()]
|
||||||
|
if ok == true {
|
||||||
|
|
||||||
|
if d := p.release(); d == true {
|
||||||
|
|
||||||
|
delete(pcaps, zone.CidrStr())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
m.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveAll() {
|
||||||
|
m.Lock()
|
||||||
|
if pcaps == nil {
|
||||||
|
m.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for k, v := range pcaps {
|
||||||
|
v.destroy()
|
||||||
|
delete(pcaps, k)
|
||||||
|
}
|
||||||
|
m.Unlock()
|
||||||
|
}
|
45
core/pcapwrapper/pcap_test.go
Normal file
45
core/pcapwrapper/pcap_test.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package pcap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/zone"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMapRemove(t *testing.T) {
|
||||||
|
|
||||||
|
m := make(map[string]string, 0)
|
||||||
|
|
||||||
|
m["1"] = "1"
|
||||||
|
m["2"] = "2"
|
||||||
|
m["3"] = "3"
|
||||||
|
assert.Equal(t, 3, len(m))
|
||||||
|
|
||||||
|
delete(m, "1")
|
||||||
|
assert.Equal(t, 2, len(m))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPcapNewRemove(t *testing.T) {
|
||||||
|
|
||||||
|
z := zone.NewZone()
|
||||||
|
|
||||||
|
GetInstance(z[0])
|
||||||
|
assert.Equal(t, 1, len(pcaps))
|
||||||
|
|
||||||
|
Release(z[0])
|
||||||
|
assert.Equal(t, 0, len(pcaps))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveAll(t *testing.T) {
|
||||||
|
|
||||||
|
z := zone.NewZone()
|
||||||
|
|
||||||
|
GetInstance(z[0])
|
||||||
|
fmt.Println("a9se8rypasd")
|
||||||
|
assert.Equal(t, 1, len(pcaps))
|
||||||
|
|
||||||
|
RemoveAll()
|
||||||
|
fmt.Println("a9se8rypasd")
|
||||||
|
assert.Equal(t, 0, len(pcaps))
|
||||||
|
}
|
272
core/pcapwrapper/pcapwrapper.go
Normal file
272
core/pcapwrapper/pcapwrapper.go
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
package pcap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/google/gopacket/pcap"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PcapWrapper struct {
|
||||||
|
m *sync.RWMutex
|
||||||
|
HND *pcap.Handle
|
||||||
|
refCount int
|
||||||
|
stop chan bool
|
||||||
|
arps []chan *layers.ARP
|
||||||
|
tcps map[string][]chan *layers.TCP
|
||||||
|
udps map[string][]chan gopacket.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPcapWrapper(zone *types.DiscoveryZone) (*PcapWrapper, error) {
|
||||||
|
|
||||||
|
// new pcap handle
|
||||||
|
handle, err := pcap.OpenLive(zone.Iface, 65536, true, pcap.BlockForever)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// set filter
|
||||||
|
// todo add tcp, udp filter
|
||||||
|
err = handle.SetBPFFilter("arp and src net " + zone.CidrStr() + " or (((tcp[tcpflags] & (tcp-syn|tcp-ack) != 0) or (tcp[tcpflags] & (tcp-rst) != 0)) and port 60000) or udp ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// make pcap wrapper
|
||||||
|
w := &PcapWrapper{
|
||||||
|
HND: handle,
|
||||||
|
arps: make([]chan *layers.ARP, 0),
|
||||||
|
tcps: make(map[string][]chan *layers.TCP, 0),
|
||||||
|
udps: make(map[string][]chan gopacket.Packet, 0),
|
||||||
|
stop: make(chan bool),
|
||||||
|
refCount: 1,
|
||||||
|
m: new(sync.RWMutex),
|
||||||
|
}
|
||||||
|
|
||||||
|
// start recv goroutine
|
||||||
|
go w.recvPacket()
|
||||||
|
return w, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// arp channel funcs
|
||||||
|
func (p *PcapWrapper) OpenARPChannel() chan *layers.ARP {
|
||||||
|
c := make(chan *layers.ARP, 0)
|
||||||
|
p.arps = append(p.arps, c)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PcapWrapper) CloseARPChannel(ch chan *layers.ARP) {
|
||||||
|
|
||||||
|
var n int = -1
|
||||||
|
for index, value := range p.arps {
|
||||||
|
if ch == value {
|
||||||
|
close(ch)
|
||||||
|
n = index
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if n != -1 {
|
||||||
|
p.arps = append(p.arps[:n], p.arps[n+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tcp channel funcs
|
||||||
|
func (p *PcapWrapper) OpenTCPChannel(host *types.DiscoveryHost) chan *layers.TCP {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
_, ok := p.tcps[host.Ip_]
|
||||||
|
if !ok {
|
||||||
|
p.tcps[host.Ip_] = make([]chan *layers.TCP, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := make(chan *layers.TCP, 0)
|
||||||
|
p.tcps[host.Ip_] = append(p.tcps[host.Ip_], c)
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
func (p *PcapWrapper) CloseTCPChannel(host *types.DiscoveryHost, ch chan *layers.TCP) {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
|
||||||
|
_, ok := p.tcps[host.Ip_]
|
||||||
|
if ok {
|
||||||
|
var n int = -1
|
||||||
|
for index, value := range p.tcps[host.Ip_] {
|
||||||
|
if ch == value {
|
||||||
|
close(ch)
|
||||||
|
n = index
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if n != -1 {
|
||||||
|
p.tcps[host.Ip_] = append(p.tcps[host.Ip_][:n], p.tcps[host.Ip_][n+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// udp channel funcs
|
||||||
|
func (p *PcapWrapper) OpenUDPChannel(host *types.DiscoveryHost) chan gopacket.Packet {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
|
||||||
|
_, ok := p.udps[host.Ip_]
|
||||||
|
if !ok {
|
||||||
|
p.udps[host.Ip_] = make([]chan gopacket.Packet, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := make(chan gopacket.Packet, 0)
|
||||||
|
p.udps[host.Ip_] = append(p.udps[host.Ip_], c)
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PcapWrapper) CloseUDPChannel(host *types.DiscoveryHost, ch chan gopacket.Packet) {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
|
||||||
|
_, ok := p.udps[host.Ip_]
|
||||||
|
if ok {
|
||||||
|
var n int = -1
|
||||||
|
for index, value := range p.udps[host.Ip_] {
|
||||||
|
if ch == value {
|
||||||
|
close(ch)
|
||||||
|
n = index
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if n != -1 {
|
||||||
|
p.udps[host.Ip_] = append(p.udps[host.Ip_][:n], p.udps[host.Ip_][n+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PcapWrapper) incRefCount() {
|
||||||
|
p.refCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PcapWrapper) release() bool {
|
||||||
|
p.refCount--
|
||||||
|
if p.refCount == 0 {
|
||||||
|
p.destroy()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PcapWrapper) closeChannels() {
|
||||||
|
|
||||||
|
// close stop
|
||||||
|
if p.stop != nil {
|
||||||
|
close(p.stop)
|
||||||
|
p.stop = nil
|
||||||
|
}
|
||||||
|
// close tcp channels
|
||||||
|
for k, v := range p.tcps {
|
||||||
|
for _, ch := range v {
|
||||||
|
close(ch)
|
||||||
|
}
|
||||||
|
v = v[:0]
|
||||||
|
delete(p.tcps, k)
|
||||||
|
}
|
||||||
|
// close udp channels
|
||||||
|
for k, v := range p.udps {
|
||||||
|
for _, ch := range v {
|
||||||
|
close(ch)
|
||||||
|
}
|
||||||
|
v = v[:0]
|
||||||
|
delete(p.udps, k)
|
||||||
|
}
|
||||||
|
// close arp channels
|
||||||
|
for _, v := range p.arps {
|
||||||
|
close(v)
|
||||||
|
}
|
||||||
|
p.arps = p.arps[:0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PcapWrapper) destroy() {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
p.closeChannels()
|
||||||
|
go p.HND.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
const arptype = 0
|
||||||
|
const tcptype = 1
|
||||||
|
const udptype = 2
|
||||||
|
|
||||||
|
func (p *PcapWrapper) recvPacket() {
|
||||||
|
|
||||||
|
src := gopacket.NewPacketSource(p.HND, layers.LayerTypeEthernet)
|
||||||
|
in := src.Packets()
|
||||||
|
|
||||||
|
for {
|
||||||
|
var packet gopacket.Packet
|
||||||
|
select {
|
||||||
|
case <-p.stop:
|
||||||
|
return
|
||||||
|
case packet = <-in:
|
||||||
|
ptype := CheckProtocol(packet)
|
||||||
|
|
||||||
|
if ptype == arptype {
|
||||||
|
if p.arps != nil {
|
||||||
|
arpLayer := packet.Layer(layers.LayerTypeARP)
|
||||||
|
arp := arpLayer.(*layers.ARP)
|
||||||
|
for _, c := range p.arps {
|
||||||
|
c <- arp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ptype == tcptype {
|
||||||
|
ipLayer := packet.Layer(layers.LayerTypeIPv4)
|
||||||
|
ip := ipLayer.(*layers.IPv4).SrcIP.String()
|
||||||
|
p.m.RLock()
|
||||||
|
chans, ok := p.tcps[ip]
|
||||||
|
if ok {
|
||||||
|
layer := packet.Layer(layers.LayerTypeTCP)
|
||||||
|
tcp, _ := layer.(*layers.TCP)
|
||||||
|
for _, c := range chans {
|
||||||
|
c <- tcp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.m.RUnlock()
|
||||||
|
} else if ptype == udptype {
|
||||||
|
ipLayer := packet.Layer(layers.LayerTypeIPv4)
|
||||||
|
if ipLayer != nil {
|
||||||
|
ip := ipLayer.(*layers.IPv4).SrcIP.String()
|
||||||
|
p.m.RLock()
|
||||||
|
chans, ok := p.udps[ip]
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
for _, c := range chans {
|
||||||
|
c <- packet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.m.RUnlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func CheckProtocol(packet gopacket.Packet) int {
|
||||||
|
if packet == nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
layer := packet.Layer(layers.LayerTypeARP)
|
||||||
|
if layer != nil {
|
||||||
|
return arptype
|
||||||
|
}
|
||||||
|
|
||||||
|
layer = packet.Layer(layers.LayerTypeTCP)
|
||||||
|
if layer != nil {
|
||||||
|
if _, ok := layer.(*layers.TCP); ok {
|
||||||
|
return tcptype
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layer = packet.Layer(layers.LayerTypeUDP)
|
||||||
|
if layer != nil {
|
||||||
|
if _, ok := layer.(*layers.UDP); ok {
|
||||||
|
return udptype
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
76
core/pcapwrapper/pcapwrapper_test.go
Normal file
76
core/pcapwrapper/pcapwrapper_test.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package pcap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestChanKey(t *testing.T) {
|
||||||
|
|
||||||
|
ch := make([]chan struct{}, 10)
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
ch[i] = make(chan struct{})
|
||||||
|
}
|
||||||
|
|
||||||
|
c := ch[5]
|
||||||
|
|
||||||
|
for n, v := range ch {
|
||||||
|
if c == v {
|
||||||
|
fmt.Println(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
close(ch[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteSlice(t *testing.T) {
|
||||||
|
|
||||||
|
a := make([]int, 0)
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
a = append(a, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(a)
|
||||||
|
|
||||||
|
i := 4
|
||||||
|
|
||||||
|
a = append(a[:i], a[i+1:]...)
|
||||||
|
t.Log(a)
|
||||||
|
|
||||||
|
a = a[:0]
|
||||||
|
t.Log(len(a))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapForRange(t *testing.T) {
|
||||||
|
a := make(map[int]int, 0)
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
a[i] = i + 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
for v, vv := range a {
|
||||||
|
t.Log(v)
|
||||||
|
t.Log(vv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const arptest = 0
|
||||||
|
|
||||||
|
func closechan(s interface{}, t int) {
|
||||||
|
if t == arptest {
|
||||||
|
close(s.(chan *layers.ARP))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCloseChannels(t *testing.T) {
|
||||||
|
a := make(chan *layers.ARP, 0)
|
||||||
|
closechan(a, arptest)
|
||||||
|
|
||||||
|
}
|
116
core/scan/host/host.go
Normal file
116
core/scan/host/host.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package host
|
||||||
|
|
||||||
|
import (
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/google/gopacket/pcap"
|
||||||
|
p "git.loafle.net/overflow/discovery/core/pcapwrapper"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"git.loafle.net/overflow/discovery/util/converter"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ArpRecvHandler func(arp *layers.ARP)
|
||||||
|
type HistoryHandler func(ip net.IP)
|
||||||
|
|
||||||
|
// discovery
|
||||||
|
func Scan(zone *types.DiscoveryZone, recvhandler ArpRecvHandler, historyhandler HistoryHandler) error {
|
||||||
|
// get channel by zone
|
||||||
|
w, err := p.GetInstance(zone)
|
||||||
|
if err != nil {
|
||||||
|
}
|
||||||
|
|
||||||
|
//// save singleton channel
|
||||||
|
ch := w.OpenARPChannel()
|
||||||
|
//
|
||||||
|
//// read channel
|
||||||
|
go func() {
|
||||||
|
for data := range ch {
|
||||||
|
recvhandler(data)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
rangeHost := MakeTargetHostRange(zone)
|
||||||
|
//// send arp
|
||||||
|
err = sendARP(w.HND, rangeHost, zone, historyhandler)
|
||||||
|
if err != nil {
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//// wait
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
//
|
||||||
|
//// release arp
|
||||||
|
w.CloseARPChannel(ch)
|
||||||
|
p.Release(zone)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendARP(handle *pcap.Handle, rangeHost []net.IP, zone *types.DiscoveryZone, hh HistoryHandler) error {
|
||||||
|
|
||||||
|
hw := zone.Mac
|
||||||
|
localIp := converter.IntToIP4(zone.Ip)
|
||||||
|
|
||||||
|
eth := makeEthernetPacket(converter.IntToMac(hw))
|
||||||
|
arp := makeArpPacket(converter.IntToMac(hw), localIp.To4())
|
||||||
|
opts := gopacket.SerializeOptions{FixLengths: true, ComputeChecksums: true}
|
||||||
|
|
||||||
|
buf := gopacket.NewSerializeBuffer()
|
||||||
|
|
||||||
|
for _, targetHost := range rangeHost {
|
||||||
|
if hh != nil {
|
||||||
|
hh(targetHost)
|
||||||
|
}
|
||||||
|
arp.DstProtAddress = []byte(targetHost)
|
||||||
|
gopacket.SerializeLayers(buf, opts, ð, &arp)
|
||||||
|
if err := handle.WritePacketData(buf.Bytes()); err != nil {
|
||||||
|
log.Critical("ARP Send Error : ", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
time.Sleep(time.Microsecond * 500)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeTargetHostRange(zone *types.DiscoveryZone) []net.IP {
|
||||||
|
|
||||||
|
//returnSlice := make([]net.IP, 0)
|
||||||
|
//
|
||||||
|
//for i := zone.FirstScanRange; i <= zone.LastScanRange; i++ {
|
||||||
|
// cIp := converter.IntToIP4(i)
|
||||||
|
// returnSlice = append(returnSlice, cIp)
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//return returnSlice
|
||||||
|
|
||||||
|
minIp := converter.IntToIP4(zone.FirstScanRange).To4()
|
||||||
|
maxIp := converter.IntToIP4(zone.LastScanRange).To4()
|
||||||
|
|
||||||
|
returnSlice := make([]net.IP, 0)
|
||||||
|
for i := minIp[3]; i <= maxIp[3]; i++ {
|
||||||
|
returnSlice = append(returnSlice, []byte{minIp[0], minIp[1], minIp[2], i})
|
||||||
|
}
|
||||||
|
return returnSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeArpPacket(hw net.HardwareAddr, ip net.IP) layers.ARP {
|
||||||
|
return layers.ARP{
|
||||||
|
AddrType: layers.LinkTypeEthernet,
|
||||||
|
Protocol: layers.EthernetTypeIPv4,
|
||||||
|
HwAddressSize: 6,
|
||||||
|
ProtAddressSize: 4,
|
||||||
|
Operation: layers.ARPRequest,
|
||||||
|
SourceHwAddress: []byte(hw),
|
||||||
|
SourceProtAddress: []byte(ip),
|
||||||
|
DstHwAddress: []byte{0, 0, 0, 0, 0, 0},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeEthernetPacket(hw net.HardwareAddr) layers.Ethernet {
|
||||||
|
return layers.Ethernet{
|
||||||
|
SrcMAC: hw,
|
||||||
|
DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||||
|
EthernetType: layers.EthernetTypeARP,
|
||||||
|
}
|
||||||
|
}
|
1
core/scan/port/port.go
Normal file
1
core/scan/port/port.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package port
|
1
core/scan/port/port_test.go
Normal file
1
core/scan/port/port_test.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package port
|
135
core/scan/port/tcp/tcp.go
Normal file
135
core/scan/port/tcp/tcp.go
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
package tcp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types/timestamp"
|
||||||
|
|
||||||
|
//"git.loafle.net/overflow/central/client/events"
|
||||||
|
//"git.loafle.net/overflow/discovery/communicate"
|
||||||
|
pw "git.loafle.net/overflow/discovery/core/pcapwrapper"
|
||||||
|
"git.loafle.net/overflow/discovery/util/converter"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tcpRecvCallback func(tcp *layers.TCP)
|
||||||
|
|
||||||
|
func Scan(host *types.DiscoveryHost, tcpCB tcpRecvCallback) {
|
||||||
|
|
||||||
|
//Recv(host.Zone, PcapTcpHandler{})
|
||||||
|
|
||||||
|
w, err := pw.GetInstance(host.Zone)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ch := w.OpenTCPChannel(host)
|
||||||
|
|
||||||
|
//read channel
|
||||||
|
go func() {
|
||||||
|
for data := range ch {
|
||||||
|
tcpCB(data)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
Send(host, nil)
|
||||||
|
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
|
||||||
|
//communicate.Send(events.NewEvent(events.CENTRAL_EVENT, events.NewPortEndEvent(host.Zone.CidrInt64(), host.Ip, host.Histories, types.TYPE_TCP)))
|
||||||
|
|
||||||
|
w.CloseTCPChannel(host, ch)
|
||||||
|
pw.Release(host.Zone)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Check(host *types.DiscoveryHost, ports []*types.DiscoveryPort) {
|
||||||
|
|
||||||
|
//Recv(host.Zone, PcapTcpHandler{})
|
||||||
|
Send(host, ports)
|
||||||
|
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Send(host *types.DiscoveryHost, ports []*types.DiscoveryPort) {
|
||||||
|
|
||||||
|
portPacket := CreatePortPacket(host.Zone, host)
|
||||||
|
|
||||||
|
defer portPacket.PacketConn.Close()
|
||||||
|
|
||||||
|
//communicate.Send(events.NewEvent(events.CENTRAL_EVENT, events.NewPortStartEvent(host.Zone.CidrInt64(), host.Ip, 10000, types.TYPE_TCP)))
|
||||||
|
host.PortDiscoveryTime = timestamp.Now()
|
||||||
|
|
||||||
|
if ports == nil {
|
||||||
|
for portNumber := host.FirstScanRange; portNumber <= host.LastScanRange; portNumber++ {
|
||||||
|
SendPortPacket(portNumber, portPacket, host)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, port := range ports {
|
||||||
|
SendPortPacket(port.Number, portPacket, host)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type PortPacket struct {
|
||||||
|
Ip *layers.IPv4
|
||||||
|
Tcp *layers.TCP
|
||||||
|
Opts gopacket.SerializeOptions
|
||||||
|
PacketConn net.PacketConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreatePortPacket(zone *types.DiscoveryZone, host *types.DiscoveryHost) *PortPacket {
|
||||||
|
|
||||||
|
pp := &PortPacket{}
|
||||||
|
|
||||||
|
pp.Ip = &layers.IPv4{
|
||||||
|
SrcIP: converter.IntToIP4(zone.Ip),
|
||||||
|
DstIP: net.ParseIP(host.Ip_),
|
||||||
|
Version: 4,
|
||||||
|
TTL: 64,
|
||||||
|
Protocol: layers.IPProtocolTCP,
|
||||||
|
}
|
||||||
|
pp.Tcp = &layers.TCP{
|
||||||
|
SrcPort: 60000,
|
||||||
|
DstPort: 0, // will be incremented during the scan
|
||||||
|
SYN: true,
|
||||||
|
Seq: 0,
|
||||||
|
}
|
||||||
|
pp.Opts = gopacket.SerializeOptions{
|
||||||
|
ComputeChecksums: true,
|
||||||
|
FixLengths: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := net.ListenPacket("ip4:tcp", "0.0.0.0")
|
||||||
|
if err != nil {
|
||||||
|
log.Error("SYN create socket error : " + err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pp.PacketConn = conn
|
||||||
|
|
||||||
|
return pp
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendPortPacket(port uint16, pp *PortPacket, host *types.DiscoveryHost) {
|
||||||
|
|
||||||
|
pp.Tcp.DstPort = layers.TCPPort(port)
|
||||||
|
pp.Tcp.SetNetworkLayerForChecksum(pp.Ip)
|
||||||
|
|
||||||
|
buf := gopacket.NewSerializeBuffer()
|
||||||
|
if err := gopacket.SerializeLayers(buf, pp.Opts, pp.Tcp); err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := pp.PacketConn.WriteTo(buf.Bytes(), &net.IPAddr{IP: net.ParseIP(host.Ip_)}); err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
types.NewPortScanHistory(host, port, types.TYPE_TCP, types.SEND, "")
|
||||||
|
time.Sleep(time.Microsecond * 200)
|
||||||
|
}
|
65
core/scan/port/tcp/tcp_test.go
Normal file
65
core/scan/port/tcp/tcp_test.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package tcp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types/timestamp"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPortScan(t *testing.T) {
|
||||||
|
|
||||||
|
zone := types.NewZones()[0]
|
||||||
|
|
||||||
|
hh := &types.DiscoveryHost{
|
||||||
|
Ip_: "192.168.1.215",
|
||||||
|
Ports_: make(map[string]*types.DiscoveryPort, 100),
|
||||||
|
Ip: 111,
|
||||||
|
Mac: 222,
|
||||||
|
CreateDate: timestamp.Now(),
|
||||||
|
UpdateDate: timestamp.Now(),
|
||||||
|
Zone:zone,
|
||||||
|
FirstScanRange:1,
|
||||||
|
LastScanRange:100,
|
||||||
|
}
|
||||||
|
|
||||||
|
Scan(hh, func(tcp *layers.TCP) {
|
||||||
|
fmt.Println(tcp)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPortCheck(t *testing.T) {
|
||||||
|
|
||||||
|
zone := types.NewZones()[0]
|
||||||
|
|
||||||
|
hh := &types.DiscoveryHost{
|
||||||
|
Ip_: "192.168.1.215",
|
||||||
|
Ports_: make(map[string]*types.DiscoveryPort, 100),
|
||||||
|
Ip: 111,
|
||||||
|
Mac: 222,
|
||||||
|
CreateDate: timestamp.Now(),
|
||||||
|
UpdateDate: timestamp.Now(),
|
||||||
|
Zone:zone,
|
||||||
|
FirstScanRange:1,
|
||||||
|
LastScanRange:100,
|
||||||
|
}
|
||||||
|
|
||||||
|
var ports []*types.DiscoveryPort
|
||||||
|
|
||||||
|
ports = append(ports, &types.DiscoveryPort{Number:1})
|
||||||
|
ports = append(ports, &types.DiscoveryPort{Number:3})
|
||||||
|
ports = append(ports, &types.DiscoveryPort{Number:5})
|
||||||
|
ports = append(ports, &types.DiscoveryPort{Number:7})
|
||||||
|
ports = append(ports, &types.DiscoveryPort{Number:9})
|
||||||
|
ports = append(ports, &types.DiscoveryPort{Number:11})
|
||||||
|
|
||||||
|
|
||||||
|
Check(hh, ports)
|
||||||
|
|
||||||
|
}
|
105
core/scan/port/udp/udp.go
Normal file
105
core/scan/port/udp/udp.go
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package udp
|
||||||
|
|
||||||
|
import (
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
|
||||||
|
//"git.loafle.net/overflow/central/client/events"
|
||||||
|
//"git.loafle.net/overflow/discovery/communicate"
|
||||||
|
pw "git.loafle.net/overflow/discovery/core/pcapwrapper"
|
||||||
|
)
|
||||||
|
|
||||||
|
type udpRecvCallback func(packet gopacket.Packet)
|
||||||
|
|
||||||
|
func Scan(host *types.DiscoveryHost, udpCB udpRecvCallback) {
|
||||||
|
|
||||||
|
//Recv(host.Zone, PcapTcpHandler{})
|
||||||
|
|
||||||
|
w, err := pw.GetInstance(host.Zone)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ch := w.OpenUDPChannel(host)
|
||||||
|
|
||||||
|
//read channel
|
||||||
|
go func() {
|
||||||
|
for data := range ch {
|
||||||
|
udpCB(data)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
Send(host, nil)
|
||||||
|
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
|
||||||
|
//communicate.Send(events.NewEvent(events.CENTRAL_EVENT, events.NewPortEndEvent(host.Zone.CidrInt64(), host.Ip, host.Histories, types.TYPE_UDP)))
|
||||||
|
|
||||||
|
//good game
|
||||||
|
w.CloseUDPChannel(host, ch)
|
||||||
|
pw.Release(host.Zone)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Check(host *types.DiscoveryHost, ports []*types.DiscoveryPort) {
|
||||||
|
|
||||||
|
//Recv(host.Zone, PcapTcpHandler{})
|
||||||
|
Send(host, ports)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Send(host *types.DiscoveryHost, ports []*types.DiscoveryPort) {
|
||||||
|
|
||||||
|
mats := matcher.GetUdpMatchers()
|
||||||
|
|
||||||
|
conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//communicate.Send(events.NewEvent(events.CENTRAL_EVENT, events.NewPortStartEvent(host.Zone.CidrInt64(), host.Ip, 10000, types.TYPE_UDP)))
|
||||||
|
|
||||||
|
for indexI := 0; indexI < len(mats); indexI++ {
|
||||||
|
|
||||||
|
mat := mats[indexI]
|
||||||
|
|
||||||
|
if ports == nil {
|
||||||
|
for portNumber := host.FirstScanRange; portNumber <= host.LastScanRange; portNumber++ {
|
||||||
|
SendUDPPortPacket(host, conn, mat, portNumber)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, port := range ports {
|
||||||
|
SendUDPPortPacket(host, conn, mat, port.Number)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.Close()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendUDPPortPacket(host *types.DiscoveryHost, conn *net.UDPConn, mat matcher.UDPMatcher, pn uint16) {
|
||||||
|
|
||||||
|
if mat.IsSend(int(pn)) != true {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
addr := &net.UDPAddr{IP: net.ParseIP(host.Ip_), Port: int(pn)}
|
||||||
|
for i := 0; i < mat.PacketCount(); i++ {
|
||||||
|
var p *packet.Packet = mat.Packet(i)
|
||||||
|
if _, err := conn.WriteToUDP(p.Buffer, addr); err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ph := types.NewPortScanHistory(host, pn, types.TYPE_UDP, types.SEND, "")
|
||||||
|
host.AddHistory(ph)
|
||||||
|
|
||||||
|
time.Sleep(time.Microsecond * 200)
|
||||||
|
}
|
33
core/scan/port/udp/udp_test.go
Normal file
33
core/scan/port/udp/udp_test.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package udp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types/timestamp"
|
||||||
|
"fmt"
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUDPPortScan(t *testing.T) {
|
||||||
|
|
||||||
|
zone := types.NewZones()[0]
|
||||||
|
|
||||||
|
hh := &types.DiscoveryHost{
|
||||||
|
Ip_: "192.168.1.215",
|
||||||
|
Ports_: make(map[string]*types.DiscoveryPort, 100),
|
||||||
|
Ip: 111,
|
||||||
|
Mac: 222,
|
||||||
|
CreateDate: timestamp.Now(),
|
||||||
|
UpdateDate: timestamp.Now(),
|
||||||
|
Zone:zone,
|
||||||
|
FirstScanRange:1,
|
||||||
|
LastScanRange:100,
|
||||||
|
}
|
||||||
|
|
||||||
|
Scan(hh, func(packet gopacket.Packet) {
|
||||||
|
fmt.Println(packet)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
}
|
67
core/scan/service/connfactory.go
Normal file
67
core/scan/service/connfactory.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConnFactory interface {
|
||||||
|
createSocket(ip string, port string) (net.Conn, error)
|
||||||
|
Type() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConnFactoryNormal struct {
|
||||||
|
t string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n ConnFactoryNormal) Type() string {
|
||||||
|
return n.t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n ConnFactoryNormal) createSocket(ip string, port string) (net.Conn, error) {
|
||||||
|
netinfo := ip + ":" + port
|
||||||
|
conn, err := net.DialTimeout("tcp", netinfo, time.Duration(3)*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = conn.SetDeadline(time.Now().Add(3 * time.Second))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return conn, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConnFactoryTLS struct {
|
||||||
|
t string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n ConnFactoryTLS) Type() string {
|
||||||
|
return n.t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n ConnFactoryTLS) createSocket(ip string, port string) (net.Conn, error) {
|
||||||
|
netinfo := ip + ":" + port
|
||||||
|
dialer := &net.Dialer{
|
||||||
|
Timeout: 3 * time.Second,
|
||||||
|
}
|
||||||
|
conn, err := tls.DialWithDialer(
|
||||||
|
dialer,
|
||||||
|
"tcp",
|
||||||
|
netinfo,
|
||||||
|
&tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: ip,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = conn.SetDeadline(time.Now().Add(3 * time.Second))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return conn, err
|
||||||
|
}
|
342
core/scan/service/matcher/activedirectory/activedirectory.go
Normal file
342
core/scan/service/matcher/activedirectory/activedirectory.go
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
package activedirectory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
AD_MESSAGE_ID = 0x99
|
||||||
|
AD_MESSAGE_ID_QUIT = 0x89
|
||||||
|
|
||||||
|
LDAP_VERSION3 = 3
|
||||||
|
|
||||||
|
LDAP_SUCCESS = 0x00
|
||||||
|
|
||||||
|
LDAP_REQ_BIND = 0x60
|
||||||
|
LDAP_RES_SEARCH_ENTRY = 0x64
|
||||||
|
|
||||||
|
LDAP_REQ_UNBIND = 0x42
|
||||||
|
LDAP_REQ_SEARCH = 0x63
|
||||||
|
|
||||||
|
LDAP_SCOPE_BASE = 0x00
|
||||||
|
LDAP_DEREF_NEVER = 0x00
|
||||||
|
LDAP_FILTER_PRESENT = 0x87
|
||||||
|
|
||||||
|
LDAP_RES_BIND = 0x61
|
||||||
|
|
||||||
|
LDAP_AUTH_SIMPLE = 0x80
|
||||||
|
|
||||||
|
AD_TYPE_STR = "supportedCapabilities"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AD_SENDaaa struct {
|
||||||
|
DefaultCode uint8
|
||||||
|
PackLenFlag uint8
|
||||||
|
PacketLen uint32
|
||||||
|
|
||||||
|
NextType1 uint8
|
||||||
|
NextTypeLength1 uint8
|
||||||
|
|
||||||
|
MessageId uint32
|
||||||
|
|
||||||
|
ProtocolOp uint8
|
||||||
|
PtLenFlag uint8
|
||||||
|
PtPacketLen uint32
|
||||||
|
NextType2 uint8
|
||||||
|
NextTypeLength2 uint8
|
||||||
|
|
||||||
|
Version uint8
|
||||||
|
|
||||||
|
NextType3 uint8
|
||||||
|
NextTypeLength3 uint8
|
||||||
|
Auth uint8
|
||||||
|
AuthLength uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type AD_SEND struct {
|
||||||
|
DefaultCode uint8
|
||||||
|
PackLenFlag uint8
|
||||||
|
|
||||||
|
PacketLen uint32
|
||||||
|
|
||||||
|
NextType1 uint8
|
||||||
|
NextType1Len uint8
|
||||||
|
|
||||||
|
MessageId uint32
|
||||||
|
|
||||||
|
ProtocolOp uint8
|
||||||
|
|
||||||
|
PtPackLenFlag uint8
|
||||||
|
PtPacketLen uint32
|
||||||
|
|
||||||
|
NextType2 uint8
|
||||||
|
NextType2Len uint8
|
||||||
|
NextType3 uint8
|
||||||
|
NextType3Len uint8
|
||||||
|
|
||||||
|
Scope uint8
|
||||||
|
|
||||||
|
NextType4 uint8
|
||||||
|
NextType4Len uint8
|
||||||
|
|
||||||
|
DerefAliases uint8
|
||||||
|
|
||||||
|
NextType5 uint8
|
||||||
|
NextType5Len uint8
|
||||||
|
|
||||||
|
SizeLimit uint8
|
||||||
|
|
||||||
|
NextType6 uint8
|
||||||
|
NextType6Len uint8
|
||||||
|
|
||||||
|
TimeLimit uint8
|
||||||
|
|
||||||
|
NextType7 uint8
|
||||||
|
NextType7Len uint8
|
||||||
|
|
||||||
|
TypesOnly uint8
|
||||||
|
|
||||||
|
Filter1 uint8
|
||||||
|
PresentLen uint8
|
||||||
|
|
||||||
|
Present [11]byte
|
||||||
|
|
||||||
|
DefaultCode2 uint8
|
||||||
|
Pack2LenFlag uint8
|
||||||
|
|
||||||
|
Packet2Len uint32
|
||||||
|
|
||||||
|
UnknwonCode8 uint8
|
||||||
|
ItemLength uint8
|
||||||
|
|
||||||
|
AttributeDescription [21]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type AD_QUIT struct {
|
||||||
|
DefaultCode uint8
|
||||||
|
PackLenFlag uint8
|
||||||
|
|
||||||
|
PacketLength uint32
|
||||||
|
|
||||||
|
NextType1 uint8
|
||||||
|
NextTypeLength1 uint8
|
||||||
|
|
||||||
|
MessageId uint32
|
||||||
|
|
||||||
|
ProtocolOp uint8
|
||||||
|
|
||||||
|
PtLenFlag uint8
|
||||||
|
PtPacketLen uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type AD_RECV struct {
|
||||||
|
DefaultCode uint8
|
||||||
|
PackLenFlag uint8
|
||||||
|
|
||||||
|
PacketLength uint32
|
||||||
|
|
||||||
|
NextType1 uint8
|
||||||
|
NextType1Len uint8
|
||||||
|
|
||||||
|
MessageId uint16
|
||||||
|
|
||||||
|
ProtocolOp uint8
|
||||||
|
|
||||||
|
PtPackLenFlag uint8
|
||||||
|
PtPacketLen uint32
|
||||||
|
|
||||||
|
NextType2 uint8
|
||||||
|
NextType2Len uint8
|
||||||
|
|
||||||
|
UnknwonCode21 uint8
|
||||||
|
UnknwonCode22 uint8
|
||||||
|
UnknwonCode23 uint8
|
||||||
|
UnknwonCode24 uint8
|
||||||
|
UnknwonCode25 uint8
|
||||||
|
UnknwonCode26 uint8
|
||||||
|
|
||||||
|
UnknwonCode31 uint8
|
||||||
|
UnknwonCode32 uint8
|
||||||
|
UnknwonCode33 uint8
|
||||||
|
UnknwonCode34 uint8
|
||||||
|
UnknwonCode35 uint8
|
||||||
|
UnknwonCode36 uint8
|
||||||
|
UnknwonCode37 uint8
|
||||||
|
|
||||||
|
TypeLength uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type ActiveDirectoryMatcher struct {
|
||||||
|
sendPackets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *ActiveDirectoryMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
buf.Write(packet.Buffer)
|
||||||
|
|
||||||
|
adRecv := AD_RECV{}
|
||||||
|
|
||||||
|
binary.Read(buf, binary.BigEndian, &adRecv)
|
||||||
|
|
||||||
|
if adRecv.MessageId != AD_MESSAGE_ID {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if adRecv.ProtocolOp != LDAP_RES_SEARCH_ENTRY {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
///AD_TYPE_STR
|
||||||
|
|
||||||
|
//
|
||||||
|
//if(packet->readCount_ < sizeof(AD_RECV) + recv->typeLength) {
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//char* type = new char[recv->typeLength];
|
||||||
|
//memcpy(type, packet->buffer_+sizeof(AD_RECV), recv->typeLength);
|
||||||
|
//std::string typeStr = type;
|
||||||
|
//
|
||||||
|
//delete[] type;
|
||||||
|
//if(typeStr.compare(AD_TYPE_STR) != 0) {
|
||||||
|
//return false;
|
||||||
|
//}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *ActiveDirectoryMatcher) PacketCount() int {
|
||||||
|
return len(ad.sendPackets)
|
||||||
|
}
|
||||||
|
func (ad *ActiveDirectoryMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return ad.sendPackets[index]
|
||||||
|
}
|
||||||
|
func (ad *ActiveDirectoryMatcher) ServiceName() string {
|
||||||
|
return "ActiveDirectory"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *ActiveDirectoryMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func (ad *ActiveDirectoryMatcher) IsNoResponse(index int) bool {
|
||||||
|
|
||||||
|
if index == 1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ad *ActiveDirectoryMatcher) IsPrePacket() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewActiveDirectoryMatcher() *ActiveDirectoryMatcher {
|
||||||
|
|
||||||
|
ls := AD_SEND{
|
||||||
|
DefaultCode: 0x30,
|
||||||
|
PackLenFlag: 0x84,
|
||||||
|
|
||||||
|
PacketLen: 0x47,
|
||||||
|
|
||||||
|
NextType1: 0x02,
|
||||||
|
NextType1Len: 0x04,
|
||||||
|
|
||||||
|
MessageId: AD_MESSAGE_ID,
|
||||||
|
|
||||||
|
ProtocolOp: LDAP_REQ_SEARCH,
|
||||||
|
|
||||||
|
PtPackLenFlag: 0x84,
|
||||||
|
PtPacketLen: 0x3b,
|
||||||
|
|
||||||
|
NextType2: 0x04,
|
||||||
|
NextType2Len: 0x00,
|
||||||
|
NextType3: 0x0a,
|
||||||
|
NextType3Len: 0x01,
|
||||||
|
|
||||||
|
Scope: LDAP_SCOPE_BASE,
|
||||||
|
|
||||||
|
NextType4: 0x0a,
|
||||||
|
NextType4Len: 0x01,
|
||||||
|
|
||||||
|
DerefAliases: LDAP_DEREF_NEVER,
|
||||||
|
|
||||||
|
NextType5: 0x02,
|
||||||
|
NextType5Len: 0x01,
|
||||||
|
|
||||||
|
SizeLimit: 0,
|
||||||
|
|
||||||
|
NextType6: 0x02,
|
||||||
|
NextType6Len: 0x01,
|
||||||
|
|
||||||
|
TimeLimit: 0x78,
|
||||||
|
|
||||||
|
NextType7: 0x01,
|
||||||
|
NextType7Len: 0x01,
|
||||||
|
|
||||||
|
TypesOnly: 0,
|
||||||
|
|
||||||
|
Filter1: LDAP_FILTER_PRESENT,
|
||||||
|
PresentLen: 0x0b,
|
||||||
|
|
||||||
|
//Present :0000,
|
||||||
|
|
||||||
|
DefaultCode2: 0x30,
|
||||||
|
Pack2LenFlag: 0x84,
|
||||||
|
|
||||||
|
Packet2Len: 0x17,
|
||||||
|
|
||||||
|
UnknwonCode8: 0x04,
|
||||||
|
ItemLength: 0x15,
|
||||||
|
|
||||||
|
//AttributeDescription:,
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(ls.Present[:], "objectclass")
|
||||||
|
copy(ls.AttributeDescription[:], AD_TYPE_STR)
|
||||||
|
|
||||||
|
mCache := new(bytes.Buffer)
|
||||||
|
binary.Write(mCache, binary.BigEndian, ls)
|
||||||
|
|
||||||
|
sendByte1 := mCache.Bytes()
|
||||||
|
|
||||||
|
adm := ActiveDirectoryMatcher{
|
||||||
|
//sendPackets: make([][]byte, 2),
|
||||||
|
}
|
||||||
|
|
||||||
|
pp := packet.NewPacket(sendByte1, len(sendByte1))
|
||||||
|
|
||||||
|
adm.sendPackets = append(adm.sendPackets, pp)
|
||||||
|
|
||||||
|
aq := AD_QUIT{
|
||||||
|
DefaultCode: 0x30,
|
||||||
|
PackLenFlag: 0x84,
|
||||||
|
PacketLength: 0x0c,
|
||||||
|
NextType1: 0x02,
|
||||||
|
NextTypeLength1: 0x04,
|
||||||
|
MessageId: AD_MESSAGE_ID_QUIT,
|
||||||
|
ProtocolOp: LDAP_REQ_UNBIND,
|
||||||
|
PtLenFlag: 0x84,
|
||||||
|
PtPacketLen: 0x00,
|
||||||
|
}
|
||||||
|
|
||||||
|
lqBuffer := new(bytes.Buffer)
|
||||||
|
binary.Write(lqBuffer, binary.BigEndian, aq)
|
||||||
|
|
||||||
|
quBytes := lqBuffer.Bytes()
|
||||||
|
|
||||||
|
pp2 := packet.NewPacket(quBytes, len(quBytes))
|
||||||
|
|
||||||
|
adm.sendPackets = append(adm.sendPackets, pp2)
|
||||||
|
|
||||||
|
return &adm
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
package activedirectory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"crypto/tls"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestADNor(t *testing.T) {
|
||||||
|
client, err := net.Dial("tcp", "192.168.1.1:389")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
dDRun(client, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestADTLS(t *testing.T) {
|
||||||
|
conn, err := tls.Dial(
|
||||||
|
"tcp",
|
||||||
|
"192.168.1.1:636",
|
||||||
|
&tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: "192.168.1.1",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
dDRun(conn, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func dDRun(client net.Conn, t *testing.T) {
|
||||||
|
|
||||||
|
lm := NewActiveDirectoryMatcher()
|
||||||
|
|
||||||
|
port := types.NewPort("389", types.NewHost("192.168.1.1"), types.TYPE_TCP)
|
||||||
|
|
||||||
|
var ipport string
|
||||||
|
ipport = port.Host.Ip + ":" + string(port.Port)
|
||||||
|
|
||||||
|
fmt.Println(ipport)
|
||||||
|
|
||||||
|
fmt.Println(lm.PacketCount())
|
||||||
|
|
||||||
|
for ii := 0; ii < lm.PacketCount(); ii++ {
|
||||||
|
|
||||||
|
pack := lm.Packet(ii)
|
||||||
|
|
||||||
|
fmt.Println(pack)
|
||||||
|
|
||||||
|
client.Write(pack.Buffer)
|
||||||
|
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
|
||||||
|
read, _ := client.Read(bytes)
|
||||||
|
|
||||||
|
fmt.Println(bytes)
|
||||||
|
|
||||||
|
b := lm.Match(ii, packet.NewPacket(bytes, read), scanInfo)
|
||||||
|
|
||||||
|
if b {
|
||||||
|
fmt.Println("Good")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(scanInfo)
|
||||||
|
}
|
105
core/scan/service/matcher/cassandra/cassandra.go
Normal file
105
core/scan/service/matcher/cassandra/cassandra.go
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package cassandra
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
COMPRESSION = "COMPRESSION"
|
||||||
|
CQL_VERSION = "CQL_VERSION"
|
||||||
|
)
|
||||||
|
|
||||||
|
type cassandra struct {
|
||||||
|
Version uint8
|
||||||
|
Flags uint8
|
||||||
|
Stream uint16
|
||||||
|
Opcode uint8
|
||||||
|
Length uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type CassandraMatcher struct {
|
||||||
|
packets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCassandraMatcher() *CassandraMatcher {
|
||||||
|
|
||||||
|
cassMatcher := &CassandraMatcher{}
|
||||||
|
c := cassandra{
|
||||||
|
Version: 4,
|
||||||
|
Flags: 0,
|
||||||
|
Stream: 0,
|
||||||
|
Opcode: 5,
|
||||||
|
Length: 0,
|
||||||
|
}
|
||||||
|
writer := new(bytes.Buffer)
|
||||||
|
binary.Write(writer, binary.LittleEndian, c)
|
||||||
|
|
||||||
|
cassMatcher.packets = append(cassMatcher.packets, packet.NewPacket(writer.Bytes(), writer.Len()))
|
||||||
|
|
||||||
|
return cassMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *CassandraMatcher) ServiceName() string {
|
||||||
|
return "Cassandra"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *CassandraMatcher) PacketCount() int {
|
||||||
|
return len(t.packets)
|
||||||
|
}
|
||||||
|
func (t *CassandraMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return t.packets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *CassandraMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *CassandraMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *CassandraMatcher) IsPrePacket() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *CassandraMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := new(bytes.Buffer)
|
||||||
|
reader.Write(packet.Buffer)
|
||||||
|
|
||||||
|
c := cassandra{}
|
||||||
|
if err := binary.Read(reader, binary.BigEndian, &c); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if c.Version != 0x84 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if c.Flags != 0x00 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if c.Stream != 0x00 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if c.Opcode != 0x06 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
var itemcount uint16
|
||||||
|
|
||||||
|
if binary.Read(reader, binary.BigEndian, &itemcount) != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if itemcount != 0 && itemcount != 2 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
73
core/scan/service/matcher/cassandra/cassandra_test.go
Normal file
73
core/scan/service/matcher/cassandra/cassandra_test.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package cassandra
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCassandra(t *testing.T) {
|
||||||
|
|
||||||
|
m := NewCassandraMatcher()
|
||||||
|
|
||||||
|
conn, err := net.Dial("tcp", "192.168.1.104:9042")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
for i := 0; i < m.PacketCount(); i++ {
|
||||||
|
|
||||||
|
pack := m.Packet(i)
|
||||||
|
conn.Write(pack.Buffer)
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(i, p, nil) {
|
||||||
|
t.Log("Cassandra found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error("Cassandra not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCassandraTLS(t *testing.T) {
|
||||||
|
|
||||||
|
m := NewCassandraMatcher()
|
||||||
|
|
||||||
|
conn, err := tls.Dial(
|
||||||
|
"tcp",
|
||||||
|
"192.168.1.104:9042",
|
||||||
|
&tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: "192.168.1.104",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
for i := 0; i < m.PacketCount(); i++ {
|
||||||
|
|
||||||
|
pack := m.Packet(i)
|
||||||
|
conn.Write(pack.Buffer)
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(i, p, nil) {
|
||||||
|
t.Log("Cassandra found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error("Cassandra not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
188
core/scan/service/matcher/dhcp/dhcp.go
Normal file
188
core/scan/service/matcher/dhcp/dhcp.go
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
package dhcp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MAGIC_COOKIE uint32 = 0x63825363
|
||||||
|
OPT_CODE_SERVER_IDENTIFIER uint8 = 54
|
||||||
|
OPT_CODE_SUBNET_MASK uint8 = 1
|
||||||
|
OPT_CODE_ROUTER uint8 = 3
|
||||||
|
OPT_CODE_DNS uint8 = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
type dhcpDiscover struct {
|
||||||
|
MsgType byte
|
||||||
|
HwType byte
|
||||||
|
HwAddrLen byte
|
||||||
|
Hops byte
|
||||||
|
Xid uint32
|
||||||
|
Secs uint16
|
||||||
|
BootpFlags uint16
|
||||||
|
ClientIp uint32
|
||||||
|
YourIp uint32
|
||||||
|
NextServerIp uint32
|
||||||
|
RelayAgentIp uint32
|
||||||
|
ClientMacAddr [6]byte
|
||||||
|
ClientHwAddrPadding [10]byte
|
||||||
|
ServerHostName [64]byte
|
||||||
|
BootFileName [128]byte
|
||||||
|
MagicCookie uint32
|
||||||
|
Mtype byte
|
||||||
|
MtypeLen byte
|
||||||
|
MtypeVal byte
|
||||||
|
Opts [200]byte
|
||||||
|
End byte
|
||||||
|
Padding [16]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func DiscoverDHCP(zone *types.DiscoveryZone) {
|
||||||
|
err := sendDHCPDiscovery()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
recvDHCPOffer(zone)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendDHCPDiscovery() error {
|
||||||
|
dhcp := dhcpDiscover{
|
||||||
|
MsgType: 0x01,
|
||||||
|
HwType: 0x01,
|
||||||
|
HwAddrLen: 0x06,
|
||||||
|
Hops: 0x00,
|
||||||
|
Xid: 0x00000000,
|
||||||
|
Secs: 0x0000,
|
||||||
|
ClientIp: 0x00000000,
|
||||||
|
YourIp: 0x00000000,
|
||||||
|
NextServerIp: 0x00000000,
|
||||||
|
RelayAgentIp: 0x00000000,
|
||||||
|
MagicCookie: MAGIC_COOKIE,
|
||||||
|
Mtype: 0x35,
|
||||||
|
MtypeLen: 0x01,
|
||||||
|
MtypeVal: 0x01,
|
||||||
|
End: 0xff,
|
||||||
|
}
|
||||||
|
|
||||||
|
var flag uint16 = 0
|
||||||
|
dhcp.BootpFlags = ^flag // flag = unicast , ^flag = broadcast
|
||||||
|
|
||||||
|
//TODO : getting mac addr from zone
|
||||||
|
dhcp.ClientMacAddr[0] = 0x50
|
||||||
|
dhcp.ClientMacAddr[1] = 0xe5
|
||||||
|
dhcp.ClientMacAddr[2] = 0x49
|
||||||
|
dhcp.ClientMacAddr[3] = 0x46
|
||||||
|
dhcp.ClientMacAddr[4] = 0x93
|
||||||
|
dhcp.ClientMacAddr[5] = 0x28
|
||||||
|
|
||||||
|
writer := new(bytes.Buffer)
|
||||||
|
binary.Write(writer, binary.BigEndian, dhcp)
|
||||||
|
conn, err := net.Dial("udp", "255.255.255.255:67")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
conn.Write(writer.Bytes())
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func recvDHCPOffer(zone *types.DiscoveryZone) {
|
||||||
|
|
||||||
|
socket, err := net.ListenUDP("udp4", &net.UDPAddr{
|
||||||
|
IP: net.IPv4(255, 255, 255, 255),
|
||||||
|
Port: 68,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = socket.SetDeadline(time.Now().Add(3 * time.Second))
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
n, _, err := socket.ReadFromUDP(buf)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n <= 0 {
|
||||||
|
log.Error("No DHCP offer.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
offer := dhcpDiscover{}
|
||||||
|
|
||||||
|
reader := new(bytes.Buffer)
|
||||||
|
reader.Write(buf)
|
||||||
|
if err := binary.Read(reader, binary.BigEndian, &offer); err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if offer.MagicCookie != MAGIC_COOKIE {
|
||||||
|
log.Error("Not a DHCP packet.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//option searching
|
||||||
|
r := new(bytes.Buffer)
|
||||||
|
r.Write(offer.Opts[:])
|
||||||
|
|
||||||
|
for i := 0; i < r.Len(); i++ {
|
||||||
|
v := r.Next(1)[0]
|
||||||
|
|
||||||
|
if v == OPT_CODE_SUBNET_MASK && r.Next(1)[0] == 4 {
|
||||||
|
ipStr := byteToIpString(r.Next(4))
|
||||||
|
log.Infof("SUBNET MASK: %s", ipStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v == OPT_CODE_ROUTER && r.Next(1)[0] == 4 {
|
||||||
|
ipStr := byteToIpString(r.Next(4))
|
||||||
|
log.Infof("ROUTER: %s", ipStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v == OPT_CODE_DNS {
|
||||||
|
len := r.Next(1)[0]
|
||||||
|
var dns []string = make([]string, 0)
|
||||||
|
var ipStr string
|
||||||
|
ipStr = byteToIpString(r.Next(4))
|
||||||
|
dns = append(dns, ipStr)
|
||||||
|
if len == 8 {
|
||||||
|
ipStr = byteToIpString(r.Next(4))
|
||||||
|
dns = append(dns, ipStr)
|
||||||
|
}
|
||||||
|
log.Info("DNS: ", dns)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v == OPT_CODE_SERVER_IDENTIFIER && r.Next(1)[0] == 4 {
|
||||||
|
ipStr := byteToIpString(r.Next(4))
|
||||||
|
log.Infof("DHCP SERVER: %s", ipStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Flush()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func byteToIpString(b []byte) string {
|
||||||
|
var ipStr string
|
||||||
|
len := len(b)
|
||||||
|
for i := 0; i < len; i++ {
|
||||||
|
v := b[i]
|
||||||
|
ipStr += fmt.Sprintf("%d", v)
|
||||||
|
if i < len-1 {
|
||||||
|
ipStr += "."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ipStr
|
||||||
|
}
|
11
core/scan/service/matcher/dhcp/dhcp_test.go
Normal file
11
core/scan/service/matcher/dhcp/dhcp_test.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package dhcp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/zone"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDHCP(t *testing.T) {
|
||||||
|
zone := zone.NewZone()
|
||||||
|
DiscoverDHCP(zone)
|
||||||
|
}
|
151
core/scan/service/matcher/dns/dns.go
Normal file
151
core/scan/service/matcher/dns/dns.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Dns_frame_header struct {
|
||||||
|
Transaction_id uint16
|
||||||
|
Flags uint16
|
||||||
|
Questions uint16
|
||||||
|
Answer_rrs uint16
|
||||||
|
Authority_rrs uint16
|
||||||
|
Additional_rrs uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type Dns_query_section struct {
|
||||||
|
Name uint8
|
||||||
|
Query_type uint16
|
||||||
|
Class_type uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type Dns_authority_section struct {
|
||||||
|
Name uint8
|
||||||
|
Auth_type uint16
|
||||||
|
Class_type uint16
|
||||||
|
Time_to_live uint32
|
||||||
|
Data_length uint16
|
||||||
|
Primary_name_server [20]uint8
|
||||||
|
Responsible_authority_mailbox [24]uint8
|
||||||
|
Serial_number uint32
|
||||||
|
Refresh_interval uint32
|
||||||
|
Retry_interval uint32
|
||||||
|
Expire_limit uint32
|
||||||
|
Minium_ttl uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type DNSMatcher struct {
|
||||||
|
packets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDnsMatcher() *DNSMatcher {
|
||||||
|
|
||||||
|
m := &DNSMatcher{}
|
||||||
|
|
||||||
|
header := Dns_frame_header{
|
||||||
|
Transaction_id: 0x2a88,
|
||||||
|
Flags: 0x0100,
|
||||||
|
Questions: 1,
|
||||||
|
Answer_rrs: 0,
|
||||||
|
Authority_rrs: 0,
|
||||||
|
Additional_rrs: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
query := Dns_query_section{
|
||||||
|
Name: 0,
|
||||||
|
Query_type: 1,
|
||||||
|
Class_type: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
binary.Write(buf, binary.BigEndian, header)
|
||||||
|
binary.Write(buf, binary.BigEndian, query)
|
||||||
|
|
||||||
|
m.packets = append(m.packets, packet.NewPacket(buf.Bytes(), buf.Len()))
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *DNSMatcher) ServiceName() string {
|
||||||
|
return "DNS"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *DNSMatcher) PacketCount() int {
|
||||||
|
return len(t.packets)
|
||||||
|
}
|
||||||
|
func (t *DNSMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return t.packets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *DNSMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *DNSMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *DNSMatcher) IsPrePacket() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *DNSMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if packet.Len <= 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := new(bytes.Buffer)
|
||||||
|
reader.Write(packet.Buffer)
|
||||||
|
|
||||||
|
h := Dns_frame_header{}
|
||||||
|
if err := binary.Read(reader, binary.BigEndian, &h); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if h.Transaction_id != 0x2a88 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if h.Flags != 0x8180 && h.Flags != 0x8182 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if h.Questions != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if h.Answer_rrs != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if h.Authority_rrs != 0 && h.Authority_rrs != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if h.Additional_rrs != 0 && h.Additional_rrs != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
q := Dns_query_section{}
|
||||||
|
if err := binary.Read(reader, binary.BigEndian, &q); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if q.Name != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if q.Query_type != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if q.Class_type != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
func (t *DNSMatcher) IsSend(port int) bool {
|
||||||
|
if port == 53 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
33
core/scan/service/matcher/dns/dns_test.go
Normal file
33
core/scan/service/matcher/dns/dns_test.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDns(t *testing.T) {
|
||||||
|
m := NewDnsMatcher()
|
||||||
|
|
||||||
|
conn, _ := net.Dial("udp", "192.168.1.215:53")
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
for i := 0; i < m.PacketCount(); i++ {
|
||||||
|
if m.IsSend(53) != true {
|
||||||
|
t.Error("not port")
|
||||||
|
}
|
||||||
|
pack := m.Packet(i)
|
||||||
|
conn.Write(pack.Buffer)
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(i, p, nil) {
|
||||||
|
t.Log("dns found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error("dns not found")
|
||||||
|
}
|
||||||
|
}
|
142
core/scan/service/matcher/ftp/ftp.go
Normal file
142
core/scan/service/matcher/ftp/ftp.go
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
package ftp
|
||||||
|
|
||||||
|
import (
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FTP Status codes, defined in RFC 959
|
||||||
|
const (
|
||||||
|
statusReadyServer = "120"
|
||||||
|
statusOK = "200"
|
||||||
|
statusNewConnectOK = "220"
|
||||||
|
statusSystemNameOK = "215"
|
||||||
|
statusCloseConnect = "221"
|
||||||
|
statusUnkownCMD = "202"
|
||||||
|
statusTlsUseOK = "234"
|
||||||
|
statusCloseControlConnect = "421"
|
||||||
|
statusSyntaxErr = "500"
|
||||||
|
statusParamSyntaxErr = "501"
|
||||||
|
statusNotUseCMD = "502"
|
||||||
|
statusIncorrectCMD = "503"
|
||||||
|
statusTlsNotUse = "534"
|
||||||
|
statusNeedUserId = "332"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FTPMatcher struct {
|
||||||
|
sendPackets []*packet.Packet
|
||||||
|
isFtps bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ftp *FTPMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
result := false
|
||||||
|
|
||||||
|
if packet == nil || packet.Buffer == nil || packet.Len == 0 {
|
||||||
|
log.Error("Packet nil")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
str := string(packet.Buffer)
|
||||||
|
//fmt.Println(str)
|
||||||
|
code := str[:3]
|
||||||
|
|
||||||
|
if index == 0 {
|
||||||
|
switch code {
|
||||||
|
case statusNewConnectOK, statusReadyServer:
|
||||||
|
//fmt.Println(code)
|
||||||
|
result = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else if index == 1 {
|
||||||
|
switch code {
|
||||||
|
case statusSystemNameOK, statusSyntaxErr, statusParamSyntaxErr, statusNotUseCMD:
|
||||||
|
//fmt.Println(code)
|
||||||
|
result = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else if index == 2 {
|
||||||
|
switch code {
|
||||||
|
case statusIncorrectCMD, statusParamSyntaxErr, statusNotUseCMD, statusNeedUserId:
|
||||||
|
//fmt.Println(code)
|
||||||
|
result = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else if index == 3 {
|
||||||
|
switch code {
|
||||||
|
case statusCloseConnect, statusSyntaxErr:
|
||||||
|
//fmt.Println(code)
|
||||||
|
result = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if index == 3 && result == true {
|
||||||
|
var err error
|
||||||
|
var isfs bool
|
||||||
|
|
||||||
|
//fmt.Println(info.Port.Host.Ip, info.Port.Port)
|
||||||
|
|
||||||
|
isfs, err = StartCheckFTPS(info.Port.Host.Ip_, info.Port.Port_)
|
||||||
|
|
||||||
|
if isfs && err == nil {
|
||||||
|
ftp.isFtps = isfs
|
||||||
|
} else if err != nil {
|
||||||
|
log.Warn("FTPS Check Error : ", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ftp *FTPMatcher) PacketCount() int {
|
||||||
|
return len(ftp.sendPackets)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ftp *FTPMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return ftp.sendPackets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ftp *FTPMatcher) ServiceName() string {
|
||||||
|
re := ""
|
||||||
|
if ftp.isFtps {
|
||||||
|
re = "FTPS"
|
||||||
|
} else {
|
||||||
|
re = "FTP"
|
||||||
|
}
|
||||||
|
return re
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ftp *FTPMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ftp *FTPMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ftp *FTPMatcher) IsPrePacket() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFTPMatcher() *FTPMatcher {
|
||||||
|
|
||||||
|
ftm := FTPMatcher{}
|
||||||
|
|
||||||
|
sysStr := "SYST\r\n"
|
||||||
|
systByte := make([]byte, len(sysStr))
|
||||||
|
copy(systByte[:], sysStr)
|
||||||
|
ftm.sendPackets = append(ftm.sendPackets, packet.NewPacket(systByte, len(sysStr)))
|
||||||
|
|
||||||
|
passStr := "PASS \r\n"
|
||||||
|
passByte := make([]byte, len(passStr))
|
||||||
|
copy(passByte[:], passStr)
|
||||||
|
ftm.sendPackets = append(ftm.sendPackets, packet.NewPacket(passByte, len(passStr)))
|
||||||
|
|
||||||
|
quitStr := "QUIT\r\n"
|
||||||
|
quitByte := make([]byte, len(quitStr))
|
||||||
|
copy(quitByte[:], quitStr)
|
||||||
|
ftm.sendPackets = append(ftm.sendPackets, packet.NewPacket(quitByte, len(quitStr)))
|
||||||
|
|
||||||
|
return &ftm
|
||||||
|
}
|
235
core/scan/service/matcher/ftp/ftp_test.go
Normal file
235
core/scan/service/matcher/ftp/ftp_test.go
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
package ftp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/scaninfo"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
//type FTP struct {
|
||||||
|
// conn net.Conn
|
||||||
|
// addr string
|
||||||
|
//
|
||||||
|
// reader *bufio.Reader
|
||||||
|
// writer *bufio.Writer
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func (ftp *FTP) Close() {
|
||||||
|
// ftp.conn.Close()
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func Connect(addr string) (*FTP, error) {
|
||||||
|
// var err error
|
||||||
|
// var conn net.Conn
|
||||||
|
//
|
||||||
|
// if conn, err = net.Dial("tcp", addr); err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// writer := bufio.NewWriter(conn)
|
||||||
|
// reader := bufio.NewReader(conn)
|
||||||
|
//
|
||||||
|
// obj := &FTP{
|
||||||
|
// conn:conn,
|
||||||
|
// addr:addr,
|
||||||
|
// reader:reader,
|
||||||
|
// writer:writer,
|
||||||
|
// }
|
||||||
|
// recv, _ := obj.receive()
|
||||||
|
//
|
||||||
|
// fmt.Println(recv)
|
||||||
|
//
|
||||||
|
// return obj, nil
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func (ftp *FTP) receive() (string, error) {
|
||||||
|
// line, err := ftp.receiveLine()
|
||||||
|
//
|
||||||
|
// if err != nil {
|
||||||
|
// return line, err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fmt.Println("len : ", len(line))
|
||||||
|
// fmt.Println("line[3] :", line[3])
|
||||||
|
// //
|
||||||
|
// //if (len(line) >= 4) && (line[3] == '-') {
|
||||||
|
// // closingCode := line[:3] + " "
|
||||||
|
// //
|
||||||
|
// // for {
|
||||||
|
// // str, err := ftp.receiveLine()
|
||||||
|
// // fmt.Println("str pre: ", str)
|
||||||
|
// // line = line + str
|
||||||
|
// // fmt.Println("str after: ", line)
|
||||||
|
// // if err != nil {
|
||||||
|
// // return line, err
|
||||||
|
// // }
|
||||||
|
// //
|
||||||
|
// // if len(str) < 4 {
|
||||||
|
// // fmt.Println("Uncorrectly terminated response")
|
||||||
|
// // }else {
|
||||||
|
// // if str[:4] == closingCode {
|
||||||
|
// // break
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// //}
|
||||||
|
//
|
||||||
|
// ftp.ReadAndDiscard()
|
||||||
|
//
|
||||||
|
// fmt.Println("receive line: ", line)
|
||||||
|
// return line, err
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func (ftp *FTP) ReadAndDiscard() (int, error) {
|
||||||
|
// var i int
|
||||||
|
// bufferSize := ftp.reader.Buffered()
|
||||||
|
//
|
||||||
|
// for i = 0; i < bufferSize ; i++ {
|
||||||
|
// if _, err := ftp.reader.ReadByte(); err != nil {
|
||||||
|
// return i, err
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return i, nil
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func (ftp *FTP) send(command string, arguments ...interface{}) error {
|
||||||
|
//
|
||||||
|
// command = fmt.Sprintf(command)
|
||||||
|
// command += "\r\n"
|
||||||
|
//
|
||||||
|
// if _, err := ftp.writer.WriteString(command); err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if err := ftp.writer.Flush(); err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return nil
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func (ftp *FTP) cmd(expects string, command string, args ...interface{}) (line string, err error) {
|
||||||
|
//
|
||||||
|
// if err = ftp.send(command, args); err != nil {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if line, err = ftp.receive(); err != nil {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// if !strings.HasPrefix(line, expects) {
|
||||||
|
// err = errors.New(line)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func (ftp *FTP) receiveLine() (string, error) {
|
||||||
|
// line, err := ftp.reader.ReadString('\n')
|
||||||
|
//
|
||||||
|
// log.Printf("< %s", line)
|
||||||
|
//
|
||||||
|
// return line, err
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func (ftp *FTP) Syst() (line string, err error) {
|
||||||
|
// if err := ftp.send("SYST"); err != nil {
|
||||||
|
// return "", err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if line, err = ftp.receive(); err != nil {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if !strings.HasPrefix(line, "215") {
|
||||||
|
// err = errors.New(line)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return strings.SplitN(strings.TrimSpace(line), " ", 2)[1], nil
|
||||||
|
//}
|
||||||
|
|
||||||
|
//func TestFtp(t *testing.T) {
|
||||||
|
// var err error
|
||||||
|
// var ftp *FTP
|
||||||
|
// //var f *FTPMatcher
|
||||||
|
//
|
||||||
|
// if ftp, err = Connect("192.168.1.202:21"); err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //f.Match(0, nil,nil)
|
||||||
|
// ftp.Syst()
|
||||||
|
// ftp.cmd("503","PASS ")
|
||||||
|
// ftp.cmd("221","QUIT")
|
||||||
|
// defer ftp.Close()
|
||||||
|
//}
|
||||||
|
|
||||||
|
func TestMatchFTP(t *testing.T) {
|
||||||
|
ftm := NewFTPMatcher()
|
||||||
|
//fmt.Println(ftm)
|
||||||
|
//fmt.Println(ftm.sendPackets[0])
|
||||||
|
|
||||||
|
//log.LoadLogConfig("../../../../../../../../bin/log.xml")
|
||||||
|
//defer log.Flush()
|
||||||
|
|
||||||
|
port := types.NewPort("21", types.NewHost("192.168.1.202"), types.TYPE_TCP)
|
||||||
|
info := scaninfo.NewServiceScanInfo(port)
|
||||||
|
|
||||||
|
var ipport string
|
||||||
|
ipport = port.Host.Ip + ":" + string(port.Port)
|
||||||
|
|
||||||
|
log.Debug(ipport)
|
||||||
|
|
||||||
|
client, _ := net.Dial("tcp", ipport)
|
||||||
|
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
//reader := bufio.NewReader(client)
|
||||||
|
//writer := bufio.NewWriter(client)
|
||||||
|
|
||||||
|
fmt.Println(ftm.PacketCount())
|
||||||
|
//fmt.Println(reader.ReadString('\n'))
|
||||||
|
|
||||||
|
bytes := make([]byte, 512)
|
||||||
|
|
||||||
|
le, _ := client.Read(bytes)
|
||||||
|
|
||||||
|
fmt.Println(bytes)
|
||||||
|
|
||||||
|
b := ftm.Match(0, packet.NewPacket(bytes, le), nil)
|
||||||
|
|
||||||
|
fmt.Println(b)
|
||||||
|
|
||||||
|
for ii := 0; ii < ftm.PacketCount(); ii++ {
|
||||||
|
pack := ftm.Packet(ii)
|
||||||
|
|
||||||
|
fmt.Println(pack)
|
||||||
|
|
||||||
|
//writer.WriteString(pack)
|
||||||
|
client.Write(pack.Buffer)
|
||||||
|
//fmt.Println(reader.ReadString('\n'))
|
||||||
|
bytes := make([]byte, 512)
|
||||||
|
|
||||||
|
l, _ := client.Read(bytes)
|
||||||
|
|
||||||
|
//fmt.Println(bytes)
|
||||||
|
|
||||||
|
b := ftm.Match(ii+1, packet.NewPacket(bytes, l), info)
|
||||||
|
|
||||||
|
fmt.Println(b)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Service Name : ", ftm.ServiceName())
|
||||||
|
}
|
191
core/scan/service/matcher/ftp/ftps.go
Normal file
191
core/scan/service/matcher/ftp/ftps.go
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
package ftp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FTP is a Session for file Transfer Protocol
|
||||||
|
type FTPS struct {
|
||||||
|
conn net.Conn
|
||||||
|
addr string
|
||||||
|
tlsconfig *tls.Config
|
||||||
|
|
||||||
|
reader *bufio.Reader
|
||||||
|
writer *bufio.Writer
|
||||||
|
|
||||||
|
isFtps bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *FTPS) close() {
|
||||||
|
fs.conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *FTPS) quit() (err error) {
|
||||||
|
if _, err := fs.cmd(statusCloseConnect, "QUIT"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fs.conn.Close()
|
||||||
|
fs.conn = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *FTPS) cmd(expects string, cmd string) (line string, err error) {
|
||||||
|
if err = fs.send(cmd); err != nil {
|
||||||
|
log.Error("ftps.go cmd send error: ", err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if line, err = fs.receive(); err != nil {
|
||||||
|
log.Error("ftps.go cmd receive error: ", err)
|
||||||
|
return line, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasPrefix(line, expects) {
|
||||||
|
err = errors.New(line)
|
||||||
|
return line, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return line, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *FTPS) readAndDiscard() (int, error) {
|
||||||
|
var i int
|
||||||
|
bufferSize := fs.reader.Buffered()
|
||||||
|
|
||||||
|
for i = 0; i < bufferSize; i++ {
|
||||||
|
if _, err := fs.reader.ReadByte(); err != nil {
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *FTPS) receive() (string, error) {
|
||||||
|
line, err := fs.reader.ReadString('\n')
|
||||||
|
//log.Debug("< %s", line)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return line, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.readAndDiscard()
|
||||||
|
//fmt.Println(line)
|
||||||
|
return line, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *FTPS) send(cmd string) (err error) {
|
||||||
|
|
||||||
|
if len(cmd) == 0 {
|
||||||
|
err = errors.New("command length 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = fmt.Sprintf(cmd)
|
||||||
|
cmd += "\r\n"
|
||||||
|
|
||||||
|
if _, err := fs.writer.WriteString(cmd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := fs.writer.Flush(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *FTPS) authTls(config *tls.Config) error {
|
||||||
|
if _, err := fs.cmd(statusTlsUseOK, "AUTH TLS"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.tlsconfig = config
|
||||||
|
|
||||||
|
fs.conn = tls.Client(fs.conn, config)
|
||||||
|
fs.writer = bufio.NewWriter(fs.conn)
|
||||||
|
fs.reader = bufio.NewReader(fs.conn)
|
||||||
|
|
||||||
|
_, err := fs.cmd(statusOK, "PBSZ 0")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = fs.cmd(statusOK, "PROT P")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (fs *FTPS) NewFTPSConnect(addr string) (*FTPS, error) {
|
||||||
|
var err error
|
||||||
|
var conn net.Conn
|
||||||
|
|
||||||
|
if conn, err = net.Dial("tcp", addr); err != nil {
|
||||||
|
log.Error("FTPS Socket Fail: ", err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = conn.SetDeadline(time.Now().Add(3 * time.Second))
|
||||||
|
if err != nil {
|
||||||
|
//log.Error("FTPS Socket Fail: ", err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
writer := bufio.NewWriter(conn)
|
||||||
|
reader := bufio.NewReader(conn)
|
||||||
|
|
||||||
|
var line string
|
||||||
|
|
||||||
|
obj := &FTPS{
|
||||||
|
conn: conn,
|
||||||
|
addr: addr,
|
||||||
|
reader: reader,
|
||||||
|
writer: writer,
|
||||||
|
}
|
||||||
|
|
||||||
|
line, err = obj.receive()
|
||||||
|
|
||||||
|
if !strings.HasPrefix(line, "220") {
|
||||||
|
err = errors.New(line)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//log.Debug(line)
|
||||||
|
|
||||||
|
return obj, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartCheckFTPS(ip string, port string) (bool, error) {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var fs *FTPS
|
||||||
|
|
||||||
|
addr := ip + ":" + port
|
||||||
|
//log.Debug("address : " + addr)
|
||||||
|
|
||||||
|
if fs, err = fs.NewFTPSConnect(addr); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer fs.close()
|
||||||
|
|
||||||
|
config := &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ClientAuth: tls.RequestClientCert,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = fs.authTls(config); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, err
|
||||||
|
}
|
13
core/scan/service/matcher/ftp/ftps_test.go
Normal file
13
core/scan/service/matcher/ftp/ftps_test.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package ftp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStartCheckFTPS(t *testing.T) {
|
||||||
|
|
||||||
|
isFtps, err := StartCheckFTPS("192.168.1.202", "80")
|
||||||
|
fmt.Println("Result : ", isFtps)
|
||||||
|
fmt.Println("Error : ", err)
|
||||||
|
}
|
90
core/scan/service/matcher/http/http.go
Normal file
90
core/scan/service/matcher/http/http.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HTTPMatcher struct {
|
||||||
|
sendPackets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HTTPMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
result := false
|
||||||
|
|
||||||
|
if packet == nil || packet.Buffer == nil || packet.Len == 0 {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
str := string(packet.Buffer)
|
||||||
|
//fmt.Println(str)
|
||||||
|
elems := strings.Split(str, "\r\n")
|
||||||
|
|
||||||
|
if len(elems) <= 0 {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol := (elems[0])[:8]
|
||||||
|
|
||||||
|
httpv0 := strings.Compare(protocol, "HTTP/1.0")
|
||||||
|
httpv1 := strings.Compare(protocol, "HTTP/1.1")
|
||||||
|
httpv2 := strings.Compare(protocol, "HTTP/1.2")
|
||||||
|
|
||||||
|
if 0 == httpv0 || 0 == httpv1 || 0 == httpv2 {
|
||||||
|
result = true
|
||||||
|
}
|
||||||
|
|
||||||
|
serverName := "Unknown Server"
|
||||||
|
|
||||||
|
for _, valueStr := range elems {
|
||||||
|
tempElems := strings.Split(valueStr, ":")
|
||||||
|
|
||||||
|
if 0 == strings.Compare(tempElems[0], "Server") {
|
||||||
|
serverName = tempElems[1]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strings.Compare(serverName, "Unknown")
|
||||||
|
//fmt.Println("HTTP Server Name: ", serverName)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HTTPMatcher) PacketCount() int {
|
||||||
|
return len(h.sendPackets)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HTTPMatcher) Packet(index int) *packet.Packet {
|
||||||
|
|
||||||
|
return h.sendPackets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HTTPMatcher) ServiceName() string {
|
||||||
|
return "HTTP"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HTTPMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HTTPMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HTTPMatcher) IsPrePacket() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHTTPMatcher() *HTTPMatcher {
|
||||||
|
|
||||||
|
h := HTTPMatcher{}
|
||||||
|
reqStr := "GET / HTTP/1.1\r\n\r\n"
|
||||||
|
byte := make([]byte, len(reqStr))
|
||||||
|
copy(byte[:], reqStr)
|
||||||
|
|
||||||
|
h.sendPackets = append(h.sendPackets, packet.NewPacket(byte, len(reqStr)))
|
||||||
|
|
||||||
|
return &h
|
||||||
|
}
|
49
core/scan/service/matcher/http/http_test.go
Normal file
49
core/scan/service/matcher/http/http_test.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHTTPMatcher_Packet(t *testing.T) {
|
||||||
|
hm := NewHTTPMatcher()
|
||||||
|
fmt.Println(hm)
|
||||||
|
fmt.Println(hm.sendPackets[0])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHTTPMatcher_Match(t *testing.T) {
|
||||||
|
fmt.Println("Match")
|
||||||
|
|
||||||
|
hm := NewHTTPMatcher()
|
||||||
|
|
||||||
|
port := types.NewPort("80", types.NewHost("192.168.1.103"), types.TYPE_TCP)
|
||||||
|
|
||||||
|
var ipport string
|
||||||
|
ipport = port.Host.Ip + ":" + string(port.Port)
|
||||||
|
|
||||||
|
//fmt.Println(ipport)
|
||||||
|
|
||||||
|
client, _ := net.Dial("tcp", ipport)
|
||||||
|
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
pack := hm.Packet(0)
|
||||||
|
|
||||||
|
//fmt.Println(pack)
|
||||||
|
|
||||||
|
//writer.WriteString(pack)
|
||||||
|
client.Write(pack.Buffer)
|
||||||
|
|
||||||
|
bytes := make([]byte, 512)
|
||||||
|
|
||||||
|
l, _ := client.Read(bytes)
|
||||||
|
|
||||||
|
//fmt.Println(bytes)
|
||||||
|
|
||||||
|
hm.Match(0, packet.NewPacket(bytes, l), nil)
|
||||||
|
|
||||||
|
}
|
55
core/scan/service/matcher/http/https_test.go
Normal file
55
core/scan/service/matcher/http/https_test.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/packet"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHTTPSMatcher_Match(t *testing.T) {
|
||||||
|
netinfo := "192.168.1.1:443"
|
||||||
|
dialer := &net.Dialer{
|
||||||
|
Timeout: 5 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := tls.DialWithDialer(
|
||||||
|
dialer,
|
||||||
|
"tcp",
|
||||||
|
netinfo,
|
||||||
|
&tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: "192.168.1.103",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
//fmt.Println(conn)
|
||||||
|
h := NewHTTPMatcher()
|
||||||
|
|
||||||
|
pac := h.Packet(0)
|
||||||
|
|
||||||
|
//fmt.Println(pac)
|
||||||
|
//fmt.Println(pac.Buffer)
|
||||||
|
|
||||||
|
//bytes := make([]byte, 1024)
|
||||||
|
|
||||||
|
l, _ := conn.Write(pac.Buffer)
|
||||||
|
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
l, _ = conn.Read(buf)
|
||||||
|
|
||||||
|
fmt.Println(string(buf))
|
||||||
|
fmt.Println(l)
|
||||||
|
is := h.Match(0, packet.NewPacket(buf, l), nil)
|
||||||
|
fmt.Println(is)
|
||||||
|
|
||||||
|
}
|
87
core/scan/service/matcher/imap/imap.go
Normal file
87
core/scan/service/matcher/imap/imap.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package imap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
PRE_COMPARE_STR = "* OK"
|
||||||
|
SEND_COMPARE_STR = "* BYE"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IMAPMatcher struct {
|
||||||
|
sendPackets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IMAPMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
|
||||||
|
recvStr := string(packet.Buffer)
|
||||||
|
|
||||||
|
if len(recvStr) < 3 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
compareStr := recvStr[0:4]
|
||||||
|
|
||||||
|
if compareStr == PRE_COMPARE_STR {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
|
||||||
|
recvStr := string(packet.Buffer)
|
||||||
|
|
||||||
|
if len(recvStr) < 5 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
compareStr := recvStr[0:5]
|
||||||
|
|
||||||
|
if compareStr == SEND_COMPARE_STR {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IMAPMatcher) PacketCount() int {
|
||||||
|
return len(i.sendPackets)
|
||||||
|
}
|
||||||
|
func (i *IMAPMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return i.sendPackets[index]
|
||||||
|
}
|
||||||
|
func (i *IMAPMatcher) ServiceName() string {
|
||||||
|
return "IMAP"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IMAPMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func (i *IMAPMatcher) IsNoResponse(index int) bool {
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IMAPMatcher) IsPrePacket() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewIMAPMatcher() *IMAPMatcher {
|
||||||
|
|
||||||
|
im := IMAPMatcher{}
|
||||||
|
|
||||||
|
reqStr := "A0001 LOGOUT\r\n"
|
||||||
|
byte := make([]byte, len(reqStr))
|
||||||
|
copy(byte[:], reqStr)
|
||||||
|
|
||||||
|
im.sendPackets = append(im.sendPackets, packet.NewPacket(byte, len(reqStr)))
|
||||||
|
|
||||||
|
return &im
|
||||||
|
|
||||||
|
}
|
147
core/scan/service/matcher/imap/imap_test.go
Normal file
147
core/scan/service/matcher/imap/imap_test.go
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
package imap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/scaninfo"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ImapRun(client net.Conn, t *testing.T) {
|
||||||
|
|
||||||
|
lm := NewIMAPMatcher()
|
||||||
|
|
||||||
|
port := types.NewPort("143", types.NewHost("192.168.1.215"), types.TYPE_TCP)
|
||||||
|
|
||||||
|
scanInfo := scaninfo.NewServiceScanInfo(port)
|
||||||
|
|
||||||
|
var ipport string
|
||||||
|
ipport = port.Host.Ip + ":" + string(port.Port)
|
||||||
|
|
||||||
|
fmt.Println(ipport)
|
||||||
|
//client, _ := net.Dial("tcp", ipport)
|
||||||
|
|
||||||
|
//defer client.Close()
|
||||||
|
|
||||||
|
bytett := make([]byte, 1024)
|
||||||
|
|
||||||
|
rr, _ := client.Read(bytett)
|
||||||
|
|
||||||
|
bb := lm.Match(0, packet.NewPacket(bytett, rr), scanInfo)
|
||||||
|
|
||||||
|
if bb {
|
||||||
|
t.Log("good!")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(lm.PacketCount())
|
||||||
|
|
||||||
|
for ii := 0; ii < lm.PacketCount(); ii++ {
|
||||||
|
|
||||||
|
pack := lm.Packet(ii)
|
||||||
|
|
||||||
|
//fmt.Println(pack)
|
||||||
|
|
||||||
|
client.Write(pack.Buffer)
|
||||||
|
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
|
||||||
|
read, _ := client.Read(bytes)
|
||||||
|
|
||||||
|
fmt.Println(cap(bytes))
|
||||||
|
|
||||||
|
//fmt.Println(bytes)
|
||||||
|
|
||||||
|
b := lm.Match(ii+1, packet.NewPacket(bytes, read), scanInfo)
|
||||||
|
|
||||||
|
if b {
|
||||||
|
t.Log("send Good!")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
t.Log(scanInfo)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIMapTls(t *testing.T) {
|
||||||
|
|
||||||
|
conn, _ := tls.Dial(
|
||||||
|
"tcp",
|
||||||
|
"192.168.1.215:993",
|
||||||
|
&tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: "192.168.1.215",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
ImapRun(conn, t)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIMapNormal(t *testing.T) {
|
||||||
|
|
||||||
|
client, _ := net.Dial("tcp", "192.168.1.215:143")
|
||||||
|
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
ImapRun(client, t)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImap(t *testing.T) {
|
||||||
|
|
||||||
|
lm := NewIMAPMatcher()
|
||||||
|
|
||||||
|
port := types.NewPort("143", types.NewHost("192.168.1.215"), types.TYPE_TCP)
|
||||||
|
|
||||||
|
scanInfo := scaninfo.NewServiceScanInfo(port)
|
||||||
|
|
||||||
|
var ipport string
|
||||||
|
ipport = port.Host.Ip + ":" + string(port.Port)
|
||||||
|
|
||||||
|
fmt.Println(ipport)
|
||||||
|
client, _ := net.Dial("tcp", ipport)
|
||||||
|
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
bytett := make([]byte, 1024)
|
||||||
|
|
||||||
|
rr, _ := client.Read(bytett)
|
||||||
|
|
||||||
|
bb := lm.Match(0, packet.NewPacket(bytett, rr), scanInfo)
|
||||||
|
|
||||||
|
if bb {
|
||||||
|
t.Log("good!")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(lm.PacketCount())
|
||||||
|
|
||||||
|
for ii := 0; ii < lm.PacketCount(); ii++ {
|
||||||
|
|
||||||
|
pack := lm.Packet(ii)
|
||||||
|
|
||||||
|
//fmt.Println(pack)
|
||||||
|
|
||||||
|
client.Write(pack.Buffer)
|
||||||
|
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
|
||||||
|
read, _ := client.Read(bytes)
|
||||||
|
|
||||||
|
fmt.Println(cap(bytes))
|
||||||
|
|
||||||
|
//fmt.Println(bytes)
|
||||||
|
|
||||||
|
b := lm.Match(ii+1, packet.NewPacket(bytes, read), scanInfo)
|
||||||
|
|
||||||
|
if b {
|
||||||
|
t.Log("send Good!")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
t.Log(scanInfo)
|
||||||
|
}
|
198
core/scan/service/matcher/ldap/ldap.go
Normal file
198
core/scan/service/matcher/ldap/ldap.go
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
package ldap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LDAPMatcher struct {
|
||||||
|
sendPackets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LDAPMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
buf.Write(packet.Buffer)
|
||||||
|
|
||||||
|
ldapRecv := LDAP_RECV{}
|
||||||
|
|
||||||
|
binary.Read(buf, binary.LittleEndian, &ldapRecv)
|
||||||
|
|
||||||
|
if ldapRecv.MessageId != LDAP_MESSAGE_ID {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ldapRecv.ProtocolOp != LDAP_RES_BIND {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if ldapRecv.ResultCode != LDAP_SUCCESS {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LDAPMatcher) PacketCount() int {
|
||||||
|
return len(l.sendPackets)
|
||||||
|
}
|
||||||
|
func (l *LDAPMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return l.sendPackets[index]
|
||||||
|
}
|
||||||
|
func (l *LDAPMatcher) ServiceName() string {
|
||||||
|
return "LDAP"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LDAPMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func (l *LDAPMatcher) IsNoResponse(index int) bool {
|
||||||
|
|
||||||
|
if index == 1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LDAPMatcher) IsPrePacket() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLDAPMatcher() *LDAPMatcher {
|
||||||
|
|
||||||
|
ls := LDAP_SEND{
|
||||||
|
DefaultCode: 0x30,
|
||||||
|
PacketLength: 0x0c, // size -2
|
||||||
|
NextType1: 0x02,
|
||||||
|
NextTypeLength1: 0x01,
|
||||||
|
MessageId: LDAP_MESSAGE_ID,
|
||||||
|
ProtocolOp: LDAP_REQ_BIND,
|
||||||
|
ProtocolOpLength: 0x07,
|
||||||
|
NextType2: 0x02,
|
||||||
|
NextTypeLength2: 0x01,
|
||||||
|
Version: LDAP_VERSION3,
|
||||||
|
NextType3: 0x04,
|
||||||
|
NextTypeLength3: 0x00,
|
||||||
|
Auth: LDAP_AUTH_SIMPLE,
|
||||||
|
AuthLength: 0x00,
|
||||||
|
}
|
||||||
|
|
||||||
|
mCache := new(bytes.Buffer)
|
||||||
|
binary.Write(mCache, binary.LittleEndian, ls)
|
||||||
|
|
||||||
|
sendByte1 := mCache.Bytes()
|
||||||
|
|
||||||
|
lm := LDAPMatcher{
|
||||||
|
//sendPackets: make([][]byte, 2),
|
||||||
|
}
|
||||||
|
|
||||||
|
pp := packet.NewPacket(sendByte1, len(sendByte1))
|
||||||
|
|
||||||
|
lm.sendPackets = append(lm.sendPackets, pp)
|
||||||
|
|
||||||
|
lq := LDAP_QUIT{
|
||||||
|
DefaultCode: 0x30,
|
||||||
|
UnknwonCode1: 0x84,
|
||||||
|
PacketLength: 0x05,
|
||||||
|
NextType1: 0x02,
|
||||||
|
NextTypeLength1: 0x01,
|
||||||
|
MessageId: LDAP_MESSAGE_ID_QUIT,
|
||||||
|
ProtocolOp: LDAP_REQ_UNBIND,
|
||||||
|
protocolOpLength: 0x00,
|
||||||
|
}
|
||||||
|
|
||||||
|
lqBuffer := new(bytes.Buffer)
|
||||||
|
binary.Write(lqBuffer, binary.BigEndian, lq)
|
||||||
|
|
||||||
|
sendByte2 := lqBuffer.Bytes()
|
||||||
|
|
||||||
|
pp2 := packet.NewPacket(sendByte2, len(sendByte2))
|
||||||
|
|
||||||
|
lm.sendPackets = append(lm.sendPackets, pp2)
|
||||||
|
|
||||||
|
return &lm
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type LDAP_SEND struct {
|
||||||
|
DefaultCode uint8
|
||||||
|
PacketLength uint8
|
||||||
|
|
||||||
|
NextType1 uint8
|
||||||
|
NextTypeLength1 uint8
|
||||||
|
|
||||||
|
MessageId uint8
|
||||||
|
|
||||||
|
ProtocolOp uint8
|
||||||
|
ProtocolOpLength uint8
|
||||||
|
NextType2 uint8
|
||||||
|
NextTypeLength2 uint8
|
||||||
|
|
||||||
|
Version uint8
|
||||||
|
|
||||||
|
NextType3 uint8
|
||||||
|
NextTypeLength3 uint8
|
||||||
|
Auth uint8
|
||||||
|
AuthLength uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type LDAP_RECV struct {
|
||||||
|
DefaultCode uint8
|
||||||
|
UnknwonCode1 uint8
|
||||||
|
EndCode11 uint8
|
||||||
|
EndCode12 uint8
|
||||||
|
|
||||||
|
MessageId uint8
|
||||||
|
|
||||||
|
ProtocolOp uint8
|
||||||
|
UnknwonCode2 uint8
|
||||||
|
EndCode21 uint8
|
||||||
|
EndCode22 uint8
|
||||||
|
|
||||||
|
ResultCode uint8
|
||||||
|
|
||||||
|
UnknwonCode3 uint8
|
||||||
|
UnknwonCode4 uint8
|
||||||
|
Auth uint8
|
||||||
|
UnknwonCode5 uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type LDAP_QUIT struct {
|
||||||
|
DefaultCode uint8
|
||||||
|
UnknwonCode1 uint8
|
||||||
|
|
||||||
|
PacketLength uint32
|
||||||
|
|
||||||
|
NextType1 uint8
|
||||||
|
NextTypeLength1 uint8
|
||||||
|
|
||||||
|
MessageId uint8
|
||||||
|
|
||||||
|
ProtocolOp uint8
|
||||||
|
|
||||||
|
protocolOpLength uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
LDAP_MESSAGE_ID = 0x99
|
||||||
|
LDAP_MESSAGE_ID_QUIT = 0x89
|
||||||
|
|
||||||
|
LDAP_VERSION3 = 3
|
||||||
|
|
||||||
|
LDAP_SUCCESS = 0x00
|
||||||
|
|
||||||
|
LDAP_REQ_BIND = 0x60
|
||||||
|
|
||||||
|
LDAP_REQ_UNBIND = 0x42
|
||||||
|
|
||||||
|
LDAP_RES_BIND = 0x61
|
||||||
|
|
||||||
|
LDAP_AUTH_SIMPLE = 0x80
|
||||||
|
)
|
109
core/scan/service/matcher/ldap/ldap_test.go
Normal file
109
core/scan/service/matcher/ldap/ldap_test.go
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
package ldap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/scaninfo"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
//func SetUp() {
|
||||||
|
// fmt.Println("SetUp")
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func TearDown() {
|
||||||
|
// fmt.Println("TearDown")
|
||||||
|
//}
|
||||||
|
|
||||||
|
//func TestMain(m *testing.M) {
|
||||||
|
// SetUp()
|
||||||
|
// m.Run()
|
||||||
|
// TearDown()
|
||||||
|
//}
|
||||||
|
|
||||||
|
func TestAAAA(t *testing.T) {
|
||||||
|
///animals := []Animal{Dog{}, Cat{}, Llama{}, JavaProgrammer{}}
|
||||||
|
|
||||||
|
var ttt [][]int = make([][]int, 10)
|
||||||
|
|
||||||
|
var aaa []int
|
||||||
|
aaa = append(aaa, 111)
|
||||||
|
|
||||||
|
ttt = append(ttt, aaa)
|
||||||
|
|
||||||
|
fmt.Println(cap(ttt))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func ldapRun(client net.Conn, t *testing.T) {
|
||||||
|
lm := NewLDAPMatcher()
|
||||||
|
|
||||||
|
port := types.NewPort("389", types.NewHost("192.168.1.215"), types.TYPE_TCP)
|
||||||
|
scanInfo := scaninfo.NewServiceScanInfo(port)
|
||||||
|
var ipport string
|
||||||
|
ipport = port.Host.Ip + ":" + string(port.Port)
|
||||||
|
|
||||||
|
fmt.Println(ipport)
|
||||||
|
//client, _ := net.Dial("tcp", ipport)
|
||||||
|
//defer client.Close()
|
||||||
|
|
||||||
|
fmt.Println(lm.PacketCount())
|
||||||
|
|
||||||
|
for ii := 0; ii < lm.PacketCount(); ii++ {
|
||||||
|
|
||||||
|
pack := lm.Packet(ii)
|
||||||
|
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
|
||||||
|
client.Write(pack.Buffer)
|
||||||
|
|
||||||
|
read, _ := client.Read(bytes)
|
||||||
|
|
||||||
|
if read <= 0 {
|
||||||
|
bb := lm.IsNoResponse(ii)
|
||||||
|
if bb {
|
||||||
|
|
||||||
|
t.Log("IsNoResponse good")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(bytes)
|
||||||
|
|
||||||
|
b := lm.Match(ii, packet.NewPacket(bytes, read), scanInfo)
|
||||||
|
|
||||||
|
if b {
|
||||||
|
t.Log("Good")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(scanInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLdapTls(t *testing.T) {
|
||||||
|
conn, _ := tls.Dial(
|
||||||
|
"tcp",
|
||||||
|
"192.168.1.215:636",
|
||||||
|
&tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: "192.168.1.215",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
ldapRun(conn, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLdapNormal(t *testing.T) {
|
||||||
|
client, _ := net.Dial("tcp", "192.168.1.215:389")
|
||||||
|
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
ldapRun(client, t)
|
||||||
|
}
|
115
core/scan/service/matcher/matcher.go
Normal file
115
core/scan/service/matcher/matcher.go
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
package matcher
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/activedirectory"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/cassandra"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/dns"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/ftp"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/http"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/imap"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/ldap"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/mongodb"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/mssql"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/mysql"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/netbios"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/oracle"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/pop"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/redis"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/rmi"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/smb"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/smtp"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/snmp"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/ssh"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/telnet"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/wmi"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
TcpMatchers []Matcher
|
||||||
|
UdpMatchers []UDPMatcher
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
//TCP
|
||||||
|
TcpMatchers = append(TcpMatchers, smtp.NewSmtpMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, ldap.NewLDAPMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, activedirectory.NewActiveDirectoryMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, mongodb.NewMongoDBMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, mysql.NewMySqlMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, mssql.NewMSSqlMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, redis.NewRedisMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, redis.NewRedisProtectedMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, netbios.NewNetBiosMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, smb.NewSMBMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, cassandra.NewCassandraMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, imap.NewIMAPMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, oracle.NewOracleMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, pop.NewPOPMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, wmi.NewWMIMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, ftp.NewFTPMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, http.NewHTTPMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, rmi.NewRMIMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, ssh.NewSSHMatcher())
|
||||||
|
TcpMatchers = append(TcpMatchers, telnet.NewTelnetMatcher())
|
||||||
|
UdpMatchers = append(UdpMatchers, dns.NewDnsMatcher())
|
||||||
|
UdpMatchers = append(UdpMatchers, snmp.NewSNMPv2Matcher())
|
||||||
|
UdpMatchers = append(UdpMatchers, snmp.NewSNMPv3Matcher())
|
||||||
|
}
|
||||||
|
|
||||||
|
type Matcher interface {
|
||||||
|
Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool
|
||||||
|
|
||||||
|
PacketCount() int
|
||||||
|
Packet(index int) *packet.Packet
|
||||||
|
ServiceName() string
|
||||||
|
|
||||||
|
IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool
|
||||||
|
IsNoResponse(index int) bool
|
||||||
|
IsPrePacket() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type UDPMatcher interface {
|
||||||
|
Matcher
|
||||||
|
IsSend(port int) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTcpMatchers(ispre bool) []Matcher {
|
||||||
|
|
||||||
|
retMatchers := make([]Matcher, 0)
|
||||||
|
l := len(TcpMatchers)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
c := TcpMatchers[i].IsPrePacket()
|
||||||
|
if c == ispre {
|
||||||
|
retMatchers = append(retMatchers, TcpMatchers[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retMatchers
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUdpMatchers() []UDPMatcher {
|
||||||
|
|
||||||
|
retMatchers := make([]UDPMatcher, 0)
|
||||||
|
l := len(UdpMatchers)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
retMatchers = append(retMatchers, UdpMatchers[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
return retMatchers
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMatcherByName(serName string) Matcher {
|
||||||
|
for _, m := range TcpMatchers {
|
||||||
|
if m.ServiceName() == serName {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, m := range UdpMatchers {
|
||||||
|
if m.ServiceName() == serName {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
91
core/scan/service/matcher/matcher_test.go
Normal file
91
core/scan/service/matcher/matcher_test.go
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package matcher
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestMatcher struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TestMatcher) ServiceName() string {
|
||||||
|
return "TestMatcher"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TestMatcher) Match(index int, packet []byte, info *ServiceScanInfo) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TestMatcher) PacketCount() int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
func (t *TestMatcher) Packet(index int) []byte {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TestMatcher) IsError(index int, packet []byte, info *ServiceScanInfo) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
func (t *TestMatcher) IsNoResponse(index int) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
func (t *TestMatcher) IsPrePacket() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
type Animal interface {
|
||||||
|
Speak() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Dog struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Dog) Speak() string {
|
||||||
|
return "Woof!"
|
||||||
|
}
|
||||||
|
|
||||||
|
type Cat struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Cat) Speak() string {
|
||||||
|
return "Meow!"
|
||||||
|
}
|
||||||
|
|
||||||
|
type Llama struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l Llama) Speak() string {
|
||||||
|
return "?????"
|
||||||
|
}
|
||||||
|
|
||||||
|
type JavaProgrammer struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j JavaProgrammer) Speak() string {
|
||||||
|
return "Design patterns!"
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMatcherTTT(t *testing.T) {
|
||||||
|
|
||||||
|
//animals := []Animal{Dog{}, Cat{}, Llama{}, JavaProgrammer{}}
|
||||||
|
|
||||||
|
var animals []Animal
|
||||||
|
|
||||||
|
animals = append(animals, &Dog{})
|
||||||
|
animals = append(animals, &Cat{})
|
||||||
|
animals = append(animals, &Llama{})
|
||||||
|
animals = append(animals, &JavaProgrammer{})
|
||||||
|
|
||||||
|
for _, a := range animals {
|
||||||
|
fmt.Println(a.Speak())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMatchersInit(t *testing.T) {
|
||||||
|
Matchers = append(Matchers, &TestMatcher{})
|
||||||
|
|
||||||
|
for _, m := range Matchers {
|
||||||
|
fmt.Println(m.ServiceName())
|
||||||
|
}
|
||||||
|
}
|
122
core/scan/service/matcher/mongodb/mongodb.go
Normal file
122
core/scan/service/matcher/mongodb/mongodb.go
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
package mongodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MONGO_OP_REQUEST uint32 = 2004
|
||||||
|
MONGO_OP_REPLY uint32 = 1
|
||||||
|
MONGO_FCNAME string = "admin.$cmd"
|
||||||
|
MONGO_ELEMENT string = "ismaster"
|
||||||
|
)
|
||||||
|
|
||||||
|
var MONGO_REQUEST_ID uint32
|
||||||
|
|
||||||
|
type mongo struct {
|
||||||
|
MessageLength uint32
|
||||||
|
RequestId uint32
|
||||||
|
ResponseTo uint32
|
||||||
|
OpCode uint32
|
||||||
|
Flags uint32
|
||||||
|
FullCollectionName [11]byte
|
||||||
|
NumberToSkip uint32
|
||||||
|
NumberToReturn int32
|
||||||
|
DocumentLength uint32
|
||||||
|
Type_ uint8
|
||||||
|
Element [9]byte
|
||||||
|
Value uint8
|
||||||
|
_ uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type MongoDBMatcher struct {
|
||||||
|
packets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMongoDBMatcher() *MongoDBMatcher {
|
||||||
|
|
||||||
|
mongoMatcher := &MongoDBMatcher{}
|
||||||
|
|
||||||
|
tempBuf := new(bytes.Buffer)
|
||||||
|
binary.Write(tempBuf, binary.BigEndian, mongo{})
|
||||||
|
|
||||||
|
var fcn [11]byte
|
||||||
|
copy(fcn[:], MONGO_FCNAME)
|
||||||
|
|
||||||
|
var elem [9]byte
|
||||||
|
copy(elem[:], MONGO_ELEMENT)
|
||||||
|
|
||||||
|
MONGO_REQUEST_ID = rand.Uint32()
|
||||||
|
m := mongo{
|
||||||
|
MessageLength: uint32(len(tempBuf.Bytes())),
|
||||||
|
RequestId: MONGO_REQUEST_ID,
|
||||||
|
ResponseTo: 0,
|
||||||
|
OpCode: MONGO_OP_REQUEST,
|
||||||
|
Flags: 0,
|
||||||
|
FullCollectionName: fcn,
|
||||||
|
NumberToSkip: 0,
|
||||||
|
NumberToReturn: -1,
|
||||||
|
DocumentLength: 16,
|
||||||
|
Type_: 0x08,
|
||||||
|
Element: elem,
|
||||||
|
Value: 1,
|
||||||
|
}
|
||||||
|
writer := new(bytes.Buffer)
|
||||||
|
binary.Write(writer, binary.LittleEndian, m)
|
||||||
|
|
||||||
|
mongoMatcher.packets = append(mongoMatcher.packets, packet.NewPacket(writer.Bytes(), writer.Len()))
|
||||||
|
|
||||||
|
return mongoMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MongoDBMatcher) ServiceName() string {
|
||||||
|
return "MongoDB"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MongoDBMatcher) PacketCount() int {
|
||||||
|
return len(t.packets)
|
||||||
|
}
|
||||||
|
func (t *MongoDBMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return t.packets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MongoDBMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MongoDBMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MongoDBMatcher) IsPrePacket() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MongoDBMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := new(bytes.Buffer)
|
||||||
|
reader.Write(packet.Buffer)
|
||||||
|
|
||||||
|
m := mongo{}
|
||||||
|
if err := binary.Read(reader, binary.LittleEndian, &m); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if uint32(packet.Len) != m.MessageLength ||
|
||||||
|
m.ResponseTo != MONGO_REQUEST_ID ||
|
||||||
|
m.OpCode != MONGO_OP_REPLY {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
54
core/scan/service/matcher/mongodb/mongodb_test.go
Normal file
54
core/scan/service/matcher/mongodb/mongodb_test.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package mongodb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMongoNor(t *testing.T) {
|
||||||
|
|
||||||
|
conn, _ := net.Dial("tcp", "192.168.1.105:27017")
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
MongoRun(conn, t)
|
||||||
|
|
||||||
|
}
|
||||||
|
func TestMongoTLS(t *testing.T) {
|
||||||
|
conn, _ := tls.Dial(
|
||||||
|
"tcp",
|
||||||
|
"192.168.1.105:27017",
|
||||||
|
&tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: "192.168.1.105",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
MongoRun(conn, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MongoRun(conn net.Conn, t *testing.T) {
|
||||||
|
|
||||||
|
m := NewMongoDBMatcher()
|
||||||
|
|
||||||
|
for i := 0; i < m.PacketCount(); i++ {
|
||||||
|
|
||||||
|
pack := m.Packet(i)
|
||||||
|
conn.Write(pack.Buffer)
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(i, p, nil) {
|
||||||
|
t.Log("MongoDB found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error("MongoDB not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
175
core/scan/service/matcher/mssql/mssql.go
Normal file
175
core/scan/service/matcher/mssql/mssql.go
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
package mssql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
HEADER_TYPE_PRELOGIN uint8 = 0x12
|
||||||
|
HEADER_TYPE_RESPONSE uint8 = 0x4
|
||||||
|
PL_OPTION_TOKEN_VERSION uint8 = 0x00
|
||||||
|
PL_OPTION_TOKEN_ENCRYPTION uint8 = 0x01
|
||||||
|
PL_OPTION_TOKEN_TRACEID uint8 = 0x05
|
||||||
|
PL_OPTION_TOKEN_TERMINATOR uint8 = 0xff
|
||||||
|
|
||||||
|
/*
|
||||||
|
ENCRYPT_OFF string = "Encryption is available but off."
|
||||||
|
ENCRYPT_ON string = "Encryption is available and on."
|
||||||
|
ENCRYPT_NOT_SUP string = "Encryption is not available."
|
||||||
|
ENCRYPT_REQ string = "Encryption is required."
|
||||||
|
*/
|
||||||
|
)
|
||||||
|
|
||||||
|
type PreloginMsg struct {
|
||||||
|
VersionToken uint8
|
||||||
|
VersionOffset uint16
|
||||||
|
VersionLength uint16
|
||||||
|
|
||||||
|
EncryptionToken uint8
|
||||||
|
EncryptionOffset uint16
|
||||||
|
EncryptionLength uint16
|
||||||
|
|
||||||
|
TraceIdToken uint8
|
||||||
|
TraceIdOffset uint16
|
||||||
|
TraceIdLength uint16
|
||||||
|
|
||||||
|
Terminator uint8
|
||||||
|
Options [7]uint8
|
||||||
|
TraceId [36]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type mssql struct {
|
||||||
|
Type_ uint8
|
||||||
|
Status uint8
|
||||||
|
Length uint16
|
||||||
|
Channel uint16
|
||||||
|
PacketNum uint8
|
||||||
|
Window uint8
|
||||||
|
Prelogin PreloginMsg
|
||||||
|
}
|
||||||
|
|
||||||
|
type PreloginResponse struct {
|
||||||
|
Msg [256]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type mssqlResponse struct {
|
||||||
|
Type_ uint8
|
||||||
|
Status uint8
|
||||||
|
Length uint16
|
||||||
|
Channel uint16
|
||||||
|
PacketNum uint8
|
||||||
|
Window uint8
|
||||||
|
PreLoginResp PreloginResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
type MSSqlMatcher struct {
|
||||||
|
packets []*packet.Packet
|
||||||
|
isSSL bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMSSqlMatcher() *MSSqlMatcher {
|
||||||
|
|
||||||
|
mssqlMatcher := &MSSqlMatcher{}
|
||||||
|
|
||||||
|
tempBuf := new(bytes.Buffer)
|
||||||
|
binary.Write(tempBuf, binary.BigEndian, mssql{})
|
||||||
|
|
||||||
|
m := mssql{
|
||||||
|
Type_: HEADER_TYPE_PRELOGIN,
|
||||||
|
Status: 0x01,
|
||||||
|
Length: uint16(len(tempBuf.Bytes())),
|
||||||
|
Channel: 0,
|
||||||
|
PacketNum: 0,
|
||||||
|
Window: 0,
|
||||||
|
Prelogin: PreloginMsg{
|
||||||
|
VersionToken: PL_OPTION_TOKEN_VERSION,
|
||||||
|
VersionOffset: 0x0010,
|
||||||
|
VersionLength: 0x0006,
|
||||||
|
EncryptionToken: PL_OPTION_TOKEN_ENCRYPTION,
|
||||||
|
EncryptionOffset: 0x0016,
|
||||||
|
EncryptionLength: 0x0001,
|
||||||
|
TraceIdToken: PL_OPTION_TOKEN_TRACEID,
|
||||||
|
TraceIdOffset: 0x0017,
|
||||||
|
TraceIdLength: 0x0024,
|
||||||
|
Terminator: PL_OPTION_TOKEN_TERMINATOR,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
writer := new(bytes.Buffer)
|
||||||
|
binary.Write(writer, binary.BigEndian, m)
|
||||||
|
|
||||||
|
mssqlMatcher.packets = append(mssqlMatcher.packets, packet.NewPacket(writer.Bytes(), writer.Len()))
|
||||||
|
|
||||||
|
return mssqlMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MSSqlMatcher) ServiceName() string {
|
||||||
|
if t.isSSL {
|
||||||
|
return "SQL Server (SSL)"
|
||||||
|
}
|
||||||
|
return "SQL Server"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MSSqlMatcher) PacketCount() int {
|
||||||
|
return len(t.packets)
|
||||||
|
}
|
||||||
|
func (t *MSSqlMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return t.packets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MSSqlMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MSSqlMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MSSqlMatcher) IsPrePacket() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MSSqlMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := new(bytes.Buffer)
|
||||||
|
reader.Write(packet.Buffer)
|
||||||
|
|
||||||
|
m := mssqlResponse{}
|
||||||
|
|
||||||
|
if err := binary.Read(reader, binary.BigEndian, &m); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Type_ != HEADER_TYPE_RESPONSE {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Length != uint16(packet.Len) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch m.PreLoginResp.Msg[m.Length-9 : m.Length-8][0] {
|
||||||
|
case 0:
|
||||||
|
return true
|
||||||
|
case 1:
|
||||||
|
t.isSSL = true
|
||||||
|
return true
|
||||||
|
case 2:
|
||||||
|
return true
|
||||||
|
case 3:
|
||||||
|
t.isSSL = true
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
}
|
63
core/scan/service/matcher/mssql/mssql_test.go
Normal file
63
core/scan/service/matcher/mssql/mssql_test.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package mssql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/packet"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
192.168.1.106:1433 - normal
|
||||||
|
192.168.1.103:1433 - ssl
|
||||||
|
*/
|
||||||
|
func TestSqlNor(t *testing.T) {
|
||||||
|
|
||||||
|
conn, _ := net.Dial("tcp", "192.168.1.103:1433")
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
sqlServerRun(conn, t)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//func TestSqlTLS(t *testing.T) {
|
||||||
|
// conn, err := tls.Dial(
|
||||||
|
// "tcp",
|
||||||
|
// "192.168.1.103:7680",
|
||||||
|
// &tls.Config{
|
||||||
|
// InsecureSkipVerify: true,
|
||||||
|
// ServerName: "192.168.1.103",
|
||||||
|
// },
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// if err != nil {
|
||||||
|
// t.Log(err)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// defer conn.Close()
|
||||||
|
//
|
||||||
|
// sqlServerRun(conn, t)
|
||||||
|
//}
|
||||||
|
|
||||||
|
func sqlServerRun(conn net.Conn, t *testing.T) {
|
||||||
|
|
||||||
|
m := NewMSSqlMatcher()
|
||||||
|
|
||||||
|
for i := 0; i < m.PacketCount(); i++ {
|
||||||
|
|
||||||
|
pack := m.Packet(i)
|
||||||
|
conn.Write(pack.Buffer)
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(i, p, nil) {
|
||||||
|
t.Log(m.ServiceName())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error("MSSQL not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
151
core/scan/service/matcher/mysql/mysql.go
Normal file
151
core/scan/service/matcher/mysql/mysql.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package mysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PacketSize struct {
|
||||||
|
PacketLength [3]byte
|
||||||
|
PacketNumber byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type mySql struct {
|
||||||
|
Payload PacketSize
|
||||||
|
Protocol byte
|
||||||
|
Version [256]byte
|
||||||
|
|
||||||
|
TreadId uint32
|
||||||
|
Salt1 [9]byte
|
||||||
|
ServerCapa uint16
|
||||||
|
ServerLang uint8
|
||||||
|
ServerStat uint16
|
||||||
|
ExtServerCapa uint16
|
||||||
|
AuthPlugLen uint8
|
||||||
|
_ [10]uint8
|
||||||
|
Salt2 [13]uint8
|
||||||
|
AuthPlugName [64]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type MySqlMatcher struct {
|
||||||
|
packets []*packet.Packet
|
||||||
|
version string
|
||||||
|
isErrResp bool
|
||||||
|
errCode int
|
||||||
|
errMsg string
|
||||||
|
isSSL bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMySqlMatcher() *MySqlMatcher {
|
||||||
|
return &MySqlMatcher{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MySqlMatcher) ServiceName() string {
|
||||||
|
if t.isErrResp {
|
||||||
|
return "MySQL" + "(Err-" + strconv.Itoa(t.errCode) + " : " + t.errMsg + ")"
|
||||||
|
}
|
||||||
|
if t.isSSL {
|
||||||
|
return "MySQL" + "-" + t.version + "(SSL)"
|
||||||
|
}
|
||||||
|
return "MySQL" + "(" + t.version + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MySqlMatcher) PacketCount() int {
|
||||||
|
return len(t.packets)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MySqlMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return t.packets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MySqlMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MySqlMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MySqlMatcher) IsPrePacket() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MySqlMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil || len(packet.Buffer) <= 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
r := new(bytes.Buffer)
|
||||||
|
r.Write(packet.Buffer)
|
||||||
|
|
||||||
|
m := mySql{}
|
||||||
|
if err := binary.Read(r, binary.LittleEndian, &m); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := bytes.NewBuffer(m.Payload.PacketLength[:])
|
||||||
|
packetLen, _ := binary.ReadUvarint(buf)
|
||||||
|
|
||||||
|
if packetLen != uint64(packet.Len-4) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Protocol == 0xff {
|
||||||
|
//MySQL error response
|
||||||
|
var code [2]uint8
|
||||||
|
copy(code[:], m.Version[:2])
|
||||||
|
|
||||||
|
var msg [256]uint8
|
||||||
|
copy(msg[:], m.Version[2:])
|
||||||
|
|
||||||
|
errCode := binary.LittleEndian.Uint16(code[:])
|
||||||
|
if errCode < 1000 || errCode > 1727 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
errMsg := bytes.Trim(msg[:], "\x00")
|
||||||
|
|
||||||
|
t.isErrResp = true
|
||||||
|
t.errCode = int(errCode)
|
||||||
|
t.errMsg = string(errMsg)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Protocol != 10 && m.Protocol != 9 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
t.checkSSL(packet)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *MySqlMatcher) checkSSL(packet *packet.Packet) {
|
||||||
|
|
||||||
|
temp := make([]byte, packet.Len)
|
||||||
|
r := new(bytes.Buffer)
|
||||||
|
r.Write(packet.Buffer)
|
||||||
|
|
||||||
|
if err := binary.Read(r, binary.LittleEndian, &temp); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.version = strings.Split(string(packet.Buffer)[5:packet.Len], "\x00")[0]
|
||||||
|
versionLen := len(t.version) + 1
|
||||||
|
data := binary.LittleEndian.Uint16(temp[18+versionLen : 20+versionLen])
|
||||||
|
s := fmt.Sprintf("%b", data)
|
||||||
|
|
||||||
|
for i, b := range s {
|
||||||
|
if i == 4 {
|
||||||
|
if b == 49 {
|
||||||
|
t.isSSL = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
70
core/scan/service/matcher/mysql/mysql_test.go
Normal file
70
core/scan/service/matcher/mysql/mysql_test.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package mysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMySql(t *testing.T) {
|
||||||
|
|
||||||
|
m := NewMySqlMatcher()
|
||||||
|
|
||||||
|
/*
|
||||||
|
192.168.1.103:3306 - normal
|
||||||
|
192.168.1.105:8306 - ssl
|
||||||
|
192.168.1.203:3306 - mysql with error code
|
||||||
|
*/
|
||||||
|
conn, _ := net.Dial("tcp", "192.168.1.215:3306")
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(0, p, nil) {
|
||||||
|
t.Log(m.ServiceName())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error("MySQL not found")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCassandraTLS(t *testing.T) {
|
||||||
|
|
||||||
|
m := NewMySqlMatcher()
|
||||||
|
|
||||||
|
conn, err := tls.Dial(
|
||||||
|
"tcp",
|
||||||
|
"192.168.1.105:8306",
|
||||||
|
&tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: "192.168.1.105",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
for i := 0; i < m.PacketCount(); i++ {
|
||||||
|
|
||||||
|
pack := m.Packet(i)
|
||||||
|
conn.Write(pack.Buffer)
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(i, p, nil) {
|
||||||
|
t.Log(m.ServiceName())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error("MySQL not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
109
core/scan/service/matcher/netbios/netbios.go
Normal file
109
core/scan/service/matcher/netbios/netbios.go
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
package netbios
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
NBSS_SESSION_REQUEST uint8 = 0x81
|
||||||
|
NBSS_POSITIVE_SESSION_RESPONSE uint8 = 0x82
|
||||||
|
NBSS_NEGATIVE_SESSION_RESPONSE uint8 = 0x83
|
||||||
|
ADDR string = "192.168.1.202:139"
|
||||||
|
)
|
||||||
|
|
||||||
|
type netBios struct {
|
||||||
|
MsgType uint8
|
||||||
|
Flags uint8 //0-6 : Reserved, must be zero. 7 : Length extension.
|
||||||
|
Length uint16
|
||||||
|
CalledNameLen uint8
|
||||||
|
CalledName [16]uint16
|
||||||
|
_ uint8
|
||||||
|
CallingNameLen uint8
|
||||||
|
CallingName [16]uint16
|
||||||
|
_ uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type NetBiosMatcher struct {
|
||||||
|
packets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNetBiosMatcher() *NetBiosMatcher {
|
||||||
|
|
||||||
|
nbssMatcher := &NetBiosMatcher{}
|
||||||
|
|
||||||
|
tempBuf := new(bytes.Buffer)
|
||||||
|
binary.Write(tempBuf, binary.BigEndian, netBios{})
|
||||||
|
|
||||||
|
query := netBios{
|
||||||
|
MsgType: NBSS_SESSION_REQUEST,
|
||||||
|
Flags: 0x00,
|
||||||
|
Length: 0x4400,
|
||||||
|
CalledNameLen: 0x20,
|
||||||
|
CallingNameLen: 0x20,
|
||||||
|
}
|
||||||
|
|
||||||
|
query.CalledName[0] = 0x4D45 // L
|
||||||
|
query.CalledName[1] = 0x4745 // F
|
||||||
|
|
||||||
|
query.CallingName[0] = 0x4D45
|
||||||
|
query.CallingName[1] = 0x4745
|
||||||
|
|
||||||
|
for i := 2; i < 16; i++ {
|
||||||
|
query.CalledName[i] = 0x4143 //Space
|
||||||
|
query.CallingName[i] = 0x4143
|
||||||
|
}
|
||||||
|
writer := new(bytes.Buffer)
|
||||||
|
binary.Write(writer, binary.LittleEndian, query)
|
||||||
|
|
||||||
|
nbssMatcher.packets = append(nbssMatcher.packets, packet.NewPacket(writer.Bytes(), writer.Len()))
|
||||||
|
|
||||||
|
return nbssMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *NetBiosMatcher) ServiceName() string {
|
||||||
|
return "NBSS"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *NetBiosMatcher) PacketCount() int {
|
||||||
|
return len(t.packets)
|
||||||
|
}
|
||||||
|
func (t *NetBiosMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return t.packets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *NetBiosMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *NetBiosMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *NetBiosMatcher) IsPrePacket() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *NetBiosMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := new(bytes.Buffer)
|
||||||
|
reader.Write(packet.Buffer)
|
||||||
|
|
||||||
|
n := netBios{}
|
||||||
|
if err := binary.Read(reader, binary.LittleEndian, &n); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if NBSS_NEGATIVE_SESSION_RESPONSE != n.MsgType {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
33
core/scan/service/matcher/netbios/netbios_test.go
Normal file
33
core/scan/service/matcher/netbios/netbios_test.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package netbios
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/packet"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNBSS(t *testing.T) {
|
||||||
|
|
||||||
|
m := NewNetBiosMatcher()
|
||||||
|
|
||||||
|
conn, _ := net.Dial("tcp", "192.168.1.202:139")
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
for i := 0; i < m.PacketCount(); i++ {
|
||||||
|
|
||||||
|
pack := m.Packet(i)
|
||||||
|
conn.Write(pack)
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(i, p, nil) {
|
||||||
|
t.Log("NBSS found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error("NBSS not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
187
core/scan/service/matcher/oracle/oracle.go
Normal file
187
core/scan/service/matcher/oracle/oracle.go
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
package oracle
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OracleMatcher struct {
|
||||||
|
sendPackets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OracleMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
header := header_packet{}
|
||||||
|
refuse := body_refuse{}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
buf.Write(packet.Buffer)
|
||||||
|
|
||||||
|
binary.Read(buf, binary.BigEndian, &header)
|
||||||
|
binary.Read(buf, binary.BigEndian, &refuse)
|
||||||
|
|
||||||
|
//fmt.Println(header)
|
||||||
|
//fmt.Println(refuse)
|
||||||
|
|
||||||
|
if header.Check_sum != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if header.Types != 4 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if header.Reserved_byte != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if header.Header_sum != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if refuse.Reason_user != 34 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if refuse.Reason_system != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var dataLen int = int(refuse.Data_len)
|
||||||
|
if dataLen != packet.Len-12 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OracleMatcher) PacketCount() int {
|
||||||
|
return len(o.sendPackets)
|
||||||
|
}
|
||||||
|
func (o *OracleMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return o.sendPackets[index]
|
||||||
|
}
|
||||||
|
func (o *OracleMatcher) ServiceName() string {
|
||||||
|
return "POP3Matcher"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OracleMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func (o *OracleMatcher) IsNoResponse(index int) bool {
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OracleMatcher) IsPrePacket() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOracleMatcher() *OracleMatcher {
|
||||||
|
|
||||||
|
pm := OracleMatcher{}
|
||||||
|
|
||||||
|
hp := header_packet{
|
||||||
|
Length: 247,
|
||||||
|
Check_sum: 0,
|
||||||
|
Types: 1,
|
||||||
|
Reserved_byte: 0,
|
||||||
|
Header_sum: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
bc := body_connect{
|
||||||
|
Version: 315,
|
||||||
|
Version_compatible: 300,
|
||||||
|
//Service_options:
|
||||||
|
Session_unit_size: 8192,
|
||||||
|
Maxumum_trans_data_unit_size: 65535,
|
||||||
|
//Nt_protocol_characteristics:
|
||||||
|
Line_turnaround_value: 0,
|
||||||
|
Value_of_1_in_hardware: 1,
|
||||||
|
Length_of_connect_data: 177,
|
||||||
|
Offset_to_connect_data: 70,
|
||||||
|
Maximum_receivable_connect_data: 0,
|
||||||
|
//Connect_flag0:
|
||||||
|
//Connect_flag1:
|
||||||
|
Trace_cross_facility_item_1: 0,
|
||||||
|
Trace_cross_facility_item_2: 0,
|
||||||
|
Trace_unique_connection_id: 0,
|
||||||
|
//Unknown_data:
|
||||||
|
//Connect_data:
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bc.Service_options[0] = 0x0c
|
||||||
|
bc.Service_options[1] = 0x41
|
||||||
|
|
||||||
|
bc.Nt_protocol_characteristics[0] = 0x4f
|
||||||
|
bc.Nt_protocol_characteristics[1] = 0x98
|
||||||
|
|
||||||
|
bc.Connect_flag0 = 0x81
|
||||||
|
bc.Connect_flag1 = 0x81
|
||||||
|
|
||||||
|
bc.Unknown_data[10] = 0x20
|
||||||
|
bc.Unknown_data[13] = 0x20
|
||||||
|
|
||||||
|
conDataStr := "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.1.30)(PORT=1521))(CONNECT_DATA=(CID=(PROGRAM=JDBC Thin Client)(HOST=__jdbc__)(USER=Jackdaw))(SERVICE_NAME=oracle.loafle.co1m)))"
|
||||||
|
connect_data := make([]byte, len(conDataStr))
|
||||||
|
copy(connect_data, conDataStr)
|
||||||
|
|
||||||
|
hpBuf := new(bytes.Buffer)
|
||||||
|
binary.Write(hpBuf, binary.BigEndian, hp)
|
||||||
|
|
||||||
|
hpBt := hpBuf.Bytes()
|
||||||
|
|
||||||
|
bcBuf := new(bytes.Buffer)
|
||||||
|
binary.Write(bcBuf, binary.BigEndian, bc)
|
||||||
|
bcBt := bcBuf.Bytes()
|
||||||
|
|
||||||
|
byteSize := len(hpBt) + len(bcBt) + len(conDataStr)
|
||||||
|
sendByte := make([]byte, byteSize)
|
||||||
|
|
||||||
|
copy(sendByte[0:], hpBt)
|
||||||
|
copy(sendByte[len(hpBt):], bcBt)
|
||||||
|
copy(sendByte[len(hpBt)+len(bcBt):], connect_data)
|
||||||
|
|
||||||
|
pm.sendPackets = append(pm.sendPackets, packet.NewPacket(sendByte, byteSize))
|
||||||
|
|
||||||
|
return &pm
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type header_packet struct {
|
||||||
|
Length uint16
|
||||||
|
Check_sum uint16
|
||||||
|
Types byte
|
||||||
|
Reserved_byte byte
|
||||||
|
Header_sum uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type body_connect struct {
|
||||||
|
Version uint16
|
||||||
|
Version_compatible uint16
|
||||||
|
Service_options [2]byte
|
||||||
|
Session_unit_size uint16
|
||||||
|
Maxumum_trans_data_unit_size uint16
|
||||||
|
Nt_protocol_characteristics [2]byte
|
||||||
|
Line_turnaround_value uint16
|
||||||
|
Value_of_1_in_hardware uint16
|
||||||
|
Length_of_connect_data uint16
|
||||||
|
Offset_to_connect_data uint16
|
||||||
|
Maximum_receivable_connect_data uint32
|
||||||
|
Connect_flag0 byte
|
||||||
|
Connect_flag1 byte
|
||||||
|
Trace_cross_facility_item_1 uint32
|
||||||
|
Trace_cross_facility_item_2 uint32
|
||||||
|
Trace_unique_connection_id uint64
|
||||||
|
Unknown_data [20]byte
|
||||||
|
//Connect_data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type body_refuse struct {
|
||||||
|
Reason_user byte
|
||||||
|
Reason_system byte
|
||||||
|
Data_len uint16
|
||||||
|
//Data []byte
|
||||||
|
}
|
52
core/scan/service/matcher/oracle/oracle_test.go
Normal file
52
core/scan/service/matcher/oracle/oracle_test.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package oracle
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/scaninfo"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOracle(t *testing.T) {
|
||||||
|
|
||||||
|
lm := NewOracleMatcher()
|
||||||
|
|
||||||
|
port := types.NewPort("1521", types.NewHost("192.168.1.30"), types.TYPE_TCP)
|
||||||
|
scanInfo := scaninfo.NewServiceScanInfo(port)
|
||||||
|
var ipport string
|
||||||
|
ipport = port.Host.Ip + ":" + string(port.Port)
|
||||||
|
|
||||||
|
fmt.Println(ipport)
|
||||||
|
client, _ := net.Dial("tcp", ipport)
|
||||||
|
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
fmt.Println(lm.PacketCount())
|
||||||
|
|
||||||
|
for ii := 0; ii < lm.PacketCount(); ii++ {
|
||||||
|
|
||||||
|
pack := lm.Packet(ii)
|
||||||
|
|
||||||
|
fmt.Println(pack)
|
||||||
|
|
||||||
|
client.Write(pack.Buffer)
|
||||||
|
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
|
||||||
|
read, _ := client.Read(bytes)
|
||||||
|
|
||||||
|
fmt.Println(bytes)
|
||||||
|
|
||||||
|
b := lm.Match(ii, packet.NewPacket(bytes, read), scanInfo)
|
||||||
|
|
||||||
|
if b {
|
||||||
|
t.Log("Good")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(scanInfo)
|
||||||
|
|
||||||
|
}
|
13
core/scan/service/matcher/packet/packet.go
Normal file
13
core/scan/service/matcher/packet/packet.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package packet
|
||||||
|
|
||||||
|
type Packet struct {
|
||||||
|
Buffer []byte
|
||||||
|
Len int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPacket(buf []byte, len int) *Packet {
|
||||||
|
return &Packet{
|
||||||
|
Buffer: buf,
|
||||||
|
Len: len,
|
||||||
|
}
|
||||||
|
}
|
73
core/scan/service/matcher/pop/pop.go
Normal file
73
core/scan/service/matcher/pop/pop.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package pop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
COMPARE_STR = "+OK"
|
||||||
|
)
|
||||||
|
|
||||||
|
type POPMatcher struct {
|
||||||
|
sendPackets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *POPMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
fallthrough
|
||||||
|
case 1:
|
||||||
|
|
||||||
|
recvStr := string(packet.Buffer)
|
||||||
|
|
||||||
|
if len(recvStr) < 3 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
compareStr := recvStr[0:3]
|
||||||
|
|
||||||
|
if compareStr == COMPARE_STR {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *POPMatcher) PacketCount() int {
|
||||||
|
return len(p.sendPackets)
|
||||||
|
}
|
||||||
|
func (p *POPMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return p.sendPackets[index]
|
||||||
|
}
|
||||||
|
func (p *POPMatcher) ServiceName() string {
|
||||||
|
return "POPMatcher"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *POPMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func (p *POPMatcher) IsNoResponse(index int) bool {
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *POPMatcher) IsPrePacket() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPOPMatcher() *POPMatcher {
|
||||||
|
|
||||||
|
pm := POPMatcher{}
|
||||||
|
|
||||||
|
reqStr := "QUIT\r\n"
|
||||||
|
byte := make([]byte, len(reqStr))
|
||||||
|
copy(byte[:], reqStr)
|
||||||
|
pm.sendPackets = append(pm.sendPackets, packet.NewPacket(byte, len(reqStr)))
|
||||||
|
|
||||||
|
return &pm
|
||||||
|
|
||||||
|
}
|
85
core/scan/service/matcher/pop/pop_test.go
Normal file
85
core/scan/service/matcher/pop/pop_test.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package pop
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/scaninfo"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPopTLS(t *testing.T) {
|
||||||
|
conn, _ := tls.Dial(
|
||||||
|
"tcp",
|
||||||
|
"192.168.1.215:995",
|
||||||
|
&tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: "192.168.1.215",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
pop3Run(conn, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPopNor(t *testing.T) {
|
||||||
|
|
||||||
|
client, _ := net.Dial("tcp", "192.168.1.215:110")
|
||||||
|
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
pop3Run(client, t)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func pop3Run(client net.Conn, t *testing.T) {
|
||||||
|
|
||||||
|
lm := NewPOPMatcher()
|
||||||
|
|
||||||
|
port := types.NewPort("110", types.NewHost("192.168.1.215"), types.TYPE_TCP)
|
||||||
|
scanInfo := scaninfo.NewServiceScanInfo(port)
|
||||||
|
var ipport string
|
||||||
|
ipport = port.Host.Ip + ":" + string(port.Port)
|
||||||
|
|
||||||
|
fmt.Println(ipport)
|
||||||
|
|
||||||
|
bytett := make([]byte, 1024)
|
||||||
|
|
||||||
|
read, _ := client.Read(bytett)
|
||||||
|
|
||||||
|
bb := lm.Match(0, packet.NewPacket(bytett, read), scanInfo)
|
||||||
|
|
||||||
|
if bb {
|
||||||
|
t.Log("good!")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(lm.PacketCount())
|
||||||
|
|
||||||
|
for ii := 0; ii < lm.PacketCount(); ii++ {
|
||||||
|
|
||||||
|
pack := lm.Packet(ii)
|
||||||
|
|
||||||
|
//fmt.Println(pack)
|
||||||
|
|
||||||
|
client.Write(pack.Buffer)
|
||||||
|
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
|
||||||
|
rr, _ := client.Read(bytes)
|
||||||
|
|
||||||
|
//fmt.Println(bytes)
|
||||||
|
|
||||||
|
b := lm.Match(ii+1, packet.NewPacket(bytes, rr), scanInfo)
|
||||||
|
|
||||||
|
if b {
|
||||||
|
t.Log("send Good!")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(scanInfo)
|
||||||
|
|
||||||
|
}
|
155
core/scan/service/matcher/postgresql/postgresql.go
Normal file
155
core/scan/service/matcher/postgresql/postgresql.go
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
package postgresql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
RESPONSE_TYPE_ERR uint8 = 0x45
|
||||||
|
)
|
||||||
|
|
||||||
|
type pgsql struct {
|
||||||
|
Len uint32
|
||||||
|
MessageType uint16
|
||||||
|
_ uint16
|
||||||
|
Name [5]byte
|
||||||
|
NameValue byte
|
||||||
|
Db [9]byte
|
||||||
|
DBValue byte
|
||||||
|
Encoding [16]byte
|
||||||
|
EncodingValue [5]byte
|
||||||
|
DateStyle [10]byte
|
||||||
|
DateStyleValue [4]byte
|
||||||
|
TimeZone [9]byte
|
||||||
|
TimeZoneValue [11]byte
|
||||||
|
ExtraDigits [19]byte
|
||||||
|
ExtraDigitsValue uint16
|
||||||
|
End byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type pgsqlErrResponse struct {
|
||||||
|
ResponseType uint8
|
||||||
|
Len [4]byte
|
||||||
|
Severity [6]byte
|
||||||
|
_ byte
|
||||||
|
Code [6]byte
|
||||||
|
_ byte
|
||||||
|
Message [53]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type PostgreSQLMatcher struct {
|
||||||
|
packets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPostgreSQLMatcher() *PostgreSQLMatcher {
|
||||||
|
|
||||||
|
pgSqlMatcher := &PostgreSQLMatcher{}
|
||||||
|
|
||||||
|
pg := pgsql{}
|
||||||
|
|
||||||
|
pg.Len = 0x00000065
|
||||||
|
pg.MessageType = 0x0003
|
||||||
|
|
||||||
|
var name [5]byte
|
||||||
|
copy(name[:], "user")
|
||||||
|
pg.Name = name
|
||||||
|
pg.NameValue = 0x00
|
||||||
|
|
||||||
|
var db [9]byte
|
||||||
|
copy(db[:], "database")
|
||||||
|
pg.Db = db
|
||||||
|
pg.DBValue = 0x00
|
||||||
|
|
||||||
|
var encoding [16]byte
|
||||||
|
copy(encoding[:], "client_encoding")
|
||||||
|
pg.Encoding = encoding
|
||||||
|
|
||||||
|
var encodingValue [5]byte
|
||||||
|
copy(encodingValue[:], "UTF8")
|
||||||
|
pg.EncodingValue = encodingValue
|
||||||
|
|
||||||
|
var dateStyle [10]byte
|
||||||
|
copy(dateStyle[:], "DateStyle")
|
||||||
|
pg.DateStyle = dateStyle
|
||||||
|
|
||||||
|
var dateStyleValue [4]byte
|
||||||
|
copy(dateStyleValue[:], "ISO")
|
||||||
|
pg.DateStyleValue = dateStyleValue
|
||||||
|
|
||||||
|
var timeZone [9]byte
|
||||||
|
copy(timeZone[:], "TimeZone")
|
||||||
|
pg.TimeZone = timeZone
|
||||||
|
|
||||||
|
var timeZoneValue [11]byte
|
||||||
|
copy(timeZoneValue[:], "Asia/Seoul")
|
||||||
|
pg.TimeZoneValue = timeZoneValue
|
||||||
|
|
||||||
|
var extraDigit [19]byte
|
||||||
|
copy(extraDigit[:], "extra_float_digits")
|
||||||
|
pg.ExtraDigits = extraDigit
|
||||||
|
|
||||||
|
pg.ExtraDigitsValue = 0x3200
|
||||||
|
|
||||||
|
writer := new(bytes.Buffer)
|
||||||
|
binary.Write(writer, binary.BigEndian, pg)
|
||||||
|
|
||||||
|
pgSqlMatcher.packets = append(pgSqlMatcher.packets, packet.NewPacket(writer.Bytes(), writer.Len()))
|
||||||
|
|
||||||
|
return pgSqlMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *PostgreSQLMatcher) ServiceName() string {
|
||||||
|
return "PostgreSQL"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *PostgreSQLMatcher) PacketCount() int {
|
||||||
|
return len(t.packets)
|
||||||
|
}
|
||||||
|
func (t *PostgreSQLMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return t.packets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *PostgreSQLMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *PostgreSQLMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *PostgreSQLMatcher) IsPrePacket() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *PostgreSQLMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := new(bytes.Buffer)
|
||||||
|
reader.Write(packet.Buffer)
|
||||||
|
|
||||||
|
pg := pgsqlErrResponse{}
|
||||||
|
if err := binary.Read(reader, binary.BigEndian, &pg); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if pg.ResponseType != RESPONSE_TYPE_ERR {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(pg.Severity[:]) != "SFATAL" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(pg.Code[:]) != "C28000" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
34
core/scan/service/matcher/postgresql/postgresql_test.go
Normal file
34
core/scan/service/matcher/postgresql/postgresql_test.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package postgresql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPG(t *testing.T) {
|
||||||
|
m := NewPostgreSQLMatcher()
|
||||||
|
|
||||||
|
conn, err := net.Dial("tcp", "192.168.1.88:5432")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
for i := 0; i < m.PacketCount(); i++ {
|
||||||
|
|
||||||
|
pack := m.Packet(i)
|
||||||
|
conn.Write(pack.Buffer)
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(i, p, nil) {
|
||||||
|
t.Log("PostgreSQL found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error("PostgreSQL not found")
|
||||||
|
}
|
||||||
|
}
|
76
core/scan/service/matcher/redis/redis.go
Normal file
76
core/scan/service/matcher/redis/redis.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const REDIS_PING string = "*1\r\n$4\r\nping\r\n"
|
||||||
|
|
||||||
|
type RedisMatcher struct {
|
||||||
|
packets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRedisMatcher() *RedisMatcher {
|
||||||
|
|
||||||
|
redisMatcher := &RedisMatcher{}
|
||||||
|
|
||||||
|
redisMatcher.packets = append(redisMatcher.packets, packet.NewPacket([]byte(REDIS_PING), len(REDIS_PING)))
|
||||||
|
|
||||||
|
return redisMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *RedisMatcher) ServiceName() string {
|
||||||
|
return "Redis"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *RedisMatcher) PacketCount() int {
|
||||||
|
return len(t.packets)
|
||||||
|
}
|
||||||
|
func (t *RedisMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return t.packets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *RedisMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *RedisMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *RedisMatcher) IsPrePacket() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *RedisMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := strings.Split(string(packet.Buffer), "\r\n")[0]
|
||||||
|
if len(resp) <= 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
sign := string([]rune(resp)[0])
|
||||||
|
if len(sign) <= 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if sign == "+" {
|
||||||
|
if resp == "+PONG" || resp == "+OK" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sign == "-" {
|
||||||
|
if resp == "-NOAUTH" || resp == "-ERR" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
}
|
78
core/scan/service/matcher/redis/redisProtected.go
Normal file
78
core/scan/service/matcher/redis/redisProtected.go
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
COMPARE_STR_1 = "-"
|
||||||
|
COMPARE_STR_2 = "DENIED"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RedisProtectedMatcher struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRedisProtectedMatcher() *RedisProtectedMatcher {
|
||||||
|
|
||||||
|
redisMatcher := &RedisProtectedMatcher{}
|
||||||
|
|
||||||
|
return redisMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RedisProtectedMatcher) ServiceName() string {
|
||||||
|
return "RedisProtectedMatcher"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RedisProtectedMatcher) PacketCount() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
func (r *RedisProtectedMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RedisProtectedMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RedisProtectedMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RedisProtectedMatcher) IsPrePacket() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RedisProtectedMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
str := string(packet.Buffer[:packet.Len])
|
||||||
|
|
||||||
|
if str == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(str) <= 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
firstCompare := str[0:1]
|
||||||
|
seconcdCompare := str[1 : len(COMPARE_STR_2)+1]
|
||||||
|
|
||||||
|
if firstCompare != COMPARE_STR_1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if seconcdCompare != COMPARE_STR_2 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
}
|
33
core/scan/service/matcher/redis/redisProtected_test.go
Normal file
33
core/scan/service/matcher/redis/redisProtected_test.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRedisProtected(t *testing.T) {
|
||||||
|
|
||||||
|
m := NewRedisProtectedMatcher()
|
||||||
|
|
||||||
|
conn, err := net.Dial("tcp", "192.168.1.215:8379")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
|
||||||
|
//fmt.Println(string(bytes[:n]))
|
||||||
|
|
||||||
|
b := m.Match(0, packet.NewPacket(bytes, n), nil)
|
||||||
|
|
||||||
|
if b {
|
||||||
|
t.Log("good!")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
core/scan/service/matcher/redis/redis_test.go
Normal file
37
core/scan/service/matcher/redis/redis_test.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ADDR string = "192.168.1.215:6379"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRedisMatcher(t *testing.T) {
|
||||||
|
|
||||||
|
m := NewRedisMatcher()
|
||||||
|
|
||||||
|
conn, _ := net.Dial("tcp", ADDR)
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
for i := 0; i < m.PacketCount(); i++ {
|
||||||
|
|
||||||
|
pack := m.Packet(i)
|
||||||
|
conn.Write(pack.Buffer)
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(i, p, nil) {
|
||||||
|
t.Log("Redis found.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error("Redis not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
111
core/scan/service/matcher/rmi/rmi.go
Normal file
111
core/scan/service/matcher/rmi/rmi.go
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
package rmi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MAGIC_NUMBER = 0x4a524d49
|
||||||
|
STREAM_PROTOCOL = 0x4b
|
||||||
|
VERSION = 0x0002
|
||||||
|
ACK_PROTOCOL = 0x4e
|
||||||
|
)
|
||||||
|
|
||||||
|
type RMI_SEND_MESSAGE struct {
|
||||||
|
magic uint32
|
||||||
|
version uint16
|
||||||
|
protocol uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type RMI_RECV_MESSAGE struct {
|
||||||
|
streamMessage uint8
|
||||||
|
packetLen uint16
|
||||||
|
host []byte
|
||||||
|
port [2]byte
|
||||||
|
}
|
||||||
|
type RMIMatcher struct {
|
||||||
|
sendPackets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RMIMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
result := false
|
||||||
|
|
||||||
|
if packet == nil || packet.Buffer == nil || packet.Len == 0 {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
//fmt.Println("packet :", packet)
|
||||||
|
rmiRecv := RMI_RECV_MESSAGE{}
|
||||||
|
|
||||||
|
buf := bytes.NewReader(packet.Buffer)
|
||||||
|
binary.Read(buf, binary.BigEndian, &rmiRecv.streamMessage)
|
||||||
|
binary.Read(buf, binary.BigEndian, &rmiRecv.packetLen)
|
||||||
|
|
||||||
|
lenInt := int(rmiRecv.packetLen)
|
||||||
|
|
||||||
|
var tempHost = make([]byte, lenInt, lenInt)
|
||||||
|
copy(rmiRecv.host, tempHost)
|
||||||
|
|
||||||
|
rmiRecv.host = tempHost
|
||||||
|
|
||||||
|
binary.Read(buf, binary.BigEndian, &rmiRecv.host)
|
||||||
|
binary.Read(buf, binary.BigEndian, &rmiRecv.port)
|
||||||
|
|
||||||
|
hostIp := string(rmiRecv.host[:lenInt])
|
||||||
|
//fmt.Println(hostIp)
|
||||||
|
|
||||||
|
//hostPort := binary.BigEndian.Uint16(rmiRecv.port[:2])
|
||||||
|
|
||||||
|
if rmiRecv.streamMessage == ACK_PROTOCOL && lenInt == len(hostIp) {
|
||||||
|
result = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RMIMatcher) PacketCount() int {
|
||||||
|
return len(r.sendPackets)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RMIMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return r.sendPackets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RMIMatcher) ServiceName() string {
|
||||||
|
return "RMI"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RMIMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RMIMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RMIMatcher) IsPrePacket() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRMIMatcher() *RMIMatcher {
|
||||||
|
|
||||||
|
r := RMIMatcher{}
|
||||||
|
rsm := RMI_SEND_MESSAGE{
|
||||||
|
magic: MAGIC_NUMBER,
|
||||||
|
version: VERSION,
|
||||||
|
protocol: STREAM_PROTOCOL,
|
||||||
|
}
|
||||||
|
|
||||||
|
mCache := new(bytes.Buffer)
|
||||||
|
binary.Write(mCache, binary.BigEndian, rsm)
|
||||||
|
|
||||||
|
sendByte1 := mCache.Bytes()
|
||||||
|
pp := packet.NewPacket(sendByte1, len(sendByte1))
|
||||||
|
|
||||||
|
r.sendPackets = append(r.sendPackets, pp)
|
||||||
|
|
||||||
|
return &r
|
||||||
|
}
|
48
core/scan/service/matcher/rmi/rmi_test.go
Normal file
48
core/scan/service/matcher/rmi/rmi_test.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package rmi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNew(t *testing.T) {
|
||||||
|
r := NewRMIMatcher()
|
||||||
|
fmt.Println("TestNew: ", r)
|
||||||
|
}
|
||||||
|
func TestRMIMatcher_Match(t *testing.T) {
|
||||||
|
|
||||||
|
fmt.Println("Match")
|
||||||
|
|
||||||
|
hm := NewRMIMatcher()
|
||||||
|
|
||||||
|
port := types.NewPort("9840", types.NewHost("192.168.1.101"), types.TYPE_TCP)
|
||||||
|
|
||||||
|
var ipport string
|
||||||
|
ipport = port.Host.Ip + ":" + string(port.Port)
|
||||||
|
|
||||||
|
//fmt.Println(ipport)
|
||||||
|
|
||||||
|
client, _ := net.Dial("tcp", ipport)
|
||||||
|
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
pack := hm.Packet(0)
|
||||||
|
|
||||||
|
fmt.Println(pack.Buffer)
|
||||||
|
|
||||||
|
//writer.WriteString(pack)
|
||||||
|
client.Write(pack.Buffer)
|
||||||
|
|
||||||
|
bytes := make([]byte, 512)
|
||||||
|
|
||||||
|
l, _ := client.Read(bytes)
|
||||||
|
|
||||||
|
//fmt.Println(bytes)
|
||||||
|
|
||||||
|
t1 := hm.Match(0, packet.NewPacket(bytes, l), nil)
|
||||||
|
|
||||||
|
fmt.Println(t1)
|
||||||
|
}
|
161
core/scan/service/matcher/smb/smb.go
Normal file
161
core/scan/service/matcher/smb/smb.go
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
package smb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SMB_COM_NEGOTIATE uint8 = 0x72
|
||||||
|
SMB_SUCCESS uint8 = 0x00
|
||||||
|
)
|
||||||
|
|
||||||
|
type netBIOS struct {
|
||||||
|
MsgType byte
|
||||||
|
MsgLength [3]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type smb struct {
|
||||||
|
NetBios netBIOS
|
||||||
|
Component [4]uint8
|
||||||
|
SmbCommand uint8
|
||||||
|
NtStatus [4]uint8
|
||||||
|
Flags uint8
|
||||||
|
Flags2 [2]uint8
|
||||||
|
ProcessId uint16
|
||||||
|
Signature uint64
|
||||||
|
Reserved uint16
|
||||||
|
Tid uint16
|
||||||
|
Pid uint16
|
||||||
|
Uid uint16
|
||||||
|
Mid uint16
|
||||||
|
Wct uint8
|
||||||
|
Bcc uint16
|
||||||
|
Bf1 uint8
|
||||||
|
Name1 [23]uint8
|
||||||
|
Bf2 uint8
|
||||||
|
Name2 [10]uint8
|
||||||
|
Bf3 uint8
|
||||||
|
Name3 [28]uint8
|
||||||
|
Bf4 uint8
|
||||||
|
Name4 [10]uint8
|
||||||
|
Bf5 uint8
|
||||||
|
Name5 [10]uint8
|
||||||
|
Bf6 uint8
|
||||||
|
Name6 [11]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type SMBMatcher struct {
|
||||||
|
packets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSMBMatcher() *SMBMatcher {
|
||||||
|
|
||||||
|
nbssMatcher := &SMBMatcher{}
|
||||||
|
|
||||||
|
query := smb{}
|
||||||
|
query.NetBios.MsgType = 0x00
|
||||||
|
query.NetBios.MsgLength[2] = 0x85
|
||||||
|
|
||||||
|
query.Component[0] = 0xff
|
||||||
|
query.Component[1] = 'S'
|
||||||
|
query.Component[2] = 'M'
|
||||||
|
query.Component[3] = 'B'
|
||||||
|
|
||||||
|
query.SmbCommand = SMB_COM_NEGOTIATE
|
||||||
|
query.NtStatus[3] = SMB_SUCCESS
|
||||||
|
query.Flags = 0x18
|
||||||
|
query.Flags2[0] = 0x53
|
||||||
|
query.Flags2[1] = 0xC8
|
||||||
|
|
||||||
|
query.ProcessId = 0x00
|
||||||
|
query.Signature = 0x00
|
||||||
|
query.Reserved = 0
|
||||||
|
query.Tid = 0
|
||||||
|
query.Pid = 0xfeff
|
||||||
|
query.Uid = 0
|
||||||
|
query.Mid = 0
|
||||||
|
query.Wct = 0
|
||||||
|
query.Bcc = 0x0062
|
||||||
|
|
||||||
|
query.Bf1 = 0x02
|
||||||
|
copy(query.Name1[:], "PC NETWORK PROGRAM 1.0")
|
||||||
|
|
||||||
|
query.Bf2 = 0x02
|
||||||
|
copy(query.Name2[:], "LANMAN1.0")
|
||||||
|
|
||||||
|
query.Bf3 = 0x02
|
||||||
|
copy(query.Name3[:], "Windows for Workgroups 3.1a")
|
||||||
|
|
||||||
|
query.Bf4 = 0x02
|
||||||
|
copy(query.Name4[:], "LM1.2X002")
|
||||||
|
|
||||||
|
query.Bf5 = 0x02
|
||||||
|
copy(query.Name5[:], "LANMAN2.1")
|
||||||
|
|
||||||
|
query.Bf6 = 0x02
|
||||||
|
copy(query.Name6[:], "NT LM 0.12")
|
||||||
|
|
||||||
|
writer := new(bytes.Buffer)
|
||||||
|
binary.Write(writer, binary.LittleEndian, query)
|
||||||
|
|
||||||
|
nbssMatcher.packets = append(nbssMatcher.packets, packet.NewPacket(writer.Bytes(), writer.Len()))
|
||||||
|
|
||||||
|
return nbssMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SMBMatcher) ServiceName() string {
|
||||||
|
return "SMB"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SMBMatcher) PacketCount() int {
|
||||||
|
return len(t.packets)
|
||||||
|
}
|
||||||
|
func (t *SMBMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return t.packets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SMBMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SMBMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SMBMatcher) IsPrePacket() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SMBMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := new(bytes.Buffer)
|
||||||
|
reader.Write(packet.Buffer)
|
||||||
|
|
||||||
|
s := smb{}
|
||||||
|
if err := binary.Read(reader, binary.BigEndian, &s); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var des [4]byte
|
||||||
|
copy(des[1:], s.NetBios.MsgLength[:])
|
||||||
|
packetLen := binary.BigEndian.Uint32(des[:])
|
||||||
|
|
||||||
|
if packetLen != uint32(packet.Len-4) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(string(s.Component[:]), "SMB") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
37
core/scan/service/matcher/smb/smb_test.go
Normal file
37
core/scan/service/matcher/smb/smb_test.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package smb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ADDR string = "192.168.1.104:139"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSMBMatcher(t *testing.T) {
|
||||||
|
|
||||||
|
m := NewSMBMatcher()
|
||||||
|
|
||||||
|
conn, _ := net.Dial("tcp", ADDR)
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
for i := 0; i < m.PacketCount(); i++ {
|
||||||
|
|
||||||
|
pack := m.Packet(i)
|
||||||
|
conn.Write(pack.Buffer)
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(i, p, nil) {
|
||||||
|
t.Log("SMB found.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error("SMB not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
71
core/scan/service/matcher/smtp/smtp.go
Normal file
71
core/scan/service/matcher/smtp/smtp.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package smtp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SmtpMatcher struct {
|
||||||
|
packets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSmtpMatcher() *SmtpMatcher {
|
||||||
|
|
||||||
|
m := &SmtpMatcher{}
|
||||||
|
b := []byte("helo test\r\n")
|
||||||
|
m.packets = append(m.packets, packet.NewPacket(b, len(b)))
|
||||||
|
b = []byte("quit\r\n")
|
||||||
|
m.packets = append(m.packets, packet.NewPacket(b, len(b)))
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SmtpMatcher) ServiceName() string {
|
||||||
|
return "SMTP"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SmtpMatcher) PacketCount() int {
|
||||||
|
return len(t.packets)
|
||||||
|
}
|
||||||
|
func (t *SmtpMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return t.packets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SmtpMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SmtpMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SmtpMatcher) IsPrePacket() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SmtpMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
buf := string(packet.Buffer)
|
||||||
|
if len(buf) == 0 || len(buf) < 5 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
splits := strings.Split(buf, "\r\n")
|
||||||
|
splits = strings.Split(buf, " ")
|
||||||
|
if index == 0 {
|
||||||
|
if splits[0] == "220" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else if index == 1 {
|
||||||
|
if splits[0] == "250" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else if index == 2 {
|
||||||
|
if splits[0] == "221" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
67
core/scan/service/matcher/smtp/smtp_test.go
Normal file
67
core/scan/service/matcher/smtp/smtp_test.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package smtp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSMTPTLS(t *testing.T) {
|
||||||
|
|
||||||
|
conn, err := tls.Dial("tcp",
|
||||||
|
"192.168.1.215:465",
|
||||||
|
&tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: "192.168.1.215",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b := make([]byte, 1024)
|
||||||
|
|
||||||
|
check(t, b, conn, "", "220")
|
||||||
|
check(t, b, conn, "helo test\r\n", "250")
|
||||||
|
check(t, b, conn, "quit\r\n", "221")
|
||||||
|
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSMTP(t *testing.T) {
|
||||||
|
|
||||||
|
conn, _ := net.Dial("tcp", "192.168.1.215:25")
|
||||||
|
|
||||||
|
b := make([]byte, 1024)
|
||||||
|
|
||||||
|
check(t, b, conn, "", "220")
|
||||||
|
check(t, b, conn, "helo test\r\n", "250")
|
||||||
|
check(t, b, conn, "quit\r\n", "221")
|
||||||
|
|
||||||
|
conn.Close()
|
||||||
|
|
||||||
|
}
|
||||||
|
func check(t *testing.T, b []byte, conn net.Conn, cmd string, compare string) {
|
||||||
|
|
||||||
|
if cmd != "" {
|
||||||
|
wlen, _ := conn.Write([]byte(cmd))
|
||||||
|
assert.Equal(t, wlen, len(cmd))
|
||||||
|
}
|
||||||
|
|
||||||
|
rlen, _ := conn.Read(b)
|
||||||
|
|
||||||
|
fmt.Println(rlen)
|
||||||
|
fmt.Println(len(b))
|
||||||
|
|
||||||
|
data := string(b[:rlen])
|
||||||
|
fmt.Println(data)
|
||||||
|
assert.Equal(t, true, rlen > 4)
|
||||||
|
splits := strings.Split(data, " ")
|
||||||
|
assert.Equal(t, compare, splits[0])
|
||||||
|
|
||||||
|
}
|
200
core/scan/service/matcher/snmp/snmpv2.go
Normal file
200
core/scan/service/matcher/snmp/snmpv2.go
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
package snmp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SNMP_START_SEQUENCE uint8 = 0X30
|
||||||
|
SNMP_TYPE_INTEGER uint8 = 0X02
|
||||||
|
SNMP_TYPE_STRING uint8 = 0X04
|
||||||
|
SNMP_TYPE_NULL uint8 = 0X05
|
||||||
|
SNMP_TYPE_OBJECT uint8 = 0X06
|
||||||
|
SNMP_GET_REQUEST uint8 = 0XA0
|
||||||
|
//SNMP_RESPONSE uint8 = 0XA2
|
||||||
|
SNMP_NO_DESC uint16 = 0X0004
|
||||||
|
SNMP_END_SEQUENCE uint8 = 0X30
|
||||||
|
SNMP_PROTOCOL_VERSION_3 uint8 = 0X03
|
||||||
|
SNMP_PROTOCOL_VERSION_2c uint8 = 0X01
|
||||||
|
SNMP_MSG_ID_MAX_VALUE uint32 = 0xFFFFFF7F
|
||||||
|
)
|
||||||
|
|
||||||
|
type snmpv2VarBinding struct {
|
||||||
|
VarBindindStart uint8
|
||||||
|
VarBindLen uint8
|
||||||
|
ObjectStart uint8
|
||||||
|
ObjectLen uint8
|
||||||
|
ValueType uint8
|
||||||
|
ValueLen uint8
|
||||||
|
ObjectValue uint64
|
||||||
|
NullValue uint8
|
||||||
|
EndIndicator uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type snmpv2Data struct {
|
||||||
|
DataType uint8
|
||||||
|
DataLen uint8
|
||||||
|
RequestIdType uint8
|
||||||
|
RequestIdLen uint8
|
||||||
|
RequestId uint8
|
||||||
|
ErrorStatusType uint8
|
||||||
|
ErrorStatusLen uint8
|
||||||
|
ErrorStatus uint8
|
||||||
|
ErrorIndexType uint8
|
||||||
|
ErrorIndexLen uint8
|
||||||
|
ErrorIndex uint8
|
||||||
|
|
||||||
|
VarBinding snmpv2VarBinding
|
||||||
|
}
|
||||||
|
|
||||||
|
type snmpv2 struct {
|
||||||
|
StartSeq uint8
|
||||||
|
SeqLen uint8
|
||||||
|
SNMPVersionType uint8
|
||||||
|
SNMPVersionLen uint8
|
||||||
|
SNMPVersion uint8
|
||||||
|
CommunityVersionType uint8
|
||||||
|
CommunityVersionLen uint8
|
||||||
|
Community [6]byte
|
||||||
|
|
||||||
|
Data snmpv2Data
|
||||||
|
}
|
||||||
|
|
||||||
|
type SNMPv2Matcher struct {
|
||||||
|
packets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSNMPv2Matcher() *SNMPv2Matcher {
|
||||||
|
|
||||||
|
snmpMatcher := &SNMPv2Matcher{}
|
||||||
|
|
||||||
|
snmpTempBuf := new(bytes.Buffer)
|
||||||
|
binary.Write(snmpTempBuf, binary.BigEndian, snmpv2{}) //For getting the struct size
|
||||||
|
|
||||||
|
snmpDataTempBuf := new(bytes.Buffer)
|
||||||
|
binary.Write(snmpDataTempBuf, binary.BigEndian, snmpv2Data{}) //For getting the struct size
|
||||||
|
|
||||||
|
snmpVarTempBuf := new(bytes.Buffer)
|
||||||
|
binary.Write(snmpVarTempBuf, binary.BigEndian, snmpv2VarBinding{}) //For getting the struct size
|
||||||
|
|
||||||
|
q := snmpv2{}
|
||||||
|
q.StartSeq = SNMP_START_SEQUENCE
|
||||||
|
q.SeqLen = uint8(len(snmpTempBuf.Bytes())) - 2
|
||||||
|
q.SNMPVersionType = SNMP_TYPE_INTEGER
|
||||||
|
q.SNMPVersionLen = 0x01
|
||||||
|
q.SNMPVersion = SNMP_PROTOCOL_VERSION_2c
|
||||||
|
q.CommunityVersionType = SNMP_TYPE_STRING
|
||||||
|
q.CommunityVersionLen = 0x06
|
||||||
|
var community [6]byte
|
||||||
|
copy(community[:], "public")
|
||||||
|
q.Community = community
|
||||||
|
q.Data.DataType = SNMP_GET_REQUEST
|
||||||
|
q.Data.DataLen = uint8(len(snmpDataTempBuf.Bytes())) - 2
|
||||||
|
q.Data.RequestIdType = SNMP_TYPE_INTEGER
|
||||||
|
q.Data.RequestIdLen = 0x01
|
||||||
|
q.Data.RequestId = 0x01
|
||||||
|
q.Data.ErrorStatusType = SNMP_TYPE_INTEGER
|
||||||
|
q.Data.ErrorStatusLen = 0x01
|
||||||
|
q.Data.ErrorStatus = 0x00
|
||||||
|
q.Data.ErrorIndexType = SNMP_TYPE_INTEGER
|
||||||
|
q.Data.ErrorIndexLen = 0x01
|
||||||
|
q.Data.ErrorIndex = 0x00
|
||||||
|
q.Data.VarBinding.VarBindindStart = SNMP_START_SEQUENCE
|
||||||
|
q.Data.VarBinding.VarBindLen = uint8(len(snmpVarTempBuf.Bytes())) - 2
|
||||||
|
q.Data.VarBinding.ObjectStart = SNMP_START_SEQUENCE
|
||||||
|
q.Data.VarBinding.ObjectLen = uint8(len(snmpVarTempBuf.Bytes())) - 4
|
||||||
|
q.Data.VarBinding.ValueType = SNMP_TYPE_OBJECT
|
||||||
|
q.Data.VarBinding.ValueLen = 0x08
|
||||||
|
q.Data.VarBinding.ObjectValue = 0x000001010201062b
|
||||||
|
q.Data.VarBinding.NullValue = SNMP_TYPE_NULL
|
||||||
|
q.Data.VarBinding.EndIndicator = 0x00
|
||||||
|
|
||||||
|
writer := new(bytes.Buffer)
|
||||||
|
binary.Write(writer, binary.LittleEndian, q)
|
||||||
|
|
||||||
|
snmpMatcher.packets = append(snmpMatcher.packets, packet.NewPacket(writer.Bytes(), writer.Len()))
|
||||||
|
|
||||||
|
return snmpMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv2Matcher) ServiceName() string {
|
||||||
|
return "SNMP"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv2Matcher) PacketCount() int {
|
||||||
|
return len(t.packets)
|
||||||
|
}
|
||||||
|
func (t *SNMPv2Matcher) Packet(index int) *packet.Packet {
|
||||||
|
return t.packets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv2Matcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv2Matcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv2Matcher) IsPrePacket() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv2Matcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
r := new(bytes.Buffer)
|
||||||
|
r.Write(packet.Buffer)
|
||||||
|
|
||||||
|
s := snmpv2{}
|
||||||
|
if err := binary.Read(r, binary.BigEndian, &s); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.StartSeq != SNMP_START_SEQUENCE {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var p uint8
|
||||||
|
reader := new(bytes.Buffer)
|
||||||
|
reader.Write(packet.Buffer)
|
||||||
|
for idx := 0; idx < 5; idx++ {
|
||||||
|
if err := binary.Read(reader, binary.BigEndian, &p); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if p == SNMP_TYPE_INTEGER {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p++
|
||||||
|
}
|
||||||
|
|
||||||
|
//finding protocol version type : 0x02 0x01 0x01
|
||||||
|
if err := binary.Read(reader, binary.BigEndian, &p); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if p == 0x01 {
|
||||||
|
if err := binary.Read(reader, binary.BigEndian, &p); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if p == 0x01 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv2Matcher) IsSend(port int) bool {
|
||||||
|
if port == 161 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
36
core/scan/service/matcher/snmp/snmpv2_test.go
Normal file
36
core/scan/service/matcher/snmp/snmpv2_test.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package snmp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSNMP2(t *testing.T) {
|
||||||
|
|
||||||
|
m := NewSNMPv2Matcher()
|
||||||
|
|
||||||
|
conn, err := net.Dial("udp", "192.168.1.215:161")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
for i := 0; i < m.PacketCount(); i++ {
|
||||||
|
|
||||||
|
pack := m.Packet(i)
|
||||||
|
conn.Write(pack.Buffer)
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(i, p, nil) {
|
||||||
|
t.Log("SNMP found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error("SNMP not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
218
core/scan/service/matcher/snmp/snmpv3.go
Normal file
218
core/scan/service/matcher/snmp/snmpv3.go
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
package snmp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type snmpv3GlobalData struct {
|
||||||
|
GlobalDataStartSeq uint8
|
||||||
|
GlobalDataLen uint8
|
||||||
|
MsgIdType uint8
|
||||||
|
MsgIdLen uint8
|
||||||
|
MsgId uint32
|
||||||
|
MsgMaxSizeType uint8
|
||||||
|
MsgMaxSizeLen uint8
|
||||||
|
MsgMaxSize [3]uint8
|
||||||
|
MsgFlagsType uint8
|
||||||
|
MsgFlagsTypeLen uint8
|
||||||
|
MsgFlags uint8
|
||||||
|
MsgSecurityModelType uint8
|
||||||
|
MsgSecurityModelLen uint8
|
||||||
|
MsgSecurityModel uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type snmpv3MsgData struct {
|
||||||
|
MsgDataStartSeq uint8
|
||||||
|
MsgDataLen uint8
|
||||||
|
ContextEngineId uint16
|
||||||
|
ContextEngineName uint16
|
||||||
|
SnmpType uint8
|
||||||
|
Len uint8
|
||||||
|
RequestIdType uint8
|
||||||
|
RequestIdLen uint8
|
||||||
|
RequestId uint32
|
||||||
|
ErrorStatusType uint8
|
||||||
|
ErrorStatusLen uint8
|
||||||
|
ErrorStatus uint8
|
||||||
|
ErrorIndexType uint8
|
||||||
|
ErrorIndexLen uint8
|
||||||
|
ErrorIndex uint8
|
||||||
|
EndSeq uint8
|
||||||
|
EndIndicator uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type snmpv3 struct {
|
||||||
|
StartSeq uint8
|
||||||
|
SeqLen uint8
|
||||||
|
SNMPVersionType uint8
|
||||||
|
SNMPVersionLen uint8
|
||||||
|
SNMPVersion uint8
|
||||||
|
MsgGlobalData snmpv3GlobalData
|
||||||
|
Unk1 uint16
|
||||||
|
Unk2 uint16
|
||||||
|
MsgAuthoritativeEngineId uint16
|
||||||
|
|
||||||
|
MsgAuthoritativeEngineBootsType uint8
|
||||||
|
MsgAuthoritativeEngineBootsLen uint8
|
||||||
|
MsgAuthoritativeEngineBoots uint8
|
||||||
|
MsgAuthoritativeEngineTimeType uint8
|
||||||
|
MsgAuthoritativeEngineTimeLen uint8
|
||||||
|
MsgAuthoritativeEngineTime uint8
|
||||||
|
MsgUserName uint16
|
||||||
|
MsgAuthenticationParam uint16
|
||||||
|
MsgPrivacyParam uint16
|
||||||
|
MsgData snmpv3MsgData
|
||||||
|
}
|
||||||
|
|
||||||
|
type SNMPv3Matcher struct {
|
||||||
|
packets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSNMPv3Matcher() *SNMPv3Matcher {
|
||||||
|
|
||||||
|
snmpMatcher := &SNMPv3Matcher{}
|
||||||
|
|
||||||
|
snmpTempBuf := new(bytes.Buffer)
|
||||||
|
binary.Write(snmpTempBuf, binary.BigEndian, snmpv3{}) //For getting the struct size
|
||||||
|
|
||||||
|
snmpMsgDataTempBuf := new(bytes.Buffer)
|
||||||
|
binary.Write(snmpMsgDataTempBuf, binary.BigEndian, snmpv3MsgData{}) //For getting the struct size
|
||||||
|
|
||||||
|
snmpGlobalTempBuf := new(bytes.Buffer)
|
||||||
|
binary.Write(snmpGlobalTempBuf, binary.BigEndian, snmpv3GlobalData{}) //For getting the struct size
|
||||||
|
|
||||||
|
q := snmpv3{}
|
||||||
|
q.StartSeq = SNMP_START_SEQUENCE
|
||||||
|
q.SeqLen = uint8(len(snmpTempBuf.Bytes())) - 2
|
||||||
|
q.SNMPVersionType = SNMP_TYPE_INTEGER
|
||||||
|
q.SNMPVersionLen = 0x01
|
||||||
|
q.SNMPVersion = SNMP_PROTOCOL_VERSION_3
|
||||||
|
q.MsgGlobalData.GlobalDataStartSeq = SNMP_START_SEQUENCE
|
||||||
|
q.MsgGlobalData.GlobalDataLen = uint8(len(snmpGlobalTempBuf.Bytes())) - 2
|
||||||
|
q.MsgGlobalData.MsgIdType = SNMP_TYPE_INTEGER
|
||||||
|
q.MsgGlobalData.MsgIdLen = 0x04
|
||||||
|
q.MsgGlobalData.MsgId = SNMP_MSG_ID_MAX_VALUE
|
||||||
|
q.MsgGlobalData.MsgMaxSizeType = SNMP_TYPE_INTEGER
|
||||||
|
q.MsgGlobalData.MsgMaxSizeLen = 0x03
|
||||||
|
q.MsgGlobalData.MsgMaxSize[2] = 0xe3
|
||||||
|
q.MsgGlobalData.MsgMaxSize[1] = 0xff
|
||||||
|
q.MsgGlobalData.MsgMaxSize[0] = 0x00
|
||||||
|
q.MsgGlobalData.MsgFlagsType = SNMP_TYPE_STRING
|
||||||
|
q.MsgGlobalData.MsgFlagsTypeLen = 0x01
|
||||||
|
q.MsgGlobalData.MsgFlags = 0x04
|
||||||
|
q.MsgGlobalData.MsgSecurityModelType = SNMP_TYPE_INTEGER
|
||||||
|
q.MsgGlobalData.MsgSecurityModelLen = 0x01
|
||||||
|
q.MsgGlobalData.MsgSecurityModel = 0x03
|
||||||
|
q.Unk1 = 0x1004
|
||||||
|
q.Unk2 = 0x0e30
|
||||||
|
q.MsgAuthoritativeEngineId = SNMP_NO_DESC
|
||||||
|
q.MsgAuthoritativeEngineBootsType = SNMP_TYPE_INTEGER
|
||||||
|
q.MsgAuthoritativeEngineBootsLen = 0x01
|
||||||
|
q.MsgAuthoritativeEngineBoots = 0x00
|
||||||
|
q.MsgAuthoritativeEngineTimeType = SNMP_TYPE_INTEGER
|
||||||
|
q.MsgAuthoritativeEngineTimeLen = 0x01
|
||||||
|
q.MsgAuthoritativeEngineTime = 0x00
|
||||||
|
q.MsgUserName = SNMP_NO_DESC
|
||||||
|
q.MsgAuthenticationParam = SNMP_NO_DESC
|
||||||
|
q.MsgPrivacyParam = SNMP_NO_DESC
|
||||||
|
|
||||||
|
q.MsgData.MsgDataStartSeq = SNMP_START_SEQUENCE
|
||||||
|
q.MsgData.MsgDataLen = uint8(len(snmpMsgDataTempBuf.Bytes())) - 2
|
||||||
|
q.MsgData.ContextEngineId = SNMP_NO_DESC
|
||||||
|
q.MsgData.ContextEngineName = SNMP_NO_DESC
|
||||||
|
q.MsgData.SnmpType = SNMP_GET_REQUEST
|
||||||
|
q.MsgData.Len = 0x0E
|
||||||
|
q.MsgData.RequestIdType = SNMP_TYPE_INTEGER
|
||||||
|
q.MsgData.RequestIdLen = 0x04
|
||||||
|
q.MsgData.RequestId = 0x00 //
|
||||||
|
q.MsgData.ErrorStatusType = SNMP_TYPE_INTEGER
|
||||||
|
q.MsgData.ErrorStatusLen = 0x01
|
||||||
|
q.MsgData.ErrorStatus = 0x00
|
||||||
|
q.MsgData.ErrorIndexType = SNMP_TYPE_INTEGER
|
||||||
|
q.MsgData.ErrorIndexLen = 0x01
|
||||||
|
q.MsgData.ErrorIndex = 0x00
|
||||||
|
q.MsgData.EndSeq = SNMP_END_SEQUENCE
|
||||||
|
q.MsgData.EndIndicator = 0x00
|
||||||
|
|
||||||
|
writer := new(bytes.Buffer)
|
||||||
|
binary.Write(writer, binary.LittleEndian, q)
|
||||||
|
|
||||||
|
snmpMatcher.packets = append(snmpMatcher.packets, packet.NewPacket(writer.Bytes(), writer.Len()))
|
||||||
|
|
||||||
|
return snmpMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv3Matcher) ServiceName() string {
|
||||||
|
return "SNMP"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv3Matcher) PacketCount() int {
|
||||||
|
return len(t.packets)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv3Matcher) Packet(index int) *packet.Packet {
|
||||||
|
return t.packets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv3Matcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func (t *SNMPv3Matcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv3Matcher) IsPrePacket() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv3Matcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := new(bytes.Buffer)
|
||||||
|
reader.Write(packet.Buffer)
|
||||||
|
|
||||||
|
s := snmpv3{}
|
||||||
|
if err := binary.Read(reader, binary.LittleEndian, &s); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.StartSeq != SNMP_START_SEQUENCE {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var p uint8
|
||||||
|
r := new(bytes.Buffer)
|
||||||
|
r.Write(packet.Buffer)
|
||||||
|
|
||||||
|
for {
|
||||||
|
binary.Read(r, binary.LittleEndian, &p)
|
||||||
|
|
||||||
|
if p == SNMP_TYPE_INTEGER {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binary.Read(r, binary.BigEndian, &p)
|
||||||
|
if p == 0x01 {
|
||||||
|
binary.Read(r, binary.BigEndian, &p)
|
||||||
|
if p == 0x03 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *SNMPv3Matcher) IsSend(port int) bool {
|
||||||
|
if port == 161 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
36
core/scan/service/matcher/snmp/snmpv3_test.go
Normal file
36
core/scan/service/matcher/snmp/snmpv3_test.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package snmp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSNMP3(t *testing.T) {
|
||||||
|
|
||||||
|
m := NewSNMPv3Matcher()
|
||||||
|
|
||||||
|
conn, err := net.Dial("udp", "192.168.1.254:161")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
for i := 0; i < m.PacketCount(); i++ {
|
||||||
|
|
||||||
|
pack := m.Packet(i)
|
||||||
|
conn.Write(pack.Buffer)
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(i, p, nil) {
|
||||||
|
t.Log("SNMP found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error("SNMP not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
66
core/scan/service/matcher/ssh/ssh.go
Normal file
66
core/scan/service/matcher/ssh/ssh.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package ssh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SSHMatcher struct {
|
||||||
|
sendPackets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ssh *SSHMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
result := false
|
||||||
|
|
||||||
|
if packet == nil || packet.Buffer == nil || packet.Len == 0 {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
str := string(packet.Buffer)
|
||||||
|
|
||||||
|
//fmt.Println(str)
|
||||||
|
temps := strings.Split(str, " ")
|
||||||
|
protocol := strings.Split(temps[0], "-")
|
||||||
|
//osType := temps[1]
|
||||||
|
|
||||||
|
if 0 == strings.Compare(protocol[0], "SSH") {
|
||||||
|
majorVersion := protocol[1]
|
||||||
|
//fmt.Println(majorVersion)
|
||||||
|
if 0 == strings.Compare(majorVersion, "2.0") || 0 == strings.Compare(majorVersion, "1.0") {
|
||||||
|
result = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ssh *SSHMatcher) PacketCount() int {
|
||||||
|
return len(ssh.sendPackets)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ssh *SSHMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return ssh.sendPackets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ssh *SSHMatcher) ServiceName() string {
|
||||||
|
return "SSH"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ssh *SSHMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ssh *SSHMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ssh *SSHMatcher) IsPrePacket() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSSHMatcher() *SSHMatcher {
|
||||||
|
r := SSHMatcher{}
|
||||||
|
|
||||||
|
return &r
|
||||||
|
}
|
33
core/scan/service/matcher/ssh/ssh_test.go
Normal file
33
core/scan/service/matcher/ssh/ssh_test.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package ssh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSSHMatcher_Match(t *testing.T) {
|
||||||
|
|
||||||
|
port := types.NewPort("22", types.NewHost("192.168.1.103"), types.TYPE_TCP)
|
||||||
|
ssh := NewSSHMatcher()
|
||||||
|
|
||||||
|
var ipport string
|
||||||
|
ipport = port.Host.Ip + ":" + string(port.Port)
|
||||||
|
|
||||||
|
client, _ := net.Dial("tcp", ipport)
|
||||||
|
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
bytes := make([]byte, 512)
|
||||||
|
|
||||||
|
l, _ := client.Read(bytes)
|
||||||
|
|
||||||
|
fmt.Println(bytes)
|
||||||
|
|
||||||
|
b := ssh.Match(0, packet.NewPacket(bytes, l), nil)
|
||||||
|
|
||||||
|
fmt.Println(b)
|
||||||
|
|
||||||
|
}
|
79
core/scan/service/matcher/telnet/telnet.go
Normal file
79
core/scan/service/matcher/telnet/telnet.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package telnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DO = 0xfd
|
||||||
|
WONT = 0x4b
|
||||||
|
WILL = 0xfb
|
||||||
|
DONT = 0xfe
|
||||||
|
CMD = 0xff
|
||||||
|
)
|
||||||
|
|
||||||
|
type TelnetMatcher struct {
|
||||||
|
sendPackets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tel *TelnetMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
result := false
|
||||||
|
|
||||||
|
if packet == nil || packet.Buffer == nil || packet.Len == 0 {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, 0, 0)
|
||||||
|
count := 0
|
||||||
|
|
||||||
|
for i := 0; i < len(packet.Buffer); i++ {
|
||||||
|
if packet.Buffer[i] > 0 {
|
||||||
|
buf = append(buf, packet.Buffer[i])
|
||||||
|
} else if count > 2 {
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx := 0; idx < len(buf); idx += 3 {
|
||||||
|
if buf[idx] == CMD && (buf[idx+1] == DO || buf[idx+1] == WONT || buf[idx+1] == WILL || buf[idx+1] == DONT) {
|
||||||
|
result = true
|
||||||
|
} else {
|
||||||
|
result = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tel *TelnetMatcher) PacketCount() int {
|
||||||
|
return len(tel.sendPackets)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tel *TelnetMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return tel.sendPackets[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tel *TelnetMatcher) ServiceName() string {
|
||||||
|
return "Telnet"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tel *TelnetMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tel *TelnetMatcher) IsNoResponse(index int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tel *TelnetMatcher) IsPrePacket() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTelnetMatcher() *TelnetMatcher {
|
||||||
|
r := TelnetMatcher{}
|
||||||
|
|
||||||
|
return &r
|
||||||
|
}
|
33
core/scan/service/matcher/telnet/telnet_test.go
Normal file
33
core/scan/service/matcher/telnet/telnet_test.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package telnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTelnetMatcher_Match(t *testing.T) {
|
||||||
|
|
||||||
|
port := types.NewPort("23", types.NewHost("192.168.1.210"), types.TYPE_TCP)
|
||||||
|
telnet := NewTelnetMatcher()
|
||||||
|
|
||||||
|
var ipport string
|
||||||
|
ipport = port.Host.Ip + ":" + string(port.Port)
|
||||||
|
|
||||||
|
client, _ := net.Dial("tcp", ipport)
|
||||||
|
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
bytes := make([]byte, 512)
|
||||||
|
|
||||||
|
l, _ := client.Read(bytes)
|
||||||
|
|
||||||
|
fmt.Println("length :", l)
|
||||||
|
fmt.Println(bytes)
|
||||||
|
|
||||||
|
b := telnet.Match(0, packet.NewPacket(bytes, l), nil)
|
||||||
|
|
||||||
|
fmt.Println(b)
|
||||||
|
}
|
250
core/scan/service/matcher/wmi/wmi.go
Normal file
250
core/scan/service/matcher/wmi/wmi.go
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
package wmi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
PDU_BIND = 11
|
||||||
|
PDU_BIND_ACK = 12
|
||||||
|
PDU_REQ = 0
|
||||||
|
PDU_RESP = 2
|
||||||
|
|
||||||
|
WMI_CALL_ID_1 = 0x95
|
||||||
|
WMI_CALL_ID_2 = 0x96
|
||||||
|
)
|
||||||
|
|
||||||
|
type WMIMatcher struct {
|
||||||
|
sendPackets []*packet.Packet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WMIMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
|
||||||
|
if packet == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
buf.Write(packet.Buffer)
|
||||||
|
|
||||||
|
wmiRecv := DCERPC_DEFAULT{}
|
||||||
|
|
||||||
|
binary.Read(buf, binary.LittleEndian, &wmiRecv)
|
||||||
|
|
||||||
|
switch index {
|
||||||
|
case 0:
|
||||||
|
if wmiRecv.Call_id != WMI_CALL_ID_1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if wmiRecv.Ptype != PDU_BIND_ACK {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
case 1:
|
||||||
|
|
||||||
|
if wmiRecv.Call_id != WMI_CALL_ID_2 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if wmiRecv.Ptype != PDU_RESP {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WMIMatcher) PacketCount() int {
|
||||||
|
return len(w.sendPackets)
|
||||||
|
}
|
||||||
|
func (w *WMIMatcher) Packet(index int) *packet.Packet {
|
||||||
|
return w.sendPackets[index]
|
||||||
|
}
|
||||||
|
func (w *WMIMatcher) ServiceName() string {
|
||||||
|
return "WMI"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WMIMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func (w *WMIMatcher) IsNoResponse(index int) bool {
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WMIMatcher) IsPrePacket() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWMIMatcher() *WMIMatcher {
|
||||||
|
|
||||||
|
wm := WMIMatcher{}
|
||||||
|
|
||||||
|
ds1 := DCERPC_DEFAULT{
|
||||||
|
Rpc_ver: 5,
|
||||||
|
Rpc_ver_minor: 0,
|
||||||
|
Ptype: PDU_BIND,
|
||||||
|
Flags: 0x03,
|
||||||
|
Drep: 0x10,
|
||||||
|
Frag_len: 16 + 56,
|
||||||
|
Auth_len: 0,
|
||||||
|
Call_id: WMI_CALL_ID_1,
|
||||||
|
}
|
||||||
|
|
||||||
|
ds2 := DCERPC_DEFAULT{
|
||||||
|
Rpc_ver: 5,
|
||||||
|
Rpc_ver_minor: 0,
|
||||||
|
Ptype: PDU_REQ,
|
||||||
|
Flags: 0x03,
|
||||||
|
Drep: 0x10,
|
||||||
|
Frag_len: 16 + 8,
|
||||||
|
Auth_len: 0,
|
||||||
|
Call_id: WMI_CALL_ID_2,
|
||||||
|
}
|
||||||
|
|
||||||
|
ioxidr := DCERPC_IOXIDResolver{
|
||||||
|
MaxXmitFrag: 0x16d0,
|
||||||
|
MaxRecvFrag: 0x16d0,
|
||||||
|
|
||||||
|
AssocGroup: 0,
|
||||||
|
NumCtxItem: 1,
|
||||||
|
|
||||||
|
ContextId: 0,
|
||||||
|
NumTransItem: 1,
|
||||||
|
|
||||||
|
//interfaces
|
||||||
|
|
||||||
|
InterfaceVer: 0,
|
||||||
|
InterfaceVerMinor: 0,
|
||||||
|
|
||||||
|
//transSyntax
|
||||||
|
|
||||||
|
TransSyntaxVer: 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
ioxidr.Interfaces[0] = 0xc4
|
||||||
|
ioxidr.Interfaces[1] = 0xfe
|
||||||
|
ioxidr.Interfaces[2] = 0xfc
|
||||||
|
ioxidr.Interfaces[3] = 0x99
|
||||||
|
|
||||||
|
ioxidr.Interfaces[4] = 0x60
|
||||||
|
ioxidr.Interfaces[5] = 0x52
|
||||||
|
|
||||||
|
ioxidr.Interfaces[6] = 0x1b
|
||||||
|
ioxidr.Interfaces[7] = 0x10
|
||||||
|
|
||||||
|
ioxidr.Interfaces[8] = 0xbb
|
||||||
|
ioxidr.Interfaces[9] = 0xcb
|
||||||
|
|
||||||
|
ioxidr.Interfaces[10] = 0x00
|
||||||
|
ioxidr.Interfaces[11] = 0xaa
|
||||||
|
ioxidr.Interfaces[12] = 0x00
|
||||||
|
ioxidr.Interfaces[13] = 0x21
|
||||||
|
ioxidr.Interfaces[14] = 0x34
|
||||||
|
ioxidr.Interfaces[15] = 0x7a
|
||||||
|
|
||||||
|
ioxidr.TransSyntax[0] = 0x04
|
||||||
|
ioxidr.TransSyntax[1] = 0x5d
|
||||||
|
ioxidr.TransSyntax[2] = 0x88
|
||||||
|
ioxidr.TransSyntax[3] = 0x8a
|
||||||
|
|
||||||
|
ioxidr.TransSyntax[4] = 0xeb
|
||||||
|
ioxidr.TransSyntax[5] = 0x1c
|
||||||
|
|
||||||
|
ioxidr.TransSyntax[6] = 0xc9
|
||||||
|
ioxidr.TransSyntax[7] = 0x11
|
||||||
|
|
||||||
|
ioxidr.TransSyntax[8] = 0x9f
|
||||||
|
ioxidr.TransSyntax[9] = 0xe8
|
||||||
|
|
||||||
|
ioxidr.TransSyntax[10] = 0x08
|
||||||
|
ioxidr.TransSyntax[11] = 0x00
|
||||||
|
ioxidr.TransSyntax[12] = 0x2b
|
||||||
|
ioxidr.TransSyntax[13] = 0x10
|
||||||
|
ioxidr.TransSyntax[14] = 0x48
|
||||||
|
ioxidr.TransSyntax[15] = 0x60
|
||||||
|
|
||||||
|
da := DCERPC_ALIVE{
|
||||||
|
AllocHint: 0,
|
||||||
|
ContextId: 0,
|
||||||
|
OpNum: 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
buf1 := new(bytes.Buffer)
|
||||||
|
|
||||||
|
binary.Write(buf1, binary.LittleEndian, ds1)
|
||||||
|
ds1Bytes := buf1.Bytes()
|
||||||
|
|
||||||
|
buf2 := new(bytes.Buffer)
|
||||||
|
|
||||||
|
binary.Write(buf2, binary.LittleEndian, ds2)
|
||||||
|
ds2Bytes := buf2.Bytes()
|
||||||
|
|
||||||
|
buf3 := new(bytes.Buffer)
|
||||||
|
|
||||||
|
binary.Write(buf3, binary.LittleEndian, ioxidr)
|
||||||
|
ioxidrBytes := buf3.Bytes()
|
||||||
|
|
||||||
|
buf4 := new(bytes.Buffer)
|
||||||
|
|
||||||
|
binary.Write(buf4, binary.LittleEndian, da)
|
||||||
|
daBytes := buf4.Bytes()
|
||||||
|
|
||||||
|
firstByte := make([]byte, len(ds1Bytes)+len(ioxidrBytes))
|
||||||
|
|
||||||
|
copy(firstByte[0:], ds1Bytes)
|
||||||
|
copy(firstByte[len(ds1Bytes):], ioxidrBytes)
|
||||||
|
|
||||||
|
secondByte := make([]byte, len(ds2Bytes)+len(daBytes))
|
||||||
|
|
||||||
|
copy(secondByte[0:], ds2Bytes)
|
||||||
|
copy(secondByte[len(ds2Bytes):], daBytes)
|
||||||
|
|
||||||
|
wm.sendPackets = append(wm.sendPackets, packet.NewPacket(firstByte, len(ds1Bytes)+len(ioxidrBytes)))
|
||||||
|
wm.sendPackets = append(wm.sendPackets, packet.NewPacket(secondByte, len(ds2Bytes)+len(daBytes)))
|
||||||
|
|
||||||
|
return &wm
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type DCERPC_DEFAULT struct {
|
||||||
|
Rpc_ver uint8
|
||||||
|
Rpc_ver_minor uint8
|
||||||
|
Ptype uint8
|
||||||
|
Flags uint8
|
||||||
|
Drep uint32
|
||||||
|
Frag_len uint16
|
||||||
|
Auth_len uint16
|
||||||
|
Call_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type DCERPC_ALIVE struct {
|
||||||
|
AllocHint uint32
|
||||||
|
ContextId uint16
|
||||||
|
OpNum uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type DCERPC_IOXIDResolver struct {
|
||||||
|
MaxXmitFrag uint16
|
||||||
|
MaxRecvFrag uint16
|
||||||
|
AssocGroup uint32
|
||||||
|
NumCtxItem uint8
|
||||||
|
UnknownCode [3]uint8
|
||||||
|
|
||||||
|
ContextId uint16
|
||||||
|
NumTransItem uint8
|
||||||
|
UnknownCode2 uint8
|
||||||
|
|
||||||
|
Interfaces [16]uint8
|
||||||
|
InterfaceVer uint16
|
||||||
|
InterfaceVerMinor uint16
|
||||||
|
TransSyntax [16]uint8
|
||||||
|
TransSyntaxVer uint32
|
||||||
|
}
|
51
core/scan/service/matcher/wmi/wmi_test.go
Normal file
51
core/scan/service/matcher/wmi/wmi_test.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package wmi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/scan/matcher/scaninfo"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWMI(t *testing.T) {
|
||||||
|
|
||||||
|
lm := NewWMIMatcher()
|
||||||
|
|
||||||
|
port := types.NewPort("135", types.NewHost("192.168.1.1"), types.TYPE_TCP)
|
||||||
|
scanInfo := scaninfo.NewServiceScanInfo(port)
|
||||||
|
var ipport string
|
||||||
|
ipport = port.Host.Ip + ":" + string(port.Port)
|
||||||
|
|
||||||
|
fmt.Println(ipport)
|
||||||
|
client, _ := net.Dial("tcp", ipport)
|
||||||
|
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
fmt.Println(lm.PacketCount())
|
||||||
|
|
||||||
|
for ii := 0; ii < lm.PacketCount(); ii++ {
|
||||||
|
|
||||||
|
pack := lm.Packet(ii)
|
||||||
|
|
||||||
|
fmt.Println(pack)
|
||||||
|
|
||||||
|
client.Write(pack.Buffer)
|
||||||
|
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
|
||||||
|
read, _ := client.Read(bytes)
|
||||||
|
|
||||||
|
//fmt.Println(bytes)
|
||||||
|
|
||||||
|
b := lm.Match(ii, packet.NewPacket(bytes, read), scanInfo)
|
||||||
|
|
||||||
|
if b {
|
||||||
|
fmt.Println("Good")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(scanInfo)
|
||||||
|
}
|
83
core/scan/service/postpacket.go
Normal file
83
core/scan/service/postpacket.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func processPostPacket(mats []matcher.Matcher, info *types.ServiceScanInfo, m ConnFactory) bool {
|
||||||
|
|
||||||
|
var ser *types.DiscoveryService = nil
|
||||||
|
var curMatcher matcher.Matcher = nil
|
||||||
|
isFound := false
|
||||||
|
|
||||||
|
for i := 0; i < len(mats); i++ {
|
||||||
|
|
||||||
|
info.History = make([]*types.ServiceScanHistory, 0)
|
||||||
|
conn, err := m.createSocket(info.Port.Host.Ip_, info.Port.Port_)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(m.Type() + " process postpacket create socket error :" + info.Port.Host.Ip_ + " port: " + info.Port.Port_ + " error: " + err.Error())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
curMatcher = mats[i]
|
||||||
|
|
||||||
|
for indexI := 0; indexI < curMatcher.PacketCount(); indexI++ {
|
||||||
|
|
||||||
|
p := curMatcher.Packet(indexI)
|
||||||
|
l, err := conn.Write(p.Buffer)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if l != p.Len {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
AddServiceScanHistory(
|
||||||
|
&info.History,
|
||||||
|
types.NewServiceScanHistory(info.Port, curMatcher.ServiceName(), types.DIRECTION_SEND, p.Buffer))
|
||||||
|
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
l, err = conn.Read(buf)
|
||||||
|
|
||||||
|
AddServiceScanHistory(
|
||||||
|
&info.History,
|
||||||
|
types.NewServiceScanHistory(info.Port, curMatcher.ServiceName(), types.DIRECTION_RECV, p.Buffer))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if curMatcher.IsNoResponse(indexI) == true {
|
||||||
|
ser = types.NewService(m.Type(), curMatcher.ServiceName(), info.Port)
|
||||||
|
isFound = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if curMatcher.Match(indexI, packet.NewPacket(buf, l), info) == true {
|
||||||
|
if indexI == (curMatcher.PacketCount() - 1) {
|
||||||
|
ser = types.NewService(m.Type(), curMatcher.ServiceName(), info.Port)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
isFound = true
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
isFound = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if isFound == true {
|
||||||
|
conn.Close()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
AddService(ser, info)
|
||||||
|
if ser == nil {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
76
core/scan/service/prepacket.go
Normal file
76
core/scan/service/prepacket.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
func processPrePacket(conn net.Conn, prepacket *packet.Packet, mats []matcher.Matcher, info *types.ServiceScanInfo, m ConnFactory) bool {
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
isFound := false
|
||||||
|
var ser *types.DiscoveryService = nil
|
||||||
|
for i := 0; i < len(mats); i++ {
|
||||||
|
|
||||||
|
info.History = make([]*types.ServiceScanHistory, 0)
|
||||||
|
|
||||||
|
AddServiceScanHistory(
|
||||||
|
&info.History,
|
||||||
|
types.NewServiceScanHistory(info.Port, mats[i].ServiceName(), types.DIRECTION_RECV, prepacket.Buffer))
|
||||||
|
|
||||||
|
if mats[i].Match(0, prepacket, info) == true {
|
||||||
|
packetCount := mats[i].PacketCount()
|
||||||
|
if packetCount == 0 {
|
||||||
|
ser = types.NewService(m.Type(), mats[i].ServiceName(), info.Port)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
isFound = false
|
||||||
|
|
||||||
|
for j := 0; j < packetCount; j++ {
|
||||||
|
|
||||||
|
p := mats[i].Packet(j)
|
||||||
|
l, err := conn.Write(p.Buffer)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if l != p.Len {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
AddServiceScanHistory(
|
||||||
|
&info.History,
|
||||||
|
types.NewServiceScanHistory(info.Port, mats[i].ServiceName(), types.DIRECTION_SEND, p.Buffer))
|
||||||
|
|
||||||
|
buffer := make([]byte, 1024)
|
||||||
|
l, err = conn.Read(buffer)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
AddServiceScanHistory(
|
||||||
|
&info.History,
|
||||||
|
types.NewServiceScanHistory(info.Port, mats[i].ServiceName(), types.DIRECTION_RECV, buffer))
|
||||||
|
|
||||||
|
if mats[i].Match(j+1, packet.NewPacket(buffer, l), info) == true {
|
||||||
|
isFound = true
|
||||||
|
} else {
|
||||||
|
isFound = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isFound == true {
|
||||||
|
ser = types.NewService(m.Type(), mats[i].ServiceName(), info.Port)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AddService(ser, info)
|
||||||
|
if ser == nil {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
177
core/scan/service/service.go
Normal file
177
core/scan/service/service.go
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
//"git.loafle.net/overflow/central/client/events"
|
||||||
|
//"git.loafle.net/overflow/discovery/communicate"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher"
|
||||||
|
"git.loafle.net/overflow/discovery/core/scan/service/matcher/packet"
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Scan(dp *types.DiscoveryPort) {
|
||||||
|
ip := dp.Host.Ip_
|
||||||
|
port := dp.Port_
|
||||||
|
|
||||||
|
factories := []ConnFactory{
|
||||||
|
ConnFactoryNormal{t: types.TYPE_TCP},
|
||||||
|
ConnFactoryTLS{t: types.TYPE_TLS},
|
||||||
|
}
|
||||||
|
info := types.NewServiceScanInfo(dp)
|
||||||
|
|
||||||
|
for i := 0; i < len(factories); i++ {
|
||||||
|
m := factories[i]
|
||||||
|
|
||||||
|
isFound := false
|
||||||
|
conn, err := m.createSocket(ip, port)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("An error has occurred on " + m.Type() + " " + ip + ":" + port + " - " + err.Error())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
l, err := conn.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
l = 0
|
||||||
|
}
|
||||||
|
if l != 0 {
|
||||||
|
isFound = processPrePacket(conn, packet.NewPacket(buf, l), matcher.GetTcpMatchers(true), info, m)
|
||||||
|
} else {
|
||||||
|
conn.Close()
|
||||||
|
isFound = processPostPacket(matcher.GetTcpMatchers(false), info, m)
|
||||||
|
}
|
||||||
|
if isFound == true {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Check(dp *types.DiscoveryPort, services []*types.DiscoveryService) error {
|
||||||
|
|
||||||
|
if len(services) <= 0 {
|
||||||
|
return errors.New("No service has bound to this port.")
|
||||||
|
}
|
||||||
|
for _, service := range services {
|
||||||
|
|
||||||
|
m := matcher.GetMatcherByName(service.ServiceName)
|
||||||
|
if m == nil {
|
||||||
|
return errors.New("Not supported service : " + service.ServiceName)
|
||||||
|
}
|
||||||
|
|
||||||
|
addr := dp.Host.Ip_ + ":" + dp.Port_
|
||||||
|
return checkService(m, addr, dp.PortType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkService(m matcher.Matcher, addr, portType string) error {
|
||||||
|
conn, err := getConnection(portType, addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
for i := 0; i < m.PacketCount(); i++ {
|
||||||
|
pack := m.Packet(i)
|
||||||
|
conn.Write(pack.Buffer)
|
||||||
|
bytes := make([]byte, 1024)
|
||||||
|
n, _ := conn.Read(bytes)
|
||||||
|
|
||||||
|
p := packet.NewPacket(bytes, n)
|
||||||
|
|
||||||
|
if m.Match(i, p, nil) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New("Fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getConnection(portType, addr string) (net.Conn, error) {
|
||||||
|
var conn net.Conn
|
||||||
|
var err error
|
||||||
|
if portType == types.TYPE_TLS {
|
||||||
|
conn, err = tls.Dial(
|
||||||
|
"tcp",
|
||||||
|
addr,
|
||||||
|
&tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: addr,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
conn, err = net.Dial(strings.ToLower(portType), addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func MatchUDPPacket(zone *types.DiscoveryZone, ipString, portString string, udpLayer gopacket.Layer) {
|
||||||
|
|
||||||
|
host, _ := zone.GetHost(ipString)
|
||||||
|
port := types.NewPort(portString, host, types.TYPE_UDP)
|
||||||
|
|
||||||
|
mats := matcher.GetUdpMatchers()
|
||||||
|
info := types.NewServiceScanInfo(port)
|
||||||
|
|
||||||
|
for i := 0; i < len(mats); i++ {
|
||||||
|
matcher := mats[i]
|
||||||
|
p := packet.NewPacket(udpLayer.LayerPayload(), len(udpLayer.LayerPayload()))
|
||||||
|
|
||||||
|
if matcher.Match(0, p, info) {
|
||||||
|
key := portString + ":" + types.TYPE_UDP
|
||||||
|
host.SetPort(key, port)
|
||||||
|
|
||||||
|
ser := types.NewService(types.TYPE_UDP, matcher.ServiceName(), info.Port)
|
||||||
|
AddService(ser, info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddService(ds *types.DiscoveryService, info *types.ServiceScanInfo) {
|
||||||
|
port := info.Port
|
||||||
|
var serviceName string
|
||||||
|
if ds != nil {
|
||||||
|
port.Services = append(port.Services, ds)
|
||||||
|
port.SetHistory(info.History)
|
||||||
|
serviceName = ds.ServiceName
|
||||||
|
log.Debugf("%s, %s:%s, Service was found : %s ", ds.PortType, port.Host.Ip_, port.Port_, ds.ServiceName)
|
||||||
|
} else {
|
||||||
|
i, _ := strconv.Atoi(port.Port_)
|
||||||
|
p := uint16(i)
|
||||||
|
expectName := layers.TCPPortNames[layers.TCPPort(p)]
|
||||||
|
serviceName = "Unknown Service was found. (Perhaps : " + expectName + ")"
|
||||||
|
log.Debugf("%s:%s. %s", port.Host.Ip_, port.Port_, serviceName)
|
||||||
|
}
|
||||||
|
|
||||||
|
sendEvent(info, serviceName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddServiceScanHistory(histories *[]*types.ServiceScanHistory, h *types.ServiceScanHistory) {
|
||||||
|
*histories = append(*histories, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendEvent(info *types.ServiceScanInfo, serviceName string) {
|
||||||
|
|
||||||
|
//communicate.Send(
|
||||||
|
// events.NewEvent(
|
||||||
|
// events.CENTRAL_EVENT,
|
||||||
|
// events.NewServiceEndEvent(
|
||||||
|
// info.Port.Host.Zone.CidrInt64(),
|
||||||
|
// info.Port.Host.Ip,
|
||||||
|
// info.Port.Number,
|
||||||
|
// serviceName)))
|
||||||
|
}
|
129
core/scan/zone/traceroute/traceroute.go
Normal file
129
core/scan/zone/traceroute/traceroute.go
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
package traceroute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const PORT = 33434
|
||||||
|
const MAX_HOPS = 30
|
||||||
|
const TIMEOUT_MS = 500
|
||||||
|
const RETRIES = 3
|
||||||
|
const PACKET_SIZE = 52
|
||||||
|
|
||||||
|
type Hop struct {
|
||||||
|
Success bool
|
||||||
|
Address [4]byte
|
||||||
|
ElapsedTime time.Duration
|
||||||
|
TTL int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Traceroute(dest string, c chan<- Hop) error {
|
||||||
|
|
||||||
|
ttl := 1
|
||||||
|
retry := 0
|
||||||
|
tv := syscall.NsecToTimeval(1000 * 1000 * TIMEOUT_MS)
|
||||||
|
|
||||||
|
for {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
recvSock, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_ICMP)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
sendSock, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
syscall.SetsockoptInt(sendSock, 0x0, syscall.IP_TTL, ttl)
|
||||||
|
syscall.SetsockoptTimeval(recvSock, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
|
||||||
|
|
||||||
|
defer syscall.Close(recvSock)
|
||||||
|
defer syscall.Close(sendSock)
|
||||||
|
|
||||||
|
sockaddr, err := socketAddr()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
syscall.Bind(recvSock, &syscall.SockaddrInet4{Port: PORT, Addr: sockaddr})
|
||||||
|
|
||||||
|
destaddr, err := destAddr(dest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
syscall.Sendto(sendSock, []byte{0x0}, 0, &syscall.SockaddrInet4{Port: PORT, Addr: destaddr})
|
||||||
|
|
||||||
|
var p = make([]byte, PACKET_SIZE)
|
||||||
|
_, from, err := syscall.Recvfrom(recvSock, p, 0)
|
||||||
|
elapsed := time.Since(start)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
currAddr := from.(*syscall.SockaddrInet4).Addr
|
||||||
|
|
||||||
|
hop := Hop{Success: true, Address: currAddr, ElapsedTime: elapsed, TTL: ttl}
|
||||||
|
c <- hop
|
||||||
|
|
||||||
|
ttl += 1
|
||||||
|
retry = 0
|
||||||
|
|
||||||
|
if ttl > MAX_HOPS || currAddr == destaddr {
|
||||||
|
close(c)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
retry += 1
|
||||||
|
if retry > RETRIES {
|
||||||
|
hop := Hop{Success: false, TTL: ttl}
|
||||||
|
c <- hop
|
||||||
|
|
||||||
|
ttl += 1
|
||||||
|
retry = 0
|
||||||
|
}
|
||||||
|
if ttl > MAX_HOPS {
|
||||||
|
close(c)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func socketAddr() (addr [4]byte, err error) {
|
||||||
|
addrs, err := net.InterfaceAddrs()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, a := range addrs {
|
||||||
|
if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||||
|
if len(ipnet.IP.To4()) == net.IPv4len {
|
||||||
|
copy(addr[:], ipnet.IP.To4())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func destAddr(dest string) (destAddr [4]byte, err error) {
|
||||||
|
addrs, err := net.LookupHost(dest)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
addr := addrs[0]
|
||||||
|
|
||||||
|
ipAddr, err := net.ResolveIPAddr("ip", addr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
copy(destAddr[:], ipAddr.IP.To4())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddressToString(addr [4]byte) string {
|
||||||
|
return fmt.Sprintf("%v.%v.%v.%v", addr[0], addr[1], addr[2], addr[3])
|
||||||
|
}
|
28
core/scan/zone/traceroute/traceroute_test.go
Normal file
28
core/scan/zone/traceroute/traceroute_test.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package traceroute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTracerouteAsync(t *testing.T) {
|
||||||
|
|
||||||
|
c := make(chan Hop, 0)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
hop, ok := <-c
|
||||||
|
if !ok {
|
||||||
|
fmt.Println()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Logf("%d. %v - %v\n", hop.TTL, AddressToString(hop.Address), hop.ElapsedTime)
|
||||||
|
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err := Traceroute("216.58.197.228", c)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
151
core/scan/zone/zone.go
Normal file
151
core/scan/zone/zone.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package zone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cihub/seelog"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.loafle.net/overflow/discovery/discovery/types"
|
||||||
|
"git.loafle.net/overflow/discovery/util/converter"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var checkStr = []string{
|
||||||
|
"docker",
|
||||||
|
"lo",
|
||||||
|
"br-f23a505183ce",
|
||||||
|
}
|
||||||
|
|
||||||
|
type FoundZoneHandler func(z *types.DiscoveryZone)
|
||||||
|
|
||||||
|
func Scan(callback FoundZoneHandler) {
|
||||||
|
startZone(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScanAndCheck(zones *[]types.DiscoveryZone) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Check(zones *[]types.DiscoveryZone) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func startZone(callback FoundZoneHandler) {
|
||||||
|
//var zones []*types.DiscoveryZone
|
||||||
|
|
||||||
|
ifaces, _ := net.Interfaces()
|
||||||
|
|
||||||
|
for _, i := range ifaces {
|
||||||
|
|
||||||
|
if checkStrByInterfaces(i.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs, err := i.Addrs()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
seelog.Critical(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
|
||||||
|
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||||
|
if ipnet.IP.To4() != nil {
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
seelog.Critical(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cidrs := strings.Split(addr.String(), "/")
|
||||||
|
tempNet, err := strconv.Atoi(cidrs[1])
|
||||||
|
if err != nil {
|
||||||
|
seelog.Critical(err)
|
||||||
|
}
|
||||||
|
netMask := uint8(tempNet)
|
||||||
|
f, l := GetMinAndMaxIPRange(addr.String())
|
||||||
|
|
||||||
|
first := net.ParseIP(f)
|
||||||
|
last := net.ParseIP(l)
|
||||||
|
zone := &types.DiscoveryZone{
|
||||||
|
M: new(sync.RWMutex),
|
||||||
|
Netmask: netMask,
|
||||||
|
Hosts_: make(map[string]*types.DiscoveryHost, 255),
|
||||||
|
Ip: converter.IP4toInt(ipnet.IP),
|
||||||
|
FirstScanRange: converter.IP4toInt(first),
|
||||||
|
LastScanRange: converter.IP4toInt(last),
|
||||||
|
Mac: converter.MacToInt(i.HardwareAddr),
|
||||||
|
Iface: i.Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
if callback != nil {
|
||||||
|
callback(zone)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test
|
||||||
|
func NewZone() *types.DiscoveryZone {
|
||||||
|
|
||||||
|
var z = &types.DiscoveryZone{}
|
||||||
|
startZone(func(zone *types.DiscoveryZone) {
|
||||||
|
if zone != nil {
|
||||||
|
z = zone
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMinAndMaxIPRange(ip string) (min string, max string) {
|
||||||
|
_, ipnet, err := net.ParseCIDR(ip)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var ips []string
|
||||||
|
cc := strings.Split(ip, "/")
|
||||||
|
|
||||||
|
cip := net.ParseIP(cc[0])
|
||||||
|
for addr := cip.Mask(ipnet.Mask); ipnet.Contains(addr); inc(addr) {
|
||||||
|
ips = append(ips, addr.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ips) < 3 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
min = ips[1]
|
||||||
|
max = ips[len(ips)-2]
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkStrByInterfaces(inter string) bool {
|
||||||
|
|
||||||
|
for _, str := range checkStr {
|
||||||
|
index := strings.Index(inter, str)
|
||||||
|
if index >= 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func inc(ip net.IP) {
|
||||||
|
for j := len(ip) - 1; j >= 0; j-- {
|
||||||
|
ip[j]++
|
||||||
|
if ip[j] > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user