commit ac4d422cd978c3fade3dd298186f5ce370401c45 Author: crusader Date: Mon Dec 4 16:27:08 2017 +0900 ing diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3733e36 --- /dev/null +++ b/.gitignore @@ -0,0 +1,68 @@ +# Created by .ignore support plugin (hsz.mobi) +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties +### Go template +# Binaries for programs and plugins +*.exe +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 +.glide/ +.idea/ +*.iml + +vendor/ +glide.lock +.DS_Store +dist/ +debug diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2ca2b1d --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,32 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug", + "type": "go", + "request": "launch", + "mode": "debug", + "remotePath": "", + "port": 2345, + "host": "127.0.0.1", + "program": "${workspaceRoot}/main.go", + "env": {}, + "args": [], + "showLog": true + }, + { + "name": "File Debug", + "type": "go", + "request": "launch", + "mode": "debug", + "remotePath": "", + "port": 2345, + "host": "127.0.0.1", + "program": "${fileDirname}", + "env": {}, + "args": [], + "showLog": true + } + + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..20af2f6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +// Place your settings in this file to overwrite default and user settings. +{ +} \ No newline at end of file diff --git a/activedirectory/activedirectory.go b/activedirectory/activedirectory.go new file mode 100644 index 0000000..b6f7e50 --- /dev/null +++ b/activedirectory/activedirectory.go @@ -0,0 +1,327 @@ +package activedirectory + +import ( + "bytes" + "encoding/binary" + + cnsm "git.loafle.net/commons_go/network_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 { + cnsm.Matchers +} + +func (m *ActiveDirectoryMatcher) ServiceName() string { + return "ActiveDirectory" +} + +func (m *ActiveDirectoryMatcher) IsPrePacket() bool { + return false +} + +func (m *ActiveDirectoryMatcher) IsError(info cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (m *ActiveDirectoryMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.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 := cnsm.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 := cnsm.NewPacket(quBytes, len(quBytes)) + + m.AddPacket(pp2) + + return m +} diff --git a/activedirectory/activedirectory_test.go b/activedirectory/activedirectory_test.go new file mode 100644 index 0000000..ce598fa --- /dev/null +++ b/activedirectory/activedirectory_test.go @@ -0,0 +1,79 @@ +package activedirectory + +import ( + "crypto/tls" + "fmt" + "net" + "testing" + + cnsm "git.loafle.net/commons_go/network_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, cnsm.NewPacket(bytes, read)) + + if b { + fmt.Println("Good") + } + + } + +} diff --git a/cassandra/cassandra.go b/cassandra/cassandra.go new file mode 100644 index 0000000..2748897 --- /dev/null +++ b/cassandra/cassandra.go @@ -0,0 +1,94 @@ +package cassandra + +import ( + "bytes" + "encoding/binary" + + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +type cassandra struct { + Version uint8 + Flags uint8 + Stream uint16 + Opcode uint8 + Length uint32 +} + +type CassandraMatcher struct { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (m *CassandraMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.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(cnsm.NewPacket(writer.Bytes(), writer.Len())) + + return m +} diff --git a/cassandra/cassandra_test.go b/cassandra/cassandra_test.go new file mode 100644 index 0000000..ec073d3 --- /dev/null +++ b/cassandra/cassandra_test.go @@ -0,0 +1,74 @@ +package cassandra + +import ( + "crypto/tls" + "net" + "testing" + + cnsm "git.loafle.net/commons_go/network_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 := cnsm.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 := cnsm.NewPacket(bytes, n) + + if m.Match(nil, i, p) { + t.Log("Cassandra found") + return + } + + t.Error("Cassandra not found") + } + +} diff --git a/dhcp/dhcp.go b/dhcp/dhcp.go new file mode 100644 index 0000000..1391822 --- /dev/null +++ b/dhcp/dhcp.go @@ -0,0 +1,188 @@ +package dhcp + +import ( + "bytes" + "encoding/binary" + "fmt" + "net" + "time" + + "git.loafle.net/commons_go/logging" +) + +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() { + err := sendDHCPDiscovery() + if err != nil { + logging.Logger().Error(fmt.Sprintf("Discovery: DHCP Matcher %v", err)) + return + } + recvDHCPOffer() +} + +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() { + + 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 +} diff --git a/dhcp/dhcp_test.go b/dhcp/dhcp_test.go new file mode 100644 index 0000000..5e06a0f --- /dev/null +++ b/dhcp/dhcp_test.go @@ -0,0 +1,9 @@ +package dhcp + +import ( + "testing" +) + +func TestDHCP(t *testing.T) { + +} diff --git a/dns/dns.go b/dns/dns.go new file mode 100644 index 0000000..4c7d1b7 --- /dev/null +++ b/dns/dns.go @@ -0,0 +1,145 @@ +package dns + +import ( + "bytes" + "encoding/binary" + + cnsm "git.loafle.net/commons_go/network_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 { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (t *DNSMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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(port int) bool { + if 53 == port { + return true + } + return false +} + +func NewMatcher() cnsm.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(cnsm.NewPacket(buf.Bytes(), buf.Len())) + + return m +} diff --git a/dns/dns_test.go b/dns/dns_test.go new file mode 100644 index 0000000..e8391b8 --- /dev/null +++ b/dns/dns_test.go @@ -0,0 +1,35 @@ +package dns + +import ( + "net" + "testing" + + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +func TestDns(t *testing.T) { + m := NewMatcher() + info := cnsm.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(53) != true { + t.Error("not port") + } + pack := m.Packet(i) + conn.Write(pack.Buffer) + bytes := make([]byte, 1024) + n, _ := conn.Read(bytes) + p := cnsm.NewPacket(bytes, n) + + if m.Match(info, i, p) { + t.Log("dns found") + return + } + + t.Error("dns not found") + } +} diff --git a/ftp/ftp.go b/ftp/ftp.go new file mode 100644 index 0000000..b1aa2fb --- /dev/null +++ b/ftp/ftp.go @@ -0,0 +1,135 @@ +package ftp + +import ( + "fmt" + + "git.loafle.net/commons_go/logging" + cnsm "git.loafle.net/commons_go/network_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 { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (ftp *FTPMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.Matcher { + + m := &FTPMatcher{} + + sysStr := "SYST\r\n" + systByte := make([]byte, len(sysStr)) + copy(systByte[:], sysStr) + m.AddPacket(cnsm.NewPacket(systByte, len(sysStr))) + + passStr := "PASS \r\n" + passByte := make([]byte, len(passStr)) + copy(passByte[:], passStr) + m.AddPacket(cnsm.NewPacket(passByte, len(passStr))) + + quitStr := "QUIT\r\n" + quitByte := make([]byte, len(quitStr)) + copy(quitByte[:], quitStr) + m.AddPacket(cnsm.NewPacket(quitByte, len(quitStr))) + + return m +} diff --git a/ftp/ftp_test.go b/ftp/ftp_test.go new file mode 100644 index 0000000..9a7f070 --- /dev/null +++ b/ftp/ftp_test.go @@ -0,0 +1,234 @@ +package ftp + +import ( + "fmt" + "testing" + + cnsm "git.loafle.net/commons_go/network_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 := cnsm.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, cnsm.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, cnsm.NewPacket(bytes, l)) + + fmt.Println(b) + + } + + fmt.Println("Service Name : ", ftm.ServiceName()) +} diff --git a/ftp/ftps.go b/ftp/ftps.go new file mode 100644 index 0000000..a10f5aa --- /dev/null +++ b/ftp/ftps.go @@ -0,0 +1,193 @@ +package ftp + +import ( + "bufio" + "crypto/tls" + "errors" + "fmt" + "net" + "strings" + "time" + + "git.loafle.net/commons_go/logging" + cnsm "git.loafle.net/commons_go/network_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 cnsm.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 +} diff --git a/ftp/ftps_test.go b/ftp/ftps_test.go new file mode 100644 index 0000000..322c9c1 --- /dev/null +++ b/ftp/ftps_test.go @@ -0,0 +1,18 @@ +package ftp + +import ( + "fmt" + "testing" + + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +func TestStartCheckFTPS(t *testing.T) { + info := cnsm.NewMatchInfo("192.168.1.202", 80) + + isFtps, err := StartCheckFTPS(info) + fmt.Println("Result : ", isFtps) + fmt.Println("Error : ", err) +} + + diff --git a/glide.yaml b/glide.yaml new file mode 100644 index 0000000..e098aaa --- /dev/null +++ b/glide.yaml @@ -0,0 +1,14 @@ +package: git.loafle.net/commons_go/network_service_matcher +import: +- package: git.loafle.net/commons_go/logging +- package: git.loafle.net/overflow/overflow_discovery + subpackages: + - service/matcher + - service/matcher/snmp +- package: git.loafle.net/overflow/overflow_probe + subpackages: + - matcher/snmp +testImport: +- package: github.com/stretchr/testify + subpackages: + - assert diff --git a/http/http.go b/http/http.go new file mode 100644 index 0000000..5932344 --- /dev/null +++ b/http/http.go @@ -0,0 +1,81 @@ +package http + +import ( + "strings" + + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +type HTTPMatcher struct { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (h *HTTPMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.Matcher { + + m := &HTTPMatcher{} + reqStr := "GET / HTTP/1.1\r\n\r\n" + byte := make([]byte, len(reqStr)) + copy(byte[:], reqStr) + + m.AddPacket(cnsm.NewPacket(byte, len(reqStr))) + + return m +} diff --git a/http/http_test.go b/http/http_test.go new file mode 100644 index 0000000..a173f9b --- /dev/null +++ b/http/http_test.go @@ -0,0 +1,51 @@ +package http + +import ( + "fmt" + + cnsm "git.loafle.net/commons_go/network_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 := cnsm.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, cnsm.NewPacket(bytes, l)) + +} diff --git a/http/https_test.go b/http/https_test.go new file mode 100644 index 0000000..b59b4fa --- /dev/null +++ b/http/https_test.go @@ -0,0 +1,58 @@ +package http + +import ( + "crypto/tls" + "fmt" + "log" + "net" + "testing" + "time" + + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +func TestHTTPSMatcher_Match(t *testing.T) { + info := cnsm.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, cnsm.NewPacket(buf, l)) + fmt.Println(is) + +} diff --git a/imap/imap.go b/imap/imap.go new file mode 100644 index 0000000..3326162 --- /dev/null +++ b/imap/imap.go @@ -0,0 +1,80 @@ +package imap + +import ( + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +const ( + PRE_COMPARE_STR = "* OK" + SEND_COMPARE_STR = "* BYE" +) + +type IMAPMatcher struct { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (i *IMAPMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.Matcher { + + m := &IMAPMatcher{} + + reqStr := "A0001 LOGOUT\r\n" + byte := make([]byte, len(reqStr)) + copy(byte[:], reqStr) + + m.AddPacket(cnsm.NewPacket(byte, len(reqStr))) + + return m + +} diff --git a/imap/imap_test.go b/imap/imap_test.go new file mode 100644 index 0000000..4c53695 --- /dev/null +++ b/imap/imap_test.go @@ -0,0 +1,151 @@ +package imap + +import ( + "crypto/tls" + "fmt" + //"git.loafle.net/overflow/overflow_discovery/collector/core/scan/port" + cnsm "git.loafle.net/commons_go/network_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, cnsm.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, cnsm.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, cnsm.NewPacket(bytett, rr), scanInfo) + bb := lm.Match(nil, 0, cnsm.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, cnsm.NewPacket(bytes, read)) + + if b { + t.Log("send Good!") + } + + } + //t.Log(scanInfo) +} diff --git a/ldap/ldap.go b/ldap/ldap.go new file mode 100644 index 0000000..723029a --- /dev/null +++ b/ldap/ldap.go @@ -0,0 +1,180 @@ +package ldap + +import ( + "bytes" + "encoding/binary" + + cnsm "git.loafle.net/commons_go/network_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 { + cnsm.Matchers +} + +func (l *LDAPMatcher) ServiceName() string { + return "LDAP" +} + +func (l *LDAPMatcher) IsPrePacket() bool { + return false +} + +func (l *LDAPMatcher) IsError(info cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (l *LDAPMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.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(cnsm.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(cnsm.NewPacket(sendByte2, len(sendByte2))) + + return m + +} diff --git a/ldap/ldap_test.go b/ldap/ldap_test.go new file mode 100644 index 0000000..7519b9a --- /dev/null +++ b/ldap/ldap_test.go @@ -0,0 +1,113 @@ +package ldap + +import ( + "crypto/tls" + "fmt" + + cnsm "git.loafle.net/commons_go/network_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, cnsm.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) +} diff --git a/matcher.go b/matcher.go new file mode 100644 index 0000000..943f65c --- /dev/null +++ b/matcher.go @@ -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(port int) 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, + } +} diff --git a/matcher_test.go b/matcher_test.go new file mode 100644 index 0000000..2e72a81 --- /dev/null +++ b/matcher_test.go @@ -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) { + +} diff --git a/mongodb/mongodb.go b/mongodb/mongodb.go new file mode 100644 index 0000000..77ad83d --- /dev/null +++ b/mongodb/mongodb.go @@ -0,0 +1,114 @@ +package mongodb + +import ( + "bytes" + "encoding/binary" + "math/rand" + + cnsm "git.loafle.net/commons_go/network_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 { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (t *MongoDBMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.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(cnsm.NewPacket(writer.Bytes(), writer.Len())) + + return mm +} diff --git a/mongodb/mongodb_test.go b/mongodb/mongodb_test.go new file mode 100644 index 0000000..f35cd3f --- /dev/null +++ b/mongodb/mongodb_test.go @@ -0,0 +1,56 @@ +package mongodb + +import ( + "crypto/tls" + "net" + "testing" + + cnsm "git.loafle.net/commons_go/network_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 := cnsm.NewPacket(bytes, n) + + if m.Match(nil, i, p) { + t.Log("MongoDB found") + return + } + + t.Error("MongoDB not found") + } + +} diff --git a/mssql/mssql.go b/mssql/mssql.go new file mode 100644 index 0000000..9e24bb9 --- /dev/null +++ b/mssql/mssql.go @@ -0,0 +1,166 @@ +package mssql + +import ( + "bytes" + "encoding/binary" + + cnsm "git.loafle.net/commons_go/network_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 { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (t *MSSqlMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.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(cnsm.NewPacket(writer.Bytes(), writer.Len())) + + return mm +} diff --git a/mssql/mssql_test.go b/mssql/mssql_test.go new file mode 100644 index 0000000..52aff93 --- /dev/null +++ b/mssql/mssql_test.go @@ -0,0 +1,64 @@ +package mssql + +import ( + "net" + "testing" + + cnsm "git.loafle.net/commons_go/network_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 := cnsm.NewPacket(bytes, n) + + if m.Match(nil, i, p) { + t.Log(m.ServiceName()) + return + } + + t.Error("MSSQL not found") + } + +} diff --git a/mysql/mysql.go b/mysql/mysql.go new file mode 100644 index 0000000..ef2d659 --- /dev/null +++ b/mysql/mysql.go @@ -0,0 +1,143 @@ +package mysql + +import ( + "bytes" + "encoding/binary" + "fmt" + "strconv" + "strings" + + cnsm "git.loafle.net/commons_go/network_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 { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (t *MySqlMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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 *cnsm.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() cnsm.Matcher { + return &MySqlMatcher{} +} diff --git a/mysql/mysql_test.go b/mysql/mysql_test.go new file mode 100644 index 0000000..97ebab5 --- /dev/null +++ b/mysql/mysql_test.go @@ -0,0 +1,71 @@ +package mysql + +import ( + "crypto/tls" + "net" + "testing" + + cnsm "git.loafle.net/commons_go/network_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 := cnsm.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 := cnsm.NewPacket(bytes, n) + + if m.Match(nil, i, p) { + t.Log(m.ServiceName()) + return + } + + t.Error("MySQL not found") + } + +} diff --git a/netbios/netbios.go b/netbios/netbios.go new file mode 100644 index 0000000..f735e50 --- /dev/null +++ b/netbios/netbios.go @@ -0,0 +1,102 @@ +package netbios + +import ( + "bytes" + "encoding/binary" + + cnsm "git.loafle.net/commons_go/network_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 { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (t *NetBiosMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.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(cnsm.NewPacket(writer.Bytes(), writer.Len())) + + return m +} diff --git a/netbios/netbios_test.go b/netbios/netbios_test.go new file mode 100644 index 0000000..39ecddd --- /dev/null +++ b/netbios/netbios_test.go @@ -0,0 +1,33 @@ +package netbios + +import ( + "net" + "testing" + + cnsm "git.loafle.net/commons_go/network_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 := cnsm.NewPacket(bytes, n) + + if m.Match(nil, i, p) { + t.Log("NBSS found") + return + } + + t.Error("NBSS not found") + } +} diff --git a/oracle/oracle.go b/oracle/oracle.go new file mode 100644 index 0000000..35b5165 --- /dev/null +++ b/oracle/oracle.go @@ -0,0 +1,185 @@ +package oracle + +import ( + "bytes" + "encoding/binary" + + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +type OracleMatcher struct { + cnsm.Matchers +} + +func (o *OracleMatcher) ServiceName() string { + return "Oracle" +} + +func (o *OracleMatcher) IsPrePacket() bool { + return false +} + +func (o *OracleMatcher) HasResponse(index int) bool { + return true +} + +func (o *OracleMatcher) IsError(info cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (o *OracleMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.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(cnsm.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 +} diff --git a/oracle/oracle_test.go b/oracle/oracle_test.go new file mode 100644 index 0000000..f8f404f --- /dev/null +++ b/oracle/oracle_test.go @@ -0,0 +1,47 @@ +package oracle + +import ( + cnsm "git.loafle.net/commons_go/network_service_matcher" + + "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, cnsm.NewPacket(bytes, read), nil) + + if b { + t.Log("Good") + } + + } + +} diff --git a/packet.go b/packet.go new file mode 100644 index 0000000..2627663 --- /dev/null +++ b/packet.go @@ -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, + } +} diff --git a/pgsql/pgsql.go b/pgsql/pgsql.go new file mode 100644 index 0000000..2040f24 --- /dev/null +++ b/pgsql/pgsql.go @@ -0,0 +1,175 @@ +package pgsql + +import ( + "bytes" + "encoding/binary" + "strings" + + cnsm "git.loafle.net/commons_go/network_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 { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (t *PostgreSQLMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.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(cnsm.NewPacket(writer.Bytes(), writer.Len())) + + return m +} diff --git a/pgsql/pgsql_test.go b/pgsql/pgsql_test.go new file mode 100644 index 0000000..200f5a7 --- /dev/null +++ b/pgsql/pgsql_test.go @@ -0,0 +1,71 @@ +package pgsql + +import ( + "crypto/tls" + "net" + "testing" + + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +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 := cnsm.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 := cnsm.NewPacket(bytes, n) + + if m.Match(i, p, nil) { + t.Log("PostgreSQL found") + return + } + + t.Error("PostgreSQL not found") + } +} diff --git a/pop/pop.go b/pop/pop.go new file mode 100644 index 0000000..28a2c13 --- /dev/null +++ b/pop/pop.go @@ -0,0 +1,65 @@ +package pop + +import ( + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +const ( + COMPARE_STR = "+OK" +) + +type POPMatcher struct { + cnsm.Matchers +} + +func (p *POPMatcher) ServiceName() string { + return "POP3" +} + +func (p *POPMatcher) IsPrePacket() bool { + return true +} + +func (p *POPMatcher) HasResponse(index int) bool { + return true +} + +func (p *POPMatcher) IsError(info cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (p *POPMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.Matcher { + + m := &POPMatcher{} + + reqStr := "QUIT\r\n" + byte := make([]byte, len(reqStr)) + copy(byte[:], reqStr) + m.AddPacket(cnsm.NewPacket(byte, len(reqStr))) + + return m + +} diff --git a/pop/pop_test.go b/pop/pop_test.go new file mode 100644 index 0000000..96da2ec --- /dev/null +++ b/pop/pop_test.go @@ -0,0 +1,83 @@ +package pop + +import ( + "crypto/tls" + "fmt" + + cnsm "git.loafle.net/commons_go/network_service_matcher" + + "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, cnsm.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, cnsm.NewPacket(bytes, rr), nil) + + if b { + t.Log("send Good!") + } + + } + +} diff --git a/redis/protected/redisProtected.go b/redis/protected/redisProtected.go new file mode 100644 index 0000000..fcc1668 --- /dev/null +++ b/redis/protected/redisProtected.go @@ -0,0 +1,70 @@ +package protected + +import ( + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +const ( + COMPARE_STR_1 = "-" + COMPARE_STR_2 = "DENIED" +) + +type RedisProtectedMatcher struct { + cnsm.Matchers +} + +func (r *RedisProtectedMatcher) ServiceName() string { + return "Redis:Protected" +} + +func (r *RedisProtectedMatcher) IsPrePacket() bool { + return true +} + +func (r *RedisProtectedMatcher) HasResponse(index int) bool { + return true +} + +func (r *RedisProtectedMatcher) IsError(info cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (r *RedisProtectedMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.Matcher { + m := &RedisProtectedMatcher{} + + return m +} diff --git a/redis/protected/redisProtected_test.go b/redis/protected/redisProtected_test.go new file mode 100644 index 0000000..94d18a9 --- /dev/null +++ b/redis/protected/redisProtected_test.go @@ -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!") +// } +// +//} diff --git a/redis/redis.go b/redis/redis.go new file mode 100644 index 0000000..1c17a48 --- /dev/null +++ b/redis/redis.go @@ -0,0 +1,70 @@ +package redis + +import ( + "strings" + + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +const REDIS_PING string = "*1\r\n$4\r\nping\r\n" + +type RedisMatcher struct { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (t *RedisMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.Matcher { + + m := &RedisMatcher{} + + m.AddPacket(cnsm.NewPacket([]byte(REDIS_PING), len(REDIS_PING))) + + return m +} diff --git a/redis/redis_test.go b/redis/redis_test.go new file mode 100644 index 0000000..2240440 --- /dev/null +++ b/redis/redis_test.go @@ -0,0 +1,38 @@ +package redis + +import ( + "net" + "testing" + + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +const ( + ADDR string = "192.168.1.16:26379" +) + +func TestRedisMatcher(t *testing.T) { + + m := NewMatcher() + + 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 := cnsm.NewPacket(bytes, n) + + if m.Match(nil, i, p) { + t.Log("Redis found.") + return + } + + t.Error("Redis not found") + } + +} diff --git a/rmi/rmi.go b/rmi/rmi.go new file mode 100644 index 0000000..38789d8 --- /dev/null +++ b/rmi/rmi.go @@ -0,0 +1,103 @@ +package rmi + +import ( + "bytes" + "encoding/binary" + + cnsm "git.loafle.net/commons_go/network_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 { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (r *RMIMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.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(cnsm.NewPacket(sendByte1, len(sendByte1))) + + return m +} diff --git a/rmi/rmi_test.go b/rmi/rmi_test.go new file mode 100644 index 0000000..2965a76 --- /dev/null +++ b/rmi/rmi_test.go @@ -0,0 +1,53 @@ +package rmi + +import ( + "fmt" + + cnsm "git.loafle.net/commons_go/network_service_matcher" + //"git.loafle.net/overflow/overflow_discovery/discovery/discovery/types" + "net" + "testing" +) + +func TestNew(t *testing.T) { + r := NewMatcher() + fmt.Println("TestNew: ", r) +} +func TestRMIMatcher_Match(t *testing.T) { + + fmt.Println("Match") + + hm := NewMatcher() + + //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(nil, 0, cnsm.NewPacket(bytes, l)) + + fmt.Println(t1) +} diff --git a/smb/smb.go b/smb/smb.go new file mode 100644 index 0000000..709c908 --- /dev/null +++ b/smb/smb.go @@ -0,0 +1,154 @@ +package smb + +import ( + "bytes" + "encoding/binary" + "strings" + + cnsm "git.loafle.net/commons_go/network_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 { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (t *SMBMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.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(cnsm.NewPacket(writer.Bytes(), writer.Len())) + + return m +} diff --git a/smb/smb_test.go b/smb/smb_test.go new file mode 100644 index 0000000..9d0b746 --- /dev/null +++ b/smb/smb_test.go @@ -0,0 +1,43 @@ +package smb + +import ( + "net" + "testing" + + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +const ( + ADDR string = "192.168.1.106:445" +) + +func TestSMBMatcher(t *testing.T) { + + m := NewMatcher() + + 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 := cnsm.NewPacket(bytes, n) + + if m.Match(nil, i, p) { + t.Log("SMB found.") + return + } + + t.Error("SMB not found") + } + +} diff --git a/smtp/smtp.go b/smtp/smtp.go new file mode 100644 index 0000000..c53fa28 --- /dev/null +++ b/smtp/smtp.go @@ -0,0 +1,67 @@ +package smtp + +import ( + "strings" + + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +type SmtpMatcher struct { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (t *SmtpMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.Matcher { + + m := &SmtpMatcher{} + + b := []byte("helo test\r\n") + m.AddPacket(cnsm.NewPacket(b, len(b))) + + b = []byte("quit\r\n") + m.AddPacket(cnsm.NewPacket(b, len(b))) + + return m +} diff --git a/smtp/smtp_test.go b/smtp/smtp_test.go new file mode 100644 index 0000000..eddcc8f --- /dev/null +++ b/smtp/smtp_test.go @@ -0,0 +1,68 @@ +package smtp + +import ( + "crypto/tls" + "fmt" + "net" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +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]) + +} diff --git a/snmp/snmp.go b/snmp/snmp.go new file mode 100644 index 0000000..d7edab4 --- /dev/null +++ b/snmp/snmp.go @@ -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 +) diff --git a/snmp/v2/snmpv2.go b/snmp/v2/snmpv2.go new file mode 100644 index 0000000..db42974 --- /dev/null +++ b/snmp/v2/snmpv2.go @@ -0,0 +1,179 @@ +package v2 + +import ( + "bytes" + "encoding/binary" + + cnsm "git.loafle.net/commons_go/network_service_matcher" + cnsms "git.loafle.net/commons_go/network_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 { + cnsm.Matchers +} + +func (t *SNMPMatcher) ServiceName() string { + return "SNMP V2" +} + +func (t *SNMPMatcher) IsPrePacket() bool { + return false +} + +func (t *SNMPMatcher) HasResponse(index int) bool { + return true +} + +func (t *SNMPMatcher) IsError(info cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (t *SNMPMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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 != cnsms.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 == cnsms.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(port int) bool { + if 161 == port { + return true + } + return false +} + +func NewMatcher() cnsm.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 = cnsms.SNMP_START_SEQUENCE + q.SeqLen = uint8(len(snmpTempBuf.Bytes())) - 2 + q.SNMPVersionType = cnsms.SNMP_TYPE_INTEGER + q.SNMPVersionLen = 0x01 + q.SNMPVersion = cnsms.SNMP_PROTOCOL_VERSION_2c + q.CommunityVersionType = cnsms.SNMP_TYPE_STRING + q.CommunityVersionLen = 0x06 + var community [6]byte + copy(community[:], "public") + q.Community = community + q.Data.DataType = cnsms.SNMP_GET_REQUEST + q.Data.DataLen = uint8(len(snmpDataTempBuf.Bytes())) - 2 + q.Data.RequestIdType = cnsms.SNMP_TYPE_INTEGER + q.Data.RequestIdLen = 0x01 + q.Data.RequestId = 0x01 + q.Data.ErrorStatusType = cnsms.SNMP_TYPE_INTEGER + q.Data.ErrorStatusLen = 0x01 + q.Data.ErrorStatus = 0x00 + q.Data.ErrorIndexType = cnsms.SNMP_TYPE_INTEGER + q.Data.ErrorIndexLen = 0x01 + q.Data.ErrorIndex = 0x00 + q.Data.VarBinding.VarBindindStart = cnsms.SNMP_START_SEQUENCE + q.Data.VarBinding.VarBindLen = uint8(len(snmpVarTempBuf.Bytes())) - 2 + q.Data.VarBinding.ObjectStart = cnsms.SNMP_START_SEQUENCE + q.Data.VarBinding.ObjectLen = uint8(len(snmpVarTempBuf.Bytes())) - 4 + q.Data.VarBinding.ValueType = cnsms.SNMP_TYPE_OBJECT + q.Data.VarBinding.ValueLen = 0x08 + q.Data.VarBinding.ObjectValue = 0x000001010201062b + q.Data.VarBinding.NullValue = cnsms.SNMP_TYPE_NULL + q.Data.VarBinding.EndIndicator = 0x00 + + writer := new(bytes.Buffer) + binary.Write(writer, binary.LittleEndian, q) + + m.AddPacket(cnsm.NewPacket(writer.Bytes(), writer.Len())) + + return m +} diff --git a/snmp/v2/snmpv2_test.go b/snmp/v2/snmpv2_test.go new file mode 100644 index 0000000..0955dff --- /dev/null +++ b/snmp/v2/snmpv2_test.go @@ -0,0 +1,37 @@ +package v2 + +import ( + "net" + "testing" + + cnsm "git.loafle.net/commons_go/network_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 := cnsm.NewPacket(bytes, n) + + if m.Match(nil, i, p) { + t.Log("SNMP found") + return + } + + t.Error("SNMP not found") + } + +} diff --git a/snmp/v3/snmpv3.go b/snmp/v3/snmpv3.go new file mode 100644 index 0000000..f7ca87b --- /dev/null +++ b/snmp/v3/snmpv3.go @@ -0,0 +1,212 @@ +package v3 + +import ( + "bytes" + "encoding/binary" + + cnsm "git.loafle.net/commons_go/network_service_matcher" + cnsms "git.loafle.net/commons_go/network_service_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 { + cnsm.Matchers +} + +func (t *SNMPMatcher) ServiceName() string { + return "SNMP V3" +} + +func (t *SNMPMatcher) IsPrePacket() bool { + return false +} + +func (t *SNMPMatcher) HasResponse(index int) bool { + return true +} + +func (t *SNMPMatcher) IsError(info cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (t *SNMPMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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 != cnsms.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 == cnsms.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(port int) bool { + if 161 == port { + return true + } + return false +} + +func NewMatcher() cnsm.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 = cnsms.SNMP_START_SEQUENCE + q.SeqLen = uint8(len(snmpTempBuf.Bytes())) - 2 + q.SNMPVersionType = cnsms.SNMP_TYPE_INTEGER + q.SNMPVersionLen = 0x01 + q.SNMPVersion = cnsms.SNMP_PROTOCOL_VERSION_3 + q.MsgGlobalData.GlobalDataStartSeq = cnsms.SNMP_START_SEQUENCE + q.MsgGlobalData.GlobalDataLen = uint8(len(snmpGlobalTempBuf.Bytes())) - 2 + q.MsgGlobalData.MsgIdType = cnsms.SNMP_TYPE_INTEGER + q.MsgGlobalData.MsgIdLen = 0x04 + q.MsgGlobalData.MsgId = cnsms.SNMP_MSG_ID_MAX_VALUE + q.MsgGlobalData.MsgMaxSizeType = cnsms.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 = cnsms.SNMP_TYPE_STRING + q.MsgGlobalData.MsgFlagsTypeLen = 0x01 + q.MsgGlobalData.MsgFlags = 0x04 + q.MsgGlobalData.MsgSecurityModelType = cnsms.SNMP_TYPE_INTEGER + q.MsgGlobalData.MsgSecurityModelLen = 0x01 + q.MsgGlobalData.MsgSecurityModel = 0x03 + q.Unk1 = 0x1004 + q.Unk2 = 0x0e30 + q.MsgAuthoritativeEngineId = cnsms.SNMP_NO_DESC + q.MsgAuthoritativeEngineBootsType = cnsms.SNMP_TYPE_INTEGER + q.MsgAuthoritativeEngineBootsLen = 0x01 + q.MsgAuthoritativeEngineBoots = 0x00 + q.MsgAuthoritativeEngineTimeType = cnsms.SNMP_TYPE_INTEGER + q.MsgAuthoritativeEngineTimeLen = 0x01 + q.MsgAuthoritativeEngineTime = 0x00 + q.MsgUserName = cnsms.SNMP_NO_DESC + q.MsgAuthenticationParam = cnsms.SNMP_NO_DESC + q.MsgPrivacyParam = cnsms.SNMP_NO_DESC + + q.MsgData.MsgDataStartSeq = cnsms.SNMP_START_SEQUENCE + q.MsgData.MsgDataLen = uint8(len(snmpMsgDataTempBuf.Bytes())) - 2 + q.MsgData.ContextEngineId = cnsms.SNMP_NO_DESC + q.MsgData.ContextEngineName = cnsms.SNMP_NO_DESC + q.MsgData.SnmpType = cnsms.SNMP_GET_REQUEST + q.MsgData.Len = 0x0E + q.MsgData.RequestIdType = cnsms.SNMP_TYPE_INTEGER + q.MsgData.RequestIdLen = 0x04 + q.MsgData.RequestId = 0x00 // + q.MsgData.ErrorStatusType = cnsms.SNMP_TYPE_INTEGER + q.MsgData.ErrorStatusLen = 0x01 + q.MsgData.ErrorStatus = 0x00 + q.MsgData.ErrorIndexType = cnsms.SNMP_TYPE_INTEGER + q.MsgData.ErrorIndexLen = 0x01 + q.MsgData.ErrorIndex = 0x00 + q.MsgData.EndSeq = cnsms.SNMP_END_SEQUENCE + q.MsgData.EndIndicator = 0x00 + + writer := new(bytes.Buffer) + binary.Write(writer, binary.LittleEndian, q) + + m.AddPacket(cnsm.NewPacket(writer.Bytes(), writer.Len())) + + return m +} diff --git a/snmp/v3/snmpv3_test.go b/snmp/v3/snmpv3_test.go new file mode 100644 index 0000000..1908ed4 --- /dev/null +++ b/snmp/v3/snmpv3_test.go @@ -0,0 +1,37 @@ +package v3 + +import ( + "net" + "testing" + + matcher "git.loafle.net/commons_go/network_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") + } + +} diff --git a/ssh/ssh.go b/ssh/ssh.go new file mode 100644 index 0000000..5f511cf --- /dev/null +++ b/ssh/ssh.go @@ -0,0 +1,58 @@ +package ssh + +import ( + "strings" + + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +type SSHMatcher struct { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (ssh *SSHMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.Matcher { + m := &SSHMatcher{} + + return m +} diff --git a/ssh/ssh_test.go b/ssh/ssh_test.go new file mode 100644 index 0000000..a798926 --- /dev/null +++ b/ssh/ssh_test.go @@ -0,0 +1,34 @@ +package ssh + +import ( + "fmt" + //"git.loafle.net/overflow/overflow_discovery/match/ssh" + cnsm "git.loafle.net/commons_go/network_service_matcher" + //"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 := NewMatcher().Match(nil, 0, cnsm.NewPacket(bytes, l)) + + fmt.Println(b) + +} diff --git a/telnet/telnet.go b/telnet/telnet.go new file mode 100644 index 0000000..523a7fd --- /dev/null +++ b/telnet/telnet.go @@ -0,0 +1,72 @@ +package telnet + +import ( + cnsm "git.loafle.net/commons_go/network_service_matcher" +) + +const ( + DO = 0xfd + WONT = 0x4b + WILL = 0xfb + DONT = 0xfe + CMD = 0xff +) + +type TelnetMatcher struct { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (tel *TelnetMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.Matcher { + m := &TelnetMatcher{} + + return m +} + + diff --git a/telnet/telnet_test.go b/telnet/telnet_test.go new file mode 100644 index 0000000..2e140e9 --- /dev/null +++ b/telnet/telnet_test.go @@ -0,0 +1,34 @@ +package telnet + +import ( + "fmt" + + cnsm "git.loafle.net/commons_go/network_service_matcher" + + "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 := NewMatcher().Match(nil, 0, cnsm.NewPacket(bytes, l)) + + fmt.Println(b) +} diff --git a/wmi/wmi.go b/wmi/wmi.go new file mode 100644 index 0000000..cba5393 --- /dev/null +++ b/wmi/wmi.go @@ -0,0 +1,244 @@ +package wmi + +import ( + "bytes" + "encoding/binary" + + cnsm "git.loafle.net/commons_go/network_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 { + cnsm.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 cnsm.MatchInfo, index int, packet *cnsm.Packet) bool { + return false +} + +func (w *WMIMatcher) Match(info cnsm.MatchInfo, index int, packet *cnsm.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() cnsm.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(cnsm.NewPacket(firstByte, len(ds1Bytes)+len(ioxidrBytes))) + m.AddPacket(cnsm.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 +} diff --git a/wmi/wmi_test.go b/wmi/wmi_test.go new file mode 100644 index 0000000..a7fcb10 --- /dev/null +++ b/wmi/wmi_test.go @@ -0,0 +1,51 @@ +package wmi + +import ( + "fmt" + + cnsm "git.loafle.net/commons_go/network_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 TestWMI(t *testing.T) { + + lm := NewMatcher() + + //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(nil, ii, cnsm.NewPacket(bytes, read)) + + if b { + fmt.Println("Good") + } + + } + +}