From 5b68e3441834c86ff1ca9859498aac5632b64309 Mon Sep 17 00:00:00 2001 From: milinddethe15 Date: Thu, 30 Jan 2025 18:08:40 +0530 Subject: [PATCH 1/7] feat: Add responses for TCP Signed-off-by: milinddethe15 --- protocols/helpers/helpers.go | 5 +++ protocols/tcp/responses/110_tcp | 1 + protocols/tcp/responses/135_tcp | Bin 0 -> 60 bytes protocols/tcp/responses/139_tcp | Bin 0 -> 4 bytes protocols/tcp/responses/1433_tcp | Bin 0 -> 37 bytes protocols/tcp/responses/21000_tcp | 4 +++ protocols/tcp/responses/21_tcp | 1 + protocols/tcp/responses/25_tcp | 1 + protocols/tcp/responses/3306_tcp | Bin 0 -> 72 bytes protocols/tcp/responses/4444_tcp | 4 +++ protocols/tcp/responses/445_tcp | Bin 0 -> 447 bytes protocols/tcp/responses/4899_tcp | Bin 0 -> 46 bytes protocols/tcp/responses/5060_tcp | 26 ++++++++++++++ protocols/tcp/responses/5900_tcp | 1 + protocols/tcp/responses/8009_tcp | Bin 0 -> 785 bytes protocols/tcp/responses/80_tcp | 15 ++++++++ protocols/tcp/tcp.go | 57 ++++++++++++++++++++++++++++-- 17 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 protocols/tcp/responses/110_tcp create mode 100644 protocols/tcp/responses/135_tcp create mode 100644 protocols/tcp/responses/139_tcp create mode 100644 protocols/tcp/responses/1433_tcp create mode 100644 protocols/tcp/responses/21000_tcp create mode 100644 protocols/tcp/responses/21_tcp create mode 100644 protocols/tcp/responses/25_tcp create mode 100644 protocols/tcp/responses/3306_tcp create mode 100644 protocols/tcp/responses/4444_tcp create mode 100644 protocols/tcp/responses/445_tcp create mode 100644 protocols/tcp/responses/4899_tcp create mode 100644 protocols/tcp/responses/5060_tcp create mode 100644 protocols/tcp/responses/5900_tcp create mode 100644 protocols/tcp/responses/8009_tcp create mode 100644 protocols/tcp/responses/80_tcp diff --git a/protocols/helpers/helpers.go b/protocols/helpers/helpers.go index 79e9939..8344ef8 100644 --- a/protocols/helpers/helpers.go +++ b/protocols/helpers/helpers.go @@ -36,3 +36,8 @@ func StorePayload(data []byte) (string, error) { } return sha256Hash, nil } + +func HashData(data []byte) string { + hash := sha256.Sum256(data) + return hex.EncodeToString(hash[:]) +} diff --git a/protocols/tcp/responses/110_tcp b/protocols/tcp/responses/110_tcp new file mode 100644 index 0000000..4f60b24 --- /dev/null +++ b/protocols/tcp/responses/110_tcp @@ -0,0 +1 @@ ++OK diff --git a/protocols/tcp/responses/135_tcp b/protocols/tcp/responses/135_tcp new file mode 100644 index 0000000000000000000000000000000000000000..874699b52f7b4ce7a934f87493d9c79e0a3d422a GIT binary patch literal 60 zcmZQ&;9(YEU|_HTVn!goAa+4)%?$ \ No newline at end of file diff --git a/protocols/tcp/responses/21_tcp b/protocols/tcp/responses/21_tcp new file mode 100644 index 0000000..bb61546 --- /dev/null +++ b/protocols/tcp/responses/21_tcp @@ -0,0 +1 @@ +220 Welcome to localhost diff --git a/protocols/tcp/responses/25_tcp b/protocols/tcp/responses/25_tcp new file mode 100644 index 0000000..1a8bb06 --- /dev/null +++ b/protocols/tcp/responses/25_tcp @@ -0,0 +1 @@ +250 localhost ESMTP Postfix diff --git a/protocols/tcp/responses/3306_tcp b/protocols/tcp/responses/3306_tcp new file mode 100644 index 0000000000000000000000000000000000000000..15cf52dda1f94d2a24c1a41ec9a5bf59fff94ca1 GIT binary patch literal 72 zcmcC!U|`@f(KFC9GKqIdP0CEn(={|GPAp1KHPp??PiJ5Q%9k2j=UJ5|Br)hHa4-S+ NNPv}r0VKl2001KS3v~bh literal 0 HcmV?d00001 diff --git a/protocols/tcp/responses/4444_tcp b/protocols/tcp/responses/4444_tcp new file mode 100644 index 0000000..433f1db --- /dev/null +++ b/protocols/tcp/responses/4444_tcp @@ -0,0 +1,4 @@ +Microsoft Windows XP [Version 5.1.2600] +(C) Copyright 1985-2001 Microsoft Corp. + +C:\WINDOWS\system32> \ No newline at end of file diff --git a/protocols/tcp/responses/445_tcp b/protocols/tcp/responses/445_tcp new file mode 100644 index 0000000000000000000000000000000000000000..69c83a3c1a486a679eb82bfd1d5015b9316cdb87 GIT binary patch literal 447 zcmZQzUY7Gz~$=3-!EU=alI7(oQX-^UCMM`i`aIPE#g z*zuo1fZ@J5^Bc{7E^a*=Z(Q+B7l;C?c?mMOSd4+;zzlXwgE<5kSpGA-1ga}x*vH@( z;^P|}9KgT?UtnyzIpYjXNvQITrjXT1C0j<9YZPDvmiHO^{fKOv!x(u1}`dF3;>f8PoV$+ literal 0 HcmV?d00001 diff --git a/protocols/tcp/responses/4899_tcp b/protocols/tcp/responses/4899_tcp new file mode 100644 index 0000000000000000000000000000000000000000..3f57eaddc67304e018ba34b6e5c6c51641ed2f46 GIT binary patch literal 46 UcmZQ%U|>)MVgU{y0m66z01Ey9M*si- literal 0 HcmV?d00001 diff --git a/protocols/tcp/responses/5060_tcp b/protocols/tcp/responses/5060_tcp new file mode 100644 index 0000000..b43a35a --- /dev/null +++ b/protocols/tcp/responses/5060_tcp @@ -0,0 +1,26 @@ +SIP/2.0 200 OK +Via: SIP/2.0/TCP 127.0.0.1:5060;branch=1234567890 +From: sip:1234567890@127.0.0.1;tag=bad-012345 +To: ;tag=bad-012345 +Call-ID: 1348979872-797979222304855 +Cseq: 15 INVITE +Contact: sip:0987654321@127.0.0.1 +Content-Length: 401 +Content-Type: application/sdp + +v=0 +Anonymous 1234567890 9876543210 IN IP4 127.0.0.1 +s=SIGMA is the best +s=gotcha +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 36952 RTP/AVP 107 119 100 106 6 0 97 105 98 8 18 3 5 101 +a=rtpmap:107 BV32/16000 +a=rtpmap:119 BV32-FEC/16000 +a=rtpmap:100 SPEEX/16000 +a=rtpmap:106 SPEEX-FEC/16000 +a=rtpmap:97 SPEEX/8000 +a=rtpmap:105 SPEEX-FEC/8000 +a=rtpmap:98 iLBC/8000 +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-11 diff --git a/protocols/tcp/responses/5900_tcp b/protocols/tcp/responses/5900_tcp new file mode 100644 index 0000000..da549fe --- /dev/null +++ b/protocols/tcp/responses/5900_tcp @@ -0,0 +1 @@ +RFB 003.008 diff --git a/protocols/tcp/responses/8009_tcp b/protocols/tcp/responses/8009_tcp new file mode 100644 index 0000000000000000000000000000000000000000..5ff6c532c6a7c8b37848fdfd0d01053d7a2afe53 GIT binary patch literal 785 zcmah{QI69v5KUV+1HVJ~ZJV~~cA-rpb+tnLfDq&Yjx&udTsyL-Y`fJ;+yM^I>+r!P zI0<$_B~}9QktlvM@4d+zZ*HQ+lis&zFrUn$XmIXD&j=5c2->L?7tA`O^`5q)m(jT& z^-)LXK{U9YrqSl6|6|bqo;|M&r(=TbzBxqm>nB#tYm8F zn06zFR&G}hAf`hQGykMRDB;A7GIn_8FMT+Oa-uNN)rx4x72xSY+J zLjY%gg40C@rjNjR3pS6ij?FISrSiUBZmgt6I0=-spykvP|2a@;Y=w5IjmFhOmb9tl zS<>Yh((u_%{}-w6$b<#1m~-nmn8%RhS(9gFUigHwq|7fH`GAeFlqJ5{*59IYtnOOE zmbTrNF6CQv+{%We(XC1$5R8?z)Zq8<87)+@0v(7_SHOVptwl{>v9aj<7Ykf3Yk@qM zn5{8Xo!MI+v_QI+eiuPqyE$0FQ_^P2mk;8 literal 0 HcmV?d00001 diff --git a/protocols/tcp/responses/80_tcp b/protocols/tcp/responses/80_tcp new file mode 100644 index 0000000..9cb49c5 --- /dev/null +++ b/protocols/tcp/responses/80_tcp @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +Connection: close +Date: Sun, 27 Nov 2005 13:07:34 GMT +Server: Microsoft-IIS/6.0 +X-Powered-By: ASP.NET +X-AspNet-Version: 2.0.50727 +Accept-Ranges: bytes +Content-Length: 30 +Cache-Control: private +Content-Type: text/html; charset=utf-8 + + + + + diff --git a/protocols/tcp/tcp.go b/protocols/tcp/tcp.go index bbbcd29..23c09ef 100644 --- a/protocols/tcp/tcp.go +++ b/protocols/tcp/tcp.go @@ -3,6 +3,7 @@ package tcp import ( "context" "crypto/rand" + "embed" "encoding/hex" "fmt" "log/slog" @@ -28,6 +29,58 @@ type tcpServer struct { events []parsedTCP } +//go:embed responses/* +var embeddedFiles embed.FS + +var responseFileMap = map[uint16]string{ + 21: "responses/21_tcp", + 25: "responses/25_tcp", + 80: "responses/80_tcp", + 110: "responses/110_tcp", + 135: "responses/135_tcp", + 139: "responses/139_tcp", + 445: "responses/445_tcp", + 1433: "responses/1433_tcp", + 3306: "responses/3306_tcp", + 4444: "responses/4444_tcp", + 4899: "responses/4899_tcp", + 5060: "responses/5060_tcp", + 5900: "responses/5900_tcp", + 8009: "responses/8009_tcp", + 21000: "responses/21000_tcp", +} + +func (s *tcpServer) getResponse(port uint16) ([]byte, error) { + filePath, exists := responseFileMap[port] + if !exists { + return nil, fmt.Errorf("file not found for port: %v", port) + } + + return embeddedFiles.ReadFile(filePath) +} + +func (s *tcpServer) sendPortSpecificResponse(conn net.Conn, port uint16, logger interfaces.Logger) error { + response, err := s.getResponse(port) + if err != nil { + // If no specific response file exists, fall back to random data + logger.Debug("No specific response file found, sending random data", + slog.String("handler", "tcp"), + slog.Uint64("port", uint64(port))) + return s.sendRandom(conn) + } + + s.events = append(s.events, parsedTCP{ + Direction: "write", + PayloadHash: helpers.HashData(response), + Payload: response, + }) + + if _, err := conn.Write(response); err != nil { + return fmt.Errorf("failed to write response: %w", err) + } + return nil +} + func (s *tcpServer) sendRandom(conn net.Conn) error { randomInt, err := rand.Int(rand.Reader, big.NewInt(500)) if err != nil { @@ -114,8 +167,8 @@ func HandleTCP(ctx context.Context, conn net.Conn, md connection.Metadata, logge } } - // sending some random data - if err := server.sendRandom(conn); err != nil { + // Send port-specific or random response + if err := server.sendPortSpecificResponse(conn, md.TargetPort, logger); err != nil { logger.Error("write error", slog.String("handler", "tcp"), producer.ErrAttr(err)) } From f2ad60ef7eb6feb7a3d72a829d8dd8f1df84e60e Mon Sep 17 00:00:00 2001 From: milinddethe15 Date: Thu, 30 Jan 2025 23:47:39 +0530 Subject: [PATCH 2/7] add banners for service ports Signed-off-by: milinddethe15 --- protocols/tcp/banners/110_tcp | 1 + protocols/tcp/banners/135_tcp | Bin 0 -> 60 bytes protocols/tcp/banners/139_tcp | Bin 0 -> 4 bytes protocols/tcp/banners/1433_tcp | Bin 0 -> 37 bytes protocols/tcp/banners/21000_tcp | 4 +++ protocols/tcp/banners/21_tcp | 1 + protocols/tcp/banners/25_tcp | 1 + protocols/tcp/banners/3306_tcp | Bin 0 -> 72 bytes protocols/tcp/banners/4444_tcp | 4 +++ protocols/tcp/banners/445_tcp | Bin 0 -> 447 bytes protocols/tcp/banners/4899_tcp | Bin 0 -> 46 bytes protocols/tcp/banners/5060_tcp | 26 +++++++++++++++ protocols/tcp/banners/5900_tcp | 1 + protocols/tcp/banners/8009_tcp | Bin 0 -> 785 bytes protocols/tcp/banners/80_tcp | 15 +++++++++ protocols/tcp/banners/README.md | 1 + protocols/tcp/tcp.go | 57 +++++++++----------------------- 17 files changed, 69 insertions(+), 42 deletions(-) create mode 100644 protocols/tcp/banners/110_tcp create mode 100644 protocols/tcp/banners/135_tcp create mode 100644 protocols/tcp/banners/139_tcp create mode 100644 protocols/tcp/banners/1433_tcp create mode 100644 protocols/tcp/banners/21000_tcp create mode 100644 protocols/tcp/banners/21_tcp create mode 100644 protocols/tcp/banners/25_tcp create mode 100644 protocols/tcp/banners/3306_tcp create mode 100644 protocols/tcp/banners/4444_tcp create mode 100644 protocols/tcp/banners/445_tcp create mode 100644 protocols/tcp/banners/4899_tcp create mode 100644 protocols/tcp/banners/5060_tcp create mode 100644 protocols/tcp/banners/5900_tcp create mode 100644 protocols/tcp/banners/8009_tcp create mode 100644 protocols/tcp/banners/80_tcp create mode 100644 protocols/tcp/banners/README.md diff --git a/protocols/tcp/banners/110_tcp b/protocols/tcp/banners/110_tcp new file mode 100644 index 0000000..4f60b24 --- /dev/null +++ b/protocols/tcp/banners/110_tcp @@ -0,0 +1 @@ ++OK diff --git a/protocols/tcp/banners/135_tcp b/protocols/tcp/banners/135_tcp new file mode 100644 index 0000000000000000000000000000000000000000..874699b52f7b4ce7a934f87493d9c79e0a3d422a GIT binary patch literal 60 zcmZQ&;9(YEU|_HTVn!goAa+4)%?$ \ No newline at end of file diff --git a/protocols/tcp/banners/21_tcp b/protocols/tcp/banners/21_tcp new file mode 100644 index 0000000..bb61546 --- /dev/null +++ b/protocols/tcp/banners/21_tcp @@ -0,0 +1 @@ +220 Welcome to localhost diff --git a/protocols/tcp/banners/25_tcp b/protocols/tcp/banners/25_tcp new file mode 100644 index 0000000..1a8bb06 --- /dev/null +++ b/protocols/tcp/banners/25_tcp @@ -0,0 +1 @@ +250 localhost ESMTP Postfix diff --git a/protocols/tcp/banners/3306_tcp b/protocols/tcp/banners/3306_tcp new file mode 100644 index 0000000000000000000000000000000000000000..15cf52dda1f94d2a24c1a41ec9a5bf59fff94ca1 GIT binary patch literal 72 zcmcC!U|`@f(KFC9GKqIdP0CEn(={|GPAp1KHPp??PiJ5Q%9k2j=UJ5|Br)hHa4-S+ NNPv}r0VKl2001KS3v~bh literal 0 HcmV?d00001 diff --git a/protocols/tcp/banners/4444_tcp b/protocols/tcp/banners/4444_tcp new file mode 100644 index 0000000..433f1db --- /dev/null +++ b/protocols/tcp/banners/4444_tcp @@ -0,0 +1,4 @@ +Microsoft Windows XP [Version 5.1.2600] +(C) Copyright 1985-2001 Microsoft Corp. + +C:\WINDOWS\system32> \ No newline at end of file diff --git a/protocols/tcp/banners/445_tcp b/protocols/tcp/banners/445_tcp new file mode 100644 index 0000000000000000000000000000000000000000..69c83a3c1a486a679eb82bfd1d5015b9316cdb87 GIT binary patch literal 447 zcmZQzUY7Gz~$=3-!EU=alI7(oQX-^UCMM`i`aIPE#g z*zuo1fZ@J5^Bc{7E^a*=Z(Q+B7l;C?c?mMOSd4+;zzlXwgE<5kSpGA-1ga}x*vH@( z;^P|}9KgT?UtnyzIpYjXNvQITrjXT1C0j<9YZPDvmiHO^{fKOv!x(u1}`dF3;>f8PoV$+ literal 0 HcmV?d00001 diff --git a/protocols/tcp/banners/4899_tcp b/protocols/tcp/banners/4899_tcp new file mode 100644 index 0000000000000000000000000000000000000000..3f57eaddc67304e018ba34b6e5c6c51641ed2f46 GIT binary patch literal 46 UcmZQ%U|>)MVgU{y0m66z01Ey9M*si- literal 0 HcmV?d00001 diff --git a/protocols/tcp/banners/5060_tcp b/protocols/tcp/banners/5060_tcp new file mode 100644 index 0000000..b43a35a --- /dev/null +++ b/protocols/tcp/banners/5060_tcp @@ -0,0 +1,26 @@ +SIP/2.0 200 OK +Via: SIP/2.0/TCP 127.0.0.1:5060;branch=1234567890 +From: sip:1234567890@127.0.0.1;tag=bad-012345 +To: ;tag=bad-012345 +Call-ID: 1348979872-797979222304855 +Cseq: 15 INVITE +Contact: sip:0987654321@127.0.0.1 +Content-Length: 401 +Content-Type: application/sdp + +v=0 +Anonymous 1234567890 9876543210 IN IP4 127.0.0.1 +s=SIGMA is the best +s=gotcha +c=IN IP4 127.0.0.1 +t=0 0 +m=audio 36952 RTP/AVP 107 119 100 106 6 0 97 105 98 8 18 3 5 101 +a=rtpmap:107 BV32/16000 +a=rtpmap:119 BV32-FEC/16000 +a=rtpmap:100 SPEEX/16000 +a=rtpmap:106 SPEEX-FEC/16000 +a=rtpmap:97 SPEEX/8000 +a=rtpmap:105 SPEEX-FEC/8000 +a=rtpmap:98 iLBC/8000 +a=rtpmap:101 telephone-event/8000 +a=fmtp:101 0-11 diff --git a/protocols/tcp/banners/5900_tcp b/protocols/tcp/banners/5900_tcp new file mode 100644 index 0000000..da549fe --- /dev/null +++ b/protocols/tcp/banners/5900_tcp @@ -0,0 +1 @@ +RFB 003.008 diff --git a/protocols/tcp/banners/8009_tcp b/protocols/tcp/banners/8009_tcp new file mode 100644 index 0000000000000000000000000000000000000000..5ff6c532c6a7c8b37848fdfd0d01053d7a2afe53 GIT binary patch literal 785 zcmah{QI69v5KUV+1HVJ~ZJV~~cA-rpb+tnLfDq&Yjx&udTsyL-Y`fJ;+yM^I>+r!P zI0<$_B~}9QktlvM@4d+zZ*HQ+lis&zFrUn$XmIXD&j=5c2->L?7tA`O^`5q)m(jT& z^-)LXK{U9YrqSl6|6|bqo;|M&r(=TbzBxqm>nB#tYm8F zn06zFR&G}hAf`hQGykMRDB;A7GIn_8FMT+Oa-uNN)rx4x72xSY+J zLjY%gg40C@rjNjR3pS6ij?FISrSiUBZmgt6I0=-spykvP|2a@;Y=w5IjmFhOmb9tl zS<>Yh((u_%{}-w6$b<#1m~-nmn8%RhS(9gFUigHwq|7fH`GAeFlqJ5{*59IYtnOOE zmbTrNF6CQv+{%We(XC1$5R8?z)Zq8<87)+@0v(7_SHOVptwl{>v9aj<7Ykf3Yk@qM zn5{8Xo!MI+v_QI+eiuPqyE$0FQ_^P2mk;8 literal 0 HcmV?d00001 diff --git a/protocols/tcp/banners/80_tcp b/protocols/tcp/banners/80_tcp new file mode 100644 index 0000000..9cb49c5 --- /dev/null +++ b/protocols/tcp/banners/80_tcp @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +Connection: close +Date: Sun, 27 Nov 2005 13:07:34 GMT +Server: Microsoft-IIS/6.0 +X-Powered-By: ASP.NET +X-AspNet-Version: 2.0.50727 +Accept-Ranges: bytes +Content-Length: 30 +Cache-Control: private +Content-Type: text/html; charset=utf-8 + + + + + diff --git a/protocols/tcp/banners/README.md b/protocols/tcp/banners/README.md new file mode 100644 index 0000000..d54fd21 --- /dev/null +++ b/protocols/tcp/banners/README.md @@ -0,0 +1 @@ +Service banners are sourced from: https://github.com/armedpot/honeytrap/tree/master/etc/responses. \ No newline at end of file diff --git a/protocols/tcp/tcp.go b/protocols/tcp/tcp.go index 23c09ef..46e4cef 100644 --- a/protocols/tcp/tcp.go +++ b/protocols/tcp/tcp.go @@ -29,54 +29,24 @@ type tcpServer struct { events []parsedTCP } -//go:embed responses/* -var embeddedFiles embed.FS - -var responseFileMap = map[uint16]string{ - 21: "responses/21_tcp", - 25: "responses/25_tcp", - 80: "responses/80_tcp", - 110: "responses/110_tcp", - 135: "responses/135_tcp", - 139: "responses/139_tcp", - 445: "responses/445_tcp", - 1433: "responses/1433_tcp", - 3306: "responses/3306_tcp", - 4444: "responses/4444_tcp", - 4899: "responses/4899_tcp", - 5060: "responses/5060_tcp", - 5900: "responses/5900_tcp", - 8009: "responses/8009_tcp", - 21000: "responses/21000_tcp", -} - -func (s *tcpServer) getResponse(port uint16) ([]byte, error) { - filePath, exists := responseFileMap[port] - if !exists { - return nil, fmt.Errorf("file not found for port: %v", port) - } +//go:embed banners/* +var bannerFiles embed.FS - return embeddedFiles.ReadFile(filePath) -} - -func (s *tcpServer) sendPortSpecificResponse(conn net.Conn, port uint16, logger interfaces.Logger) error { - response, err := s.getResponse(port) +func (s *tcpServer) sendBanner(conn net.Conn, port uint16) error { + bannerPath := fmt.Sprintf("banners/%d_tcp", port) + banner, err := bannerFiles.ReadFile(bannerPath) if err != nil { - // If no specific response file exists, fall back to random data - logger.Debug("No specific response file found, sending random data", - slog.String("handler", "tcp"), - slog.Uint64("port", uint64(port))) - return s.sendRandom(conn) + return fmt.Errorf("failed to get banner: %w", err) } s.events = append(s.events, parsedTCP{ Direction: "write", - PayloadHash: helpers.HashData(response), - Payload: response, + PayloadHash: helpers.HashData(banner), + Payload: banner, }) - if _, err := conn.Write(response); err != nil { - return fmt.Errorf("failed to write response: %w", err) + if _, err := conn.Write(banner); err != nil { + return fmt.Errorf("failed to write banner: %w", err) } return nil } @@ -151,6 +121,9 @@ func HandleTCP(ctx context.Context, conn net.Conn, md connection.Metadata, logge if err := h.UpdateConnectionTimeout(ctx, conn); err != nil { return err } + if err := server.sendBanner(conn, md.TargetPort); err != nil { + logger.Error("write error", slog.String("handler", "tcp"), producer.ErrAttr(err)) + } n, err := conn.Read(buffer) if err != nil { logger.Error("read error", slog.String("handler", "tcp"), producer.ErrAttr(err)) @@ -167,8 +140,8 @@ func HandleTCP(ctx context.Context, conn net.Conn, md connection.Metadata, logge } } - // Send port-specific or random response - if err := server.sendPortSpecificResponse(conn, md.TargetPort, logger); err != nil { + // sending some random data + if err := server.sendRandom(conn); err != nil { logger.Error("write error", slog.String("handler", "tcp"), producer.ErrAttr(err)) } From beeb3018ed039cc6524a58d440795ba86e6e49b7 Mon Sep 17 00:00:00 2001 From: milinddethe15 Date: Fri, 31 Jan 2025 15:15:27 +0530 Subject: [PATCH 3/7] handle service banner Signed-off-by: milinddethe15 --- protocols/protocols.go | 3 +++ protocols/tcp/banners.go | 22 ++++++++++++++++++++++ protocols/tcp/tcp.go | 26 -------------------------- 3 files changed, 25 insertions(+), 26 deletions(-) create mode 100644 protocols/tcp/banners.go diff --git a/protocols/protocols.go b/protocols/protocols.go index 31e9087..a5b3992 100644 --- a/protocols/protocols.go +++ b/protocols/protocols.go @@ -66,6 +66,9 @@ func MapTCPProtocolHandlers(log interfaces.Logger, h interfaces.Honeypot) map[st return tcp.HandleADB(ctx, conn, md, log, h) } protocolHandlers["tcp"] = func(ctx context.Context, conn net.Conn, md connection.Metadata) error { + if err := tcp.SendBanner(conn, md.TargetPort); err != nil { + log.Error("failed to send service banner", producer.ErrAttr(err)) + } snip, bufConn, err := Peek(conn, 4) if err != nil { if err := conn.Close(); err != nil { diff --git a/protocols/tcp/banners.go b/protocols/tcp/banners.go new file mode 100644 index 0000000..96cd7cd --- /dev/null +++ b/protocols/tcp/banners.go @@ -0,0 +1,22 @@ +package tcp + +import ( + "embed" + "fmt" + "net" +) + +//go:embed banners/* +var bannerFiles embed.FS + +func SendBanner(conn net.Conn, port uint16) error { + bannerPath := fmt.Sprintf("banners/%d_tcp", port) + banner, err := bannerFiles.ReadFile(bannerPath) + if err != nil { + return fmt.Errorf("failed to get banner: %w", err) + } + if _, err := conn.Write(banner); err != nil { + return fmt.Errorf("failed to write banner: %w", err) + } + return nil +} diff --git a/protocols/tcp/tcp.go b/protocols/tcp/tcp.go index 46e4cef..bbbcd29 100644 --- a/protocols/tcp/tcp.go +++ b/protocols/tcp/tcp.go @@ -3,7 +3,6 @@ package tcp import ( "context" "crypto/rand" - "embed" "encoding/hex" "fmt" "log/slog" @@ -29,28 +28,6 @@ type tcpServer struct { events []parsedTCP } -//go:embed banners/* -var bannerFiles embed.FS - -func (s *tcpServer) sendBanner(conn net.Conn, port uint16) error { - bannerPath := fmt.Sprintf("banners/%d_tcp", port) - banner, err := bannerFiles.ReadFile(bannerPath) - if err != nil { - return fmt.Errorf("failed to get banner: %w", err) - } - - s.events = append(s.events, parsedTCP{ - Direction: "write", - PayloadHash: helpers.HashData(banner), - Payload: banner, - }) - - if _, err := conn.Write(banner); err != nil { - return fmt.Errorf("failed to write banner: %w", err) - } - return nil -} - func (s *tcpServer) sendRandom(conn net.Conn) error { randomInt, err := rand.Int(rand.Reader, big.NewInt(500)) if err != nil { @@ -121,9 +98,6 @@ func HandleTCP(ctx context.Context, conn net.Conn, md connection.Metadata, logge if err := h.UpdateConnectionTimeout(ctx, conn); err != nil { return err } - if err := server.sendBanner(conn, md.TargetPort); err != nil { - logger.Error("write error", slog.String("handler", "tcp"), producer.ErrAttr(err)) - } n, err := conn.Read(buffer) if err != nil { logger.Error("read error", slog.String("handler", "tcp"), producer.ErrAttr(err)) From 97785ca50af27f703c3cd73029889e6950cb21d9 Mon Sep 17 00:00:00 2001 From: milinddethe15 Date: Thu, 6 Feb 2025 02:16:06 +0530 Subject: [PATCH 4/7] send banner after timeout Signed-off-by: milinddethe15 --- protocols/protocols.go | 15 ++++++++++++--- protocols/tcp/banners.go | 22 +++++++++++++++++++--- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/protocols/protocols.go b/protocols/protocols.go index a5b3992..de01261 100644 --- a/protocols/protocols.go +++ b/protocols/protocols.go @@ -3,8 +3,10 @@ package protocols import ( "bytes" "context" + "errors" "net" "strings" + "time" "github.com/mushorg/glutton/connection" "github.com/mushorg/glutton/producer" @@ -66,10 +68,17 @@ func MapTCPProtocolHandlers(log interfaces.Logger, h interfaces.Honeypot) map[st return tcp.HandleADB(ctx, conn, md, log, h) } protocolHandlers["tcp"] = func(ctx context.Context, conn net.Conn, md connection.Metadata) error { - if err := tcp.SendBanner(conn, md.TargetPort); err != nil { - log.Error("failed to send service banner", producer.ErrAttr(err)) - } + conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond)) snip, bufConn, err := Peek(conn, 4) + var netErr net.Error + if errors.As(err, &netErr) && netErr.Timeout() { + if err := tcp.SendBanner(md.TargetPort, conn, md, log, h); err != nil { + log.Error("Failed to send service banner", producer.ErrAttr(err)) + } + conn.SetReadDeadline(time.Time{}) + return tcp.HandleTCP(ctx, conn, md, log, h) + } + conn.SetReadDeadline(time.Time{}) if err != nil { if err := conn.Close(); err != nil { log.Error("failed to close connection", producer.ErrAttr(err)) diff --git a/protocols/tcp/banners.go b/protocols/tcp/banners.go index 96cd7cd..b2a3b04 100644 --- a/protocols/tcp/banners.go +++ b/protocols/tcp/banners.go @@ -3,20 +3,36 @@ package tcp import ( "embed" "fmt" + "io" + "log/slog" "net" + + "github.com/mushorg/glutton/connection" + "github.com/mushorg/glutton/producer" + "github.com/mushorg/glutton/protocols/interfaces" ) //go:embed banners/* var bannerFiles embed.FS -func SendBanner(conn net.Conn, port uint16) error { +// SendBanner retrieves and sends service banner for the specified port. +func SendBanner(port uint16, conn net.Conn, md connection.Metadata, logger interfaces.Logger, h interfaces.Honeypot) error { bannerPath := fmt.Sprintf("banners/%d_tcp", port) - banner, err := bannerFiles.ReadFile(bannerPath) + banner, err := bannerFiles.Open(bannerPath) if err != nil { return fmt.Errorf("failed to get banner: %w", err) } - if _, err := conn.Write(banner); err != nil { + defer banner.Close() + + bannerData, err := io.ReadAll(banner) + if err != nil { + return fmt.Errorf("failed to read banner content: %w", err) + } + if _, err := conn.Write(bannerData); err != nil { return fmt.Errorf("failed to write banner: %w", err) } + if err = h.ProduceTCP("banner", conn, md, bannerData, nil); err != nil { + logger.Error("Failed to produce message", producer.ErrAttr(err), slog.String("handler", "banner")) + } return nil } From 8279706830bac741b56b2981f1f5f981e2236b92 Mon Sep 17 00:00:00 2001 From: milinddethe15 Date: Sat, 15 Feb 2025 17:14:01 +0530 Subject: [PATCH 5/7] log if error Signed-off-by: milinddethe15 --- protocols/protocols.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/protocols/protocols.go b/protocols/protocols.go index de01261..b14622c 100644 --- a/protocols/protocols.go +++ b/protocols/protocols.go @@ -68,23 +68,25 @@ func MapTCPProtocolHandlers(log interfaces.Logger, h interfaces.Honeypot) map[st return tcp.HandleADB(ctx, conn, md, log, h) } protocolHandlers["tcp"] = func(ctx context.Context, conn net.Conn, md connection.Metadata) error { - conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond)) + if err := conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond)); err != nil { + log.Error("failed to set read deadline", producer.ErrAttr(err)) + } snip, bufConn, err := Peek(conn, 4) var netErr net.Error if errors.As(err, &netErr) && netErr.Timeout() { if err := tcp.SendBanner(md.TargetPort, conn, md, log, h); err != nil { log.Error("Failed to send service banner", producer.ErrAttr(err)) } - conn.SetReadDeadline(time.Time{}) + if err := conn.SetReadDeadline(time.Time{}); err != nil { + log.Error("failed to reset read deadline", producer.ErrAttr(err)) + } return tcp.HandleTCP(ctx, conn, md, log, h) } - conn.SetReadDeadline(time.Time{}) + if err := conn.SetReadDeadline(time.Time{}); err != nil { + log.Error("failed to reset read deadline", producer.ErrAttr(err)) + } if err != nil { - if err := conn.Close(); err != nil { - log.Error("failed to close connection", producer.ErrAttr(err)) - } log.Debug("failed to peek connection", producer.ErrAttr(err)) - return nil } // poor mans check for HTTP request httpMap := map[string]bool{"GET ": true, "POST": true, "HEAD": true, "OPTI": true, "CONN": true} From f5caecaaecc3b37656cefb300185432531312179 Mon Sep 17 00:00:00 2001 From: milinddethe15 Date: Sat, 15 Feb 2025 18:47:29 +0530 Subject: [PATCH 6/7] update test Signed-off-by: milinddethe15 --- protocols/protocols.go | 2 +- protocols/protocols_test.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/protocols/protocols.go b/protocols/protocols.go index b14622c..6d03c5a 100644 --- a/protocols/protocols.go +++ b/protocols/protocols.go @@ -75,7 +75,7 @@ func MapTCPProtocolHandlers(log interfaces.Logger, h interfaces.Honeypot) map[st var netErr net.Error if errors.As(err, &netErr) && netErr.Timeout() { if err := tcp.SendBanner(md.TargetPort, conn, md, log, h); err != nil { - log.Error("Failed to send service banner", producer.ErrAttr(err)) + log.Info("Failed to send service banner", producer.ErrAttr(err)) } if err := conn.SetReadDeadline(time.Time{}); err != nil { log.Error("failed to reset read deadline", producer.ErrAttr(err)) diff --git a/protocols/protocols_test.go b/protocols/protocols_test.go index aedcd63..b916991 100644 --- a/protocols/protocols_test.go +++ b/protocols/protocols_test.go @@ -44,6 +44,10 @@ func TestMapTCPProtocolHandlers(t *testing.T) { h := &mocks.MockHoneypot{} l := &mocks.MockLogger{} l.EXPECT().Debug(mock.Anything, mock.Anything).Return().Maybe() + l.EXPECT().Info(mock.Anything, mock.Anything).Return().Maybe() + + h.EXPECT().UpdateConnectionTimeout(mock.Anything, mock.Anything).Return(nil).Maybe() + h.EXPECT().ProduceTCP(mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() m := MapTCPProtocolHandlers(l, h) require.NotEmpty(t, m, "should get a non-empty map") From 07e10d36c55499e855d7f01547869c9f81da0e97 Mon Sep 17 00:00:00 2001 From: milinddethe15 Date: Tue, 4 Mar 2025 02:32:05 +0530 Subject: [PATCH 7/7] handle conn Signed-off-by: milinddethe15 --- protocols/protocols.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/protocols/protocols.go b/protocols/protocols.go index 6d03c5a..ac5fe16 100644 --- a/protocols/protocols.go +++ b/protocols/protocols.go @@ -68,21 +68,18 @@ func MapTCPProtocolHandlers(log interfaces.Logger, h interfaces.Honeypot) map[st return tcp.HandleADB(ctx, conn, md, log, h) } protocolHandlers["tcp"] = func(ctx context.Context, conn net.Conn, md connection.Metadata) error { - if err := conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond)); err != nil { - log.Error("failed to set read deadline", producer.ErrAttr(err)) - } snip, bufConn, err := Peek(conn, 4) var netErr net.Error if errors.As(err, &netErr) && netErr.Timeout() { - if err := tcp.SendBanner(md.TargetPort, conn, md, log, h); err != nil { + if err := tcp.SendBanner(md.TargetPort, bufConn, md, log, h); err != nil { log.Info("Failed to send service banner", producer.ErrAttr(err)) } - if err := conn.SetReadDeadline(time.Time{}); err != nil { + if err := bufConn.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil { log.Error("failed to reset read deadline", producer.ErrAttr(err)) } - return tcp.HandleTCP(ctx, conn, md, log, h) + return tcp.HandleTCP(ctx, bufConn, md, log, h) } - if err := conn.SetReadDeadline(time.Time{}); err != nil { + if err := bufConn.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil { log.Error("failed to reset read deadline", producer.ErrAttr(err)) } if err != nil {