This commit is contained in:
crusader 2017-11-21 21:47:55 +09:00
parent 753fafced4
commit 3dd6cb79ca
102 changed files with 9778 additions and 1 deletions

View File

@ -17,12 +17,12 @@ func scanPortTCP(host *model.Host, dp *model.DiscoveryPort, resultChan chan inte
defer func() {
wg.Done()
}()
ps, err := pcap.RetainScanner(host.Zone)
if nil != err {
errChan <- fmt.Errorf("Discovery: Cannot retain pcap instance %v", err)
return
}
defer func() {
pcap.ReleaseScanner(host.Zone)
}()

View File

@ -1,9 +1,16 @@
package ipv4
import (
"fmt"
"net"
"sync"
"time"
"git.loafle.net/commons_go/logging"
"git.loafle.net/overflow/overflow_discovery/api/module/discovery/model"
"git.loafle.net/overflow/overflow_discovery/commons/pcap"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)
func scanPortUDP(host *model.Host, dp *model.DiscoveryPort, resultChan chan interface{}, errChan chan error, stopChan chan struct{}, wg *sync.WaitGroup) {
@ -11,4 +18,157 @@ func scanPortUDP(host *model.Host, dp *model.DiscoveryPort, resultChan chan inte
wg.Done()
}()
ps, err := pcap.RetainScanner(host.Zone)
if nil != err {
errChan <- fmt.Errorf("Discovery: Cannot retain pcap instance %v", err)
return
}
defer func() {
pcap.ReleaseScanner(host.Zone)
}()
udpChan := ps.OpenUDP(host.IP)
defer func() {
ps.CloseUDP(host.IP, udpChan)
}()
go func() {
for {
select {
case packet, ok := <-udpChan:
if !ok {
logging.Logger().Debug(fmt.Sprintf("Discovery: tcp channel is closed"))
return
}
if p := handlePacketUDP(host, packet); nil != p {
resultChan <- p
}
case <-stopChan:
return
}
}
}()
if err := sendUDP(host, dp, stopChan); nil != err {
errChan <- err
return
}
timer := time.NewTimer(3 * time.Second)
select {
case <-stopChan:
return
case <-timer.C:
return
}
}
func sendUDP(host *model.Host, dp *model.DiscoveryPort, stopChan chan struct{}) error {
tcpPacket, err := makePacketPortTCP(host)
if nil != err {
return err
}
defer func() {
tcpPacket.PacketConn.Close()
}()
buf := gopacket.NewSerializeBuffer()
Loop:
for portNumber := dp.FirstScanRange; portNumber < dp.LastScanRange; portNumber++ {
if nil != dp.ExcludePorts {
for _, exPortNumber := range dp.ExcludePorts {
if portNumber == exPortNumber {
continue Loop
}
}
}
tcpPacket.TCP.DstPort = layers.TCPPort(portNumber)
tcpPacket.TCP.SetNetworkLayerForChecksum(tcpPacket.IP)
if err := gopacket.SerializeLayers(buf, tcpPacket.Opts, tcpPacket.TCP); err != nil {
return err
}
if _, err := tcpPacket.PacketConn.WriteTo(buf.Bytes(), &net.IPAddr{IP: tcpPacket.IP.DstIP}); err != nil {
return err
}
select {
case <-stopChan:
return nil
default:
}
time.Sleep(time.Microsecond * 100)
}
return nil
}
func handlePacketUDP(host *model.Host, packet *layers.TCP) *model.Port {
if nil == packet || packet.DstPort != 60000 {
return nil
}
if packet.RST {
return nil
}
portNumber := int(packet.SrcPort)
p := &model.Port{
PortType: model.PortTypeTCP,
PortNumber: portNumber,
}
p.Host = host
return p
}
type PortPacketTCP struct {
IP *layers.IPv4
TCP *layers.TCP
Opts gopacket.SerializeOptions
PacketConn net.PacketConn
}
func makePacketPortTCP(host *model.Host) (*PortPacketTCP, error) {
packetTCP := &PortPacketTCP{}
srcIP := net.ParseIP(host.Zone.IP)
if nil == srcIP {
return nil, fmt.Errorf("Discovery: IP(%s) of zone is not valid", host.Zone.IP)
}
dstIP := net.ParseIP(host.IP)
if nil == dstIP {
return nil, fmt.Errorf("Discovery: IP(%s) of host is not valid", host.IP)
}
packetTCP.IP = &layers.IPv4{
SrcIP: srcIP.To4(),
DstIP: dstIP.To4(),
Version: 4,
TTL: 64,
Protocol: layers.IPProtocolTCP,
}
packetTCP.TCP = &layers.TCP{
SrcPort: 60000,
DstPort: 0, // will be incremented during the scan
SYN: true,
Seq: 0,
}
packetTCP.Opts = gopacket.SerializeOptions{
ComputeChecksums: true,
FixLengths: true,
}
conn, err := net.ListenPacket("ip4:tcp", "0.0.0.0")
if err != nil {
return nil, fmt.Errorf("Discovery: SYN create socket error %v", err)
}
packetTCP.PacketConn = conn
return packetTCP, nil
}

View File

@ -0,0 +1,79 @@
package activedirectory
import (
"crypto/tls"
"net"
"testing"
"fmt"
"git.loafle.net/overflow/overflow_discovery/match/packet"
)
func TestADNor(t *testing.T) {
client, err := net.Dial("tcp", "192.168.1.15: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), nil)
if b {
fmt.Println("Good")
}
}
}

View File

@ -0,0 +1,73 @@
package cassandra
import (
"crypto/tls"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
func TestCassandra(t *testing.T) {
m := NewCassandraMatcher()
conn, err := net.Dial("tcp", "192.168.1.16:19042")
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.16:19042",
&tls.Config{
InsecureSkipVerify: true,
ServerName: "192.168.1.16",
},
)
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")
}
}

190
matcher/dhcp/dhcp.go Normal file
View File

@ -0,0 +1,190 @@
package dhcp
import (
"bytes"
"encoding/binary"
"fmt"
log "github.com/cihub/seelog"
//"git.loafle.net/overflow/overflow_discovery/match"
"net"
"time"
"git.loafle.net/overflow/overflow_discovery/discovery/discovery/types"
)
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.Infof("DNS: %s", 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
}

33
matcher/dns/dns_test.go Normal file
View File

@ -0,0 +1,33 @@
package dns
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
func TestDns(t *testing.T) {
m := NewDnsMatcher()
conn, _ := net.Dial("udp", "168.126.63.1: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
matcher/ftp/ftp.go Normal file
View File

@ -0,0 +1,142 @@
package ftp
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
log "github.com/cihub/seelog"
)
// 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 scaninfo.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.GetIP(), info.GetPort())
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 scaninfo.ServiceScanInfo) bool {
return false
}
func (ftp *FTPMatcher) HasResponse(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
}

234
matcher/ftp/ftp_test.go Normal file
View File

@ -0,0 +1,234 @@
package ftp
import (
"fmt"
"testing"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"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.NewScanInfoImpl("192.168.1.15","21")
//
//var ipport string
//ipport = port.Host.Ip + ":" + string(port.Port)
//
//log.Debug(ipport)
client, _ := net.Dial("tcp", "192.168.1.15:21")
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())
}

49
matcher/http/http_test.go Normal file
View File

@ -0,0 +1,49 @@
package http
import (
"fmt"
"git.loafle.net/overflow/overflow_discovery/match/packet"
//"git.loafle.net/overflow/overflow_discovery/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", "192.168.1.15:38980")
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)
}

View File

@ -0,0 +1,55 @@
package http
import (
"crypto/tls"
"fmt"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"log"
"net"
"testing"
"time"
)
func TestHTTPSMatcher_Match(t *testing.T) {
netinfo := "192.168.1.10:10443"
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
matcher/imap/imap.go Normal file
View File

@ -0,0 +1,87 @@
package imap
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
)
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 scaninfo.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 scaninfo.ServiceScanInfo) bool {
return false
}
func (i *IMAPMatcher) HasResponse(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
}

153
matcher/imap/imap_test.go Normal file
View File

