forked from projectdiscovery/interactsh
/
smb_server.go
125 lines (113 loc) · 2.98 KB
/
smb_server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package server
import (
"bytes"
"fmt"
"github.com/JanHoffmannTU/interactsh/pkg/communication"
"io/ioutil"
"net"
"os"
"os/exec"
"strings"
"sync/atomic"
"time"
"github.com/JanHoffmannTU/interactsh/pkg/filewatcher"
jsoniter "github.com/json-iterator/go"
"github.com/projectdiscovery/fileutil"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/stringsutil"
)
var smbMonitorList map[string]string = map[string]string{
// search term : extract after
"INFO: ": "INFO: ",
}
// SMBServer is a smb wrapper server instance
type SMBServer struct {
options *Options
LogFile string
ipAddress net.IP
cmd *exec.Cmd
tmpFile string
}
// NewSMBServer returns a new SMB server.
func NewSMBServer(options *Options) (*SMBServer, error) {
server := &SMBServer{
options: options,
ipAddress: net.ParseIP(options.IPAddress),
}
return server, nil
}
// ListenAndServe listens on smb port
func (h *SMBServer) ListenAndServe(smbAlive chan bool) error {
smbAlive <- true
defer func() {
smbAlive <- false
}()
tmpFile, err := ioutil.TempFile("", "")
if err != nil {
return err
}
h.tmpFile = tmpFile.Name()
tmpFile.Close()
// execute smb_server.py - only works with ./interactsh-server
cmdLine := fmt.Sprintf("python3 smb_server.py %s %d", h.tmpFile, h.options.SmbPort)
args := strings.Fields(cmdLine)
h.cmd = exec.Command(args[0], args[1:]...)
err = h.cmd.Start()
if err != nil {
return err
}
// watch output file
outputFile := h.tmpFile
// wait until the file is created
for !fileutil.FileExists(outputFile) {
time.Sleep(1 * time.Second)
}
fw, err := filewatcher.New(filewatcher.Options{
Interval: time.Duration(5 * time.Second),
File: outputFile,
})
if err != nil {
return err
}
ch, err := fw.Watch()
if err != nil {
return err
}
// This fetches the content at each change.
go func() {
for data := range ch {
atomic.AddUint64(&h.options.Stats.Smb, 1)
for searchTerm, extractAfter := range smbMonitorList {
if strings.Contains(data, searchTerm) {
smbData, err := stringsutil.After(data, extractAfter)
if err != nil {
gologger.Warning().Msgf("Could not get smb interaction: %s\n", err)
continue
}
// Correlation id doesn't apply here, we skip encryption
interaction := &communication.Interaction{
Protocol: "smb",
RawRequest: smbData,
Timestamp: time.Now(),
}
buffer := &bytes.Buffer{}
if err := jsoniter.NewEncoder(buffer).Encode(interaction); err != nil {
gologger.Warning().Msgf("Could not encode smb interaction: %s\n", err)
} else {
gologger.Debug().Msgf("SMB Interaction: \n%s\n", buffer.String())
if err := h.options.Storage.AddInteractionWithId(h.options.Token, buffer.Bytes()); err != nil {
gologger.Warning().Msgf("Could not store dns interaction: %s\n", err)
}
}
}
}
}
}()
return h.cmd.Wait()
}
func (h *SMBServer) Close() {
_ = h.cmd.Process.Kill()
if fileutil.FileExists(h.tmpFile) {
os.RemoveAll(h.tmpFile)
}
}