/
telnet.go
130 lines (109 loc) · 2.68 KB
/
telnet.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
126
127
128
129
130
package session
import (
"fmt"
"net"
"strconv"
"strings"
"sync"
"github.com/evilsocket/shellz/core"
"github.com/evilsocket/islazy/log"
"github.com/evilsocket/shellz/models"
"github.com/evilsocket/islazy/async"
"github.com/evilsocket/islazy/str"
"github.com/reiver/go-telnet"
)
type TelnetSession struct {
sync.Mutex
host string
client *telnet.Conn
timeouts core.Timeouts
}
func NewTelnet(sh models.Shell, timeouts core.Timeouts) (error, Session) {
var err error
t := &TelnetSession{
host: net.JoinHostPort(sh.Host, strconv.Itoa(sh.Port)),
timeouts: timeouts,
}
_, err = async.WithTimeout(timeouts.Connect, func() interface{} {
t.client, err = telnet.DialTo(t.host)
return err
})
if err != nil {
return err, nil
}
if sh.Identity.Username != "" && sh.Identity.Password != "" {
t.doReadUntil(": ")
if _, err = t.doWrite([]byte(sh.Identity.Username + "\n")); err != nil {
return fmt.Errorf("error while sending telnet username: %s", err), nil
}
t.doReadUntil(": ")
if _, err = t.doWrite([]byte(sh.Identity.Password + "\n")); err != nil {
return fmt.Errorf("error while sending telnet password: %s", err), nil
}
}
return nil, t
}
func (t *TelnetSession) Type() string {
return "telnet"
}
type rw struct {
e error
n int
}
func (t *TelnetSession) doRead(buf []byte) (int, error) {
obj, err := async.WithTimeout(t.timeouts.Read, func() interface{} {
n, err := t.client.Read(buf)
return rw{e: err, n: n}
})
if err != nil {
return -1, err
}
r := obj.(rw)
return r.n, r.e
}
func (t *TelnetSession) doWrite(buf []byte) (int, error) {
obj, err := async.WithTimeout(t.timeouts.Write, func() interface{} {
n, err := t.client.Write(buf)
return rw{e: err, n: n}
})
if err != nil {
return -1, err
}
w := obj.(rw)
return w.n, w.e
}
func (t *TelnetSession) doReadUntil(s string) (error, string) {
log.Debug("doReadUntil(%s)", s)
buff := ""
for buff = ""; !strings.Contains(buff, s); {
b := []byte{0}
if _, err := t.doRead(b); err != nil {
return err, ""
}
// log.Debug(" read 0x%x %c", b[0], b[0])
buff += string(b[0])
}
log.Debug(" => '%s'", buff)
return nil, buff
}
func (t *TelnetSession) Exec(cmd string) ([]byte, error) {
t.Lock()
defer t.Unlock()
cmd = fmt.Sprintf("(%s || echo) && echo PLACEHOLDER", cmd)
if _, err := t.doWrite([]byte(cmd + "\n")); err != nil {
return nil, fmt.Errorf("error while sending telnet command: %s", err)
}
t.doReadUntil(cmd)
if err, s := t.doReadUntil("PLACEHOLDER"); err != nil {
return nil, err
} else {
s = strings.Replace(s, "PLACEHOLDER", "", -1)
s = str.TrimLeft(s)
return []byte(s), nil
}
}
func (t *TelnetSession) Close() {
t.Lock()
defer t.Unlock()
t.client.Close()
}