@ -0,0 +1,153 @@
package imap
import (
"crypto/tls"
"fmt"
//"git.loafle.net/overflow/overflow_discovery/collector/core/scan/port"
"git.loafle.net/overflow/overflow_discovery/match/packet"
//"git.loafle.net/overflow/overflow_discovery/collector/core/scan/service/matcher/scaninfo"
//"git.loafle.net/overflow/overflow_discovery/collector/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 := types.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), nil)
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), nil)
if b {
t.Log("send Good!")
}
}
}
func TestIMapTls(t *testing.T) {
conn, _ := tls.Dial(
"tcp",
"192.168.1.15:993",
&tls.Config{
InsecureSkipVerify: true,
ServerName: "192.168.1.15",
},
)
defer conn.Close()
ImapRun(conn, t)
}
func TestIMapNormal(t *testing.T) {
client, err := net.Dial("tcp", "192.168.1.15:143")
if err != nil {
t.Fatal(err)
}
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 + ":" + 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)
bb := lm.Match(0, packet.NewPacket(bytett, rr), nil)
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), nil)
if b {
t.Log("send Good!")
}
}
//t.Log(scanInfo)
}

198
matcher/ldap/ldap.go Normal file
View File

@ -0,0 +1,198 @@
package ldap
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
)
type LDAPMatcher struct {
sendPackets []*packet.Packet
}
func (l *LDAPMatcher) Match(index int, packet *packet.Packet, info scaninfo.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 scaninfo.ServiceScanInfo) bool {
return false
}
func (l *LDAPMatcher) HasResponse(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
)

115
matcher/ldap/ldap_test.go Normal file
View File

@ -0,0 +1,115 @@
package ldap
import (
"crypto/tls"
"fmt"
"git.loafle.net/overflow/overflow_discovery/match/packet"
//"git.loafle.net/overflow/overflow_discovery/collector/discovery/scan/matcher/scaninfo"
//"git.loafle.net/overflow/overflow_discovery/collector/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.HasResponse(ii)
if bb {
t.Log("HasResponse good")
break
}
}
fmt.Println(bytes)
b := lm.Match(ii, packet.NewPacket(bytes, read), nil)
if b {
t.Log("Good")
}
}
}
func TestLdapTls(t *testing.T) {
conn, err := tls.Dial(
"tcp",
"192.168.1.15:636",
&tls.Config{
InsecureSkipVerify: true,
ServerName: "192.168.1.15",
},
)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
ldapRun(conn, t)
}
func TestLdapNormal(t *testing.T) {
client, _ := net.Dial("tcp", "192.168.1.15:389")
defer client.Close()
ldapRun(client, t)
}

122
matcher/mongodb/mongodb.go Normal file
View File

@ -0,0 +1,122 @@
package mongodb
import (
"bytes"
"encoding/binary"
"math/rand"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
)
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 scaninfo.ServiceScanInfo) bool {
return false
}
func (t *MongoDBMatcher) HasResponse(index int) bool {
return false
}
func (t *MongoDBMatcher) IsPrePacket() bool {
return false
}
func (t *MongoDBMatcher) Match(index int, packet *packet.Packet, info scaninfo.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
}

View File

@ -0,0 +1,54 @@
package mongodb
import (
"crypto/tls"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
func TestMongoNor(t *testing.T) {
conn, _ := net.Dial("tcp", "192.168.1.16:37017")
defer conn.Close()
MongoRun(conn, t)
}
func TestMongoTLS(t *testing.T) {
conn, _ := tls.Dial(
"tcp",
"192.168.1.16:47017",
&tls.Config{
InsecureSkipVerify: true,
ServerName: "192.168.1.16",
},
)
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")
}
}

173
matcher/mssql/mssql.go Normal file
View File

@ -0,0 +1,173 @@
package mssql
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
)
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 scaninfo.ServiceScanInfo) bool {
return false
}
func (t *MSSqlMatcher) HasResponse(index int) bool {
return false
}
func (t *MSSqlMatcher) IsPrePacket() bool {
return false
}
func (t *MSSqlMatcher) Match(index int, packet *packet.Packet, info scaninfo.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
}

View File

@ -0,0 +1,63 @@
package mssql
import (
"git.loafle.net/overflow/overflow_discovery/match/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.16:11433")
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
matcher/mysql/mysql.go Normal file
View File

@ -0,0 +1,151 @@
package mysql
import (
"bytes"
"encoding/binary"
"fmt"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
"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 scaninfo.ServiceScanInfo) bool {
return false
}
func (t *MySqlMatcher) HasResponse(index int) bool {
return false
}
func (t *MySqlMatcher) IsPrePacket() bool {
return true
}
func (t *MySqlMatcher) Match(index int, packet *packet.Packet, info scaninfo.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
}
}
}
}

View File

@ -0,0 +1,71 @@
package mysql
import (
"crypto/tls"
"git.loafle.net/overflow/overflow_discovery/match/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.15:33068")
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
matcher/netbios/netbios.go Normal file
View File

@ -0,0 +1,109 @@
package netbios
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
)
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 scaninfo.ServiceScanInfo) bool {
return false
}
func (t *NetBiosMatcher) HasResponse(index int) bool {
return false
}
func (t *NetBiosMatcher) IsPrePacket() bool {
return false
}
func (t *NetBiosMatcher) Match(index int, packet *packet.Packet, info scaninfo.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
}

View File

@ -0,0 +1,34 @@
package netbios
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
func TestNBSS(t *testing.T) {
m := NewNetBiosMatcher()
conn, _ := net.Dial("tcp", "192.168.1.106:139")
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("NBSS found")
return
}
t.Error("NBSS not found")
}
}

191
matcher/oracle/oracle.go Normal file
View File

@ -0,0 +1,191 @@
package oracle
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
)
type OracleMatcher struct {
sendPackets []*packet.Packet
}
func (o *OracleMatcher) Match(index int, packet *packet.Packet, info scaninfo.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 { //
if dataLen != packet.Len-22 { // morformed packet error not user not service
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 "OracleMatcher"
}
func (o *OracleMatcher) IsError(index int, packet *packet.Packet, info scaninfo.ServiceScanInfo) bool {
return false
}
func (o *OracleMatcher) HasResponse(index int) bool {
return false
}
func (o *OracleMatcher) IsPrePacket() bool {
return false
}
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=loafle.match))(SERVICE_NAME=oracle.loafle.com1)))"
//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
}

View File

@ -0,0 +1,53 @@
package oracle
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"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)
client, _ := net.Dial("tcp", "192.168.1.15:1521")
defer client.Close()
t.Log(lm.PacketCount())
for ii := 0; ii < lm.PacketCount(); ii++ {
pack := lm.Packet(ii)
t.Log(pack)
client.Write(pack.Buffer)
bytes := make([]byte, 1024)
read, _ := client.Read(bytes)
t.Log(bytes)
b := lm.Match(ii, packet.NewPacket(bytes, read), nil)
if b {
t.Log("Good")
}
}
}

182
matcher/pgsql/pgsql.go Normal file
View File

@ -0,0 +1,182 @@
package pgsql
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
"strings"
)
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 pgsqlErrResponse2 struct {
ResponseType uint8
Len [4]byte
Data [128]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 scaninfo.ServiceScanInfo) bool {
return false
}
func (t *PostgreSQLMatcher) HasResponse(index int) bool {
return false
}
func (t *PostgreSQLMatcher) IsPrePacket() bool {
return false
}
func (t *PostgreSQLMatcher) Match(index int, packet *packet.Packet, info scaninfo.ServiceScanInfo) bool {
if packet == nil {
return false
}
reader := new(bytes.Buffer)
reader.Write(packet.Buffer)
pg := pgsqlErrResponse2{}
if err := binary.Read(reader, binary.BigEndian, &pg); err != nil {
return false
}
if pg.ResponseType != RESPONSE_TYPE_ERR {
return false
}
length := binary.BigEndian.Uint32(pg.Len[:])
if length+1 != uint32(packet.Len) {
return false
}
data := string(pg.Data[:])
splits := strings.Split(data, "\x00")
var findSeverity bool = false
var findErrorCode bool = false
for _, s := range splits {
if strings.Contains(s, "FATAL") {
findSeverity = true
}
if strings.Contains(s, "28000") {
findErrorCode = true
}
}
if !findSeverity || !findErrorCode {
return false
}
return true
}

View File

@ -0,0 +1,70 @@
package pgsql
import (
"crypto/tls"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
func TestPG(t *testing.T) {
m := NewPostgreSQLMatcher()
conn, err := net.Dial("tcp", "192.168.1.106:5432") //107
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")
}
}
func TestSqlTLS(t *testing.T) {
conn, err := tls.Dial(
"tcp",
"192.168.1.107:5432",
&tls.Config{
InsecureSkipVerify: true,
ServerName: "192.168.1.107",
},
)
if err != nil {
t.Error(err)
return
}
defer conn.Close()
m := NewPostgreSQLMatcher()
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")
}
}

