From 4ebbd8cf59cfc1798cb16ffe5b450b28f423d445 Mon Sep 17 00:00:00 2001 From: solar Date: Wed, 6 Mar 2019 15:57:54 +0800 Subject: [PATCH] fixed tds query & format date --- core/cmd.go | 61 ++++--- core/plug.go | 6 +- plugSrc/http/build/entry.go | 43 ++--- plugSrc/mssql/build/entry.go | 18 +- plugSrc/mssql/build/token.go | 328 ++++++++++++++++++++++++++++++++++- plugSrc/redis/build/entry.go | 57 +++--- 6 files changed, 419 insertions(+), 94 deletions(-) diff --git a/core/cmd.go b/core/cmd.go index 9091cda..210765d 100644 --- a/core/cmd.go +++ b/core/cmd.go @@ -1,11 +1,11 @@ package core import ( - "os" - "strings" "fmt" "net" + "os" "strconv" + "strings" ) const InternalCmdPrefix = "--" @@ -18,14 +18,14 @@ const ( ) type Cmd struct { - Device string + Device string plugHandle *Plug } func NewCmd(p *Plug) *Cmd { return &Cmd{ - plugHandle:p, + plugHandle: p, } } @@ -55,27 +55,27 @@ func (cm *Cmd) parseInternalCmd() { cmd := strings.Trim(arg, InternalCmdPrefix) switch cmd { - case InternalCmdHelp: - cm.printHelpMessage() - break - case InternalCmdEnv: - fmt.Println("External plug-in path : "+cm.plugHandle.dir) - break - case InternalCmdList: - cm.plugHandle.PrintList() - break - case InternalCmdVer: - fmt.Println(cxt.Version) - break - case InternalDevice: - cm.printDevice() - break + case InternalCmdHelp: + cm.printHelpMessage() + break + case InternalCmdEnv: + fmt.Println("External plug-in path : " + cm.plugHandle.dir) + break + case InternalCmdList: + cm.plugHandle.PrintList() + break + case InternalCmdVer: + fmt.Println(cxt.Version) + break + case InternalDevice: + cm.printDevice() + break } os.Exit(1) } //usage -func (cm *Cmd) printHelpMessage() { +func (cm *Cmd) printHelpMessage() { fmt.Println("==================================================================================") fmt.Println("[Usage]") @@ -85,6 +85,7 @@ func (cm *Cmd) printHelpMessage() { fmt.Println(" [exp]") fmt.Println(" go-sniffer en0 redis Capture redis packet") fmt.Println(" go-sniffer en0 mysql -p 3306 Capture mysql packet") + fmt.Println(" go-sniffer en0 mssql -p 1433 Capture mssql packet") fmt.Println() fmt.Println(" go-sniffer --[commend]") fmt.Println(" --help \"this page\"") @@ -104,21 +105,21 @@ func (cm *Cmd) printHelpMessage() { func (cm *Cmd) printPlugList() { l := len(cm.plugHandle.InternalPlugList) l += len(cm.plugHandle.ExternalPlugList) - fmt.Println("# Number of plug-ins : "+strconv.Itoa(l)) + fmt.Println("# Number of plug-ins : " + strconv.Itoa(l)) } //print device func (cm *Cmd) printDevice() { - ifaces, err:= net.Interfaces() + ifaces, err := net.Interfaces() if err != nil { panic(err) } for _, iface := range ifaces { addrs, _ := iface.Addrs() - for _,a:=range addrs { + for _, a := range addrs { if ipnet, ok := a.(*net.IPNet); ok { if ip4 := ipnet.IP.To4(); ip4 != nil { - fmt.Println("[device] : "+iface.Name+" : "+iface.HardwareAddr.String()+" "+ip4.String()) + fmt.Println("[device] : " + iface.Name + " : " + iface.HardwareAddr.String() + " " + ip4.String()) } } } @@ -126,7 +127,7 @@ func (cm *Cmd) printDevice() { } //Parameters needed for plug-ins -func (cm *Cmd) parsePlugCmd() { +func (cm *Cmd) parsePlugCmd() { if len(os.Args) < 3 { fmt.Println("not found [Plug-in name]") @@ -134,12 +135,8 @@ func (cm *Cmd) parsePlugCmd() { os.Exit(1) } - cm.Device = os.Args[1] - plugName := os.Args[2] - plugParams:= os.Args[3:] + cm.Device = os.Args[1] + plugName := os.Args[2] + plugParams := os.Args[3:] cm.plugHandle.SetOption(plugName, plugParams) } - - - - diff --git a/core/plug.go b/core/plug.go index ebf8475..4b2a1e4 100644 --- a/core/plug.go +++ b/core/plug.go @@ -8,11 +8,11 @@ import ( "path/filepath" "plugin" - hp "github.com/40t/go-sniffer/plugSrc/http/build" - mongodb "github.com/40t/go-sniffer/plugSrc/mongodb/build" - redis "github.com/40t/go-sniffer/plugSrc/redis/build" + hp "github.com/feiin/go-sniffer/plugSrc/http/build" + mongodb "github.com/feiin/go-sniffer/plugSrc/mongodb/build" mssql "github.com/feiin/go-sniffer/plugSrc/mssql/build" mysql "github.com/feiin/go-sniffer/plugSrc/mysql/build" + redis "github.com/feiin/go-sniffer/plugSrc/redis/build" "github.com/google/gopacket" ) diff --git a/plugSrc/http/build/entry.go b/plugSrc/http/build/entry.go index 7682f04..050a1c0 100644 --- a/plugSrc/http/build/entry.go +++ b/plugSrc/http/build/entry.go @@ -1,28 +1,29 @@ package build import ( - "github.com/google/gopacket" - "io" - "log" - "strconv" - "fmt" - "os" "bufio" + "fmt" + "io" "net/http" + "os" + "strconv" + "time" + + "github.com/google/gopacket" ) const ( - Port = 80 - Version = "0.1" + Port = 80 + Version = "0.1" ) const ( - CmdPort = "-p" + CmdPort = "-p" ) type H struct { - port int - version string + port int + version string } var hp *H @@ -30,8 +31,8 @@ var hp *H func NewInstance() *H { if hp == nil { hp = &H{ - port :Port, - version:Version, + port: Port, + version: Version, } } return hp @@ -58,39 +59,39 @@ func (m *H) ResolveStream(net, transport gopacket.Flow, buf io.Reader) { msg += req.Form.Encode() msg += "]" - log.Println(msg) - + fmt.Printf(time.Now().Format("2006-01-02 15:04:05.000") + " | " + msg) + // log.Println() req.Body.Close() } } } func (m *H) BPFFilter() string { - return "tcp and port "+strconv.Itoa(m.port); + return "tcp and port " + strconv.Itoa(m.port) } func (m *H) Version() string { return Version } -func (m *H) SetFlag(flg []string) { +func (m *H) SetFlag(flg []string) { c := len(flg) if c == 0 { return } - if c >> 1 == 0 { + if c>>1 == 0 { fmt.Println("ERR : Http Number of parameters") os.Exit(1) } - for i:=0;i 0 { io.CopyN(&buffer, r, int64(p.length-8)) - } p.payload = buffer.Bytes() return p, nil @@ -201,9 +200,20 @@ func readStream(r io.Reader) (*packet, error) { func (m *stream) resolveClientPacket(p *packet) { var msg string + switch p.packetType { case 1: - msg = fmt.Sprintf("【query】 %s", string(p.payload)) + headerLength := int(binary.LittleEndian.Uint32(p.payload[0:4])) + // fmt.Printf("headers %d\n", headerLength) + if headerLength > 22 { + //not exists headers + msg = fmt.Sprintf("【query】 %s", string(p.payload)) + + } else { + //tds 7.2+ + msg = fmt.Sprintf("【query】 %s", string(p.payload[headerLength:])) + } + case 4: msg = fmt.Sprintf("【query】 %s", "Tabular result") @@ -218,10 +228,10 @@ func (m *stream) resolveServerPacket(p *packet) { switch p.packetType { case 4: var b = int32(p.payload[0]) - msg = fmt.Sprintf("【OK】 %d", b) + msg = fmt.Sprintf("【OK】%d", b) } - parseToken(p.payload) + // parseToken(p.payload) fmt.Println(GetNowStr(false), msg) } diff --git a/plugSrc/mssql/build/token.go b/plugSrc/mssql/build/token.go index dc834c1..8ed03a2 100644 --- a/plugSrc/mssql/build/token.go +++ b/plugSrc/mssql/build/token.go @@ -2,6 +2,7 @@ package build import ( "encoding/binary" + "fmt" ) type token byte @@ -24,24 +25,339 @@ const ( tokenDoneInProc token = 255 ) -func parseToken(buf []byte) string { +// fixed-length data types +// http://msdn.microsoft.com/en-us/library/dd341171.aspx +const ( + typeNull = 0x1f + typeInt1 = 0x30 + typeBit = 0x32 + typeInt2 = 0x34 + typeInt4 = 0x38 + typeDateTim4 = 0x3a + typeFlt4 = 0x3b + typeMoney = 0x3c + typeDateTime = 0x3d + typeFlt8 = 0x3e + typeMoney4 = 0x7a + typeInt8 = 0x7f +) + +// variable-length data types +// http://msdn.microsoft.com/en-us/library/dd358341.aspx +const ( + // byte len types + typeGuid = 0x24 + typeIntN = 0x26 + typeDecimal = 0x37 // legacy + typeNumeric = 0x3f // legacy + typeBitN = 0x68 + typeDecimalN = 0x6a + typeNumericN = 0x6c + typeFltN = 0x6d + typeMoneyN = 0x6e + typeDateTimeN = 0x6f + typeDateN = 0x28 + typeTimeN = 0x29 + typeDateTime2N = 0x2a + typeDateTimeOffsetN = 0x2b + typeChar = 0x2f // legacy + typeVarChar = 0x27 // legacy + typeBinary = 0x2d // legacy + typeVarBinary = 0x25 // legacy + + // short length types + typeBigVarBin = 0xa5 + typeBigVarChar = 0xa7 + typeBigBinary = 0xad + typeBigChar = 0xaf + typeNVarChar = 0xe7 + typeNChar = 0xef + typeXml = 0xf1 + typeUdt = 0xf0 + typeTvp = 0xf3 + + // long length types + typeText = 0x23 + typeImage = 0x22 + typeNText = 0x63 + typeVariant = 0x62 +) + +type columnStruct struct { + UserType uint32 + Flags uint16 + ColName string + Size int + TypeId int +} + +func readTypeInfo(pos int, buf []byte, column *columnStruct) (count int) { + typeId := buf[pos+1] + + count = 1 + pos++ + column.TypeId = int(typeId) + switch typeId { + case typeNull, typeInt1, typeBit, typeInt2, typeInt4, typeDateTim4, + typeFlt4, typeMoney, typeDateTime, typeFlt8, typeMoney4, typeInt8: + count += 0 + switch typeId { + case typeNull: + column.Size = 0 + case typeInt1, typeBit: + column.Size = 1 + case typeInt2: + column.Size = 2 + case typeInt4, typeDateTim4, typeFlt4, typeMoney4: + column.Size = 4 + case typeMoney, typeDateTime, typeFlt8, typeInt8: + column.Size = 8 + } + // those are fixed length types + default: // all others are VARLENTYPE + count += readVarLen(int(typeId), pos, buf, column) + } + return count +} + +func readVarLen(typeId int, pos int, buf []byte, column *columnStruct) (count int) { + count = 0 + switch typeId { + case typeDateN: + column.Size = 3 + case typeTimeN, typeDateTime2N, typeDateTimeOffsetN: + + pos += 1 //Scale + count += 1 + + scale := buf[pos] + + switch scale { + case 0, 1, 2: + column.Size = 3 + case 3, 4: + column.Size = 4 + case 5, 6, 7: + column.Size = 5 + } + + switch typeId { + case typeDateTime2N: + column.Size += 3 + case typeDateTimeOffsetN: + column.Size += 5 + } + + case typeGuid, typeIntN, typeDecimal, typeNumeric, + typeBitN, typeDecimalN, typeNumericN, typeFltN, + typeMoneyN, typeDateTimeN, typeChar, + typeVarChar, typeBinary, typeVarBinary: + // byle len types + + pos += 1 //byle len types + count += 1 + + column.Size = int(buf[pos]) //size + switch typeId { + case typeDecimal, typeNumeric, typeDecimalN, typeNumericN: + pos += 2 //byle len types + count += 2 + } + case typeXml: + pos += 1 //byle len types + count += 1 + schemaPresent := buf[pos] + + if schemaPresent != 0 { + pos += 1 //byle len types + count += 1 + l := int(buf[pos]) // dbname + count += l + pos += l + + pos += 1 // owning schema + count += 1 + l = int(buf[pos]) // owning schema + count += l + pos += l + + // xml schema collection + pos += 1 + l = int(binary.LittleEndian.Uint16(buf[pos : pos+2])) + pos += 1 + count += 2 + pos += l * 2 + count += l * 2 + } + case typeUdt: + pos += 1 + l := int(binary.LittleEndian.Uint16(buf[pos : pos+2])) + pos += 1 + count += 2 + //ti.Size + column.Size = l + + //DBName + pos += 1 // owning schema + count += 1 + l = int(buf[pos]) + count += l + pos += l + + //SchemaName + pos += 1 // owning schema + count += 1 + l = int(buf[pos]) + count += l + pos += l + + //TypeName + pos += 1 // owning schema + count += 1 + l = int(buf[pos]) + count += l + pos += l + + //AssemblyQualifiedName + pos += 1 + l = int(binary.LittleEndian.Uint16(buf[pos : pos+2])) + pos += 1 + count += 2 + pos += l * 2 + count += l * 2 + + case typeBigVarBin, typeBigVarChar, typeBigBinary, typeBigChar, + typeNVarChar, typeNChar: + // short len types + pos += 1 + l := int(binary.LittleEndian.Uint16(buf[pos : pos+2])) + pos += 1 + count += 2 + + column.Size = l + + switch typeId { + case typeBigVarChar, typeBigChar, typeNVarChar, typeNChar: + pos += 5 + count += 5 + } + + case typeText, typeImage, typeNText, typeVariant: + // LONGLEN_TYPE + + l := int(binary.LittleEndian.Uint16(buf[pos+1 : pos+5])) + column.Size = l + + pos += 4 + count += 4 + + switch typeId { + case typeText, typeNText: + pos += 6 + count += 6 + // ignore tablenames + numparts := int(buf[pos]) + for i := 0; i < numparts; i++ { + pos += 1 + l := int(binary.LittleEndian.Uint16(buf[pos : pos+2])) + pos += 1 + count += 2 + pos += l + count += l + } + + case typeImage: + // ignore tablenames + pos++ + count++ + numparts := int(buf[pos]) + for i := 0; i < numparts; i++ { + pos += 1 + l := int(binary.LittleEndian.Uint16(buf[pos : pos+2])) + pos += 1 + count += 2 + pos += l + count += l + } + } + default: + count += 0 + } + return count +} + +func parseToken(buf []byte) int { var pos = 0 length := 0 + rowCount := 0 + + var columns []columnStruct + for { - if len(buf) < pos+1 { - break - } + token := token(buf[pos]) + switch token { case tokenSSPI: pos += 1 - length = int(binary.LittleEndian.Uint16(buf[pos+1 : pos+2])) + length = int(binary.LittleEndian.Uint16(buf[pos : pos+2])) + pos += 1 pos += length + case tokenReturnStatus: + pos += 4 + case tokenLoginAck: + pos += 1 + length = int(binary.LittleEndian.Uint16(buf[pos : pos+2])) + pos += 1 + pos += length + case tokenOrder: + pos += 1 + length = int(binary.LittleEndian.Uint16(buf[pos : pos+2])) + pos += 1 + pos += length + case tokenDoneInProc: + pos += 5 + rowCount = int(binary.LittleEndian.Uint64(buf[pos : pos+8])) + pos += 8 + pos += rowCount + case tokenDone, tokenDoneProc: + pos += 5 + rowCount = int(binary.LittleEndian.Uint64(buf[pos : pos+8])) + pos += 8 + pos += rowCount + case tokenColMetadata: + pos += 1 + //http://msdn.microsoft.com/en-us/library/dd357363.aspx + count := int(binary.LittleEndian.Uint16(buf[pos : pos+2])) + columns = make([]columnStruct, count) + pos += 1 + + if count > 0 { + for i := 0; i < count; i++ { + + // fmt.Printf("colums %d %d", i, count) + column := &columns[i] + // x := pos + pos += 4 //UserType + pos += 2 //Flags + pos += readTypeInfo(pos, buf, column) + + //ColName + pos += 1 // owning schema + l := int(buf[pos]) + pos += l * 2 + + // fmt.Printf("%d, %d ,%x\n", x, pos, buf[x+1:pos+1]) + + fmt.Print("%v", column) + } + } + case tokenRow: } break } - return "" + return rowCount } diff --git a/plugSrc/redis/build/entry.go b/plugSrc/redis/build/entry.go index 6116e89..e8085d0 100644 --- a/plugSrc/redis/build/entry.go +++ b/plugSrc/redis/build/entry.go @@ -1,33 +1,35 @@ package build import ( - "github.com/google/gopacket" - "io" - "strings" - "fmt" - "strconv" "bufio" + "fmt" + "io" + "strconv" + "strings" + "time" + + "github.com/google/gopacket" ) type Redis struct { - port int + port int version string - cmd chan string - done chan bool + cmd chan string + done chan bool } const ( - Port int = 6379 + Port int = 6379 Version string = "0.1" CmdPort string = "-p" ) -var redis = &Redis { - port:Port, - version:Version, +var redis = &Redis{ + port: Port, + version: Version, } -func NewInstance() *Redis{ +func NewInstance() *Redis { return redis } @@ -63,35 +65,35 @@ func (red Redis) ResolveStream(net, transport gopacket.Flow, r io.Reader) { l := string(line[1]) cmdCount, _ = strconv.Atoi(l) cmd = "" - for j := 0; j < cmdCount * 2; j++ { + for j := 0; j < cmdCount*2; j++ { c, _, _ := buf.ReadLine() - if j & 1 == 0 { + if j&1 == 0 { continue } cmd += " " + string(c) } - fmt.Println(cmd) + fmt.Println(time.Now().Format("2006-01-02 15:04:05.000") + " | " + cmd) } } /** - SetOption - */ -func (red *Redis) SetFlag(flg []string) { +SetOption +*/ +func (red *Redis) SetFlag(flg []string) { c := len(flg) if c == 0 { return } - if c >> 1 != 1 { + if c>>1 != 1 { panic("ERR : Redis num of params") } - for i:=0;i