mirror of
https://github.com/yv1ing/ShotRDP.git
synced 2025-09-16 15:10:57 +08:00
230 lines
5.7 KiB
Go
230 lines
5.7 KiB
Go
package tpkt
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"fmt"
|
|
|
|
"ShotRDP/grdp/core"
|
|
"ShotRDP/grdp/emission"
|
|
"ShotRDP/grdp/glog"
|
|
"ShotRDP/grdp/protocol/nla"
|
|
)
|
|
|
|
// take idea from https://github.com/Madnikulin50/gordp
|
|
|
|
/**
|
|
* Type of tpkt packet
|
|
* Fastpath is use to shortcut RDP stack
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240621.aspx
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240589.aspx
|
|
*/
|
|
const (
|
|
FASTPATH_ACTION_FASTPATH = 0x0
|
|
FASTPATH_ACTION_X224 = 0x3
|
|
)
|
|
|
|
/**
|
|
* TPKT layer of rdp stack
|
|
*/
|
|
type TPKT struct {
|
|
emission.Emitter
|
|
Conn *core.SocketLayer
|
|
ntlm *nla.NTLMv2
|
|
secFlag byte
|
|
lastShortLength int
|
|
fastPathListener core.FastPathListener
|
|
ntlmSec *nla.NTLMv2Security
|
|
}
|
|
|
|
func New(s *core.SocketLayer, ntlm *nla.NTLMv2) *TPKT {
|
|
t := &TPKT{
|
|
Emitter: *emission.NewEmitter(),
|
|
Conn: s,
|
|
secFlag: 0,
|
|
ntlm: ntlm}
|
|
core.StartReadBytes(2, s, t.recvHeader)
|
|
return t
|
|
}
|
|
|
|
func (t *TPKT) StartTLS() error {
|
|
return t.Conn.StartTLS()
|
|
}
|
|
|
|
func (t *TPKT) StartNLA() error {
|
|
err := t.StartTLS()
|
|
if err != nil {
|
|
glog.Info("start tls failed", err)
|
|
return err
|
|
}
|
|
req := nla.EncodeDERTRequest([]nla.Message{t.ntlm.GetNegotiateMessage()}, nil, nil)
|
|
_, err = t.Conn.Write(req)
|
|
if err != nil {
|
|
glog.Info("send NegotiateMessage", err)
|
|
return err
|
|
}
|
|
|
|
resp := make([]byte, 1024)
|
|
n, err := t.Conn.Read(resp)
|
|
if err != nil {
|
|
return fmt.Errorf("read %s", err)
|
|
} else {
|
|
glog.Debug("StartNLA Read success")
|
|
}
|
|
return t.recvChallenge(resp[:n])
|
|
}
|
|
|
|
func (t *TPKT) recvChallenge(data []byte) error {
|
|
glog.Trace("recvChallenge", hex.EncodeToString(data))
|
|
tsreq, err := nla.DecodeDERTRequest(data)
|
|
if err != nil {
|
|
glog.Info("DecodeDERTRequest", err)
|
|
return err
|
|
}
|
|
glog.Debugf("tsreq:%+v", tsreq)
|
|
// get pubkey
|
|
pubkey, err := t.Conn.TlsPubKey()
|
|
glog.Debugf("pubkey=%+v", pubkey)
|
|
|
|
authMsg, ntlmSec := t.ntlm.GetAuthenticateMessage(tsreq.NegoTokens[0].Data)
|
|
t.ntlmSec = ntlmSec
|
|
|
|
encryptPubkey := ntlmSec.GssEncrypt(pubkey)
|
|
req := nla.EncodeDERTRequest([]nla.Message{authMsg}, nil, encryptPubkey)
|
|
_, err = t.Conn.Write(req)
|
|
if err != nil {
|
|
glog.Info("send AuthenticateMessage", err)
|
|
return err
|
|
}
|
|
resp := make([]byte, 1024)
|
|
n, err := t.Conn.Read(resp)
|
|
if err != nil {
|
|
glog.Error("Read:", err)
|
|
return fmt.Errorf("read %s", err)
|
|
} else {
|
|
glog.Debug("recvChallenge Read success")
|
|
}
|
|
return t.recvPubKeyInc(resp[:n])
|
|
}
|
|
|
|
func (t *TPKT) recvPubKeyInc(data []byte) error {
|
|
glog.Trace("recvPubKeyInc", hex.EncodeToString(data))
|
|
tsreq, err := nla.DecodeDERTRequest(data)
|
|
if err != nil {
|
|
glog.Info("DecodeDERTRequest", err)
|
|
return err
|
|
}
|
|
glog.Trace("PubKeyAuth:", tsreq.PubKeyAuth)
|
|
//ignore
|
|
//pubkey := t.ntlmSec.GssDecrypt([]byte(tsreq.PubKeyAuth))
|
|
domain, username, password := t.ntlm.GetEncodedCredentials()
|
|
credentials := nla.EncodeDERTCredentials(domain, username, password)
|
|
authInfo := t.ntlmSec.GssEncrypt(credentials)
|
|
req := nla.EncodeDERTRequest(nil, authInfo, nil)
|
|
_, err = t.Conn.Write(req)
|
|
if err != nil {
|
|
glog.Info("send AuthenticateMessage", err)
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (t *TPKT) Read(b []byte) (n int, err error) {
|
|
return t.Conn.Read(b)
|
|
}
|
|
|
|
func (t *TPKT) Write(data []byte) (n int, err error) {
|
|
buff := &bytes.Buffer{}
|
|
core.WriteUInt8(FASTPATH_ACTION_X224, buff)
|
|
core.WriteUInt8(0, buff)
|
|
core.WriteUInt16BE(uint16(len(data)+4), buff)
|
|
buff.Write(data)
|
|
glog.Trace("tpkt Write", hex.EncodeToString(buff.Bytes()))
|
|
return t.Conn.Write(buff.Bytes())
|
|
}
|
|
|
|
func (t *TPKT) Close() error {
|
|
return t.Conn.Close()
|
|
}
|
|
|
|
func (t *TPKT) SetFastPathListener(f core.FastPathListener) {
|
|
t.fastPathListener = f
|
|
}
|
|
|
|
func (t *TPKT) SendFastPath(secFlag byte, data []byte) (n int, err error) {
|
|
buff := &bytes.Buffer{}
|
|
core.WriteUInt8(FASTPATH_ACTION_FASTPATH|((secFlag&0x3)<<6), buff)
|
|
core.WriteUInt16BE(uint16(len(data)+3)|0x8000, buff)
|
|
buff.Write(data)
|
|
glog.Trace("TPTK SendFastPath", hex.EncodeToString(buff.Bytes()))
|
|
return t.Conn.Write(buff.Bytes())
|
|
}
|
|
|
|
func (t *TPKT) recvHeader(s []byte, err error) {
|
|
glog.Trace("tpkt recvHeader", hex.EncodeToString(s), err)
|
|
if err != nil {
|
|
t.Emit("error", err)
|
|
return
|
|
}
|
|
r := bytes.NewReader(s)
|
|
version, _ := core.ReadUInt8(r)
|
|
if version == FASTPATH_ACTION_X224 {
|
|
glog.Debug("tptk recvHeader FASTPATH_ACTION_X224, wait for recvExtendedHeader")
|
|
core.StartReadBytes(2, t.Conn, t.recvExtendedHeader)
|
|
} else {
|
|
t.secFlag = (version >> 6) & 0x3
|
|
length, _ := core.ReadUInt8(r)
|
|
t.lastShortLength = int(length)
|
|
if t.lastShortLength&0x80 != 0 {
|
|
core.StartReadBytes(1, t.Conn, t.recvExtendedFastPathHeader)
|
|
} else {
|
|
core.StartReadBytes(t.lastShortLength-2, t.Conn, t.recvFastPath)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (t *TPKT) recvExtendedHeader(s []byte, err error) {
|
|
glog.Trace("tpkt recvExtendedHeader", hex.EncodeToString(s), err)
|
|
if err != nil {
|
|
return
|
|
}
|
|
r := bytes.NewReader(s)
|
|
size, _ := core.ReadUint16BE(r)
|
|
glog.Debug("tpkt wait recvData:", size)
|
|
core.StartReadBytes(int(size-4), t.Conn, t.recvData)
|
|
}
|
|
|
|
func (t *TPKT) recvData(s []byte, err error) {
|
|
glog.Trace("tpkt recvData", hex.EncodeToString(s), err)
|
|
if err != nil {
|
|
return
|
|
}
|
|
t.Emit("data", s)
|
|
core.StartReadBytes(2, t.Conn, t.recvHeader)
|
|
}
|
|
|
|
func (t *TPKT) recvExtendedFastPathHeader(s []byte, err error) {
|
|
glog.Trace("tpkt recvExtendedFastPathHeader", hex.EncodeToString(s))
|
|
r := bytes.NewReader(s)
|
|
rightPart, err := core.ReadUInt8(r)
|
|
if err != nil {
|
|
glog.Error("TPTK recvExtendedFastPathHeader", err)
|
|
return
|
|
}
|
|
|
|
leftPart := t.lastShortLength & ^0x80
|
|
packetSize := (leftPart << 8) + int(rightPart)
|
|
core.StartReadBytes(packetSize-3, t.Conn, t.recvFastPath)
|
|
}
|
|
|
|
func (t *TPKT) recvFastPath(s []byte, err error) {
|
|
glog.Trace("tpkt recvFastPath")
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
t.fastPathListener.RecvFastPath(t.secFlag, s)
|
|
core.StartReadBytes(2, t.Conn, t.recvHeader)
|
|
}
|