73
matcher/pop/pop.go Normal file
View File

@ -0,0 +1,73 @@
package pop
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
)
const (
COMPARE_STR = "+OK"
)
type POPMatcher struct {
sendPackets []*packet.Packet
}
func (p *POPMatcher) Match(index int, packet *packet.Packet, info scaninfo.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 scaninfo.ServiceScanInfo) bool {
return false
}
func (p *POPMatcher) HasResponse(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
}

86
matcher/pop/pop_test.go Normal file
View File

@ -0,0 +1,86 @@
package pop
import (
"crypto/tls"
"fmt"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
func TestPopTLS(t *testing.T) {
conn, _ := tls.Dial(
"tcp",
"192.168.1.15:995",
&tls.Config{
InsecureSkipVerify: true,
ServerName: "192.168.1.15",
},
)
defer conn.Close()
pop3Run(conn, t)
}
func TestPopNor(t *testing.T) {
client, _ := net.Dial("tcp", "192.168.1.15: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), nil)
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), nil)
if b {
t.Log("send Good!")
}
}
}

76
matcher/redis/redis.go Normal file
View File

@ -0,0 +1,76 @@
package redis
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
"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 scaninfo.ServiceScanInfo) bool {
return false
}
func (t *RedisMatcher) HasResponse(index int) bool {
return false
}
func (t *RedisMatcher) IsPrePacket() bool {
return false
}
func (t *RedisMatcher) Match(index int, packet *packet.Packet, info scaninfo.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
}

View File

@ -0,0 +1,78 @@
package redis
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
)
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 scaninfo.ServiceScanInfo) bool {
return false
}
func (r *RedisProtectedMatcher) HasResponse(index int) bool {
return false
}
func (r *RedisProtectedMatcher) IsPrePacket() bool {
return true
}
func (r *RedisProtectedMatcher) Match(index int, packet *packet.Packet, info scaninfo.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
}

View File

@ -0,0 +1,37 @@
package redis
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
const (
ADDR string = "192.168.1.16:26379"
)
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
matcher/rmi/rmi.go Normal file
View File

@ -0,0 +1,111 @@
package rmi
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
)
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 scaninfo.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 scaninfo.ServiceScanInfo) bool {
return false
}
func (r *RMIMatcher) HasResponse(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
}

52
matcher/rmi/rmi_test.go Normal file
View File

@ -0,0 +1,52 @@
package rmi
import (
"fmt"
"git.loafle.net/overflow/overflow_discovery/match/packet"
//"git.loafle.net/overflow/overflow_discovery/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, err := net.Dial("tcp", "192.168.1.101:9840")
if err != nil {
t.Fatal(err)
}
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
matcher/smb/smb.go Normal file
View File

@ -0,0 +1,161 @@
package smb
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
"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 scaninfo.ServiceScanInfo) bool {
return false
}
func (t *SMBMatcher) HasResponse(index int) bool {
return false
}
func (t *SMBMatcher) IsPrePacket() bool {
return false
}
func (t *SMBMatcher) Match(index int, packet *packet.Packet, info scaninfo.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
}

42
matcher/smb/smb_test.go Normal file
View File

@ -0,0 +1,42 @@
package smb
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
const (
ADDR string = "192.168.1.106:445"
)
func TestSMBMatcher(t *testing.T) {
m := NewSMBMatcher()
conn, err := net.Dial("tcp", ADDR)
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("SMB found.")
return
}
t.Error("SMB not found")
}
}

71
matcher/smtp/smtp.go Normal file
View File

@ -0,0 +1,71 @@
package smtp
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
"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 scaninfo.ServiceScanInfo) bool {
return false
}
func (t *SmtpMatcher) HasResponse(index int) bool {
return false
}
func (t *SmtpMatcher) IsPrePacket() bool {
return true
}
func (t *SmtpMatcher) Match(index int, packet *packet.Packet, info scaninfo.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
}

View File

@ -0,0 +1,37 @@
package snmp
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
func TestSNMP2(t *testing.T) {
m := NewSNMPv2Matcher()
conn, err := net.Dial("udp", "192.168.1.15: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")
}
}

View File

@ -0,0 +1,37 @@
package snmp
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
func TestSNMP3(t *testing.T) {
m := NewSNMPv3Matcher()
conn, err := net.Dial("udp", "192.168.1.15: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
matcher/ssh/ssh.go Normal file
View File

@ -0,0 +1,66 @@
package ssh
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
"strings"
)
type SSHMatcher struct {
sendPackets []*packet.Packet
}
func (ssh *SSHMatcher) Match(index int, packet *packet.Packet, info scaninfo.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 scaninfo.ServiceScanInfo) bool {
return false
}
func (ssh *SSHMatcher) HasResponse(index int) bool {
return false
}
func (ssh *SSHMatcher) IsPrePacket() bool {
return true
}
func NewSSHMatcher() *SSHMatcher {
r := SSHMatcher{}
return &r
}

35
matcher/ssh/ssh_test.go Normal file
View File

@ -0,0 +1,35 @@
package ssh
import (
"fmt"
//"git.loafle.net/overflow/overflow_discovery/match/ssh"
"git.loafle.net/overflow/overflow_discovery/match/packet"
//"git.loafle.net/overflow/overflow_discovery/collector/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", "192.168.1.10:22")
defer client.Close()
bytes := make([]byte, 512)
l, _ := client.Read(bytes)
fmt.Println(bytes)
b := NewSSHMatcher().Match(0, packet.NewPacket(bytes, l), nil)
fmt.Println(b)
}

79
matcher/telnet/telnet.go Normal file
View File

@ -0,0 +1,79 @@
package telnet
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
)
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 scaninfo.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 scaninfo.ServiceScanInfo) bool {
return false
}
func (tel *TelnetMatcher) HasResponse(index int) bool {
return false
}
func (tel *TelnetMatcher) IsPrePacket() bool {
return true
}
func NewTelnetMatcher() *TelnetMatcher {
r := TelnetMatcher{}
return &r
}

View File

@ -0,0 +1,33 @@
package telnet
import (
"fmt"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"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", "192.168.1.105:23")
defer client.Close()
bytes := make([]byte, 512)
l, _ := client.Read(bytes)
fmt.Println("length :", l)
fmt.Println(bytes)
b := NewTelnetMatcher().Match(0, packet.NewPacket(bytes, l), nil)
fmt.Println(b)
}

250
matcher/wmi/wmi.go Normal file
View File

@ -0,0 +1,250 @@
package wmi
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"git.loafle.net/overflow/overflow_discovery/model/scaninfo"
)
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 scaninfo.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 scaninfo.ServiceScanInfo) bool {
return false
}
func (w *WMIMatcher) HasResponse(index int) bool {
return false
}
func (w *WMIMatcher) IsPrePacket() bool {
return false
}
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
matcher/wmi/wmi_test.go Normal file
View File

@ -0,0 +1,51 @@
package wmi
import (
"fmt"
"git.loafle.net/overflow/overflow_discovery/match/packet"
//"git.loafle.net/overflow/overflow_discovery/collector/discovery/scan/matcher/scaninfo"
//"git.loafle.net/overflow/overflow_discovery/collector/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", "192.168.1.106:135")
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), nil)
if b {
fmt.Println("Good")
}
}
}

View File

