mirror of
https://github.com/yv1ing/ShotRDP.git
synced 2025-09-16 15:10:57 +08:00
471 lines
11 KiB
Go
471 lines
11 KiB
Go
// rfb.go
|
|
package rfb
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/des"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net"
|
|
|
|
"github.com/lunixbochs/struc"
|
|
|
|
"ShotRDP/grdp/core"
|
|
"ShotRDP/grdp/emission"
|
|
"ShotRDP/grdp/glog"
|
|
)
|
|
|
|
// ProtocolVersion
|
|
const (
|
|
RFB003003 = "RFB 003.003\n"
|
|
RFB003007 = "RFB 003.007\n"
|
|
RFB003008 = "RFB 003.008\n"
|
|
)
|
|
|
|
// SecurityType
|
|
const (
|
|
SEC_INVALID uint8 = 0
|
|
SEC_NONE uint8 = 1
|
|
SEC_VNC uint8 = 2
|
|
)
|
|
|
|
type RFBConn struct {
|
|
emission.Emitter
|
|
// The Socket connection to the client
|
|
Conn net.Conn
|
|
s *ServerInit
|
|
NbRect uint16
|
|
BitRect *BitRect
|
|
Password string
|
|
}
|
|
|
|
func NewRFBConn(s net.Conn, passwd string) *RFBConn {
|
|
fc := &RFBConn{
|
|
Emitter: *emission.NewEmitter(),
|
|
Conn: s,
|
|
BitRect: new(BitRect),
|
|
Password: passwd,
|
|
}
|
|
core.StartReadBytes(12, fc, fc.recvProtocolVersion)
|
|
|
|
return fc
|
|
}
|
|
func (fc *RFBConn) Read(b []byte) (n int, err error) {
|
|
return fc.Conn.Read(b)
|
|
}
|
|
|
|
func (fc *RFBConn) Write(data []byte) (n int, err error) {
|
|
buff := &bytes.Buffer{}
|
|
buff.Write(data)
|
|
return fc.Conn.Write(buff.Bytes())
|
|
}
|
|
func (fc *RFBConn) Close() error {
|
|
return fc.Conn.Close()
|
|
}
|
|
func (fc *RFBConn) recvProtocolVersion(s []byte, err error) {
|
|
version := string(s)
|
|
glog.Debug("RFBConn recvProtocolVersion", version, err)
|
|
if err != nil {
|
|
fc.Emit("error", err)
|
|
return
|
|
}
|
|
fc.Emit("data", version)
|
|
|
|
if version == RFB003003 {
|
|
fc.Emit("error", fmt.Errorf("%s", "Not Support RFB003003"))
|
|
return
|
|
//core.StartReadBytes(4, fc, fc.recvSecurityServer)
|
|
} else {
|
|
core.StartReadBytes(1, fc, fc.checkSecurityList)
|
|
}
|
|
}
|
|
func (fc *RFBConn) checkSecurityList(s []byte, err error) {
|
|
r := bytes.NewReader(s)
|
|
result, _ := core.ReadUInt8(r)
|
|
glog.Debug("RFBConn recvSecurityList", result, err)
|
|
|
|
core.StartReadBytes(int(result), fc, fc.recvSecurityList)
|
|
}
|
|
func (fc *RFBConn) recvSecurityList(s []byte, err error) {
|
|
r := bytes.NewReader(s)
|
|
secLevel := SEC_VNC
|
|
for r.Len() > 0 {
|
|
result, _ := core.ReadUInt8(r)
|
|
if result == SEC_NONE || result == SEC_VNC {
|
|
secLevel = result
|
|
break
|
|
}
|
|
}
|
|
|
|
glog.Debug("RFBConn recvSecurityList", secLevel, err)
|
|
buff := &bytes.Buffer{}
|
|
core.WriteUInt8(secLevel, buff)
|
|
fc.Write(buff.Bytes())
|
|
if secLevel == SEC_VNC {
|
|
core.StartReadBytes(16, fc, fc.recvVNCChallenge)
|
|
} else {
|
|
core.StartReadBytes(4, fc, fc.recvSecurityResult)
|
|
}
|
|
|
|
}
|
|
|
|
func fixDesKeyByte(val byte) byte {
|
|
var newval byte = 0
|
|
for i := 0; i < 8; i++ {
|
|
newval <<= 1
|
|
newval += (val & 1)
|
|
val >>= 1
|
|
}
|
|
return newval
|
|
}
|
|
|
|
// fixDesKey will make sure that exactly 8 bytes is used either by truncating or padding with nulls
|
|
// The bytes are then bit mirrored and returned
|
|
func fixDesKey(key []byte) []byte {
|
|
tmp := key
|
|
buf := make([]byte, 8)
|
|
if len(tmp) <= 8 {
|
|
copy(buf, tmp)
|
|
} else {
|
|
copy(buf, tmp[:8])
|
|
}
|
|
for i := 0; i < 8; i++ {
|
|
buf[i] = fixDesKeyByte(buf[i])
|
|
}
|
|
return buf
|
|
}
|
|
|
|
func (fc *RFBConn) recvVNCChallenge(s []byte, err error) {
|
|
glog.Debug("RFBConn recvVNCChallenge", hex.EncodeToString(s), len(s), err)
|
|
key := core.UnicodeEncode(fc.Password)
|
|
bk, err := des.NewCipher(fixDesKey(key))
|
|
if err != nil {
|
|
log.Printf("Error generating authentication cipher: %s\n", err.Error())
|
|
return
|
|
}
|
|
result := make([]byte, 16)
|
|
bk.Encrypt(result, s) //Encrypt first 8 bytes
|
|
bk.Encrypt(result[8:], s[8:])
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
fmt.Println(string(result))
|
|
fc.Write(result)
|
|
core.StartReadBytes(4, fc, fc.recvSecurityResult)
|
|
}
|
|
func (fc *RFBConn) recvSecurityResult(s []byte, err error) {
|
|
r := bytes.NewReader(s)
|
|
result, _ := core.ReadUInt32BE(r)
|
|
glog.Debug("RFBConn recvSecurityResult", result, err)
|
|
if result == 1 {
|
|
fc.Emit("error", fmt.Errorf("%s", "Authentification failed"))
|
|
return
|
|
}
|
|
buff := &bytes.Buffer{}
|
|
core.WriteUInt8(0, buff) //share
|
|
fc.Write(buff.Bytes())
|
|
core.StartReadBytes(20, fc, fc.recvServerInit)
|
|
}
|
|
|
|
type ServerInit struct {
|
|
Width uint16 `struc:"little"`
|
|
Height uint16 `struc:"little"`
|
|
PixelFormat *PixelFormat `struc:"little"`
|
|
}
|
|
|
|
func (fc *RFBConn) recvServerInit(s []byte, err error) {
|
|
glog.Debug("RFBConn recvServerInit", len(s), err)
|
|
r := bytes.NewReader(s)
|
|
si := &ServerInit{}
|
|
si.Width, err = core.ReadUint16BE(r)
|
|
si.Height, err = core.ReadUint16BE(r)
|
|
si.PixelFormat = ReadPixelFormat(r)
|
|
glog.Infof("serverInit:%+v, %+v", si, si.PixelFormat)
|
|
fc.s = si
|
|
fc.BitRect.Pf = si.PixelFormat
|
|
core.StartReadBytes(4, fc, fc.checkServerName)
|
|
}
|
|
func (fc *RFBConn) checkServerName(s []byte, err error) {
|
|
r := bytes.NewReader(s)
|
|
result, _ := core.ReadUInt32BE(r)
|
|
glog.Debug("RFBConn recvSecurityList", result, err)
|
|
|
|
core.StartReadBytes(int(result), fc, fc.recvServerName)
|
|
}
|
|
func (fc *RFBConn) recvServerName(s []byte, err error) {
|
|
glog.Debug("RFBConn recvServerName", string(s), err)
|
|
//fc.sendPixelFormat()
|
|
fc.sendSetEncoding()
|
|
fc.sendFramebufferUpdateRequest(0, 0, 0, fc.s.Width, fc.s.Height)
|
|
|
|
fc.Emit("ready")
|
|
core.StartReadBytes(1, fc, fc.recvServerOrder)
|
|
}
|
|
|
|
func (fc *RFBConn) sendPixelFormat() {
|
|
glog.Debug("sendPixelFormat")
|
|
buff := &bytes.Buffer{}
|
|
core.WriteUInt8(0, buff)
|
|
core.WriteUInt16BE(0, buff)
|
|
core.WriteUInt8(0, buff)
|
|
err := struc.Pack(buff, NewPixelFormat())
|
|
if err != nil {
|
|
fc.Emit("error", err)
|
|
return
|
|
}
|
|
fc.Write(buff.Bytes())
|
|
}
|
|
func (fc *RFBConn) sendSetEncoding() {
|
|
glog.Debug("sendSetEncoding")
|
|
buff := &bytes.Buffer{}
|
|
core.WriteUInt8(2, buff)
|
|
core.WriteUInt8(0, buff)
|
|
core.WriteUInt16BE(1, buff)
|
|
core.WriteUInt32BE(0, buff)
|
|
fc.Write(buff.Bytes())
|
|
}
|
|
|
|
type FrameBufferUpdateRequest struct {
|
|
Incremental uint8
|
|
X uint16
|
|
Y uint16
|
|
Width uint16
|
|
Height uint16
|
|
}
|
|
|
|
func (fc *RFBConn) sendFramebufferUpdateRequest(Incremental uint8,
|
|
X uint16,
|
|
Y uint16,
|
|
Width uint16,
|
|
Height uint16) {
|
|
glog.Debug("sendFramebufferUpdateRequest")
|
|
buff := &bytes.Buffer{}
|
|
core.WriteUInt8(3, buff)
|
|
core.WriteUInt8(Incremental, buff)
|
|
core.WriteUInt16BE(X, buff)
|
|
core.WriteUInt16BE(Y, buff)
|
|
core.WriteUInt16BE(Width, buff)
|
|
core.WriteUInt16BE(Height, buff)
|
|
fc.Write(buff.Bytes())
|
|
}
|
|
func (fc *RFBConn) recvServerOrder(s []byte, err error) {
|
|
glog.Debug("RFBConn recvServerOrder", hex.EncodeToString(s), err)
|
|
r := bytes.NewReader(s)
|
|
packetType, _ := core.ReadUInt8(r)
|
|
switch packetType {
|
|
case 0:
|
|
core.StartReadBytes(3, fc, fc.recvFrameBufferUpdateHeader)
|
|
case 2:
|
|
//TODO
|
|
case 3:
|
|
core.StartReadBytes(7, fc, fc.recvServerCutTextHeader)
|
|
default:
|
|
glog.Errorf("Unknown message type %s", packetType)
|
|
}
|
|
|
|
}
|
|
|
|
type BitRect struct {
|
|
Rects []Rectangles
|
|
Pf *PixelFormat
|
|
}
|
|
|
|
type Rectangles struct {
|
|
Rect *Rectangle
|
|
Data []byte
|
|
}
|
|
|
|
func (fc *RFBConn) recvFrameBufferUpdateHeader(s []byte, err error) {
|
|
glog.Debug("RFBConn recvFrameBufferUpdateHeader", hex.EncodeToString(s), err)
|
|
r := bytes.NewReader(s)
|
|
core.ReadUInt8(r)
|
|
NbRect, _ := core.ReadUint16BE(r)
|
|
fc.NbRect = NbRect
|
|
fc.BitRect.Rects = make([]Rectangles, fc.NbRect)
|
|
if NbRect == 0 {
|
|
return
|
|
}
|
|
glog.Info("NbRect:", NbRect)
|
|
core.StartReadBytes(12, fc, fc.recvRectHeader)
|
|
}
|
|
|
|
type Rectangle struct {
|
|
X uint16 `struc:"little"`
|
|
Y uint16 `struc:"little"`
|
|
Width uint16 `struc:"little"`
|
|
Height uint16 `struc:"little"`
|
|
Encoding uint32 `struc:"little"`
|
|
}
|
|
|
|
func (fc *RFBConn) recvRectHeader(s []byte, err error) {
|
|
glog.Debug("RFBConn recvRectHeader", hex.EncodeToString(s), err)
|
|
r := bytes.NewReader(s)
|
|
x, err := core.ReadUint16BE(r)
|
|
y, err := core.ReadUint16BE(r)
|
|
w, err := core.ReadUint16BE(r)
|
|
h, err := core.ReadUint16BE(r)
|
|
e, err := core.ReadUInt32BE(r)
|
|
rect := &Rectangle{x, y, w, h, e}
|
|
|
|
fc.BitRect.Rects[fc.NbRect-1].Rect = rect
|
|
glog.Infof("rect:%+v, len=%d", rect, int(rect.Width)*int(rect.Height)*4)
|
|
core.StartReadBytes(int(rect.Width)*int(rect.Height)*4, fc, fc.recvRectBody)
|
|
}
|
|
func (fc *RFBConn) recvRectBody(s []byte, err error) {
|
|
glog.Debug("RFBConn recvRectBody", hex.EncodeToString(s), err)
|
|
fc.BitRect.Rects[fc.NbRect-1].Data = s
|
|
fc.NbRect--
|
|
glog.Info("fc.NbRect:", fc.NbRect)
|
|
if fc.NbRect == 0 {
|
|
fc.Emit("bitmap", fc.BitRect)
|
|
fc.sendFramebufferUpdateRequest(1, 0, 0, fc.s.Width, fc.s.Height)
|
|
core.StartReadBytes(1, fc, fc.recvServerOrder)
|
|
} else {
|
|
core.StartReadBytes(12, fc, fc.recvRectHeader)
|
|
}
|
|
}
|
|
|
|
type ServerCutTextHeader struct {
|
|
Padding [3]byte `struc:"little"`
|
|
Size uint32 `struc:"little"`
|
|
}
|
|
|
|
func (fc *RFBConn) recvServerCutTextHeader(s []byte, err error) {
|
|
glog.Debug("RFBConn recvServerCutTextHeader", string(s), err)
|
|
r := bytes.NewReader(s)
|
|
header := &ServerCutTextHeader{}
|
|
err = struc.Unpack(r, header)
|
|
if err != nil {
|
|
fc.Emit("error", err)
|
|
return
|
|
}
|
|
|
|
core.StartReadBytes(int(header.Size), fc, fc.recvServerCutTextBody)
|
|
}
|
|
func (fc *RFBConn) recvServerCutTextBody(s []byte, err error) {
|
|
glog.Debug("RFBConn recvServerCutTextBody", string(s), err)
|
|
fc.Emit("CutText", s)
|
|
core.StartReadBytes(1, fc, fc.recvServerOrder)
|
|
}
|
|
|
|
type PixelFormat struct {
|
|
BitsPerPixel uint8 `struc:"little"`
|
|
Depth uint8 `struc:"little"`
|
|
BigEndianFlag uint8 `struc:"little"`
|
|
TrueColorFlag uint8 `struc:"little"`
|
|
RedMax uint16 `struc:"little"`
|
|
GreenMax uint16 `struc:"little"`
|
|
BlueMax uint16 `struc:"little"`
|
|
RedShift uint8 `struc:"little"`
|
|
GreenShift uint8 `struc:"little"`
|
|
BlueShift uint8 `struc:"little"`
|
|
Padding uint16 `struc:"little"`
|
|
Padding1 uint8 `struc:"little"`
|
|
}
|
|
|
|
func ReadPixelFormat(r io.Reader) *PixelFormat {
|
|
p := NewPixelFormat()
|
|
p.BitsPerPixel, _ = core.ReadUInt8(r)
|
|
p.Depth, _ = core.ReadUInt8(r)
|
|
p.BigEndianFlag, _ = core.ReadUInt8(r)
|
|
p.TrueColorFlag, _ = core.ReadUInt8(r)
|
|
p.RedMax, _ = core.ReadUint16BE(r)
|
|
p.GreenMax, _ = core.ReadUint16BE(r)
|
|
p.BlueMax, _ = core.ReadUint16BE(r)
|
|
p.RedShift, _ = core.ReadUInt8(r)
|
|
p.GreenShift, _ = core.ReadUInt8(r)
|
|
p.BlueShift, _ = core.ReadUInt8(r)
|
|
p.Padding, _ = core.ReadUint16BE(r)
|
|
p.Padding1, _ = core.ReadUInt8(r)
|
|
|
|
return p
|
|
}
|
|
func NewPixelFormat() *PixelFormat {
|
|
return &PixelFormat{
|
|
32, 24, 0, 1, 65280, 65280, 65280, 16, 8, 0, 0, 0,
|
|
}
|
|
}
|
|
|
|
type RFB struct {
|
|
core.Transport
|
|
Version string
|
|
SecurityLevel uint8
|
|
ServerName string
|
|
PixelFormat *PixelFormat
|
|
NbRect int
|
|
CurrentRect *Rectangle
|
|
}
|
|
|
|
func NewRFB(t core.Transport) *RFB {
|
|
fb := &RFB{t, RFB003008, SEC_INVALID, "", NewPixelFormat(), 0, &Rectangle{}}
|
|
|
|
return fb
|
|
}
|
|
|
|
func (fb *RFB) Connect() error {
|
|
if fb.Transport == nil {
|
|
return errors.New("no transport")
|
|
}
|
|
fb.Once("data", fb.recvProtocolVersion)
|
|
return nil
|
|
}
|
|
|
|
func (fb *RFB) recvProtocolVersion(version string) {
|
|
if version != RFB003003 || version != RFB003007 || version != RFB003008 {
|
|
version = RFB003008
|
|
}
|
|
glog.Infof("version:%s", version)
|
|
b := &bytes.Buffer{}
|
|
b.WriteString(version)
|
|
fb.Write(b.Bytes())
|
|
}
|
|
|
|
type KeyEvent struct {
|
|
DownFlag uint8 `struc:"little"`
|
|
Padding uint16 `struc:"little"`
|
|
Key uint32 `struc:"little"`
|
|
}
|
|
|
|
func (fb *RFB) SendKeyEvent(k *KeyEvent) {
|
|
b := &bytes.Buffer{}
|
|
core.WriteUInt8(4, b)
|
|
core.WriteUInt8(k.DownFlag, b)
|
|
core.WriteUInt16BE(k.Padding, b)
|
|
core.WriteUInt32BE(k.Key, b)
|
|
fmt.Println(b.Bytes())
|
|
fb.Write(b.Bytes())
|
|
}
|
|
|
|
type PointerEvent struct {
|
|
Mask uint8 `struc:"little"`
|
|
XPos uint16 `struc:"little"`
|
|
YPos uint16 `struc:"little"`
|
|
}
|
|
|
|
func (fb *RFB) SendPointEvent(p *PointerEvent) {
|
|
b := &bytes.Buffer{}
|
|
core.WriteUInt8(5, b)
|
|
core.WriteUInt8(p.Mask, b)
|
|
core.WriteUInt16BE(p.XPos, b)
|
|
core.WriteUInt16BE(p.YPos, b)
|
|
fmt.Println(b.Bytes())
|
|
fb.Write(b.Bytes())
|
|
}
|
|
|
|
type ClientCutText struct {
|
|
Padding uint16 `struc:"little"`
|
|
Padding1 uint8 `struc:"little"`
|
|
Size uint32 `struc:"little"`
|
|
Message string `struc:"little"`
|
|
}
|
|
|
|
func (fb *RFB) SendClientCutText(t *ClientCutText) {
|
|
b := &bytes.Buffer{}
|
|
core.WriteUInt8(6, b)
|
|
struc.Pack(b, t)
|
|
fb.Write(b.Bytes())
|
|
}
|