@ -0,0 +1,327 @@
package activedirectory
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
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 {
matcher.Matchers
}
func (m *ActiveDirectoryMatcher) ServiceName() string {
return "ActiveDirectory"
}
func (m *ActiveDirectoryMatcher) IsPrePacket() bool {
return false
}
func (m *ActiveDirectoryMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (m *ActiveDirectoryMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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 NewMatcher() matcher.Matcher {
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()
m := &ActiveDirectoryMatcher{
//sendPackets: make([][]byte, 2),
}
pp := matcher.NewPacket(sendByte1, len(sendByte1))
m.AddPacket(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 := matcher.NewPacket(quBytes, len(quBytes))
m.AddPacket(pp2)
return m
}

View File

@ -0,0 +1,79 @@
package activedirectory
import (
"crypto/tls"
"fmt"
"net"
"testing"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
func TestADNor(t *testing.T) {
client, err := net.Dial("tcp", "192.168.1.15: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 := NewMatcher()
//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(nil, ii, matcher.NewPacket(bytes, read))
if b {
fmt.Println("Good")
}
}
}

View File

@ -0,0 +1,94 @@
package cassandra
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
type cassandra struct {
Version uint8
Flags uint8
Stream uint16
Opcode uint8
Length uint32
}
type CassandraMatcher struct {
matcher.Matchers
}
func (m *CassandraMatcher) ServiceName() string {
return "Cassandra"
}
func (m *CassandraMatcher) IsPrePacket() bool {
return false
}
func (m *CassandraMatcher) HasResponse(index int) bool {
return true
}
func (m *CassandraMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (m *CassandraMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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
}
func NewMatcher() matcher.Matcher {
m := &CassandraMatcher{}
c := cassandra{
Version: 4,
Flags: 0,
Stream: 0,
Opcode: 5,
Length: 0,
}
writer := new(bytes.Buffer)
binary.Write(writer, binary.LittleEndian, c)
m.AddPacket(matcher.NewPacket(writer.Bytes(), writer.Len()))
return m
}

View File

@ -0,0 +1,74 @@
package cassandra
import (
"crypto/tls"
"net"
"testing"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
func TestCassandra(t *testing.T) {
m := NewMatcher()
conn, err := net.Dial("tcp", "192.168.1.16:19042")
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 := matcher.NewPacket(bytes, n)
if m.Match(nil, i, p) {
t.Log("Cassandra found")
return
}
t.Error("Cassandra not found")
}
}
func TestCassandraTLS(t *testing.T) {
m := NewMatcher()
conn, err := tls.Dial(
"tcp",
"192.168.1.16:19042",
&tls.Config{
InsecureSkipVerify: true,
ServerName: "192.168.1.16",
},
)
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 := matcher.NewPacket(bytes, n)
if m.Match(nil, i, p) {
t.Log("Cassandra found")
return
}
t.Error("Cassandra not found")
}
}

View File

@ -0,0 +1,189 @@
package dhcp
import (
"bytes"
"encoding/binary"
"fmt"
"net"
"time"
"git.loafle.net/commons_go/logging"
"git.loafle.net/overflow/overflow_discovery/api/module/discovery/model"
)
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 *model.DiscoveryZone) {
err := sendDHCPDiscovery()
if err != nil {
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher %v", 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 *model.DiscoveryZone) {
socket, err := net.ListenUDP("udp4", &net.UDPAddr{
IP: net.IPv4(255, 255, 255, 255),
Port: 68,
})
if err != nil {
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher %v", err))
return
}
err = socket.SetDeadline(time.Now().Add(3 * time.Second))
if err != nil {
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher %v", err))
return
}
buf := make([]byte, 4096)
n, _, err := socket.ReadFromUDP(buf)
if err != nil {
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher %v", err))
return
}
if n <= 0 {
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher has no DHCP offer."))
return
}
offer := dhcpDiscover{}
reader := new(bytes.Buffer)
reader.Write(buf)
if err := binary.Read(reader, binary.BigEndian, &offer); err != nil {
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher %v", err))
return
}
if offer.MagicCookie != MAGIC_COOKIE {
logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher is 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))
logging.Logger().Info(fmt.Sprintf("Discovery: DHCP Matcher SUBNET MASK: %s", ipStr))
}
if v == OPT_CODE_ROUTER && r.Next(1)[0] == 4 {
ipStr := byteToIpString(r.Next(4))
logging.Logger().Info(fmt.Sprintf("Discovery: DHCP Matcher 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)
}
logging.Logger().Info(fmt.Sprintf("Discovery: DHCP Matcher DNS: %s", dns))
}
if v == OPT_CODE_SERVER_IDENTIFIER && r.Next(1)[0] == 4 {
ipStr := byteToIpString(r.Next(4))
logging.Logger().Info(fmt.Sprintf("Discovery: DHCP Matcher DHCP SERVER: %s", ipStr))
}
}
logging.Logger().Sync()
}
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
}

View File

@ -0,0 +1,9 @@
package dhcp
import (
"testing"
)
func TestDHCP(t *testing.T) {
}

145
service/matcher/dns/dns.go Normal file
View File

@ -0,0 +1,145 @@
package dns
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
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 {
matcher.Matchers
}
func (t *DNSMatcher) ServiceName() string {
return "DNS"
}
func (t *DNSMatcher) IsPrePacket() bool {
return false
}
func (t *DNSMatcher) HasResponse(index int) bool {
return true
}
func (t *DNSMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (t *DNSMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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(info matcher.MatchInfo) bool {
if 53 == info.Port() {
return true
}
return false
}
func NewMatcher() matcher.UDPMatcher {
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.AddPacket(matcher.NewPacket(buf.Bytes(), buf.Len()))
return m
}

View File

@ -0,0 +1,35 @@
package dns
import (
"net"
"testing"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
func TestDns(t *testing.T) {
m := NewMatcher()
info := matcher.NewMatchInfo("168.126.63.1", 53)
conn, _ := net.Dial("udp", "168.126.63.1:53")
defer conn.Close()
for i := 0; i < m.PacketCount(); i++ {
if m.IsSend(info) != true {
t.Error("not port")
}
pack := m.Packet(i)
conn.Write(pack.Buffer)
bytes := make([]byte, 1024)
n, _ := conn.Read(bytes)
p := matcher.NewPacket(bytes, n)
if m.Match(info, i, p) {
t.Log("dns found")
return
}
t.Error("dns not found")
}
}

135
service/matcher/ftp/ftp.go Normal file
View File

@ -0,0 +1,135 @@
package ftp
import (
"fmt"
"git.loafle.net/commons_go/logging"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
// 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 {
matcher.Matchers
isFtps bool
}
func (ftp *FTPMatcher) ServiceName() string {
re := ""
if ftp.isFtps {
re = "FTPS"
} else {
re = "FTP"
}
return re
}
func (ftp *FTPMatcher) IsPrePacket() bool {
return true
}
func (ftp *FTPMatcher) HasResponse(index int) bool {
return true
}
func (ftp *FTPMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (ftp *FTPMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
result := false
if packet == nil || packet.Buffer == nil || packet.Len == 0 {
logging.Logger().Error(fmt.Sprintf("Discovery: FTP Matcher 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)
if isfs && err == nil {
ftp.isFtps = isfs
} else if err != nil {
logging.Logger().Warn(fmt.Sprintf("Discovery: FTP Matcher Check Error %v", err))
}
}
return result
}
func NewMatcher() matcher.Matcher {
m := &FTPMatcher{}
sysStr := "SYST\r\n"
systByte := make([]byte, len(sysStr))
copy(systByte[:], sysStr)
m.AddPacket(matcher.NewPacket(systByte, len(sysStr)))
passStr := "PASS \r\n"
passByte := make([]byte, len(passStr))
copy(passByte[:], passStr)
m.AddPacket(matcher.NewPacket(passByte, len(passStr)))
quitStr := "QUIT\r\n"
quitByte := make([]byte, len(quitStr))
copy(quitByte[:], quitStr)
m.AddPacket(matcher.NewPacket(quitByte, len(quitStr)))
return m
}

View File

@ -0,0 +1,234 @@
package ftp
import (
"fmt"
"testing"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
"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 := NewMatcher()
//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 := matcher.NewMatchInfo("192.168.1.15", 21)
//
//var ipport string
//ipport = port.Host.Ip + ":" + string(port.Port)
//
//log.Debug(ipport)
client, _ := net.Dial("tcp", "192.168.1.15:21")
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(info, 0, matcher.NewPacket(bytes, le))
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(info, ii+1, matcher.NewPacket(bytes, l))
fmt.Println(b)
}
fmt.Println("Service Name : ", ftm.ServiceName())
}

193
service/matcher/ftp/ftps.go Normal file
View File

@ -0,0 +1,193 @@
package ftp
import (
"bufio"
"crypto/tls"
"errors"
"fmt"
"net"
"strings"
"time"
"git.loafle.net/commons_go/logging"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
// 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 {
logging.Logger().Error(fmt.Sprintf("Discovery: FTPS Matcher cmd send error %v", err))
return "", err
}
if line, err = fs.receive(); err != nil {
logging.Logger().Error(fmt.Sprintf("Discovery: FTPS Matcher cmd receive error %v", 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 {
logging.Logger().Error(fmt.Sprintf("Discovery: FTPS Matcher Socket Fail %v", err))
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(info matcher.MatchInfo) (bool, error) {
var err error
var fs *FTPS
addr := fmt.Sprintf("%s:%d", info.IP(), info.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
}

View File

@ -0,0 +1,16 @@
package ftp
import (
"fmt"
"testing"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
func TestStartCheckFTPS(t *testing.T) {
info := matcher.NewMatchInfo("192.168.1.202", 80)
isFtps, err := StartCheckFTPS(info)
fmt.Println("Result : ", isFtps)
fmt.Println("Error : ", err)
}

View File

@ -0,0 +1,81 @@
package http
import (
"strings"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
type HTTPMatcher struct {
matcher.Matchers
}
func (h *HTTPMatcher) ServiceName() string {
return "HTTP"
}
func (h *HTTPMatcher) IsPrePacket() bool {
return false
}
func (h *HTTPMatcher) HasResponse(index int) bool {
return true
}
func (h *HTTPMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (h *HTTPMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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 NewMatcher() matcher.Matcher {
m := &HTTPMatcher{}
reqStr := "GET / HTTP/1.1\r\n\r\n"
byte := make([]byte, len(reqStr))
copy(byte[:], reqStr)
m.AddPacket(matcher.NewPacket(byte, len(reqStr)))
return m
}

View File

@ -0,0 +1,51 @@
package http
import (
"fmt"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
//"git.loafle.net/overflow/overflow_discovery/discovery/discovery/types"
"net"
"testing"
)
func TestHTTPMatcher_Packet(t *testing.T) {
hm := NewMatcher().(*HTTPMatcher)
fmt.Println(hm)
fmt.Println(hm.sendPackets[0])
}
func TestHTTPMatcher_Match(t *testing.T) {
fmt.Println("Match")
info := matcher.NewMatchInfo("192.168.1.15", 38980)
hm := NewMatcher()
//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", "192.168.1.15:38980")
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(info, 0, matcher.NewPacket(bytes, l))
}

View File

@ -0,0 +1,58 @@
package http
import (
"crypto/tls"
"fmt"
"log"
"net"
"testing"
"time"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
func TestHTTPSMatcher_Match(t *testing.T) {
info := matcher.NewMatchInfo("192.168.1.10", 10443)
netinfo := "192.168.1.10:10443"
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 := NewMatcher()
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(info, 0, matcher.NewPacket(buf, l))
fmt.Println(is)
}

View File

@ -0,0 +1,80 @@
package imap
import (
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
const (
PRE_COMPARE_STR = "* OK"
SEND_COMPARE_STR = "* BYE"
)
type IMAPMatcher struct {
matcher.Matchers
}
func (i *IMAPMatcher) ServiceName() string {
return "IMAP"
}
func (i *IMAPMatcher) IsPrePacket() bool {
return true
}
func (i *IMAPMatcher) HasResponse(index int) bool {
return true
}
func (i *IMAPMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (i *IMAPMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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 NewMatcher() matcher.Matcher {
m := &IMAPMatcher{}
reqStr := "A0001 LOGOUT\r\n"
byte := make([]byte, len(reqStr))
copy(byte[:], reqStr)
m.AddPacket(matcher.NewPacket(byte, len(reqStr)))
return m
}

View File

@ -0,0 +1,151 @@
package imap
import (
"crypto/tls"
"fmt"
//"git.loafle.net/overflow/overflow_discovery/collector/core/scan/port"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
//"git.loafle.net/overflow/overflow_discovery/collector/core/scan/service/matcher/scaninfo"
//"git.loafle.net/overflow/overflow_discovery/collector/discovery/types"
"net"
"testing"
)
func ImapRun(client net.Conn, t *testing.T) {
lm := NewMatcher()
//port := types.NewPort("143", types.NewHost("192.168.1.215"), types.TYPE_TCP)
//
//scanInfo := types.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(nil, 0, matcher.NewPacket(bytett, rr))
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(nil, ii+1, matcher.NewPacket(bytes, read))
if b {
t.Log("send Good!")
}
}
}
func TestIMapTls(t *testing.T) {
conn, _ := tls.Dial(
"tcp",
"192.168.1.15:993",
&tls.Config{
InsecureSkipVerify: true,
ServerName: "192.168.1.15",
},
)
defer conn.Close()
ImapRun(conn, t)
}
func TestIMapNormal(t *testing.T) {
client, err := net.Dial("tcp", "192.168.1.15:143")
if err != nil {
t.Fatal(err)
}
defer client.Close()
ImapRun(client, t)
}
func TestImap(t *testing.T) {
lm := NewMatcher()
//port := types.NewPort("143", types.NewHost("192.168.1.215"), types.TYPE_TCP)
//scanInfo := scaninfo.NewServiceScanInfo(port)
var ipport string
//ipport = port.Host.Ip + ":" + 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, matcher.NewPacket(bytett, rr), scanInfo)
bb := lm.Match(nil, 0, matcher.NewPacket(bytett, rr))
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(nil, ii+1, matcher.NewPacket(bytes, read))
if b {
t.Log("send Good!")
}
}
//t.Log(scanInfo)
}

View File

@ -0,0 +1,180 @@
package ldap
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
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
)
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
}
type LDAPMatcher struct {
matcher.Matchers
}
func (l *LDAPMatcher) ServiceName() string {
return "LDAP"
}
func (l *LDAPMatcher) IsPrePacket() bool {
return false
}
func (l *LDAPMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (l *LDAPMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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 NewMatcher() matcher.Matcher {
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()
m := &LDAPMatcher{
//sendPackets: make([][]byte, 2),
}
m.AddPacket(matcher.NewPacket(sendByte1, len(sendByte1)))
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()
m.AddPacket(matcher.NewPacket(sendByte2, len(sendByte2)))
return m
}

View File

@ -0,0 +1,113 @@
package ldap
import (
"crypto/tls"
"fmt"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
//"git.loafle.net/overflow/overflow_discovery/collector/discovery/scan/matcher/scaninfo"
//"git.loafle.net/overflow/overflow_discovery/collector/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 := NewMatcher()
//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.HasResponse(ii)
if !bb {
t.Log("HasResponse good")
break
}
}
fmt.Println(bytes)
b := lm.Match(nil, ii, matcher.NewPacket(bytes, read))
if b {
t.Log("Good")
}
}
}
func TestLdapTls(t *testing.T) {
conn, err := tls.Dial(
"tcp",
"192.168.1.15:636",
&tls.Config{
InsecureSkipVerify: true,
ServerName: "192.168.1.15",
},
)
if err != nil {
t.Fatal(err)
}
defer conn.Close()
ldapRun(conn, t)
}
func TestLdapNormal(t *testing.T) {
client, _ := net.Dial("tcp", "192.168.1.15:389")
defer client.Close()
ldapRun(client, t)
}

View File

@ -0,0 +1,63 @@
package matcher
type Matcher interface {
ServiceName() string
IsPrePacket() bool
PacketCount() int
Packet(index int) *Packet
HasResponse(index int) bool
IsError(info MatchInfo, index int, packet *Packet) bool
Match(info MatchInfo, index int, packet *Packet) bool
}
type UDPMatcher interface {
Matcher
IsSend(info MatchInfo) bool
}
type Matchers struct {
packets []*Packet
}
func (m *Matchers) PacketCount() int {
return len(m.packets)
}
func (m *Matchers) Packet(index int) *Packet {
return m.packets[index]
}
func (m *Matchers) HasResponse(index int) bool {
return len(m.packets)-1 > index
}
func (m *Matchers) AddPacket(packet *Packet) {
m.packets = append(m.packets, packet)
}
type MatchInfo interface {
IP() string
Port() int
}
type simpleMatchInfo struct {
ip string
port int
}
func (mi *simpleMatchInfo) IP() string {
return mi.ip
}
func (mi *simpleMatchInfo) Port() int {
return mi.port
}
func NewMatchInfo(ip string, port int) MatchInfo {
return &simpleMatchInfo{
ip: ip,
port: port,
}
}

View File

@ -0,0 +1,87 @@
package matcher
import (
"fmt"
"testing"
)
type TestMatcher struct {
}
func (t *TestMatcher) ServiceName() string {
return "TestMatcher"
}
func (t *TestMatcher) Match(info MatchInfo, index int, packet []byte) bool {
return true
}
func (t *TestMatcher) PacketCount() int {
return 1
}
func (t *TestMatcher) Packet(index int) []byte {
return nil
}
func (t *TestMatcher) IsError(info MatchInfo, index int, packet []byte) bool {
return true
}
func (t *TestMatcher) HasResponse(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) {
}

View File

@ -0,0 +1,114 @@
package mongodb
import (
"bytes"
"encoding/binary"
"math/rand"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
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 {
matcher.Matchers
}
func (t *MongoDBMatcher) ServiceName() string {
return "MongoDB"
}
func (t *MongoDBMatcher) IsPrePacket() bool {
return false
}
func (t *MongoDBMatcher) HasResponse(index int) bool {
return true
}
func (t *MongoDBMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (t *MongoDBMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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
}
func NewMatcher() matcher.Matcher {
mm := &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)
mm.AddPacket(matcher.NewPacket(writer.Bytes(), writer.Len()))
return mm
}

View File

@ -0,0 +1,56 @@
package mongodb
import (
"crypto/tls"
"net"
"testing"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
func TestMongoNor(t *testing.T) {
conn, _ := net.Dial("tcp", "192.168.1.16:37017")
defer conn.Close()
MongoRun(conn, t)
}
func TestMongoTLS(t *testing.T) {
conn, _ := tls.Dial(
"tcp",
"192.168.1.16:47017",
&tls.Config{
InsecureSkipVerify: true,
ServerName: "192.168.1.16",
},
)
defer conn.Close()
MongoRun(conn, t)
}
func MongoRun(conn net.Conn, t *testing.T) {
m := NewMatcher()
for i := 0; i < m.PacketCount(); i++ {
pack := m.Packet(i)
conn.Write(pack.Buffer)
bytes := make([]byte, 1024)
n, _ := conn.Read(bytes)
p := matcher.NewPacket(bytes, n)
if m.Match(nil, i, p) {
t.Log("MongoDB found")
return
}
t.Error("MongoDB not found")
}
}

View File

@ -0,0 +1,166 @@
package mssql
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
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 {
matcher.Matchers
isSSL bool
}
func (t *MSSqlMatcher) ServiceName() string {
if t.isSSL {
return "SQL Server (SSL)"
}
return "SQL Server"
}
func (t *MSSqlMatcher) IsPrePacket() bool {
return false
}
func (t *MSSqlMatcher) HasResponse(index int) bool {
return true
}
func (t *MSSqlMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (t *MSSqlMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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
}
func NewMatcher() matcher.Matcher {
mm := &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)
mm.AddPacket(matcher.NewPacket(writer.Bytes(), writer.Len()))
return mm
}

View File

@ -0,0 +1,64 @@
package mssql
import (
"net"
"testing"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
/*
192.168.1.106:1433 - normal
192.168.1.103:1433 - ssl
*/
func TestSqlNor(t *testing.T) {
conn, _ := net.Dial("tcp", "192.168.1.16:11433")
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 := NewMatcher()
for i := 0; i < m.PacketCount(); i++ {
pack := m.Packet(i)
conn.Write(pack.Buffer)
bytes := make([]byte, 1024)
n, _ := conn.Read(bytes)
p := matcher.NewPacket(bytes, n)
if m.Match(nil, i, p) {
t.Log(m.ServiceName())
return
}
t.Error("MSSQL not found")
}
}

View File

@ -0,0 +1,143 @@
package mysql
import (
"bytes"
"encoding/binary"
"fmt"
"strconv"
"strings"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
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 {
matcher.Matchers
version string
isErrResp bool
errCode int
errMsg string
isSSL bool
}
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) IsPrePacket() bool {
return true
}
func (t *MySqlMatcher) HasResponse(index int) bool {
return true
}
func (t *MySqlMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (t *MySqlMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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 *matcher.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
}
}
}
}
func NewMatcher() matcher.Matcher {
return &MySqlMatcher{}
}

View File

@ -0,0 +1,71 @@
package mysql
import (
"crypto/tls"
"net"
"testing"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
func TestMySql(t *testing.T) {
m := NewMatcher()
/*
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.15:33068")
defer conn.Close()
bytes := make([]byte, 1024)
n, _ := conn.Read(bytes)
p := matcher.NewPacket(bytes, n)
if m.Match(nil, 0, p) {
t.Log(m.ServiceName())
return
}
t.Error("MySQL not found")
}
func TestCassandraTLS(t *testing.T) {
m := NewMatcher()
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 := matcher.NewPacket(bytes, n)
if m.Match(nil, i, p) {
t.Log(m.ServiceName())
return
}
t.Error("MySQL not found")
}
}

View File

@ -0,0 +1,102 @@
package netbios
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
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 {
matcher.Matchers
}
func (t *NetBiosMatcher) ServiceName() string {
return "NBSS"
}
func (t *NetBiosMatcher) IsPrePacket() bool {
return false
}
func (t *NetBiosMatcher) HasResponse(index int) bool {
return true
}
func (t *NetBiosMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (t *NetBiosMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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
}
func NewMatcher() matcher.Matcher {
m := &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)
m.AddPacket(matcher.NewPacket(writer.Bytes(), writer.Len()))
return m
}

View File

@ -0,0 +1,33 @@
package netbios
import (
"net"
"testing"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
func TestNBSS(t *testing.T) {
m := NewMatcher()
conn, _ := net.Dial("tcp", "192.168.1.106:139")
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 := matcher.NewPacket(bytes, n)
if m.Match(nil, i, p) {
t.Log("NBSS found")
return
}
t.Error("NBSS not found")
}
}

View File

@ -0,0 +1,185 @@
package oracle
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
type OracleMatcher struct {
matcher.Matchers
}
func (o *OracleMatcher) ServiceName() string {
return "OracleMatcher"
}
func (o *OracleMatcher) IsPrePacket() bool {
return false
}
func (o *OracleMatcher) HasResponse(index int) bool {
return true
}
func (o *OracleMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (o *OracleMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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 { //
if dataLen != packet.Len-22 { // morformed packet error not user not service
return false
}
}
return true
}
func NewMatcher() matcher.Matcher {
m := &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=loafle.match))(SERVICE_NAME=oracle.loafle.com1)))"
//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)
m.AddPacket(matcher.NewPacket(sendByte, byteSize))
return m
}
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
}

View File

@ -0,0 +1,53 @@
package oracle
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"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)
client, _ := net.Dial("tcp", "192.168.1.15:1521")
defer client.Close()
t.Log(lm.PacketCount())
for ii := 0; ii < lm.PacketCount(); ii++ {
pack := lm.Packet(ii)
t.Log(pack)
client.Write(pack.Buffer)
bytes := make([]byte, 1024)
read, _ := client.Read(bytes)
t.Log(bytes)
b := lm.Match(ii, packet.NewPacket(bytes, read), nil)
if b {
t.Log("Good")
}
}
}

13
service/matcher/packet.go Normal file
View File

@ -0,0 +1,13 @@
package matcher
type Packet struct {
Buffer []byte
Len int
}
func NewPacket(buf []byte, len int) *Packet {
return &Packet{
Buffer: buf,
Len: len,
}
}

View File

@ -0,0 +1,175 @@
package pgsql
import (
"bytes"
"encoding/binary"
"strings"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
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 pgsqlErrResponse2 struct {
ResponseType uint8
Len [4]byte
Data [128]byte
//Severity [6]byte
//_ byte
//Code [6]byte
//_ byte
//Message [53]byte
}
type PostgreSQLMatcher struct {
matcher.Matchers
}
func (t *PostgreSQLMatcher) ServiceName() string {
return "PostgreSQL"
}
func (t *PostgreSQLMatcher) IsPrePacket() bool {
return false
}
func (t *PostgreSQLMatcher) HasResponse(index int) bool {
return true
}
func (t *PostgreSQLMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (t *PostgreSQLMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
if packet == nil {
return false
}
reader := new(bytes.Buffer)
reader.Write(packet.Buffer)
pg := pgsqlErrResponse2{}
if err := binary.Read(reader, binary.BigEndian, &pg); err != nil {
return false
}
if pg.ResponseType != RESPONSE_TYPE_ERR {
return false
}
length := binary.BigEndian.Uint32(pg.Len[:])
if length+1 != uint32(packet.Len) {
return false
}
data := string(pg.Data[:])
splits := strings.Split(data, "\x00")
var findSeverity bool = false
var findErrorCode bool = false
for _, s := range splits {
if strings.Contains(s, "FATAL") {
findSeverity = true
}
if strings.Contains(s, "28000") {
findErrorCode = true
}
}
if !findSeverity || !findErrorCode {
return false
}
return true
}
func NewMatcher() matcher.Matcher {
m := &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)
m.AddPacket(matcher.NewPacket(writer.Bytes(), writer.Len()))
return m
}

View File

@ -0,0 +1,70 @@
package pgsql
import (
"crypto/tls"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
func TestPG(t *testing.T) {
m := NewPostgreSQLMatcher()
conn, err := net.Dial("tcp", "192.168.1.106:5432") //107
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")
}
}
func TestSqlTLS(t *testing.T) {
conn, err := tls.Dial(
"tcp",
"192.168.1.107:5432",
&tls.Config{
InsecureSkipVerify: true,
ServerName: "192.168.1.107",
},
)
if err != nil {
t.Error(err)
return
}
defer conn.Close()
m := NewPostgreSQLMatcher()
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")
}
}

View File

@ -0,0 +1,65 @@
package pop
import (
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
const (
COMPARE_STR = "+OK"
)
type POPMatcher struct {
matcher.Matchers
}
func (p *POPMatcher) ServiceName() string {
return "POPMatcher"
}
func (p *POPMatcher) IsPrePacket() bool {
return true
}
func (p *POPMatcher) HasResponse(index int) bool {
return true
}
func (p *POPMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (p *POPMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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 NewMatcher() matcher.Matcher {
m := &POPMatcher{}
reqStr := "QUIT\r\n"
byte := make([]byte, len(reqStr))
copy(byte[:], reqStr)
m.AddPacket(matcher.NewPacket(byte, len(reqStr)))
return m
}

View File

@ -0,0 +1,86 @@
package pop
import (
"crypto/tls"
"fmt"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
func TestPopTLS(t *testing.T) {
conn, _ := tls.Dial(
"tcp",
"192.168.1.15:995",
&tls.Config{
InsecureSkipVerify: true,
ServerName: "192.168.1.15",
},
)
defer conn.Close()
pop3Run(conn, t)
}
func TestPopNor(t *testing.T) {
client, _ := net.Dial("tcp", "192.168.1.15: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), nil)
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), nil)
if b {
t.Log("send Good!")
}
}
}

View File

@ -0,0 +1,70 @@
package protected
import (
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
const (
COMPARE_STR_1 = "-"
COMPARE_STR_2 = "DENIED"
)
type RedisProtectedMatcher struct {
matcher.Matchers
}
func (r *RedisProtectedMatcher) ServiceName() string {
return "RedisProtectedMatcher"
}
func (r *RedisProtectedMatcher) IsPrePacket() bool {
return true
}
func (r *RedisProtectedMatcher) HasResponse(index int) bool {
return true
}
func (r *RedisProtectedMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (r *RedisProtectedMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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
}
func NewMatcher() matcher.Matcher {
m := &RedisProtectedMatcher{}
return m
}

View File

@ -0,0 +1,33 @@
package protected
//import (
// "git.loafle.net/overflow/overflow_discovery/collector/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, matcher.NewPacket(bytes, n), nil)
//
// if b {
// t.Log("good!")
// }
//
//}

View File

@ -0,0 +1,69 @@
package redis
import (
"strings"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
const REDIS_PING string = "*1\r\n$4\r\nping\r\n"
type RedisMatcher struct {
matcher.Matchers
}
func (t *RedisMatcher) ServiceName() string {
return "Redis"
}
func (t *RedisMatcher) IsPrePacket() bool {
return false
}
func (t *RedisMatcher) HasResponse(index int) bool {
return true
}
func (t *RedisMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (t *RedisMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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
}
func NewMatcher() matcher.Matcher {
m := &RedisMatcher{}
m.AddPacket(matcher.NewPacket([]byte(REDIS_PING), len(REDIS_PING)))
return m
}

View File

@ -0,0 +1,37 @@
package redis
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
const (
ADDR string = "192.168.1.16:26379"
)
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")
}
}

103
service/matcher/rmi/rmi.go Normal file
View File

@ -0,0 +1,103 @@
package rmi
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
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 {
matcher.Matchers
}
func (r *RMIMatcher) ServiceName() string {
return "RMI"
}
func (r *RMIMatcher) IsPrePacket() bool {
return false
}
func (r *RMIMatcher) HasResponse(index int) bool {
return true
}
func (r *RMIMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (r *RMIMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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 NewMatcher() matcher.Matcher {
m := &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()
m.AddPacket(matcher.NewPacket(sendByte1, len(sendByte1)))
return m
}

View File

@ -0,0 +1,52 @@
package rmi
import (
"fmt"
"git.loafle.net/overflow/overflow_discovery/match/packet"
//"git.loafle.net/overflow/overflow_discovery/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, err := net.Dial("tcp", "192.168.1.101:9840")
if err != nil {
t.Fatal(err)
}
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)
}

154
service/matcher/smb/smb.go Normal file
View File

@ -0,0 +1,154 @@
package smb
import (
"bytes"
"encoding/binary"
"strings"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
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 {
matcher.Matchers
}
func (t *SMBMatcher) ServiceName() string {
return "SMB"
}
func (t *SMBMatcher) IsPrePacket() bool {
return false
}
func (t *SMBMatcher) HasResponse(index int) bool {
return true
}
func (t *SMBMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (t *SMBMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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
}
func NewMatcher() matcher.Matcher {
m := &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)
m.AddPacket(matcher.NewPacket(writer.Bytes(), writer.Len()))
return m
}

View File

@ -0,0 +1,42 @@
package smb
import (
"git.loafle.net/overflow/overflow_discovery/match/packet"
"net"
"testing"
)
const (
ADDR string = "192.168.1.106:445"
)
func TestSMBMatcher(t *testing.T) {
m := NewSMBMatcher()
conn, err := net.Dial("tcp", ADDR)
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("SMB found.")
return
}
t.Error("SMB not found")
}
}

View File

@ -0,0 +1,67 @@
package smtp
import (
"strings"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
type SmtpMatcher struct {
matcher.Matchers
}
func (t *SmtpMatcher) ServiceName() string {
return "SMTP"
}
func (t *SmtpMatcher) IsPrePacket() bool {
return true
}
func (t *SmtpMatcher) HasResponse(index int) bool {
return true
}
func (t *SmtpMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (t *SmtpMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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
}
func NewMatcher() matcher.Matcher {
m := &SmtpMatcher{}
b := []byte("helo test\r\n")
m.AddPacket(matcher.NewPacket(b, len(b)))
b = []byte("quit\r\n")
m.AddPacket(matcher.NewPacket(b, len(b)))
return m
}

View File

@ -0,0 +1,68 @@
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.15: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])
}

View File

@ -0,0 +1,16 @@
package snmp
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
)

View File

@ -0,0 +1,179 @@
package v2
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
"git.loafle.net/overflow/overflow_discovery/service/matcher/snmp"
)
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 SNMPMatcher struct {
matcher.Matchers
}
func (t *SNMPMatcher) ServiceName() string {
return "SNMP"
}
func (t *SNMPMatcher) IsPrePacket() bool {
return false
}
func (t *SNMPMatcher) HasResponse(index int) bool {
return true
}
func (t *SNMPMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (t *SNMPMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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.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.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 *SNMPMatcher) IsSend(info matcher.MatchInfo) bool {
if info.Port() == 161 {
return true
}
return false
}
func NewMatcher() matcher.UDPMatcher {
m := &SNMPMatcher{}
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.SNMP_START_SEQUENCE
q.SeqLen = uint8(len(snmpTempBuf.Bytes())) - 2
q.SNMPVersionType = snmp.SNMP_TYPE_INTEGER
q.SNMPVersionLen = 0x01
q.SNMPVersion = snmp.SNMP_PROTOCOL_VERSION_2c
q.CommunityVersionType = snmp.SNMP_TYPE_STRING
q.CommunityVersionLen = 0x06
var community [6]byte
copy(community[:], "public")
q.Community = community
q.Data.DataType = snmp.SNMP_GET_REQUEST
q.Data.DataLen = uint8(len(snmpDataTempBuf.Bytes())) - 2
q.Data.RequestIdType = snmp.SNMP_TYPE_INTEGER
q.Data.RequestIdLen = 0x01
q.Data.RequestId = 0x01
q.Data.ErrorStatusType = snmp.SNMP_TYPE_INTEGER
q.Data.ErrorStatusLen = 0x01
q.Data.ErrorStatus = 0x00
q.Data.ErrorIndexType = snmp.SNMP_TYPE_INTEGER
q.Data.ErrorIndexLen = 0x01
q.Data.ErrorIndex = 0x00
q.Data.VarBinding.VarBindindStart = snmp.SNMP_START_SEQUENCE
q.Data.VarBinding.VarBindLen = uint8(len(snmpVarTempBuf.Bytes())) - 2
q.Data.VarBinding.ObjectStart = snmp.SNMP_START_SEQUENCE
q.Data.VarBinding.ObjectLen = uint8(len(snmpVarTempBuf.Bytes())) - 4
q.Data.VarBinding.ValueType = snmp.SNMP_TYPE_OBJECT
q.Data.VarBinding.ValueLen = 0x08
q.Data.VarBinding.ObjectValue = 0x000001010201062b
q.Data.VarBinding.NullValue = snmp.SNMP_TYPE_NULL
q.Data.VarBinding.EndIndicator = 0x00
writer := new(bytes.Buffer)
binary.Write(writer, binary.LittleEndian, q)
m.AddPacket(matcher.NewPacket(writer.Bytes(), writer.Len()))
return m
}

View File

@ -0,0 +1,37 @@
package v2
import (
"net"
"testing"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
func TestSNMP2(t *testing.T) {
m := NewMatcher()
conn, err := net.Dial("udp", "192.168.1.15: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 := matcher.NewPacket(bytes, n)
if m.Match(nil, i, p) {
t.Log("SNMP found")
return
}
t.Error("SNMP not found")
}
}

View File

@ -0,0 +1,212 @@
package v3
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
"git.loafle.net/overflow/overflow_probe/matcher/snmp"
)
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 SNMPMatcher struct {
matcher.Matchers
}
func (t *SNMPMatcher) ServiceName() string {
return "SNMP"
}
func (t *SNMPMatcher) IsPrePacket() bool {
return false
}
func (t *SNMPMatcher) HasResponse(index int) bool {
return true
}
func (t *SNMPMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (t *SNMPMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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.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.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 *SNMPMatcher) IsSend(info matcher.MatchInfo) bool {
if info.Port() == 161 {
return true
}
return false
}
func NewMatcher() matcher.UDPMatcher {
m := &SNMPMatcher{}
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.SNMP_START_SEQUENCE
q.SeqLen = uint8(len(snmpTempBuf.Bytes())) - 2
q.SNMPVersionType = snmp.SNMP_TYPE_INTEGER
q.SNMPVersionLen = 0x01
q.SNMPVersion = snmp.SNMP_PROTOCOL_VERSION_3
q.MsgGlobalData.GlobalDataStartSeq = snmp.SNMP_START_SEQUENCE
q.MsgGlobalData.GlobalDataLen = uint8(len(snmpGlobalTempBuf.Bytes())) - 2
q.MsgGlobalData.MsgIdType = snmp.SNMP_TYPE_INTEGER
q.MsgGlobalData.MsgIdLen = 0x04
q.MsgGlobalData.MsgId = snmp.SNMP_MSG_ID_MAX_VALUE
q.MsgGlobalData.MsgMaxSizeType = snmp.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.SNMP_TYPE_STRING
q.MsgGlobalData.MsgFlagsTypeLen = 0x01
q.MsgGlobalData.MsgFlags = 0x04
q.MsgGlobalData.MsgSecurityModelType = snmp.SNMP_TYPE_INTEGER
q.MsgGlobalData.MsgSecurityModelLen = 0x01
q.MsgGlobalData.MsgSecurityModel = 0x03
q.Unk1 = 0x1004
q.Unk2 = 0x0e30
q.MsgAuthoritativeEngineId = snmp.SNMP_NO_DESC
q.MsgAuthoritativeEngineBootsType = snmp.SNMP_TYPE_INTEGER
q.MsgAuthoritativeEngineBootsLen = 0x01
q.MsgAuthoritativeEngineBoots = 0x00
q.MsgAuthoritativeEngineTimeType = snmp.SNMP_TYPE_INTEGER
q.MsgAuthoritativeEngineTimeLen = 0x01
q.MsgAuthoritativeEngineTime = 0x00
q.MsgUserName = snmp.SNMP_NO_DESC
q.MsgAuthenticationParam = snmp.SNMP_NO_DESC
q.MsgPrivacyParam = snmp.SNMP_NO_DESC
q.MsgData.MsgDataStartSeq = snmp.SNMP_START_SEQUENCE
q.MsgData.MsgDataLen = uint8(len(snmpMsgDataTempBuf.Bytes())) - 2
q.MsgData.ContextEngineId = snmp.SNMP_NO_DESC
q.MsgData.ContextEngineName = snmp.SNMP_NO_DESC
q.MsgData.SnmpType = snmp.SNMP_GET_REQUEST
q.MsgData.Len = 0x0E
q.MsgData.RequestIdType = snmp.SNMP_TYPE_INTEGER
q.MsgData.RequestIdLen = 0x04
q.MsgData.RequestId = 0x00 //
q.MsgData.ErrorStatusType = snmp.SNMP_TYPE_INTEGER
q.MsgData.ErrorStatusLen = 0x01
q.MsgData.ErrorStatus = 0x00
q.MsgData.ErrorIndexType = snmp.SNMP_TYPE_INTEGER
q.MsgData.ErrorIndexLen = 0x01
q.MsgData.ErrorIndex = 0x00
q.MsgData.EndSeq = snmp.SNMP_END_SEQUENCE
q.MsgData.EndIndicator = 0x00
writer := new(bytes.Buffer)
binary.Write(writer, binary.LittleEndian, q)
m.AddPacket(matcher.NewPacket(writer.Bytes(), writer.Len()))
return m
}

View File

@ -0,0 +1,37 @@
package v3
import (
"net"
"testing"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
func TestSNMP3(t *testing.T) {
m := NewMatcher()
conn, err := net.Dial("udp", "192.168.1.15: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 := matcher.NewPacket(bytes, n)
if m.Match(nil, i, p) {
t.Log("SNMP found")
return
}
t.Error("SNMP not found")
}
}

View File

@ -0,0 +1,58 @@
package ssh
import (
"strings"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
type SSHMatcher struct {
matcher.Matchers
}
func (ssh *SSHMatcher) ServiceName() string {
return "SSH"
}
func (ssh *SSHMatcher) IsPrePacket() bool {
return true
}
func (ssh *SSHMatcher) HasResponse(index int) bool {
return true
}
func (ssh *SSHMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (ssh *SSHMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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 NewMatcher() matcher.Matcher {
m := &SSHMatcher{}
return m
}

View File

@ -0,0 +1,35 @@
package ssh
import (
"fmt"
//"git.loafle.net/overflow/overflow_discovery/match/ssh"
"git.loafle.net/overflow/overflow_discovery/match/packet"
//"git.loafle.net/overflow/overflow_discovery/collector/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", "192.168.1.10:22")
defer client.Close()
bytes := make([]byte, 512)
l, _ := client.Read(bytes)
fmt.Println(bytes)
b := NewSSHMatcher().Match(0, packet.NewPacket(bytes, l), nil)
fmt.Println(b)
}

View File

@ -0,0 +1,70 @@
package telnet
import (
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
const (
DO = 0xfd
WONT = 0x4b
WILL = 0xfb
DONT = 0xfe
CMD = 0xff
)
type TelnetMatcher struct {
matcher.Matchers
}
func (tel *TelnetMatcher) ServiceName() string {
return "Telnet"
}
func (tel *TelnetMatcher) IsPrePacket() bool {
return true
}
func (tel *TelnetMatcher) HasResponse(index int) bool {
return true
}
func (tel *TelnetMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (tel *TelnetMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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 NewMatcher() matcher.Matcher {
m := &TelnetMatcher{}
return m
}

View File

@ -0,0 +1,33 @@
package telnet
import (
"fmt"
"git.loafle.net/overflow/overflow_discovery/match/packet"
"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", "192.168.1.105:23")
defer client.Close()
bytes := make([]byte, 512)
l, _ := client.Read(bytes)
fmt.Println("length :", l)
fmt.Println(bytes)
b := NewTelnetMatcher().Match(0, packet.NewPacket(bytes, l), nil)
fmt.Println(b)
}

244
service/matcher/wmi/wmi.go Normal file
View File

@ -0,0 +1,244 @@
package wmi
import (
"bytes"
"encoding/binary"
"git.loafle.net/overflow/overflow_discovery/service/matcher"
)
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 {
matcher.Matchers
}
func (w *WMIMatcher) ServiceName() string {
return "WMI"
}
func (w *WMIMatcher) IsPrePacket() bool {
return false
}
func (w *WMIMatcher) HasResponse(index int) bool {
return true
}
func (w *WMIMatcher) IsError(info matcher.MatchInfo, index int, packet *matcher.Packet) bool {
return false
}
func (w *WMIMatcher) Match(info matcher.MatchInfo, index int, packet *matcher.Packet) 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 NewMatcher() matcher.Matcher {
m := &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)
m.AddPacket(matcher.NewPacket(firstByte, len(ds1Bytes)+len(ioxidrBytes)))
m.AddPacket(matcher.NewPacket(secondByte, len(ds2Bytes)+len(daBytes)))
return m
}
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
}

Some files were not shown because too many files have changed in this diff Show More