mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-22 19:21:52 +08:00
refactor(grdp): 精简RDP库,删除认证检测不需要的代码
- 删除 VNC 协议支持 (protocol/rfb, client/rfb.go) - 删除完整客户端框架 (client/) - 删除 RemoteApp 等插件 (plugin/) - 删除 RLE 图形解压 (core/rle.go) - 删除绘图指令处理 (pdu/orders.go, pdu/gdi.go) - 精简 screen.go,移除截图和完整会话功能 - 移除未使用的 RGB 转换函数 grdp 代码从 13,044 行精简至 7,581 行,削减 42%
This commit is contained in:
@@ -1,174 +0,0 @@
|
||||
// client.go
|
||||
package client
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/glog"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/protocol/pdu"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/protocol/rfb"
|
||||
)
|
||||
|
||||
const (
|
||||
CLIP_OFF = 0
|
||||
CLIP_IN = 0x1
|
||||
CLIP_OUT = 0x2
|
||||
)
|
||||
|
||||
const (
|
||||
TC_RDP = 0
|
||||
TC_VNC = 1
|
||||
)
|
||||
|
||||
type Control interface {
|
||||
Login(host, user, passwd string, width, height int) error
|
||||
KeyUp(sc int, name string)
|
||||
KeyDown(sc int, name string)
|
||||
MouseMove(x, y int)
|
||||
MouseWheel(scroll, x, y int)
|
||||
MouseUp(button int, x, y int)
|
||||
MouseDown(button int, x, y int)
|
||||
On(event string, msg interface{})
|
||||
Close()
|
||||
}
|
||||
|
||||
func init() {
|
||||
glog.SetLevel(glog.INFO)
|
||||
logger := log.New(os.Stdout, "", 0)
|
||||
glog.SetLogger(logger)
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
host string
|
||||
user string
|
||||
passwd string
|
||||
ctl Control
|
||||
tc int
|
||||
setting *Setting
|
||||
}
|
||||
|
||||
func NewClient(host, user, passwd string, t int, s *Setting) *Client {
|
||||
if s == nil {
|
||||
s = NewSetting()
|
||||
}
|
||||
c := &Client{
|
||||
host: host,
|
||||
user: user,
|
||||
passwd: passwd,
|
||||
tc: t,
|
||||
setting: s,
|
||||
}
|
||||
|
||||
switch t {
|
||||
case TC_VNC:
|
||||
c.ctl = newVncClient(s)
|
||||
default:
|
||||
c.ctl = newRdpClient(s)
|
||||
}
|
||||
|
||||
s.SetLogLevel()
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Client) Login() error {
|
||||
return c.ctl.Login(c.host, c.user, c.passwd, c.setting.Width, c.setting.Height)
|
||||
}
|
||||
|
||||
func (c *Client) KeyUp(sc int, name string) {
|
||||
c.ctl.KeyUp(sc, name)
|
||||
}
|
||||
func (c *Client) KeyDown(sc int, name string) {
|
||||
c.ctl.KeyDown(sc, name)
|
||||
}
|
||||
func (c *Client) MouseMove(x, y int) {
|
||||
c.ctl.MouseMove(x, y)
|
||||
}
|
||||
func (c *Client) MouseWheel(scroll, x, y int) {
|
||||
c.ctl.MouseWheel(scroll, x, y)
|
||||
}
|
||||
func (c *Client) MouseUp(button, x, y int) {
|
||||
c.ctl.MouseUp(button, x, y)
|
||||
}
|
||||
func (c *Client) MouseDown(button, x, y int) {
|
||||
c.ctl.MouseDown(button, x, y)
|
||||
}
|
||||
func (c *Client) OnError(f func(e error)) {
|
||||
c.ctl.On("error", f)
|
||||
}
|
||||
func (c *Client) OnClose(f func()) {
|
||||
c.ctl.On("close", f)
|
||||
}
|
||||
func (c *Client) OnSuccess(f func()) {
|
||||
c.ctl.On("success", f)
|
||||
}
|
||||
func (c *Client) OnReady(f func()) {
|
||||
c.ctl.On("ready", f)
|
||||
}
|
||||
func (c *Client) OnBitmap(f func([]Bitmap)) {
|
||||
f1 := func(data interface{}) {
|
||||
bs := make([]Bitmap, 0, 50)
|
||||
if c.tc == TC_VNC {
|
||||
br := data.(*rfb.BitRect)
|
||||
for _, v := range br.Rects {
|
||||
b := Bitmap{int(v.Rect.X), int(v.Rect.Y), int(v.Rect.X + v.Rect.Width), int(v.Rect.Y + v.Rect.Height),
|
||||
int(v.Rect.Width), int(v.Rect.Height),
|
||||
Bpp(uint16(br.Pf.BitsPerPixel)), false, v.Data}
|
||||
bs = append(bs, b)
|
||||
}
|
||||
} else {
|
||||
for _, v := range data.([]pdu.BitmapData) {
|
||||
IsCompress := v.IsCompress()
|
||||
stream := v.BitmapDataStream
|
||||
if IsCompress {
|
||||
stream = bitmapDecompress(&v)
|
||||
IsCompress = false
|
||||
}
|
||||
|
||||
b := Bitmap{int(v.DestLeft), int(v.DestTop), int(v.DestRight), int(v.DestBottom),
|
||||
int(v.Width), int(v.Height), Bpp(v.BitsPerPixel), IsCompress, stream}
|
||||
bs = append(bs, b)
|
||||
}
|
||||
}
|
||||
f(bs)
|
||||
}
|
||||
|
||||
c.ctl.On("bitmap", f1)
|
||||
}
|
||||
|
||||
type Bitmap struct {
|
||||
DestLeft int `json:"destLeft"`
|
||||
DestTop int `json:"destTop"`
|
||||
DestRight int `json:"destRight"`
|
||||
DestBottom int `json:"destBottom"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
BitsPerPixel int `json:"bitsPerPixel"`
|
||||
IsCompress bool `json:"isCompress"`
|
||||
Data []byte `json:"data"`
|
||||
}
|
||||
|
||||
func Bpp(bp uint16) int {
|
||||
return int(bp / 8)
|
||||
}
|
||||
|
||||
type Setting struct {
|
||||
Width int
|
||||
Height int
|
||||
Protocol string
|
||||
LogLevel glog.LEVEL
|
||||
}
|
||||
|
||||
func NewSetting() *Setting {
|
||||
return &Setting{
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
LogLevel: glog.INFO,
|
||||
}
|
||||
}
|
||||
func (s *Setting) SetLogLevel() {
|
||||
glog.SetLevel(s.LogLevel)
|
||||
}
|
||||
|
||||
func (s *Setting) SetRequestedProtocol(p uint32) {}
|
||||
func (s *Setting) SetClipboard(c int) {}
|
||||
@@ -1,156 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/core"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/plugin"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/protocol/nla"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/protocol/pdu"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/protocol/sec"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/protocol/t125"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/protocol/tpkt"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/protocol/x224"
|
||||
)
|
||||
|
||||
type RdpClient struct {
|
||||
tpkt *tpkt.TPKT
|
||||
x224 *x224.X224
|
||||
mcs *t125.MCSClient
|
||||
sec *sec.Client
|
||||
pdu *pdu.Client
|
||||
channels *plugin.Channels
|
||||
}
|
||||
|
||||
func newRdpClient(s *Setting) *RdpClient {
|
||||
return &RdpClient{}
|
||||
}
|
||||
|
||||
func bitmapDecompress(bitmap *pdu.BitmapData) []byte {
|
||||
return core.Decompress(bitmap.BitmapDataStream, int(bitmap.Width), int(bitmap.Height), Bpp(bitmap.BitsPerPixel))
|
||||
}
|
||||
func split(user string) (domain string, uname string) {
|
||||
if strings.Index(user, "\\") != -1 {
|
||||
t := strings.Split(user, "\\")
|
||||
domain = t[0]
|
||||
uname = t[len(t)-1]
|
||||
} else if strings.Index(user, "/") != -1 {
|
||||
t := strings.Split(user, "/")
|
||||
domain = t[0]
|
||||
uname = t[len(t)-1]
|
||||
} else {
|
||||
uname = user
|
||||
}
|
||||
return
|
||||
}
|
||||
func (c *RdpClient) Login(host, user, pwd string, width, height int) error {
|
||||
conn, err := net.DialTimeout("tcp", host, 3*time.Second)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[dial err] %v", err)
|
||||
}
|
||||
|
||||
domain, user := split(user)
|
||||
c.tpkt = tpkt.New(core.NewSocketLayer(conn), nla.NewNTLMv2(domain, user, pwd))
|
||||
c.x224 = x224.New(c.tpkt)
|
||||
c.mcs = t125.NewMCSClient(c.x224)
|
||||
c.sec = sec.NewClient(c.mcs)
|
||||
c.pdu = pdu.NewClient(c.sec)
|
||||
c.channels = plugin.NewChannels(c.sec)
|
||||
|
||||
//c.mcs.SetClientDesktop(uint16(width), uint16(height))
|
||||
|
||||
c.sec.SetUser(user)
|
||||
c.sec.SetPwd(pwd)
|
||||
c.sec.SetDomain(domain)
|
||||
|
||||
c.tpkt.SetFastPathListener(c.sec)
|
||||
c.sec.SetFastPathListener(c.pdu)
|
||||
c.sec.SetChannelSender(c.mcs)
|
||||
c.channels.SetChannelSender(c.sec)
|
||||
|
||||
//c.x224.SetRequestedProtocol(x224.PROTOCOL_RDP)
|
||||
//c.x224.SetRequestedProtocol(x224.PROTOCOL_SSL)
|
||||
|
||||
err = c.x224.Connect()
|
||||
if err != nil {
|
||||
return fmt.Errorf("[x224 connect err] %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (c *RdpClient) On(event string, f interface{}) {
|
||||
c.pdu.On(event, f)
|
||||
}
|
||||
func (c *RdpClient) KeyUp(sc int, name string) {
|
||||
p := &pdu.ScancodeKeyEvent{}
|
||||
p.KeyCode = uint16(sc)
|
||||
p.KeyboardFlags |= pdu.KBDFLAGS_RELEASE
|
||||
c.pdu.SendInputEvents(pdu.INPUT_EVENT_SCANCODE, []pdu.InputEventsInterface{p})
|
||||
}
|
||||
func (c *RdpClient) KeyDown(sc int, name string) {
|
||||
p := &pdu.ScancodeKeyEvent{}
|
||||
p.KeyCode = uint16(sc)
|
||||
c.pdu.SendInputEvents(pdu.INPUT_EVENT_SCANCODE, []pdu.InputEventsInterface{p})
|
||||
}
|
||||
|
||||
func (c *RdpClient) MouseMove(x, y int) {
|
||||
p := &pdu.PointerEvent{}
|
||||
p.PointerFlags |= pdu.PTRFLAGS_MOVE
|
||||
p.XPos = uint16(x)
|
||||
p.YPos = uint16(y)
|
||||
c.pdu.SendInputEvents(pdu.INPUT_EVENT_MOUSE, []pdu.InputEventsInterface{p})
|
||||
}
|
||||
|
||||
func (c *RdpClient) MouseWheel(scroll, x, y int) {
|
||||
p := &pdu.PointerEvent{}
|
||||
p.PointerFlags |= pdu.PTRFLAGS_WHEEL
|
||||
p.XPos = uint16(x)
|
||||
p.YPos = uint16(y)
|
||||
c.pdu.SendInputEvents(pdu.INPUT_EVENT_SCANCODE, []pdu.InputEventsInterface{p})
|
||||
}
|
||||
|
||||
func (c *RdpClient) MouseUp(button int, x, y int) {
|
||||
p := &pdu.PointerEvent{}
|
||||
|
||||
switch button {
|
||||
case 0:
|
||||
p.PointerFlags |= pdu.PTRFLAGS_BUTTON1
|
||||
case 2:
|
||||
p.PointerFlags |= pdu.PTRFLAGS_BUTTON2
|
||||
case 1:
|
||||
p.PointerFlags |= pdu.PTRFLAGS_BUTTON3
|
||||
default:
|
||||
p.PointerFlags |= pdu.PTRFLAGS_MOVE
|
||||
}
|
||||
|
||||
p.XPos = uint16(x)
|
||||
p.YPos = uint16(y)
|
||||
c.pdu.SendInputEvents(pdu.INPUT_EVENT_MOUSE, []pdu.InputEventsInterface{p})
|
||||
}
|
||||
func (c *RdpClient) MouseDown(button int, x, y int) {
|
||||
p := &pdu.PointerEvent{}
|
||||
|
||||
p.PointerFlags |= pdu.PTRFLAGS_DOWN
|
||||
|
||||
switch button {
|
||||
case 0:
|
||||
p.PointerFlags |= pdu.PTRFLAGS_BUTTON1
|
||||
case 2:
|
||||
p.PointerFlags |= pdu.PTRFLAGS_BUTTON2
|
||||
case 1:
|
||||
p.PointerFlags |= pdu.PTRFLAGS_BUTTON3
|
||||
default:
|
||||
p.PointerFlags |= pdu.PTRFLAGS_MOVE
|
||||
}
|
||||
|
||||
p.XPos = uint16(x)
|
||||
p.YPos = uint16(y)
|
||||
c.pdu.SendInputEvents(pdu.INPUT_EVENT_MOUSE, []pdu.InputEventsInterface{p})
|
||||
}
|
||||
func (c *RdpClient) Close() {
|
||||
if c != nil && c.tpkt != nil {
|
||||
c.tpkt.Close()
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
// rfb.go
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/protocol/rfb"
|
||||
)
|
||||
|
||||
type VncClient struct {
|
||||
vnc *rfb.RFB
|
||||
}
|
||||
|
||||
func newVncClient(s *Setting) *VncClient {
|
||||
return &VncClient{}
|
||||
}
|
||||
|
||||
func (c *VncClient) Login(host, user, pwd string, width, height int) error {
|
||||
conn, err := net.DialTimeout("tcp", host, 3*time.Second)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[dial err] %v", err)
|
||||
}
|
||||
|
||||
c.vnc = rfb.NewRFB(rfb.NewRFBConn(conn, pwd))
|
||||
|
||||
err = c.vnc.Connect()
|
||||
if err != nil {
|
||||
return fmt.Errorf("[vnc connect err] %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
func (c *VncClient) On(event string, f interface{}) {
|
||||
c.vnc.On(event, f)
|
||||
}
|
||||
|
||||
func (c *VncClient) KeyUp(sc int, name string) {
|
||||
k := &rfb.KeyEvent{}
|
||||
k.Key = uint32(sc)
|
||||
c.vnc.SendKeyEvent(k)
|
||||
}
|
||||
func (c *VncClient) KeyDown(sc int, name string) {
|
||||
k := &rfb.KeyEvent{}
|
||||
k.DownFlag = 1
|
||||
k.Key = uint32(sc)
|
||||
c.vnc.SendKeyEvent(k)
|
||||
}
|
||||
|
||||
func (c *VncClient) MouseMove(x, y int) {
|
||||
p := &rfb.PointerEvent{}
|
||||
time.Sleep(8 * time.Millisecond)
|
||||
p.XPos = uint16(x)
|
||||
p.YPos = uint16(y)
|
||||
c.vnc.SendPointEvent(p)
|
||||
}
|
||||
|
||||
func (c *VncClient) MouseWheel(scroll, x, y int) {
|
||||
}
|
||||
|
||||
func (c *VncClient) MouseUp(button int, x, y int) {
|
||||
p := &rfb.PointerEvent{}
|
||||
|
||||
switch button {
|
||||
case 0:
|
||||
p.Mask = 1
|
||||
case 2:
|
||||
p.Mask = 1<<3 - 1
|
||||
case 1:
|
||||
p.Mask = 1<<2 - 1
|
||||
default:
|
||||
p.Mask = 0
|
||||
}
|
||||
p.XPos = uint16(x)
|
||||
p.YPos = uint16(y)
|
||||
c.vnc.SendPointEvent(p)
|
||||
}
|
||||
func (c *VncClient) MouseDown(button int, x, y int) {
|
||||
p := &rfb.PointerEvent{}
|
||||
|
||||
switch button {
|
||||
case 0:
|
||||
p.Mask = 1
|
||||
case 2:
|
||||
p.Mask = 1<<3 - 1
|
||||
case 1:
|
||||
p.Mask = 1<<2 - 1
|
||||
default:
|
||||
p.Mask = 0
|
||||
}
|
||||
|
||||
p.XPos = uint16(x)
|
||||
p.YPos = uint16(y)
|
||||
c.MouseMove(x, y)
|
||||
c.vnc.SendPointEvent(p)
|
||||
}
|
||||
|
||||
func (c *VncClient) Close() {
|
||||
if c.vnc != nil {
|
||||
c.vnc.Close()
|
||||
}
|
||||
}
|
||||
@@ -130,25 +130,3 @@ func Uint16BE(d0, d1 uint8) uint16 {
|
||||
|
||||
return binary.BigEndian.Uint16(b)
|
||||
}
|
||||
|
||||
func RGB565ToRGB(data uint16) (r, g, b uint8) {
|
||||
r = uint8((data & 0xF800) >> 8)
|
||||
r |= r >> 5
|
||||
g = uint8((data & 0x07E0) >> 3)
|
||||
g |= g >> 6
|
||||
b = uint8((data & 0x001F) << 3)
|
||||
b |= b >> 5
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func RGB555ToRGB(data uint16) (r, g, b uint8) {
|
||||
r = uint8((data & 0x7C00) >> 7)
|
||||
r |= r >> 5
|
||||
g = uint8((data & 0x03E0) >> 2)
|
||||
g |= g >> 5
|
||||
b = uint8((data & 0x001F) << 3)
|
||||
b |= b >> 5
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+3
-438
@@ -1,8 +1,6 @@
|
||||
package login
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/core"
|
||||
@@ -15,12 +13,7 @@ import (
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/protocol/x224"
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/net/proxy"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"image/jpeg"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -34,39 +27,6 @@ var (
|
||||
OutputDir string
|
||||
)
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
func RdpConn(host, domain, user, password string, timeout int64, rdpProtocol uint32) (bool, error) {
|
||||
g := NewClient(host, LogLever)
|
||||
status, err, reconnectProtocol := g.ScreenShot(domain, user, password, timeout, rdpProtocol)
|
||||
if status == true {
|
||||
return true, err
|
||||
} else {
|
||||
if reconnectProtocol != rdpProtocol {
|
||||
glog.Info("reconnect with protocol:", reconnectProtocol)
|
||||
return RdpConn(host, domain, user, password, timeout, reconnectProtocol)
|
||||
} else {
|
||||
return status, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func RdpCrack(host, domain, user, password string, timeout int64, rdpProtocol uint32) (bool, error) {
|
||||
g := NewClient(host, LogLever)
|
||||
status, err, reconnectProtocol := g.Crack(domain, user, password, timeout, rdpProtocol)
|
||||
if status == true {
|
||||
return true, err
|
||||
} else {
|
||||
if reconnectProtocol != rdpProtocol {
|
||||
glog.Info("reconnect with protocol:", reconnectProtocol)
|
||||
return RdpCrack(host, domain, user, password, timeout, reconnectProtocol)
|
||||
} else {
|
||||
return status, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NlaAuth 仅进行NLA认证验证,不建立RDP会话,不会挤掉已登录用户
|
||||
// 返回: (认证成功, 错误信息)
|
||||
func NlaAuth(host, domain, user, password string, timeout int64) (bool, error) {
|
||||
@@ -99,14 +59,13 @@ func WrapperTcpWithTimeout(network, address string, timeout time.Duration) (net.
|
||||
net_ip = net.ParseIP("0.0.0.0")
|
||||
}
|
||||
local_addr := &net.TCPAddr{
|
||||
IP: net_ip, // 替换为你想要使用的本地IP地址
|
||||
IP: net_ip,
|
||||
}
|
||||
d := &net.Dialer{Timeout: timeout, LocalAddr: local_addr}
|
||||
return WrapperTCP(network, address, d)
|
||||
}
|
||||
|
||||
func WrapperTCP(network, address string, forward *net.Dialer) (net.Conn, error) {
|
||||
//get conn
|
||||
var conn net.Conn
|
||||
if Socks5Proxy == "" {
|
||||
var err error
|
||||
@@ -121,10 +80,8 @@ func WrapperTCP(network, address string, forward *net.Dialer) (net.Conn, error)
|
||||
}
|
||||
conn, err = dailer.Dial(network, address)
|
||||
if err != nil {
|
||||
// fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
timeout := forward.Timeout
|
||||
@@ -136,7 +93,6 @@ func WrapperTCP(network, address string, forward *net.Dialer) (net.Conn, error)
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
|
||||
}
|
||||
|
||||
func Socks5Dailer(forward *net.Dialer) (proxy.Dialer, error) {
|
||||
@@ -166,60 +122,6 @@ func Socks5Dailer(forward *net.Dialer) (proxy.Dialer, error) {
|
||||
return dailer, nil
|
||||
}
|
||||
|
||||
type Bitmap struct {
|
||||
DestLeft int `json:"destLeft"`
|
||||
DestTop int `json:"destTop"`
|
||||
DestRight int `json:"destRight"`
|
||||
DestBottom int `json:"destBottom"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
BitsPerPixel int `json:"bitsPerPixel"`
|
||||
IsCompress bool `json:"isCompress"`
|
||||
Data []byte `json:"data"`
|
||||
}
|
||||
|
||||
func Bpp(BitsPerPixel uint16) (pixel int) {
|
||||
switch BitsPerPixel {
|
||||
case 15:
|
||||
pixel = 1
|
||||
|
||||
case 16:
|
||||
pixel = 2
|
||||
|
||||
case 24:
|
||||
pixel = 3
|
||||
|
||||
case 32:
|
||||
pixel = 4
|
||||
|
||||
default:
|
||||
glog.Error("-------------------------------------Bpp func. invalid bitmap data format")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func BitmapDecompress(bitmap *pdu.BitmapData) []byte {
|
||||
return core.Decompress(bitmap.BitmapDataStream, int(bitmap.Width), int(bitmap.Height), Bpp(bitmap.BitsPerPixel))
|
||||
}
|
||||
|
||||
func ToRGBA(pixel int, i int, data []byte) (r, g, b, a uint8) {
|
||||
a = 255
|
||||
switch pixel {
|
||||
case 1:
|
||||
rgb555 := core.Uint16BE(data[i], data[i+1])
|
||||
r, g, b = core.RGB555ToRGB(rgb555)
|
||||
case 2:
|
||||
rgb565 := core.Uint16BE(data[i], data[i+1])
|
||||
r, g, b = core.RGB565ToRGB(rgb565)
|
||||
case 3, 4:
|
||||
fallthrough
|
||||
default:
|
||||
r, g, b = data[i+2], data[i+1], data[i]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// NlaAuthOnly 仅进行NLA认证验证凭据,不建立RDP会话
|
||||
// 这样不会挤掉已登录的用户
|
||||
func (g *Client) NlaAuthOnly(domain, user, pwd string, timeout int64) (bool, error) {
|
||||
@@ -307,7 +209,7 @@ func (g *Client) ProbeOSInfo(host, domain, user, pwd string, timeout int64, rdpP
|
||||
g.pdu.Emit("done")
|
||||
})
|
||||
|
||||
g.x224.SetRequestedProtocol(rdpProtocol) //x224.PROTOCOL_SSL , x224.PROTOCOL_RDP , x224.PROTOCOL_HYBRID , x224.PROTOCOL_HYBRID_EX
|
||||
g.x224.SetRequestedProtocol(rdpProtocol)
|
||||
g.x224.On("reconnect", func(protocol uint32) {
|
||||
info["reconn"] = protocol
|
||||
g.pdu.Emit("close")
|
||||
@@ -353,7 +255,7 @@ func (g *Client) ProbeOSInfo(host, domain, user, pwd string, timeout int64, rdpP
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * time.Duration(timeout)): //
|
||||
case <-time.After(time.Second * time.Duration(timeout)):
|
||||
break loop
|
||||
case <-exitFlag:
|
||||
break loop
|
||||
@@ -365,340 +267,3 @@ loop:
|
||||
glog.Debug("循环结束,总时间过去了:", time.Since(start))
|
||||
return info
|
||||
}
|
||||
|
||||
func (g *Client) ScreenShot(domain, user, pwd string, timeout int64, rdpProtocol uint32) (status bool, err error, reconnProtocol uint32) {
|
||||
//glog.SetLevel(glog.ERROR)
|
||||
reconnProtocol = rdpProtocol
|
||||
pic_length := 1280 //1280
|
||||
pic_width := 800 //800
|
||||
needReconnect := false
|
||||
isScreenOK := false
|
||||
refresh := make(chan bool)
|
||||
exitFlag := make(chan bool)
|
||||
start := time.Now()
|
||||
now := start
|
||||
screenImage := image.NewRGBA(image.Rect(0, 0, pic_length, pic_width))
|
||||
|
||||
targetSlice := strings.Split(g.Host, ":")
|
||||
ip := targetSlice[0]
|
||||
port := targetSlice[1]
|
||||
status = false
|
||||
conn, err := WrapperTcpWithTimeout("tcp", g.Host, time.Duration(timeout)*time.Second)
|
||||
if err != nil {
|
||||
return status, fmt.Errorf("[dial err] %v", err), reconnProtocol
|
||||
}
|
||||
defer conn.Close()
|
||||
glog.Info(conn.LocalAddr().String())
|
||||
|
||||
g.tpkt = tpkt.New(core.NewSocketLayer(conn), nla.NewNTLMv2(domain, user, pwd))
|
||||
g.x224 = x224.New(g.tpkt)
|
||||
g.mcs = t125.NewMCSClient(g.x224)
|
||||
g.sec = sec.NewClient(g.mcs)
|
||||
g.pdu = pdu.NewClient(g.sec)
|
||||
|
||||
g.sec.SetUser(user)
|
||||
g.sec.SetPwd(pwd)
|
||||
g.sec.SetDomain(domain)
|
||||
//g.sec.SetClientAutoReconnect()
|
||||
|
||||
g.tpkt.SetFastPathListener(g.sec)
|
||||
g.sec.SetFastPathListener(g.pdu)
|
||||
g.pdu.SetFastPathSender(g.tpkt)
|
||||
g.sec.SetChannelSender(g.mcs)
|
||||
|
||||
g.tpkt.On("os_info", func(info map[string]any) {
|
||||
glog.Debug("[+] callback, get os info ........................")
|
||||
for k, v := range info {
|
||||
glog.Debugf("%s: %s\n", k, v)
|
||||
}
|
||||
})
|
||||
|
||||
g.x224.SetRequestedProtocol(rdpProtocol) //x224.PROTOCOL_SSL , x224.PROTOCOL_RDP , x224.PROTOCOL_HYBRID , x224.PROTOCOL_HYBRID_EX
|
||||
g.x224.On("reconnect", func(protocol uint32) {
|
||||
needReconnect = true
|
||||
reconnProtocol = protocol
|
||||
glog.Info("need reconnect with protocol:", protocol)
|
||||
g.pdu.Emit("close")
|
||||
exitFlag <- true
|
||||
})
|
||||
g.x224.On("more_timeout", func() {
|
||||
timeout += 18 //如果是PROTOCOL_RDP协议,可以适当延长超时时间
|
||||
})
|
||||
|
||||
err = g.x224.Connect()
|
||||
if err != nil {
|
||||
return status, fmt.Errorf("[x224 connect err] %v", err), reconnProtocol
|
||||
}
|
||||
glog.Info("wait connect ok")
|
||||
|
||||
g.pdu.On("error", func(e error) {
|
||||
err = e
|
||||
glog.Error("error", e)
|
||||
g.pdu.Emit("done")
|
||||
})
|
||||
g.pdu.On("close", func() {
|
||||
err = errors.New("close")
|
||||
glog.Info("on close")
|
||||
g.pdu.Emit("done")
|
||||
})
|
||||
g.pdu.On("success", func() {
|
||||
glog.Debugf("===============login success %s===============", ip)
|
||||
status = true
|
||||
err = nil
|
||||
g.pdu.Emit("done")
|
||||
})
|
||||
g.pdu.On("ready", func() {
|
||||
err = nil
|
||||
glog.Debug("on ready")
|
||||
//g.pdu.Emit("done")
|
||||
})
|
||||
g.pdu.On("bitmap", func(rectangles []pdu.BitmapData) {
|
||||
now = time.Now()
|
||||
// 发送一个鼠标事件,作用是与服务器保持联系不要断开
|
||||
rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
randomNumber := rand.Intn(1000) + 10 // 10到1000之间的随机数
|
||||
mouseX := 60 + randomNumber
|
||||
mouseY := 10 + randomNumber
|
||||
pevent := &pdu.PointerEvent{}
|
||||
pevent.PointerFlags |= pdu.PTRFLAGS_MOVE
|
||||
pevent.XPos = uint16(mouseX)
|
||||
pevent.YPos = uint16(mouseY)
|
||||
g.pdu.SendInputEvents(pdu.INPUT_EVENT_MOUSE, []pdu.InputEventsInterface{pevent})
|
||||
|
||||
glog.Debug("on update bitmap:", len(rectangles))
|
||||
bs := make([]Bitmap, 0)
|
||||
for _, v := range rectangles {
|
||||
IsCompress := v.IsCompress()
|
||||
data := v.BitmapDataStream
|
||||
if IsCompress {
|
||||
data = BitmapDecompress(&v)
|
||||
IsCompress = false
|
||||
}
|
||||
b := Bitmap{int(v.DestLeft), int(v.DestTop), int(v.DestRight), int(v.DestBottom),
|
||||
int(v.Width), int(v.Height), Bpp(v.BitsPerPixel), IsCompress, data}
|
||||
bs = append(bs, b)
|
||||
}
|
||||
var (
|
||||
pixel int
|
||||
i int
|
||||
r, g, b, a uint8
|
||||
)
|
||||
|
||||
for _, bm := range bs {
|
||||
i = 0
|
||||
pixel = bm.BitsPerPixel
|
||||
m := image.NewRGBA(image.Rect(0, 0, bm.Width, bm.Height))
|
||||
for y := 0; y < bm.Height; y++ {
|
||||
for x := 0; x < bm.Width; x++ {
|
||||
r, g, b, a = ToRGBA(pixel, i, bm.Data)
|
||||
c := color.RGBA{R: r, G: g, B: b, A: a}
|
||||
i += pixel
|
||||
m.Set(x, y, c)
|
||||
}
|
||||
}
|
||||
draw.Draw(screenImage, screenImage.Bounds().Add(image.Pt(bm.DestLeft, bm.DestTop)), m, m.Bounds().Min, draw.Src)
|
||||
}
|
||||
// Encode to jpeg.
|
||||
//var imageBuf bytes.Buffer
|
||||
//err = jpeg.Encode(&imageBuf, screenImage, nil)
|
||||
//
|
||||
//if err != nil {
|
||||
// glog.Info("trans bitmap to jpeg err:", err)
|
||||
//}
|
||||
|
||||
// Write to file.
|
||||
//fo, err := os.Create(fmt.Sprintf("img/%s-%d.jpg", ip, index))
|
||||
//if err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
//index += 1
|
||||
//fw := bufio.NewWriter(fo)
|
||||
//fw.Write(imageBuf.Bytes())
|
||||
|
||||
isScreenOK = true
|
||||
refresh <- true
|
||||
|
||||
})
|
||||
g.pdu.On("done", func() {
|
||||
glog.Debug("done信号触发")
|
||||
exitFlag <- true
|
||||
})
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout*6)*time.Second)
|
||||
defer cancel()
|
||||
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * time.Duration(timeout*3)): //
|
||||
glog.Debug("本次获取bitmap超时了, 距离上次获取到图像过去了:", time.Since(now))
|
||||
break loop
|
||||
case <-refresh:
|
||||
continue loop
|
||||
case <-exitFlag:
|
||||
break loop
|
||||
case <-ctx.Done():
|
||||
glog.Debug("总超时已达到,退出")
|
||||
break loop
|
||||
}
|
||||
}
|
||||
glog.Debug("循环结束,总时间过去了:", time.Since(start))
|
||||
|
||||
// 认证结果由 success 事件回调设置,不在此处覆盖
|
||||
|
||||
if needReconnect {
|
||||
return status, err, reconnProtocol
|
||||
} else if isScreenOK {
|
||||
glog.Info("get screen ok")
|
||||
// Encode to jpeg.
|
||||
var imageBuf bytes.Buffer
|
||||
encodeErr := jpeg.Encode(&imageBuf, screenImage, nil)
|
||||
if encodeErr != nil {
|
||||
glog.Error("Failed to encode screenshot:", encodeErr)
|
||||
return status, err, reconnProtocol
|
||||
}
|
||||
|
||||
// Write to file.
|
||||
saveDate := time.Now().Format("2006_01_02_15_04_05")
|
||||
fo, writeErr := os.Create(fmt.Sprintf("%s/%s_%s_%s.jpg", OutputDir, ip, port, saveDate))
|
||||
if writeErr != nil {
|
||||
glog.Error("Can not create rdp screenshot file:", writeErr)
|
||||
} else {
|
||||
defer fo.Close()
|
||||
fw := bufio.NewWriter(fo)
|
||||
_, writeErr := fw.Write(imageBuf.Bytes())
|
||||
if writeErr != nil {
|
||||
glog.Error("Can not write rdp screenshot file:", writeErr)
|
||||
} else {
|
||||
fw.Flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
return status, err, reconnProtocol
|
||||
|
||||
}
|
||||
|
||||
func (g *Client) Crack(domain, user, pwd string, timeout int64, rdpProtocol uint32) (status bool, err error, reconnProtocol uint32) {
|
||||
//glog.SetLevel(glog.ERROR)
|
||||
reconnProtocol = rdpProtocol
|
||||
refresh := make(chan bool)
|
||||
exitFlag := make(chan bool)
|
||||
start := time.Now()
|
||||
now := start
|
||||
|
||||
targetSlice := strings.Split(g.Host, ":")
|
||||
ip := targetSlice[0]
|
||||
status = false
|
||||
conn, err := WrapperTcpWithTimeout("tcp", g.Host, time.Duration(timeout)*time.Second)
|
||||
if err != nil {
|
||||
return status, fmt.Errorf("[dial err] %v", err), reconnProtocol
|
||||
}
|
||||
defer conn.Close()
|
||||
glog.Info(conn.LocalAddr().String())
|
||||
|
||||
g.tpkt = tpkt.New(core.NewSocketLayer(conn), nla.NewNTLMv2(domain, user, pwd))
|
||||
g.x224 = x224.New(g.tpkt)
|
||||
g.mcs = t125.NewMCSClient(g.x224)
|
||||
g.sec = sec.NewClient(g.mcs)
|
||||
g.pdu = pdu.NewClient(g.sec)
|
||||
|
||||
g.sec.SetUser(user)
|
||||
g.sec.SetPwd(pwd)
|
||||
g.sec.SetDomain(domain)
|
||||
//g.sec.SetClientAutoReconnect()
|
||||
|
||||
g.tpkt.SetFastPathListener(g.sec)
|
||||
g.sec.SetFastPathListener(g.pdu)
|
||||
g.pdu.SetFastPathSender(g.tpkt)
|
||||
g.sec.SetChannelSender(g.mcs)
|
||||
|
||||
g.tpkt.On("os_info", func(info map[string]any) {
|
||||
glog.Debug("[+] callback, get os info ........................")
|
||||
for k, v := range info {
|
||||
glog.Debugf("%s: %s\n", k, v)
|
||||
}
|
||||
})
|
||||
|
||||
g.x224.SetRequestedProtocol(rdpProtocol) //x224.PROTOCOL_SSL , x224.PROTOCOL_RDP , x224.PROTOCOL_HYBRID , x224.PROTOCOL_HYBRID_EX
|
||||
g.x224.On("reconnect", func(protocol uint32) {
|
||||
reconnProtocol = protocol
|
||||
glog.Info("need reconnect with protocol:", protocol)
|
||||
g.pdu.Emit("close")
|
||||
exitFlag <- true
|
||||
})
|
||||
g.x224.On("more_timeout", func() {
|
||||
timeout += 18 //如果是PROTOCOL_RDP协议,可以适当延长超时时间
|
||||
})
|
||||
|
||||
err = g.x224.Connect()
|
||||
if err != nil {
|
||||
return status, fmt.Errorf("[x224 connect err] %v", err), reconnProtocol
|
||||
}
|
||||
glog.Info("wait connect ok")
|
||||
|
||||
g.pdu.On("error", func(e error) {
|
||||
err = e
|
||||
glog.Error("error", e)
|
||||
g.pdu.Emit("done")
|
||||
})
|
||||
g.pdu.On("close", func() {
|
||||
err = errors.New("close")
|
||||
glog.Info("on close")
|
||||
g.pdu.Emit("done")
|
||||
})
|
||||
g.pdu.On("success", func() {
|
||||
glog.Debugf("===============login success %s===============", ip)
|
||||
status = true
|
||||
err = nil
|
||||
g.pdu.Emit("done")
|
||||
})
|
||||
g.pdu.On("ready", func() {
|
||||
err = nil
|
||||
glog.Debug("on ready")
|
||||
//g.pdu.Emit("done")
|
||||
})
|
||||
g.pdu.On("bitmap", func(rectangles []pdu.BitmapData) {
|
||||
now = time.Now()
|
||||
// 发送一个鼠标事件,作用是与服务器保持联系不要断开
|
||||
rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
randomNumber := rand.Intn(1000) + 10 // 10到1000之间的随机数
|
||||
mouseX := 60 + randomNumber
|
||||
mouseY := 10 + randomNumber
|
||||
pevent := &pdu.PointerEvent{}
|
||||
pevent.PointerFlags |= pdu.PTRFLAGS_MOVE
|
||||
pevent.XPos = uint16(mouseX)
|
||||
pevent.YPos = uint16(mouseY)
|
||||
g.pdu.SendInputEvents(pdu.INPUT_EVENT_MOUSE, []pdu.InputEventsInterface{pevent})
|
||||
|
||||
glog.Debug("on update bitmap:", len(rectangles))
|
||||
refresh <- true
|
||||
|
||||
})
|
||||
g.pdu.On("done", func() {
|
||||
glog.Debug("done信号触发")
|
||||
exitFlag <- true
|
||||
})
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout*6)*time.Second)
|
||||
defer cancel()
|
||||
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * time.Duration(timeout*3)): //
|
||||
glog.Debug("本次获取bitmap超时了, 距离上次获取到图像过去了:", time.Since(now))
|
||||
break loop
|
||||
case <-refresh:
|
||||
continue loop
|
||||
case <-exitFlag:
|
||||
break loop
|
||||
case <-ctx.Done():
|
||||
glog.Debug("总超时已达到,退出")
|
||||
break loop
|
||||
}
|
||||
}
|
||||
glog.Debug("循环结束,总时间过去了:", time.Since(start))
|
||||
|
||||
// 认证结果由 success 事件回调设置,不在此处覆盖
|
||||
return status, err, reconnProtocol
|
||||
}
|
||||
|
||||
@@ -1,328 +0,0 @@
|
||||
// +build ignore
|
||||
|
||||
// addins.go
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
openHandleSeq uint32
|
||||
freerdpClient2 = syscall.NewLazyDLL("freerdp-client2.dll")
|
||||
winpr2 = syscall.NewLazyDLL("winpr2.dll")
|
||||
freerdp2 = syscall.NewLazyDLL("freerdp2.dll")
|
||||
)
|
||||
|
||||
var (
|
||||
virtualChannelEntry = freerdpClient2.NewProc("VirtualChannelEntry")
|
||||
virtualChannelEntryEx = freerdpClient2.NewProc("VirtualChannelEntryEx")
|
||||
)
|
||||
|
||||
func VirtualChannelEntryEx(ex *ChannelEntryPointsEx, pInitHandle interface{}) (err error) {
|
||||
r0, _, ec := virtualChannelEntryEx.Call(uintptr(unsafe.Pointer(ex)),
|
||||
uintptr(unsafe.Pointer(&pInitHandle)))
|
||||
if r0 == 0 {
|
||||
err = error(ec)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ChannelsClientLoadEx(cs *rdpChannels) {
|
||||
var client ChannelClientData
|
||||
client.entryEx = VIRTUALCHANNELENTRYEX(VirtualChannelEntryEx)
|
||||
cs.clientDataList = append(cs.clientDataList, client)
|
||||
cs.clientDataCount++
|
||||
|
||||
var init ChannelInitData
|
||||
init.channels = cs
|
||||
init.openDataMap = make(map[uint32]*ChannelOpenData)
|
||||
cs.initDataList = append(cs.initDataList, init)
|
||||
cs.initDataCount++
|
||||
|
||||
ex := NewChannelEntryPointsEx()
|
||||
ex.PVirtualChannelInitEx = VIRTUALCHANNELINITEX(RdpVirtualChannelInitEx)
|
||||
ex.PVirtualChannelOpenEx = VIRTUALCHANNELOPENEX(RdpVirtualChannelOpenEx)
|
||||
ex.PVirtualChannelCloseEx = VIRTUALCHANNELCLOSEEX(RdpVirtualChannelCloseEx)
|
||||
ex.PVirtualChannelWriteEx = VIRTUALCHANNELWRITEEX(RdpVirtualChannelWriteEx)
|
||||
client.entryEx(ex, uintptr(unsafe.Pointer(&init)))
|
||||
}
|
||||
|
||||
type ChannelClientData struct {
|
||||
//PVIRTUALCHANNELENTRY entry;
|
||||
entryEx VIRTUALCHANNELENTRYEX
|
||||
// pChannelInitEventProc *CHANNEL_INIT_EVENT_FN
|
||||
pChannelInitEventProcEx CHANNEL_INIT_EVENT_EX_FN
|
||||
pInitHandle interface{}
|
||||
lpUserParam interface{}
|
||||
}
|
||||
type ChannelOpenData struct {
|
||||
name string
|
||||
OpenHandle uint32
|
||||
options uint32
|
||||
flags int
|
||||
pInterface interface{}
|
||||
channels *rdpChannels
|
||||
lpUserParam interface{}
|
||||
//pChannelOpenEventProc *CHANNEL_OPEN_EVENT_FN
|
||||
pChannelOpenEventProcEx *CHANNEL_OPEN_EVENT_EX_FN
|
||||
}
|
||||
type ChannelInitData struct {
|
||||
channels *rdpChannels
|
||||
pInterface interface{}
|
||||
openDataMap map[uint32]*ChannelOpenData
|
||||
}
|
||||
type rdpChannels struct {
|
||||
clientDataCount int
|
||||
clientDataList []ChannelClientData
|
||||
|
||||
openDataCount int
|
||||
openDataList []ChannelOpenData
|
||||
|
||||
initDataCount int
|
||||
initDataList []ChannelInitData
|
||||
|
||||
/* control for entry into MyVirtualChannelInit */
|
||||
can_call_init bool
|
||||
|
||||
/* true once freerdp_channels_post_connect is called */
|
||||
connected bool
|
||||
|
||||
/* used for locating the channels for a given instance */
|
||||
//freerdp* instance;
|
||||
|
||||
//wMessageQueue* queue;
|
||||
|
||||
//DrdynvcClientContext* drdynvc;
|
||||
//CRITICAL_SECTION channelsLock;
|
||||
}
|
||||
type ChannelOpenEvent struct {
|
||||
Data interface{}
|
||||
DataLength uint32
|
||||
UserData interface{}
|
||||
pChannelOpenData *ChannelOpenData
|
||||
}
|
||||
|
||||
func RdpVirtualChannelInitEx(lpUserParam interface{}, clientContext interface{},
|
||||
pInitHandle interface{}, pChannel []ChannelDef,
|
||||
channelCount int, versionRequested uint32,
|
||||
pChannelInitEventProcEx CHANNEL_INIT_EVENT_EX_FN) uint {
|
||||
var (
|
||||
//rdpSettings* settings;
|
||||
pChannelInitData *ChannelInitData
|
||||
pChannelClientData *ChannelClientData
|
||||
channels *rdpChannels
|
||||
)
|
||||
|
||||
if pInitHandle == nil {
|
||||
return CHANNEL_RC_BAD_INIT_HANDLE
|
||||
}
|
||||
|
||||
if pChannel == nil {
|
||||
return CHANNEL_RC_BAD_CHANNEL
|
||||
}
|
||||
|
||||
if (channelCount <= 0) || pChannelInitEventProcEx == nil {
|
||||
return CHANNEL_RC_INITIALIZATION_ERROR
|
||||
}
|
||||
|
||||
pChannelInitData = pInitHandle.(*ChannelInitData)
|
||||
//WINPR_ASSERT(pChannelInitData);
|
||||
|
||||
channels = pChannelInitData.channels
|
||||
//WINPR_ASSERT(channels);
|
||||
|
||||
if !channels.can_call_init {
|
||||
return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY
|
||||
}
|
||||
|
||||
if (channels.openDataCount + channelCount) > 30 {
|
||||
return CHANNEL_RC_TOO_MANY_CHANNELS
|
||||
}
|
||||
|
||||
if channels.connected {
|
||||
return CHANNEL_RC_ALREADY_CONNECTED
|
||||
}
|
||||
|
||||
if versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000 {
|
||||
}
|
||||
|
||||
for i := range pChannel {
|
||||
pChannelDef := &pChannel[i]
|
||||
if getChannelOpenDataByName(channels, pChannelDef.Name) == nil {
|
||||
return CHANNEL_RC_BAD_CHANNEL
|
||||
}
|
||||
}
|
||||
|
||||
pChannelClientData = &channels.clientDataList[channels.clientDataCount]
|
||||
pChannelClientData.pChannelInitEventProcEx = pChannelInitEventProcEx
|
||||
pChannelClientData.pInitHandle = pInitHandle
|
||||
pChannelClientData.lpUserParam = lpUserParam
|
||||
channels.clientDataCount++
|
||||
|
||||
//WINPR_ASSERT(channels->instance);
|
||||
//WINPR_ASSERT(channels->instance->context);
|
||||
//settings = channels.instance.context.settings
|
||||
//WINPR_ASSERT(settings);
|
||||
|
||||
for i := range pChannel {
|
||||
pChannelDef := &pChannel[i]
|
||||
var pChannelOpenData ChannelOpenData
|
||||
|
||||
//WINPR_ASSERT(pChannelOpenData)
|
||||
|
||||
pChannelOpenData.OpenHandle = atomic.AddUint32(&openHandleSeq, 1)
|
||||
pChannelOpenData.channels = channels
|
||||
pChannelOpenData.lpUserParam = lpUserParam
|
||||
if _, ok := pChannelInitData.openDataMap[pChannelOpenData.OpenHandle]; ok {
|
||||
return CHANNEL_RC_INITIALIZATION_ERROR
|
||||
}
|
||||
|
||||
pChannelInitData.pInterface = clientContext
|
||||
|
||||
pChannelOpenData.flags = 1
|
||||
pChannelOpenData.name = pChannelDef.Name
|
||||
pChannelOpenData.options = pChannelDef.Options
|
||||
pChannelInitData.openDataMap[pChannelOpenData.OpenHandle] = &pChannelOpenData
|
||||
channels.openDataList = append(channels.openDataList, pChannelOpenData)
|
||||
channels.openDataCount++
|
||||
/*
|
||||
if settings.ChannelCount < 30 {
|
||||
channel := freerdp_settings_get_pointer_array_writable(
|
||||
settings, FreeRDP_ChannelDefArray, settings.ChannelCount)
|
||||
channel.name = pChannelDef.Name
|
||||
channel.options = pChannelDef.Options
|
||||
settings.ChannelCount++
|
||||
}*/
|
||||
|
||||
channels.openDataCount++
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK
|
||||
}
|
||||
func getChannelOpenDataByName(channel *rdpChannels, name string) *ChannelOpenData {
|
||||
for _, v := range channel.openDataList {
|
||||
if strings.EqualFold(name, v.name) {
|
||||
return &v
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func RdpVirtualChannelOpenEx(pInitHandle interface{}, pOpenHandle *uint32, pChannelName string,
|
||||
pChannelOpenEventProcEx *CHANNEL_OPEN_EVENT_EX_FN) uint {
|
||||
pChannelInitData := pInitHandle.(*ChannelInitData)
|
||||
channels := pChannelInitData.channels
|
||||
pInterface := pChannelInitData.pInterface
|
||||
|
||||
if pOpenHandle == nil {
|
||||
return CHANNEL_RC_BAD_CHANNEL_HANDLE
|
||||
}
|
||||
if pChannelOpenEventProcEx == nil {
|
||||
return CHANNEL_RC_BAD_PROC
|
||||
}
|
||||
|
||||
if !channels.connected {
|
||||
return CHANNEL_RC_NOT_CONNECTED
|
||||
}
|
||||
|
||||
pChannelOpenData := getChannelOpenDataByName(channels, pChannelName)
|
||||
|
||||
if pChannelOpenData == nil {
|
||||
return CHANNEL_RC_UNKNOWN_CHANNEL_NAME
|
||||
}
|
||||
|
||||
if pChannelOpenData.flags == 2 {
|
||||
return CHANNEL_RC_ALREADY_OPEN
|
||||
}
|
||||
|
||||
pChannelOpenData.flags = 2 /* open */
|
||||
pChannelOpenData.pInterface = pInterface
|
||||
pChannelOpenData.pChannelOpenEventProcEx = pChannelOpenEventProcEx
|
||||
*pOpenHandle = pChannelOpenData.OpenHandle
|
||||
return CHANNEL_RC_OK
|
||||
}
|
||||
func RdpVirtualChannelCloseEx(pInitHandle interface{}, openHandle uint32) uint {
|
||||
if pInitHandle == nil {
|
||||
return CHANNEL_RC_BAD_INIT_HANDLE
|
||||
}
|
||||
pChannelInitData := pInitHandle.(*ChannelInitData)
|
||||
pChannelOpenData := pChannelInitData.openDataMap[openHandle]
|
||||
|
||||
if pChannelOpenData == nil {
|
||||
return CHANNEL_RC_BAD_CHANNEL_HANDLE
|
||||
}
|
||||
|
||||
if pChannelOpenData.flags != 2 {
|
||||
return CHANNEL_RC_NOT_OPEN
|
||||
}
|
||||
|
||||
pChannelOpenData.flags = 0
|
||||
|
||||
return CHANNEL_RC_OK
|
||||
}
|
||||
func RdpVirtualChannelWriteEx(pInitHandle interface{}, openHandle uint32,
|
||||
pData interface{}, dataLength uint32,
|
||||
pUserData interface{}) uint {
|
||||
|
||||
//wMessage message;
|
||||
|
||||
if pInitHandle == nil {
|
||||
return CHANNEL_RC_BAD_INIT_HANDLE
|
||||
}
|
||||
|
||||
pChannelInitData := pInitHandle.(*ChannelInitData)
|
||||
channels := pChannelInitData.channels
|
||||
|
||||
if channels == nil {
|
||||
return CHANNEL_RC_BAD_CHANNEL_HANDLE
|
||||
}
|
||||
|
||||
pChannelOpenData := pChannelInitData.openDataMap[openHandle]
|
||||
if pChannelOpenData == nil {
|
||||
return CHANNEL_RC_BAD_CHANNEL_HANDLE
|
||||
}
|
||||
|
||||
if !channels.connected {
|
||||
return CHANNEL_RC_NOT_CONNECTED
|
||||
}
|
||||
|
||||
if pData == nil {
|
||||
return CHANNEL_RC_NULL_DATA
|
||||
}
|
||||
|
||||
if dataLength == 0 {
|
||||
return CHANNEL_RC_ZERO_LENGTH
|
||||
}
|
||||
|
||||
if pChannelOpenData.flags != 2 {
|
||||
return CHANNEL_RC_NOT_OPEN
|
||||
}
|
||||
|
||||
pChannelOpenEvent := new(ChannelOpenEvent)
|
||||
|
||||
if pChannelOpenEvent == nil {
|
||||
return CHANNEL_RC_NO_MEMORY
|
||||
|
||||
}
|
||||
|
||||
pChannelOpenEvent.Data = pData
|
||||
pChannelOpenEvent.DataLength = dataLength
|
||||
pChannelOpenEvent.UserData = pUserData
|
||||
pChannelOpenEvent.pChannelOpenData = pChannelOpenData
|
||||
/*message.context = channels;
|
||||
message.id = 0;
|
||||
message.wParam = pChannelOpenEvent;
|
||||
message.lParam = NULL;
|
||||
message.Free = channel_queue_message_free;
|
||||
|
||||
if (!MessageQueue_Dispatch(channels->queue, &message))
|
||||
{
|
||||
free(pChannelOpenEvent);
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}*/
|
||||
|
||||
return CHANNEL_RC_OK
|
||||
}
|
||||
@@ -1,304 +0,0 @@
|
||||
package plugin
|
||||
|
||||
import "C"
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/glog"
|
||||
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/core"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/emission"
|
||||
)
|
||||
|
||||
const (
|
||||
CHANNEL_RC_OK = 0
|
||||
CHANNEL_RC_ALREADY_INITIALIZED = 1
|
||||
CHANNEL_RC_NOT_INITIALIZED = 2
|
||||
CHANNEL_RC_ALREADY_CONNECTED = 3
|
||||
CHANNEL_RC_NOT_CONNECTED = 4
|
||||
CHANNEL_RC_TOO_MANY_CHANNELS = 5
|
||||
CHANNEL_RC_BAD_CHANNEL = 6
|
||||
CHANNEL_RC_BAD_CHANNEL_HANDLE = 7
|
||||
CHANNEL_RC_NO_BUFFER = 8
|
||||
CHANNEL_RC_BAD_INIT_HANDLE = 9
|
||||
CHANNEL_RC_NOT_OPEN = 10
|
||||
CHANNEL_RC_BAD_PROC = 11
|
||||
CHANNEL_RC_NO_MEMORY = 12
|
||||
CHANNEL_RC_UNKNOWN_CHANNEL_NAME = 13
|
||||
CHANNEL_RC_ALREADY_OPEN = 14
|
||||
CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY = 15
|
||||
CHANNEL_RC_NULL_DATA = 16
|
||||
CHANNEL_RC_ZERO_LENGTH = 17
|
||||
CHANNEL_RC_INVALID_INSTANCE = 18
|
||||
CHANNEL_RC_UNSUPPORTED_VERSION = 19
|
||||
CHANNEL_RC_INITIALIZATION_ERROR = 20
|
||||
)
|
||||
const (
|
||||
VIRTUAL_CHANNEL_VERSION_WIN2000 = 1
|
||||
)
|
||||
|
||||
const (
|
||||
CHANNEL_EVENT_INITIALIZED = 0
|
||||
CHANNEL_EVENT_CONNECTED = 1
|
||||
CHANNEL_EVENT_V1_CONNECTED = 2
|
||||
CHANNEL_EVENT_DISCONNECTED = 3
|
||||
CHANNEL_EVENT_TERMINATED = 4
|
||||
CHANNEL_EVENT_REMOTE_CONTROL_START = 5
|
||||
CHANNEL_EVENT_REMOTE_CONTROL_STOP = 6
|
||||
CHANNEL_EVENT_ATTACHED = 7
|
||||
CHANNEL_EVENT_DETACHED = 8
|
||||
CHANNEL_EVENT_DATA_RECEIVED = 10
|
||||
CHANNEL_EVENT_WRITE_COMPLETE = 11
|
||||
CHANNEL_EVENT_WRITE_CANCELLED = 12
|
||||
)
|
||||
|
||||
const (
|
||||
CHANNEL_OPTION_INITIALIZED = 0x80000000
|
||||
CHANNEL_OPTION_ENCRYPT_RDP = 0x40000000
|
||||
CHANNEL_OPTION_ENCRYPT_SC = 0x20000000
|
||||
CHANNEL_OPTION_ENCRYPT_CS = 0x10000000
|
||||
CHANNEL_OPTION_PRI_HIGH = 0x08000000
|
||||
CHANNEL_OPTION_PRI_MED = 0x04000000
|
||||
CHANNEL_OPTION_PRI_LOW = 0x02000000
|
||||
CHANNEL_OPTION_COMPRESS_RDP = 0x00800000
|
||||
CHANNEL_OPTION_COMPRESS = 0x00400000
|
||||
CHANNEL_OPTION_SHOW_PROTOCOL = 0x00200000
|
||||
CHANNEL_OPTION_REMOTE_CONTROL_PERSISTENT = 0x00100000
|
||||
)
|
||||
|
||||
type ChannelDef struct {
|
||||
Name string
|
||||
Options uint32
|
||||
}
|
||||
type CHANNEL_INIT_EVENT_EX_FN func(lpUserParam interface{},
|
||||
pInitHandle interface{}, event uint, pData uintptr, dataLength uint)
|
||||
type VIRTUALCHANNELINITEX func(lpUserParam interface{}, clientContext interface{},
|
||||
pInitHandle interface{}, pChannel []ChannelDef,
|
||||
channelCount int, versionRequested uint32,
|
||||
pChannelInitEventProcEx CHANNEL_INIT_EVENT_EX_FN) uint
|
||||
|
||||
type CHANNEL_OPEN_EVENT_EX_FN func(lpUserParam uintptr,
|
||||
openHandle uint32, event uint,
|
||||
pData uintptr, dataLength uint32, totalLength uint32, dataFlags uint32)
|
||||
type VIRTUALCHANNELOPENEX func(pInitHandle interface{}, pOpenHandle *uint32,
|
||||
pChannelName string,
|
||||
pChannelOpenEventProcEx *CHANNEL_OPEN_EVENT_EX_FN) uint
|
||||
|
||||
type VIRTUALCHANNELCLOSEEX func(pInitHandle interface{}, openHandle uint32) uint
|
||||
|
||||
type VIRTUALCHANNELWRITEEX func(pInitHandle interface{}, openHandle uint32, pData interface{},
|
||||
dataLength uint32, pUserData interface{}) uint
|
||||
|
||||
type ChannelEntryPointsEx struct {
|
||||
CbSize uint32
|
||||
ProtocolVersion uint32
|
||||
PVirtualChannelInitEx VIRTUALCHANNELINITEX
|
||||
PVirtualChannelOpenEx VIRTUALCHANNELOPENEX
|
||||
PVirtualChannelCloseEx VIRTUALCHANNELCLOSEEX
|
||||
PVirtualChannelWriteEx VIRTUALCHANNELWRITEEX
|
||||
}
|
||||
|
||||
func NewChannelEntryPointsEx() *ChannelEntryPointsEx {
|
||||
e := &ChannelEntryPointsEx{}
|
||||
e.CbSize = uint32(unsafe.Sizeof(e))
|
||||
e.ProtocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000
|
||||
return e
|
||||
}
|
||||
|
||||
type VIRTUALCHANNELENTRYEX func(pEntryPointsEx *ChannelEntryPointsEx,
|
||||
pInitHandle interface{}) error
|
||||
|
||||
/*
|
||||
type ChannelEntryPoints struct {
|
||||
CbSize uint32
|
||||
ProtocolVersion uint32
|
||||
PVirtualChannelInit PVIRTUALCHANNELINIT
|
||||
PVirtualChannelOpen PVIRTUALCHANNELOPEN
|
||||
PVirtualChannelClose PVIRTUALCHANNELCLOSE
|
||||
PVirtualChannelWrite PVIRTUALCHANNELWRITE
|
||||
}
|
||||
typedef VOID VCAPITYPE CHANNEL_INIT_EVENT_FN(LPVOID pInitHandle,
|
||||
UINT event, LPVOID pData, UINT dataLength);
|
||||
|
||||
typedef CHANNEL_INIT_EVENT_FN* PCHANNEL_INIT_EVENT_FN;
|
||||
typedef VOID VCAPITYPE CHANNEL_OPEN_EVENT_FN(DWORD openHandle, UINT event,
|
||||
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags);
|
||||
|
||||
typedef CHANNEL_OPEN_EVENT_FN* PCHANNEL_OPEN_EVENT_FN;
|
||||
typedef UINT VCAPITYPE VIRTUALCHANNELINIT(LPVOID* ppInitHandle, PCHANNEL_DEF pChannel,
|
||||
INT channelCount, ULONG versionRequested,
|
||||
PCHANNEL_INIT_EVENT_FN pChannelInitEventProc);
|
||||
typedef VIRTUALCHANNELINIT* PVIRTUALCHANNELINIT;
|
||||
|
||||
typedef UINT VCAPITYPE VIRTUALCHANNELOPEN(LPVOID pInitHandle, LPDWORD pOpenHandle,
|
||||
PCHAR pChannelName,
|
||||
PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc);
|
||||
|
||||
typedef VIRTUALCHANNELOPEN* PVIRTUALCHANNELOPEN;
|
||||
|
||||
typedef UINT VCAPITYPE VIRTUALCHANNELCLOSE(DWORD openHandle);
|
||||
typedef VIRTUALCHANNELCLOSE* PVIRTUALCHANNELCLOSE;
|
||||
|
||||
typedef UINT VCAPITYPE VIRTUALCHANNELWRITE(DWORD openHandle, LPVOID pData, ULONG dataLength,
|
||||
LPVOID pUserData);
|
||||
typedef VIRTUALCHANNELWRITE* PVIRTUALCHANNELWRITE;
|
||||
|
||||
typedef UINT VCAPITYPE VIRTUALCHANNELINITEX(LPVOID lpUserParam, LPVOID clientContext,
|
||||
LPVOID pInitHandle, PCHANNEL_DEF pChannel,
|
||||
INT channelCount, ULONG versionRequested,
|
||||
PCHANNEL_INIT_EVENT_EX_FN pChannelInitEventProcEx);
|
||||
typedef VIRTUALCHANNELINITEX* PVIRTUALCHANNELINITEX;
|
||||
|
||||
typedef UINT VCAPITYPE VIRTUALCHANNELOPENEX(LPVOID pInitHandle, LPDWORD pOpenHandle,
|
||||
PCHAR pChannelName,
|
||||
PCHANNEL_OPEN_EVENT_EX_FN pChannelOpenEventProcEx);
|
||||
typedef VIRTUALCHANNELOPENEX* PVIRTUALCHANNELOPENEX;
|
||||
|
||||
|
||||
typedef UINT VCAPITYPE VIRTUALCHANNELCLOSEEX(LPVOID pInitHandle, DWORD openHandle);
|
||||
typedef VIRTUALCHANNELCLOSEEX* PVIRTUALCHANNELCLOSEEX;
|
||||
|
||||
typedef UINT VCAPITYPE VIRTUALCHANNELWRITEEX(LPVOID pInitHandle, DWORD openHandle, LPVOID pData,
|
||||
ULONG dataLength, LPVOID pUserData);
|
||||
typedef VIRTUALCHANNELWRITEEX* PVIRTUALCHANNELWRITEEX;
|
||||
*/
|
||||
|
||||
// static channel name
|
||||
const (
|
||||
CLIPRDR_SVC_CHANNEL_NAME = "cliprdr" //剪切板
|
||||
RDPDR_SVC_CHANNEL_NAME = "rdpdr" //设备重定向(打印机,磁盘,端口,智能卡等)
|
||||
RDPSND_SVC_CHANNEL_NAME = "rdpsnd" //音频输出
|
||||
RAIL_SVC_CHANNEL_NAME = "rail" //远程应用
|
||||
DRDYNVC_SVC_CHANNEL_NAME = "drdynvc" //动态虚拟通道
|
||||
REMDESK_SVC_CHANNEL_NAME = "remdesk" //远程协助
|
||||
)
|
||||
|
||||
const (
|
||||
RDPGFX_DVC_CHANNEL_NAME = "Microsoft::Windows::RDS::Graphics" //图形扩展
|
||||
)
|
||||
|
||||
var StaticVirtualChannels = map[string]int{
|
||||
CLIPRDR_SVC_CHANNEL_NAME: CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
|
||||
CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL,
|
||||
RDPDR_SVC_CHANNEL_NAME: CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP,
|
||||
RDPSND_SVC_CHANNEL_NAME: CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
|
||||
CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL,
|
||||
RAIL_SVC_CHANNEL_NAME: CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
|
||||
CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL,
|
||||
}
|
||||
|
||||
const (
|
||||
CHANNEL_CHUNK_LENGTH = 1600
|
||||
CHANNEL_FLAG_FIRST = 0x01
|
||||
CHANNEL_FLAG_LAST = 0x02
|
||||
CHANNEL_FLAG_SHOW_PROTOCOL = 0x10
|
||||
)
|
||||
|
||||
type ChannelTransport interface {
|
||||
GetType() (string, uint32)
|
||||
Sender(core.ChannelSender)
|
||||
Process(s []byte)
|
||||
}
|
||||
type ChannelClient struct {
|
||||
ChannelDef
|
||||
t ChannelTransport
|
||||
}
|
||||
|
||||
type Channels struct {
|
||||
emission.Emitter
|
||||
channels map[string]ChannelClient
|
||||
transport core.Transport
|
||||
buff *bytes.Buffer
|
||||
channelSender core.ChannelSender
|
||||
}
|
||||
|
||||
func NewChannels(t core.Transport) *Channels {
|
||||
c := &Channels{
|
||||
Emitter: *emission.NewEmitter(),
|
||||
channels: make(map[string]ChannelClient, 20),
|
||||
transport: t,
|
||||
buff: &bytes.Buffer{},
|
||||
}
|
||||
t.On("channel", c.process)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Channels) SetChannelSender(f core.ChannelSender) {
|
||||
c.channelSender = f
|
||||
}
|
||||
func (c *Channels) Register(t ChannelTransport) {
|
||||
name, option := t.GetType()
|
||||
_, ok := c.channels[name]
|
||||
if ok {
|
||||
glog.Warn("Already register channel:", name)
|
||||
return
|
||||
}
|
||||
t.Sender(c)
|
||||
c.channels[name] = ChannelClient{ChannelDef{name, option}, t}
|
||||
}
|
||||
|
||||
func (c *Channels) SendToChannel(channel string, s []byte) (int, error) {
|
||||
cli, ok := c.channels[channel]
|
||||
if !ok {
|
||||
glog.Warn("No register channel:", channel)
|
||||
return 0, fmt.Errorf("No register channel: %s", channel)
|
||||
}
|
||||
idx := 0
|
||||
ln := len(s)
|
||||
b := &bytes.Buffer{}
|
||||
for ln > 0 {
|
||||
var flag uint32 = 0
|
||||
if cli.Options&CHANNEL_OPTION_SHOW_PROTOCOL != 0 {
|
||||
flag |= CHANNEL_FLAG_SHOW_PROTOCOL
|
||||
}
|
||||
if idx == 0 {
|
||||
flag |= CHANNEL_FLAG_FIRST
|
||||
}
|
||||
|
||||
var ss []byte
|
||||
if ln > CHANNEL_CHUNK_LENGTH {
|
||||
ss = s[idx : idx+CHANNEL_CHUNK_LENGTH]
|
||||
idx += CHANNEL_CHUNK_LENGTH
|
||||
} else {
|
||||
flag |= CHANNEL_FLAG_LAST
|
||||
ss = s[idx : idx+ln]
|
||||
}
|
||||
glog.Debug("len:", len(ss), "flag:", flag)
|
||||
ln -= len(ss)
|
||||
b.Reset()
|
||||
core.WriteUInt32LE(uint32(len(s)), b)
|
||||
core.WriteUInt32LE(flag, b)
|
||||
b.Write(ss)
|
||||
c.channelSender.SendToChannel(channel, b.Bytes())
|
||||
}
|
||||
return ln, nil
|
||||
}
|
||||
|
||||
func (c *Channels) process(channel string, s []byte) {
|
||||
cli, ok := c.channels[channel]
|
||||
if !ok {
|
||||
glog.Warn("No found channel:", channel)
|
||||
return
|
||||
}
|
||||
r := bytes.NewReader(s)
|
||||
ln, _ := core.ReadUInt32LE(r)
|
||||
flags, _ := core.ReadUInt32LE(r)
|
||||
glog.Debugf("channel:%s length: %d, flags: %d", channel, ln, flags)
|
||||
if flags&CHANNEL_FLAG_FIRST == 0 || flags&CHANNEL_FLAG_LAST == 0 {
|
||||
if flags&CHANNEL_FLAG_FIRST != 0 {
|
||||
c.buff.Reset()
|
||||
}
|
||||
b, _ := core.ReadBytes(r.Len(), r)
|
||||
c.buff.Write(b)
|
||||
if flags&CHANNEL_FLAG_LAST == 0 {
|
||||
return
|
||||
}
|
||||
s = c.buff.Bytes()
|
||||
} else {
|
||||
s, _ = core.ReadBytes(r.Len(), r)
|
||||
}
|
||||
|
||||
cli.t.Process(s)
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
package drdynvc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/core"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/glog"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/plugin"
|
||||
)
|
||||
|
||||
const (
|
||||
ChannelName = plugin.DRDYNVC_SVC_CHANNEL_NAME
|
||||
ChannelOption = plugin.CHANNEL_OPTION_INITIALIZED |
|
||||
plugin.CHANNEL_OPTION_ENCRYPT_RDP
|
||||
)
|
||||
|
||||
const (
|
||||
MAX_DVC_CHANNELS = 20
|
||||
)
|
||||
|
||||
const (
|
||||
DYNVC_CREATE_REQ = 0x01
|
||||
DYNVC_DATA_FIRST = 0x02
|
||||
DYNVC_DATA = 0x03
|
||||
DYNVC_CLOSE = 0x04
|
||||
DYNVC_CAPABILITIES = 0x05
|
||||
DYNVC_DATA_FIRST_COMPRESSED = 0x06
|
||||
DYNVC_DATA_COMPRESSED = 0x07
|
||||
DYNVC_SOFT_SYNC_REQUEST = 0x08
|
||||
DYNVC_SOFT_SYNC_RESPONSE = 0x09
|
||||
)
|
||||
|
||||
type ChannelClient struct {
|
||||
}
|
||||
|
||||
type DvcClient struct {
|
||||
w core.ChannelSender
|
||||
channels map[string]ChannelClient
|
||||
}
|
||||
|
||||
func NewDvcClient() *DvcClient {
|
||||
return &DvcClient{
|
||||
channels: make(map[string]ChannelClient, 100),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *DvcClient) LoadAddin(f core.ChannelSender) {
|
||||
|
||||
}
|
||||
|
||||
type DvcHeader struct {
|
||||
cmd uint8
|
||||
sp uint8
|
||||
cbChId uint8
|
||||
}
|
||||
|
||||
func readHeader(r io.Reader) *DvcHeader {
|
||||
value, _ := core.ReadUInt8(r)
|
||||
cmd := (value & 0xf0) >> 4
|
||||
sp := (value & 0x0c) >> 2
|
||||
cbChId := (value & 0x03) >> 0
|
||||
return &DvcHeader{cmd, sp, cbChId}
|
||||
}
|
||||
|
||||
func (h *DvcHeader) serialize(channelId uint32) []byte {
|
||||
b := &bytes.Buffer{}
|
||||
core.WriteUInt8((h.cmd<<4)|(h.sp<<2)|h.cbChId, b)
|
||||
if h.cbChId == 0 {
|
||||
core.WriteUInt8(uint8(channelId), b)
|
||||
} else if h.cbChId == 1 {
|
||||
core.WriteUInt16LE(uint16(channelId), b)
|
||||
} else {
|
||||
core.WriteUInt32LE(channelId, b)
|
||||
}
|
||||
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func (c *DvcClient) Send(s []byte) (int, error) {
|
||||
glog.Debug("len:", len(s), "data:", hex.EncodeToString(s))
|
||||
name, _ := c.GetType()
|
||||
return c.w.SendToChannel(name, s)
|
||||
}
|
||||
func (c *DvcClient) Sender(f core.ChannelSender) {
|
||||
c.w = f
|
||||
}
|
||||
func (c *DvcClient) GetType() (string, uint32) {
|
||||
return ChannelName, ChannelOption
|
||||
}
|
||||
|
||||
func (c *DvcClient) Process(s []byte) {
|
||||
glog.Debug("recv:", hex.EncodeToString(s))
|
||||
r := bytes.NewReader(s)
|
||||
hdr := readHeader(r)
|
||||
glog.Infof("dvc: Cmd=0x%x, Sp=%d CbChId=%d all=%d", hdr.cmd, hdr.sp, hdr.cbChId, r.Len())
|
||||
|
||||
b, _ := core.ReadBytes(r.Len(), r)
|
||||
|
||||
switch hdr.cmd {
|
||||
case DYNVC_CAPABILITIES:
|
||||
glog.Info("DYNVC_CAPABILITIES")
|
||||
c.processCapsPdu(hdr, b)
|
||||
case DYNVC_CREATE_REQ:
|
||||
glog.Info("DYNVC_CREATE_REQ")
|
||||
c.processCreateReq(hdr, b)
|
||||
case DYNVC_DATA_FIRST:
|
||||
glog.Info("DYNVC_DATA_FIRST")
|
||||
case DYNVC_DATA:
|
||||
glog.Info("DYNVC_DATA")
|
||||
case DYNVC_CLOSE:
|
||||
glog.Info("DYNVC_CLOSE")
|
||||
default:
|
||||
glog.Errorf("type 0x%x not supported", hdr.cmd)
|
||||
}
|
||||
}
|
||||
func (c *DvcClient) processCreateReq(hdr *DvcHeader, s []byte) {
|
||||
r := bytes.NewReader(s)
|
||||
channelId := readDvcId(r, hdr.cbChId)
|
||||
name, _ := core.ReadBytes(r.Len(), r)
|
||||
channelName := string(name)
|
||||
glog.Infof("Server requests channelId=%d, name=%s", channelId, channelName)
|
||||
|
||||
//response
|
||||
b := &bytes.Buffer{}
|
||||
b.Write(hdr.serialize(channelId))
|
||||
core.WriteUInt32LE(0, b)
|
||||
c.Send(b.Bytes())
|
||||
}
|
||||
|
||||
func readDvcId(r io.Reader, cbLen uint8) (id uint32) {
|
||||
switch cbLen {
|
||||
case 0:
|
||||
i, _ := core.ReadUInt8(r)
|
||||
id = uint32(i)
|
||||
case 1:
|
||||
i, _ := core.ReadUint16LE(r)
|
||||
id = uint32(i)
|
||||
default:
|
||||
id, _ = core.ReadUInt32LE(r)
|
||||
}
|
||||
return
|
||||
}
|
||||
func (c *DvcClient) processCapsPdu(hdr *DvcHeader, s []byte) {
|
||||
r := bytes.NewReader(s)
|
||||
core.ReadUInt8(r)
|
||||
ver, _ := core.ReadUint16LE(r)
|
||||
glog.Infof("Server supports dvc=%d", ver)
|
||||
|
||||
hdr.cmd = DYNVC_CAPABILITIES
|
||||
hdr.cbChId = 0
|
||||
hdr.sp = 0
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
core.WriteUInt16LE(0x0050, b)
|
||||
core.WriteUInt16LE(ver, b)
|
||||
c.Send(b.Bytes())
|
||||
}
|
||||
@@ -1,451 +0,0 @@
|
||||
// rail.go
|
||||
package rail
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/core"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/glog"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/plugin"
|
||||
)
|
||||
|
||||
const (
|
||||
ChannelName = plugin.RAIL_SVC_CHANNEL_NAME
|
||||
ChannelOption = plugin.CHANNEL_OPTION_INITIALIZED | plugin.CHANNEL_OPTION_ENCRYPT_RDP |
|
||||
plugin.CHANNEL_OPTION_COMPRESS_RDP | plugin.CHANNEL_OPTION_SHOW_PROTOCOL
|
||||
)
|
||||
|
||||
const (
|
||||
TS_RAIL_ORDER_EXEC = 0x0001
|
||||
TS_RAIL_ORDER_ACTIVATE = 0x0002
|
||||
TS_RAIL_ORDER_SYSPARAM = 0x0003
|
||||
TS_RAIL_ORDER_SYSCOMMAND = 0x0004
|
||||
TS_RAIL_ORDER_HANDSHAKE = 0x0005
|
||||
TS_RAIL_ORDER_NOTIFY_EVENT = 0x0006
|
||||
TS_RAIL_ORDER_WINDOWMOVE = 0x0008
|
||||
TS_RAIL_ORDER_LOCALMOVESIZE = 0x0009
|
||||
TS_RAIL_ORDER_MINMAXINFO = 0x000A
|
||||
TS_RAIL_ORDER_CLIENTSTATUS = 0x000B
|
||||
TS_RAIL_ORDER_SYSMENU = 0x000C
|
||||
TS_RAIL_ORDER_LANGBARINFO = 0x000D
|
||||
TS_RAIL_ORDER_GET_APPID_REQ = 0x000E
|
||||
TS_RAIL_ORDER_GET_APPID_RESP = 0x000F
|
||||
TS_RAIL_ORDER_TASKBARINFO = 0x0010
|
||||
TS_RAIL_ORDER_LANGUAGEIMEINFO = 0x0011
|
||||
TS_RAIL_ORDER_COMPARTMENTINFO = 0x0012
|
||||
TS_RAIL_ORDER_HANDSHAKE_EX = 0x0013
|
||||
TS_RAIL_ORDER_ZORDER_SYNC = 0x0014
|
||||
TS_RAIL_ORDER_CLOAK = 0x0015
|
||||
TS_RAIL_ORDER_POWER_DISPLAY_REQUEST = 0x0016
|
||||
TS_RAIL_ORDER_SNAP_ARRANGE = 0x0017
|
||||
TS_RAIL_ORDER_GET_APPID_RESP_EX = 0x0018
|
||||
TS_RAIL_ORDER_EXEC_RESULT = 0x0080
|
||||
)
|
||||
|
||||
type RailClient struct {
|
||||
w core.ChannelSender
|
||||
DesktopWidth uint16
|
||||
DesktopHeight uint16
|
||||
RemoteApplicationProgram string
|
||||
ShellWorkingDirectory string
|
||||
RemoteApplicationCmdLine string
|
||||
}
|
||||
|
||||
func NewClient() *RailClient {
|
||||
return &RailClient{
|
||||
DesktopWidth: 800,
|
||||
DesktopHeight: 600,
|
||||
RemoteApplicationProgram: "calc",
|
||||
ShellWorkingDirectory: "/tmp",
|
||||
}
|
||||
}
|
||||
|
||||
type RailPDUHeader struct {
|
||||
OrderType uint16 `struc:"little"`
|
||||
OrderLength uint16 `struc:"little"`
|
||||
}
|
||||
|
||||
func NewRailPDUHeader(mType, ln uint16) *RailPDUHeader {
|
||||
return &RailPDUHeader{
|
||||
OrderType: mType,
|
||||
OrderLength: ln,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *RailPDUHeader) serialize() []byte {
|
||||
b := &bytes.Buffer{}
|
||||
core.WriteUInt16LE(h.OrderType, b)
|
||||
core.WriteUInt16LE(h.OrderLength, b)
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func (c *RailClient) sendData(mType uint16, ln int, s []byte) {
|
||||
glog.Debug(ln, ":ln:", len(s), "data:", hex.EncodeToString(s))
|
||||
header := NewRailPDUHeader(mType, uint16(ln))
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
core.WriteBytes(header.serialize(), b)
|
||||
core.WriteBytes(s, b)
|
||||
|
||||
c.Send(b.Bytes())
|
||||
}
|
||||
|
||||
func (c *RailClient) Send(s []byte) (int, error) {
|
||||
glog.Debug("len:", len(s), "data:", hex.EncodeToString(s))
|
||||
name, _ := c.GetType()
|
||||
return c.w.SendToChannel(name, s)
|
||||
}
|
||||
func (c *RailClient) Sender(f core.ChannelSender) {
|
||||
c.w = f
|
||||
}
|
||||
func (c *RailClient) GetType() (string, uint32) {
|
||||
return ChannelName, ChannelOption
|
||||
}
|
||||
|
||||
func (c *RailClient) Process(s []byte) {
|
||||
glog.Debug("recv:", hex.EncodeToString(s))
|
||||
r := bytes.NewReader(s)
|
||||
msgType, _ := core.ReadUint16LE(r)
|
||||
length, _ := core.ReadUint16LE(r)
|
||||
|
||||
glog.Infof("rail: type=0x%x length=%d, all=%d", msgType, length, r.Len())
|
||||
|
||||
b, _ := core.ReadBytes(int(length), r)
|
||||
glog.Info("b:", hex.EncodeToString(b))
|
||||
|
||||
switch msgType {
|
||||
case TS_RAIL_ORDER_HANDSHAKE:
|
||||
glog.Info("TS_RAIL_ORDER_HANDSHAKE")
|
||||
c.processOrderHandshake(b)
|
||||
case TS_RAIL_ORDER_SYSPARAM:
|
||||
glog.Info("TS_RAIL_ORDER_SYSPARAM")
|
||||
c.processOrderSysparam(b)
|
||||
case TS_RAIL_ORDER_EXEC_RESULT:
|
||||
glog.Info("TS_RAIL_ORDER_EXEC_RESULT")
|
||||
c.processExecResult(b)
|
||||
|
||||
default:
|
||||
glog.Errorf("type 0x%x not supported", msgType)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *RailClient) processOrderHandshake(b []byte) {
|
||||
r := bytes.NewReader(b)
|
||||
buildNumber, _ := core.ReadUInt32LE(r)
|
||||
glog.Info("buildNumber:", buildNumber)
|
||||
|
||||
//send client info
|
||||
c.sendClientStatus()
|
||||
|
||||
//send client systemparam
|
||||
c.sendClientSystemparam()
|
||||
|
||||
//send client execute
|
||||
c.sendClientExecute()
|
||||
}
|
||||
|
||||
const (
|
||||
TS_RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE = 0x00000001
|
||||
TS_RAIL_CLIENTSTATUS_AUTORECONNECT = 0x00000002
|
||||
TS_RAIL_CLIENTSTATUS_ZORDER_SYNC = 0x00000004
|
||||
TS_RAIL_CLIENTSTATUS_WINDOW_RESIZE_MARGIN_SUPPORTED = 0x00000010
|
||||
TS_RAIL_CLIENTSTATUS_HIGH_DPI_ICONS_SUPPORTED = 0x00000020
|
||||
TS_RAIL_CLIENTSTATUS_APPBAR_REMOTING_SUPPORTED = 0x00000040
|
||||
TS_RAIL_CLIENTSTATUS_POWER_DISPLAY_REQUEST_SUPPORTED = 0x00000080
|
||||
TS_RAIL_CLIENTSTATUS_GET_APPID_RESPONSE_EX_SUPPORTED = 0x00000100
|
||||
TS_RAIL_CLIENTSTATUS_BIDIRECTIONAL_CLOAK_SUPPORTED = 0x00000200
|
||||
)
|
||||
|
||||
func (c *RailClient) sendClientStatus() {
|
||||
glog.Info("Send client Status")
|
||||
var flags uint32 = TS_RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE
|
||||
|
||||
//if (settings->AutoReconnectionEnabled)
|
||||
//clientStatus.flags |= TS_RAIL_CLIENTSTATUS_AUTORECONNECT;
|
||||
|
||||
flags |= TS_RAIL_CLIENTSTATUS_ZORDER_SYNC
|
||||
flags |= TS_RAIL_CLIENTSTATUS_WINDOW_RESIZE_MARGIN_SUPPORTED
|
||||
flags |= TS_RAIL_CLIENTSTATUS_APPBAR_REMOTING_SUPPORTED
|
||||
flags |= TS_RAIL_CLIENTSTATUS_POWER_DISPLAY_REQUEST_SUPPORTED
|
||||
flags |= TS_RAIL_CLIENTSTATUS_BIDIRECTIONAL_CLOAK_SUPPORTED
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
core.WriteUInt32LE(flags, b)
|
||||
|
||||
c.sendData(TS_RAIL_ORDER_CLIENTSTATUS, 4, b.Bytes())
|
||||
}
|
||||
|
||||
const (
|
||||
SPI_SET_SCREEN_SAVE_ACTIVE = 0x00000011
|
||||
SPI_SET_SCREEN_SAVE_SECURE = 0x00000077
|
||||
)
|
||||
const (
|
||||
/*Bit mask values for SPI_ parameters*/
|
||||
SPI_MASK_SET_DRAG_FULL_WINDOWS = 0x00000001
|
||||
SPI_MASK_SET_KEYBOARD_CUES = 0x00000002
|
||||
SPI_MASK_SET_KEYBOARD_PREF = 0x00000004
|
||||
SPI_MASK_SET_MOUSE_BUTTON_SWAP = 0x00000008
|
||||
SPI_MASK_SET_WORK_AREA = 0x00000010
|
||||
SPI_MASK_DISPLAY_CHANGE = 0x00000020
|
||||
SPI_MASK_TASKBAR_POS = 0x00000040
|
||||
SPI_MASK_SET_HIGH_CONTRAST = 0x00000080
|
||||
SPI_MASK_SET_SCREEN_SAVE_ACTIVE = 0x00000100
|
||||
SPI_MASK_SET_SET_SCREEN_SAVE_SECURE = 0x00000200
|
||||
SPI_MASK_SET_CARET_WIDTH = 0x00000400
|
||||
SPI_MASK_SET_STICKY_KEYS = 0x00000800
|
||||
SPI_MASK_SET_TOGGLE_KEYS = 0x00001000
|
||||
SPI_MASK_SET_FILTER_KEYS = 0x00002000
|
||||
)
|
||||
const (
|
||||
SPI_SET_DRAG_FULL_WINDOWS = 0x00000025
|
||||
SPI_SET_KEYBOARD_CUES = 0x0000100B
|
||||
SPI_SET_KEYBOARD_PREF = 0x00000045
|
||||
SPI_SET_MOUSE_BUTTON_SWAP = 0x00000021
|
||||
SPI_SET_WORK_AREA = 0x0000002F
|
||||
SPI_DISPLAY_CHANGE = 0x0000F001
|
||||
SPI_TASKBAR_POS = 0x0000F000
|
||||
SPI_SET_HIGH_CONTRAST = 0x00000043
|
||||
SPI_SETCARETWIDTH = 0x00002007
|
||||
SPI_SETSTICKYKEYS = 0x0000003B
|
||||
SPI_SETTOGGLEKEYS = 0x00000035
|
||||
SPI_SETFILTERKEYS = 0x00000033
|
||||
)
|
||||
|
||||
type TsFilterKeys struct {
|
||||
Flags uint32
|
||||
WaitTime uint32
|
||||
DelayTime uint32
|
||||
RepeatTime uint32
|
||||
BounceTime uint32
|
||||
}
|
||||
type RailHighContrast struct {
|
||||
flags uint32
|
||||
colorSchemeLength uint32
|
||||
colorScheme string
|
||||
}
|
||||
type Rectangle16 struct {
|
||||
left uint16
|
||||
top uint16
|
||||
right uint16
|
||||
bottom uint16
|
||||
}
|
||||
type RailSysparamOrder struct {
|
||||
param uint32
|
||||
params uint32
|
||||
dragFullWindows uint8
|
||||
keyboardCues uint8
|
||||
keyboardPref uint8
|
||||
mouseButtonSwap uint8
|
||||
workArea Rectangle16
|
||||
displayChange Rectangle16
|
||||
taskbarPos Rectangle16
|
||||
highContrast RailHighContrast
|
||||
caretWidth uint32
|
||||
stickyKeys uint32
|
||||
toggleKeys uint32
|
||||
filterKeys TsFilterKeys
|
||||
setScreenSaveActive uint8
|
||||
setScreenSaveSecure uint8
|
||||
}
|
||||
|
||||
func (c *RailClient) sendClientSystemparam() {
|
||||
glog.Info("Send client Systemparam")
|
||||
|
||||
var sp RailSysparamOrder
|
||||
sp.params = 0
|
||||
sp.params |= SPI_MASK_SET_HIGH_CONTRAST
|
||||
sp.highContrast.colorScheme = ""
|
||||
sp.highContrast.colorSchemeLength = 0
|
||||
sp.highContrast.flags = 0x7E
|
||||
sp.params |= SPI_MASK_SET_MOUSE_BUTTON_SWAP
|
||||
sp.mouseButtonSwap = 0
|
||||
sp.params |= SPI_MASK_SET_KEYBOARD_PREF
|
||||
sp.keyboardPref = 0
|
||||
sp.params |= SPI_MASK_SET_DRAG_FULL_WINDOWS
|
||||
sp.dragFullWindows = 0
|
||||
sp.params |= SPI_MASK_SET_KEYBOARD_CUES
|
||||
sp.keyboardCues = 0
|
||||
sp.params |= SPI_MASK_SET_WORK_AREA
|
||||
sp.workArea.left = 0
|
||||
sp.workArea.top = 0
|
||||
sp.workArea.right = c.DesktopWidth
|
||||
sp.workArea.bottom = c.DesktopHeight
|
||||
|
||||
if sp.params&SPI_MASK_SET_HIGH_CONTRAST != 0 {
|
||||
sp.param = SPI_SET_HIGH_CONTRAST
|
||||
c.sendOneClientSysparam(&sp)
|
||||
}
|
||||
|
||||
if sp.params&SPI_MASK_TASKBAR_POS != 0 {
|
||||
sp.param = SPI_TASKBAR_POS
|
||||
c.sendOneClientSysparam(&sp)
|
||||
}
|
||||
|
||||
if sp.params&SPI_MASK_SET_MOUSE_BUTTON_SWAP != 0 {
|
||||
sp.param = SPI_SET_MOUSE_BUTTON_SWAP
|
||||
c.sendOneClientSysparam(&sp)
|
||||
}
|
||||
|
||||
if sp.params&SPI_MASK_SET_KEYBOARD_PREF != 0 {
|
||||
sp.param = SPI_SET_KEYBOARD_PREF
|
||||
c.sendOneClientSysparam(&sp)
|
||||
}
|
||||
|
||||
if sp.params&SPI_MASK_SET_DRAG_FULL_WINDOWS != 0 {
|
||||
sp.param = SPI_SET_DRAG_FULL_WINDOWS
|
||||
c.sendOneClientSysparam(&sp)
|
||||
}
|
||||
|
||||
if sp.params&SPI_MASK_SET_KEYBOARD_CUES != 0 {
|
||||
sp.param = SPI_SET_KEYBOARD_CUES
|
||||
c.sendOneClientSysparam(&sp)
|
||||
}
|
||||
|
||||
if sp.params&SPI_MASK_SET_WORK_AREA != 0 {
|
||||
sp.param = SPI_SET_WORK_AREA
|
||||
glog.Debug("SPI_SET_WORK_AREA")
|
||||
c.sendOneClientSysparam(&sp)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *RailClient) sendOneClientSysparam(sp *RailSysparamOrder) {
|
||||
length := 0
|
||||
b := &bytes.Buffer{}
|
||||
core.WriteUInt32LE(sp.param, b)
|
||||
switch sp.param {
|
||||
case SPI_SET_DRAG_FULL_WINDOWS:
|
||||
core.WriteUInt8(sp.dragFullWindows, b)
|
||||
|
||||
case SPI_SET_KEYBOARD_CUES:
|
||||
core.WriteUInt8(sp.keyboardCues, b)
|
||||
|
||||
case SPI_SET_KEYBOARD_PREF:
|
||||
core.WriteUInt8(sp.keyboardPref, b)
|
||||
|
||||
case SPI_SET_MOUSE_BUTTON_SWAP:
|
||||
core.WriteUInt8(sp.mouseButtonSwap, b)
|
||||
|
||||
case SPI_SET_WORK_AREA:
|
||||
core.WriteUInt16LE(sp.workArea.left, b)
|
||||
core.WriteUInt16LE(sp.workArea.top, b)
|
||||
core.WriteUInt16LE(sp.workArea.right, b)
|
||||
core.WriteUInt16LE(sp.workArea.bottom, b)
|
||||
|
||||
case SPI_DISPLAY_CHANGE:
|
||||
core.WriteUInt16LE(sp.displayChange.left, b)
|
||||
core.WriteUInt16LE(sp.displayChange.top, b)
|
||||
core.WriteUInt16LE(sp.displayChange.right, b)
|
||||
core.WriteUInt16LE(sp.displayChange.bottom, b)
|
||||
|
||||
case SPI_TASKBAR_POS:
|
||||
core.WriteUInt16LE(sp.taskbarPos.left, b)
|
||||
core.WriteUInt16LE(sp.taskbarPos.top, b)
|
||||
core.WriteUInt16LE(sp.taskbarPos.right, b)
|
||||
core.WriteUInt16LE(sp.taskbarPos.bottom, b)
|
||||
|
||||
case SPI_SET_HIGH_CONTRAST:
|
||||
core.WriteUInt32LE(sp.highContrast.flags, b)
|
||||
core.WriteUInt32LE(sp.highContrast.colorSchemeLength, b)
|
||||
data := core.UnicodeEncode(sp.highContrast.colorScheme)
|
||||
core.WriteBytes(data, b)
|
||||
|
||||
case SPI_SETFILTERKEYS:
|
||||
core.WriteUInt32LE(sp.filterKeys.Flags, b)
|
||||
core.WriteUInt32LE(sp.filterKeys.WaitTime, b)
|
||||
core.WriteUInt32LE(sp.filterKeys.DelayTime, b)
|
||||
core.WriteUInt32LE(sp.filterKeys.RepeatTime, b)
|
||||
core.WriteUInt32LE(sp.filterKeys.BounceTime, b)
|
||||
|
||||
case SPI_SETSTICKYKEYS:
|
||||
core.WriteUInt32LE(sp.stickyKeys, b)
|
||||
|
||||
case SPI_SETCARETWIDTH:
|
||||
core.WriteUInt32LE(sp.caretWidth, b)
|
||||
|
||||
case SPI_SETTOGGLEKEYS:
|
||||
core.WriteUInt32LE(sp.toggleKeys, b)
|
||||
|
||||
case SPI_MASK_SET_SET_SCREEN_SAVE_SECURE:
|
||||
core.WriteUInt8(sp.setScreenSaveSecure, b)
|
||||
|
||||
case SPI_MASK_SET_SCREEN_SAVE_ACTIVE:
|
||||
core.WriteUInt8(sp.setScreenSaveActive, b)
|
||||
|
||||
default:
|
||||
glog.Error("ERROR_BAD_ARGUMENTS")
|
||||
return
|
||||
}
|
||||
|
||||
c.sendData(TS_RAIL_ORDER_SYSPARAM, length+b.Len(), b.Bytes())
|
||||
}
|
||||
|
||||
type RailExecOrder struct {
|
||||
flags uint16
|
||||
RemoteApplicationProgram string
|
||||
RemoteApplicationWorkingDir string
|
||||
RemoteApplicationArguments string
|
||||
}
|
||||
|
||||
func (c *RailClient) sendClientExecute() {
|
||||
glog.Info("Send Client Execute")
|
||||
var exec RailExecOrder
|
||||
//exec.flags = TS_RAIL_EXEC_FLAG_EXPAND_ARGUMENTS
|
||||
exec.RemoteApplicationProgram = c.RemoteApplicationProgram
|
||||
exec.RemoteApplicationWorkingDir = c.ShellWorkingDirectory
|
||||
exec.RemoteApplicationArguments = c.RemoteApplicationCmdLine
|
||||
|
||||
program := core.UnicodeEncode(exec.RemoteApplicationProgram)
|
||||
workdir := core.UnicodeEncode(exec.RemoteApplicationWorkingDir)
|
||||
arguments := core.UnicodeEncode(exec.RemoteApplicationArguments)
|
||||
|
||||
length := 4
|
||||
b := &bytes.Buffer{}
|
||||
core.WriteUInt16LE(exec.flags, b)
|
||||
core.WriteUInt16LE(uint16(len(program)), b)
|
||||
core.WriteUInt16LE(uint16(len(workdir)), b)
|
||||
core.WriteUInt16LE(uint16(len(arguments)), b)
|
||||
core.WriteBytes(program, b)
|
||||
core.WriteBytes(workdir, b)
|
||||
core.WriteBytes(arguments, b)
|
||||
length += b.Len()
|
||||
|
||||
c.sendData(TS_RAIL_ORDER_EXEC, length, b.Bytes())
|
||||
|
||||
}
|
||||
|
||||
func (c *RailClient) processOrderSysparam(b []byte) {
|
||||
r := bytes.NewReader(b)
|
||||
systemParam, _ := core.ReadUInt32LE(r)
|
||||
body, _ := core.ReadUInt8(r)
|
||||
glog.Infof("systemParam:0x%x, body:%d", systemParam, body)
|
||||
}
|
||||
|
||||
const (
|
||||
//The Client Execute request was successful and the requested application or file has been launched.
|
||||
RAIL_EXEC_S_OK = 0x0000
|
||||
//The Client Execute request could not be satisfied because the server is not monitoring the current input desktop.
|
||||
RAIL_EXEC_E_HOOK_NOT_LOADED = 0x0001
|
||||
//The Execute request could not be satisfied because the request PDU was malformed.
|
||||
RAIL_EXEC_E_DECODE_FAILED = 0x0002
|
||||
//The Client Execute request could not be satisfied because the requested application was blocked by policy from being launched on the server.
|
||||
RAIL_EXEC_E_NOT_IN_ALLOWLIST = 0x0003
|
||||
//The Client Execute request could not be satisfied because the application or file path could not be found.
|
||||
RAIL_EXEC_E_FILE_NOT_FOUND = 0x0005
|
||||
//The Client Execute request could not be satisfied because an unspecified error occurred on the server.
|
||||
RAIL_EXEC_E_FAIL = 0x0006
|
||||
//The Client Execute request could not be satisfied because the remote session is locked.
|
||||
RAIL_EXEC_E_SESSION_LOCKED = 0x0007
|
||||
)
|
||||
|
||||
func (c *RailClient) processExecResult(b []byte) {
|
||||
r := bytes.NewReader(b)
|
||||
flags, _ := core.ReadUint16LE(r)
|
||||
execResult, _ := core.ReadUint16LE(r)
|
||||
rawResult, _ := core.ReadUInt32LE(r)
|
||||
core.ReadUint16LE(r)
|
||||
exeOrFileLength, _ := core.ReadUint16LE(r)
|
||||
exeOrFile, _ := core.ReadBytes(r.Len(), r)
|
||||
glog.Info("flags:", flags, "execResult:", execResult, "rawResult:", rawResult)
|
||||
glog.Info("length:", exeOrFileLength, "file:", core.UnicodeDecode(exeOrFile))
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package rdpgfx
|
||||
|
||||
import (
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/plugin"
|
||||
)
|
||||
|
||||
const (
|
||||
ChannelName = plugin.RDPGFX_DVC_CHANNEL_NAME
|
||||
)
|
||||
@@ -909,7 +909,8 @@ func readFastPathUpdatePDU(r io.Reader, code uint8) (*FastPathUpdatePDU, error)
|
||||
//glog.Debugf("FastPathPDU type %s(0x%x)", FastPathUpdateType(code), code)
|
||||
switch code {
|
||||
case FASTPATH_UPDATETYPE_ORDERS:
|
||||
d = &FastPathOrdersPDU{}
|
||||
// 绘图指令,认证检测不需要处理
|
||||
return nil, errors.New(fmt.Sprintf("Unsupport FastPathPDU type 0x%x", code))
|
||||
case FASTPATH_UPDATETYPE_BITMAP:
|
||||
d = &FastPathBitmapUpdateDataPDU{}
|
||||
case FASTPATH_UPDATETYPE_PALETTE:
|
||||
|
||||
@@ -1,541 +0,0 @@
|
||||
package pdu
|
||||
|
||||
/* Binary Raster Operations (ROP2) */
|
||||
const (
|
||||
GDI_R2_BLACK = 0x01
|
||||
GDI_R2_NOTMERGEPEN = 0x02
|
||||
GDI_R2_MASKNOTPEN = 0x03
|
||||
GDI_R2_NOTCOPYPEN = 0x04
|
||||
GDI_R2_MASKPENNOT = 0x05
|
||||
GDI_R2_NOT = 0x06
|
||||
GDI_R2_XORPEN = 0x07
|
||||
GDI_R2_NOTMASKPEN = 0x08
|
||||
GDI_R2_MASKPEN = 0x09
|
||||
GDI_R2_NOTXORPEN = 0x0A
|
||||
GDI_R2_NOP = 0x0B
|
||||
GDI_R2_MERGENOTPEN = 0x0C
|
||||
GDI_R2_COPYPEN = 0x0D
|
||||
GDI_R2_MERGEPENNOT = 0x0E
|
||||
GDI_R2_MERGEPEN = 0x0F
|
||||
GDI_R2_WHITE = 0x10
|
||||
)
|
||||
|
||||
/* Ternary Raster Operations (ROP3) */
|
||||
const (
|
||||
GDI_BLACKNESS = 0x00000042
|
||||
GDI_DPSoon = 0x00010289
|
||||
GDI_DPSona = 0x00020C89
|
||||
GDI_PSon = 0x000300AA
|
||||
GDI_SDPona = 0x00040C88
|
||||
GDI_DPon = 0x000500A9
|
||||
GDI_PDSxnon = 0x00060865
|
||||
GDI_PDSaon = 0x000702C5
|
||||
GDI_SDPnaa = 0x00080F08
|
||||
GDI_PDSxon = 0x00090245
|
||||
GDI_DPna = 0x000A0329
|
||||
GDI_PSDnaon = 0x000B0B2A
|
||||
GDI_SPna = 0x000C0324
|
||||
GDI_PDSnaon = 0x000D0B25
|
||||
GDI_PDSonon = 0x000E08A5
|
||||
GDI_Pn = 0x000F0001
|
||||
GDI_PDSona = 0x00100C85
|
||||
GDI_NOTSRCERASE = 0x001100A6
|
||||
GDI_SDPxnon = 0x00120868
|
||||
GDI_SDPaon = 0x001302C8
|
||||
GDI_DPSxnon = 0x00140869
|
||||
GDI_DPSaon = 0x001502C9
|
||||
GDI_PSDPSanaxx = 0x00165CCA
|
||||
GDI_SSPxDSxaxn = 0x00171D54
|
||||
GDI_SPxPDxa = 0x00180D59
|
||||
GDI_SDPSanaxn = 0x00191CC8
|
||||
GDI_PDSPaox = 0x001A06C5
|
||||
GDI_SDPSxaxn = 0x001B0768
|
||||
GDI_PSDPaox = 0x001C06CA
|
||||
GDI_DSPDxaxn = 0x001D0766
|
||||
GDI_PDSox = 0x001E01A5
|
||||
GDI_PDSoan = 0x001F0385
|
||||
GDI_DPSnaa = 0x00200F09
|
||||
GDI_SDPxon = 0x00210248
|
||||
GDI_DSna = 0x00220326
|
||||
GDI_SPDnaon = 0x00230B24
|
||||
GDI_SPxDSxa = 0x00240D55
|
||||
GDI_PDSPanaxn = 0x00251CC5
|
||||
GDI_SDPSaox = 0x002606C8
|
||||
GDI_SDPSxnox = 0x00271868
|
||||
GDI_DPSxa = 0x00280369
|
||||
GDI_PSDPSaoxxn = 0x002916CA
|
||||
GDI_DPSana = 0x002A0CC9
|
||||
GDI_SSPxPDxaxn = 0x002B1D58
|
||||
GDI_SPDSoax = 0x002C0784
|
||||
GDI_PSDnox = 0x002D060A
|
||||
GDI_PSDPxox = 0x002E064A
|
||||
GDI_PSDnoan = 0x002F0E2A
|
||||
GDI_PSna = 0x0030032A
|
||||
GDI_SDPnaon = 0x00310B28
|
||||
GDI_SDPSoox = 0x00320688
|
||||
GDI_NOTSRCCOPY = 0x00330008
|
||||
GDI_SPDSaox = 0x003406C4
|
||||
GDI_SPDSxnox = 0x00351864
|
||||
GDI_SDPox = 0x003601A8
|
||||
GDI_SDPoan = 0x00370388
|
||||
GDI_PSDPoax = 0x0038078A
|
||||
GDI_SPDnox = 0x00390604
|
||||
GDI_SPDSxox = 0x003A0644
|
||||
GDI_SPDnoan = 0x003B0E24
|
||||
GDI_PSx = 0x003C004A
|
||||
GDI_SPDSonox = 0x003D18A4
|
||||
GDI_SPDSnaox = 0x003E1B24
|
||||
GDI_PSan = 0x003F00EA
|
||||
GDI_PSDnaa = 0x00400F0A
|
||||
GDI_DPSxon = 0x00410249
|
||||
GDI_SDxPDxa = 0x00420D5D
|
||||
GDI_SPDSanaxn = 0x00431CC4
|
||||
GDI_SRCERASE = 0x00440328
|
||||
GDI_DPSnaon = 0x00450B29
|
||||
GDI_DSPDaox = 0x004606C6
|
||||
GDI_PSDPxaxn = 0x0047076A
|
||||
GDI_SDPxa = 0x00480368
|
||||
GDI_PDSPDaoxxn = 0x004916C5
|
||||
GDI_DPSDoax = 0x004A0789
|
||||
GDI_PDSnox = 0x004B0605
|
||||
GDI_SDPana = 0x004C0CC8
|
||||
GDI_SSPxDSxoxn = 0x004D1954
|
||||
GDI_PDSPxox = 0x004E0645
|
||||
GDI_PDSnoan = 0x004F0E25
|
||||
GDI_PDna = 0x00500325
|
||||
GDI_DSPnaon = 0x00510B26
|
||||
GDI_DPSDaox = 0x005206C9
|
||||
GDI_SPDSxaxn = 0x00530764
|
||||
GDI_DPSonon = 0x005408A9
|
||||
GDI_DSTINVERT = 0x00550009
|
||||
GDI_DPSox = 0x005601A9
|
||||
GDI_DPSoan = 0x00570389
|
||||
GDI_PDSPoax = 0x00580785
|
||||
GDI_DPSnox = 0x00590609
|
||||
GDI_PATINVERT = 0x005A0049
|
||||
GDI_DPSDonox = 0x005B18A9
|
||||
GDI_DPSDxox = 0x005C0649
|
||||
GDI_DPSnoan = 0x005D0E29
|
||||
GDI_DPSDnaox = 0x005E1B29
|
||||
GDI_DPan = 0x005F00E9
|
||||
GDI_PDSxa = 0x00600365
|
||||
GDI_DSPDSaoxxn = 0x006116C6
|
||||
GDI_DSPDoax = 0x00620786
|
||||
GDI_SDPnox = 0x00630608
|
||||
GDI_SDPSoax = 0x00640788
|
||||
GDI_DSPnox = 0x00650606
|
||||
GDI_SRCINVERT = 0x00660046
|
||||
GDI_SDPSonox = 0x006718A8
|
||||
GDI_DSPDSonoxxn = 0x006858A6
|
||||
GDI_PDSxxn = 0x00690145
|
||||
GDI_DPSax = 0x006A01E9
|
||||
GDI_PSDPSoaxxn = 0x006B178A
|
||||
GDI_SDPax = 0x006C01E8
|
||||
GDI_PDSPDoaxxn = 0x006D1785
|
||||
GDI_SDPSnoax = 0x006E1E28
|
||||
GDI_PDSxnan = 0x006F0C65
|
||||
GDI_PDSana = 0x00700CC5
|
||||
GDI_SSDxPDxaxn = 0x00711D5C
|
||||
GDI_SDPSxox = 0x00720648
|
||||
GDI_SDPnoan = 0x00730E28
|
||||
GDI_DSPDxox = 0x00740646
|
||||
GDI_DSPnoan = 0x00750E26
|
||||
GDI_SDPSnaox = 0x00761B28
|
||||
GDI_DSan = 0x007700E6
|
||||
GDI_PDSax = 0x007801E5
|
||||
GDI_DSPDSoaxxn = 0x00791786
|
||||
GDI_DPSDnoax = 0x007A1E29
|
||||
GDI_SDPxnan = 0x007B0C68
|
||||
GDI_SPDSnoax = 0x007C1E24
|
||||
GDI_DPSxnan = 0x007D0C69
|
||||
GDI_SPxDSxo = 0x007E0955
|
||||
GDI_DPSaan = 0x007F03C9
|
||||
GDI_DPSaa = 0x008003E9
|
||||
GDI_SPxDSxon = 0x00810975
|
||||
GDI_DPSxna = 0x00820C49
|
||||
GDI_SPDSnoaxn = 0x00831E04
|
||||
GDI_SDPxna = 0x00840C48
|
||||
GDI_PDSPnoaxn = 0x00851E05
|
||||
GDI_DSPDSoaxx = 0x008617A6
|
||||
GDI_PDSaxn = 0x008701C5
|
||||
GDI_SRCAND = 0x008800C6
|
||||
GDI_SDPSnaoxn = 0x00891B08
|
||||
GDI_DSPnoa = 0x008A0E06
|
||||
GDI_DSPDxoxn = 0x008B0666
|
||||
GDI_SDPnoa = 0x008C0E08
|
||||
GDI_SDPSxoxn = 0x008D0668
|
||||
GDI_SSDxPDxax = 0x008E1D7C
|
||||
GDI_PDSanan = 0x008F0CE5
|
||||
GDI_PDSxna = 0x00900C45
|
||||
GDI_SDPSnoaxn = 0x00911E08
|
||||
GDI_DPSDPoaxx = 0x009217A9
|
||||
GDI_SPDaxn = 0x009301C4
|
||||
GDI_PSDPSoaxx = 0x009417AA
|
||||
GDI_DPSaxn = 0x009501C9
|
||||
GDI_DPSxx = 0x00960169
|
||||
GDI_PSDPSonoxx = 0x0097588A
|
||||
GDI_SDPSonoxn = 0x00981888
|
||||
GDI_DSxn = 0x00990066
|
||||
GDI_DPSnax = 0x009A0709
|
||||
GDI_SDPSoaxn = 0x009B07A8
|
||||
GDI_SPDnax = 0x009C0704
|
||||
GDI_DSPDoaxn = 0x009D07A6
|
||||
GDI_DSPDSaoxx = 0x009E16E6
|
||||
GDI_PDSxan = 0x009F0345
|
||||
GDI_DPa = 0x00A000C9
|
||||
GDI_PDSPnaoxn = 0x00A11B05
|
||||
GDI_DPSnoa = 0x00A20E09
|
||||
GDI_DPSDxoxn = 0x00A30669
|
||||
GDI_PDSPonoxn = 0x00A41885
|
||||
GDI_PDxn = 0x00A50065
|
||||
GDI_DSPnax = 0x00A60706
|
||||
GDI_PDSPoaxn = 0x00A707A5
|
||||
GDI_DPSoa = 0x00A803A9
|
||||
GDI_DPSoxn = 0x00A90189
|
||||
GDI_DSTCOPY = 0x00AA0029
|
||||
GDI_DPSono = 0x00AB0889
|
||||
GDI_SPDSxax = 0x00AC0744
|
||||
GDI_DPSDaoxn = 0x00AD06E9
|
||||
GDI_DSPnao = 0x00AE0B06
|
||||
GDI_DPno = 0x00AF0229
|
||||
GDI_PDSnoa = 0x00B00E05
|
||||
GDI_PDSPxoxn = 0x00B10665
|
||||
GDI_SSPxDSxox = 0x00B21974
|
||||
GDI_SDPanan = 0x00B30CE8
|
||||
GDI_PSDnax = 0x00B4070A
|
||||
GDI_DPSDoaxn = 0x00B507A9
|
||||
GDI_DPSDPaoxx = 0x00B616E9
|
||||
GDI_SDPxan = 0x00B70348
|
||||
GDI_PSDPxax = 0x00B8074A
|
||||
GDI_DSPDaoxn = 0x00B906E6
|
||||
GDI_DPSnao = 0x00BA0B09
|
||||
GDI_MERGEPAINT = 0x00BB0226
|
||||
GDI_SPDSanax = 0x00BC1CE4
|
||||
GDI_SDxPDxan = 0x00BD0D7D
|
||||
GDI_DPSxo = 0x00BE0269
|
||||
GDI_DPSano = 0x00BF08C9
|
||||
GDI_MERGECOPY = 0x00C000CA
|
||||
GDI_SPDSnaoxn = 0x00C11B04
|
||||
GDI_SPDSonoxn = 0x00C21884
|
||||
GDI_PSxn = 0x00C3006A
|
||||
GDI_SPDnoa = 0x00C40E04
|
||||
GDI_SPDSxoxn = 0x00C50664
|
||||
GDI_SDPnax = 0x00C60708
|
||||
GDI_PSDPoaxn = 0x00C707AA
|
||||
GDI_SDPoa = 0x00C803A8
|
||||
GDI_SPDoxn = 0x00C90184
|
||||
GDI_DPSDxax = 0x00CA0749
|
||||
GDI_SPDSaoxn = 0x00CB06E4
|
||||
GDI_SRCCOPY = 0x00CC0020
|
||||
GDI_SDPono = 0x00CD0888
|
||||
GDI_SDPnao = 0x00CE0B08
|
||||
GDI_SPno = 0x00CF0224
|
||||
GDI_PSDnoa = 0x00D00E0A
|
||||
GDI_PSDPxoxn = 0x00D1066A
|
||||
GDI_PDSnax = 0x00D20705
|
||||
GDI_SPDSoaxn = 0x00D307A4
|
||||
GDI_SSPxPDxax = 0x00D41D78
|
||||
GDI_DPSanan = 0x00D50CE9
|
||||
GDI_PSDPSaoxx = 0x00D616EA
|
||||
GDI_DPSxan = 0x00D70349
|
||||
GDI_PDSPxax = 0x00D80745
|
||||
GDI_SDPSaoxn = 0x00D906E8
|
||||
GDI_DPSDanax = 0x00DA1CE9
|
||||
GDI_SPxDSxan = 0x00DB0D75
|
||||
GDI_SPDnao = 0x00DC0B04
|
||||
GDI_SDno = 0x00DD0228
|
||||
GDI_SDPxo = 0x00DE0268
|
||||
GDI_SDPano = 0x00DF08C8
|
||||
GDI_PDSoa = 0x00E003A5
|
||||
GDI_PDSoxn = 0x00E10185
|
||||
GDI_DSPDxax = 0x00E20746
|
||||
GDI_PSDPaoxn = 0x00E306EA
|
||||
GDI_SDPSxax = 0x00E40748
|
||||
GDI_PDSPaoxn = 0x00E506E5
|
||||
GDI_SDPSanax = 0x00E61CE8
|
||||
GDI_SPxPDxan = 0x00E70D79
|
||||
GDI_SSPxDSxax = 0x00E81D74
|
||||
GDI_DSPDSanaxxn = 0x00E95CE6
|
||||
GDI_DPSao = 0x00EA02E9
|
||||
GDI_DPSxno = 0x00EB0849
|
||||
GDI_SDPao = 0x00EC02E8
|
||||
GDI_SDPxno = 0x00ED0848
|
||||
GDI_SRCPAINT = 0x00EE0086
|
||||
GDI_SDPnoo = 0x00EF0A08
|
||||
GDI_PATCOPY = 0x00F00021
|
||||
GDI_PDSono = 0x00F10885
|
||||
GDI_PDSnao = 0x00F20B05
|
||||
GDI_PSno = 0x00F3022A
|
||||
GDI_PSDnao = 0x00F40B0A
|
||||
GDI_PDno = 0x00F50225
|
||||
GDI_PDSxo = 0x00F60265
|
||||
GDI_PDSano = 0x00F708C5
|
||||
GDI_PDSao = 0x00F802E5
|
||||
GDI_PDSxno = 0x00F90845
|
||||
GDI_DPo = 0x00FA0089
|
||||
GDI_PATPAINT = 0x00FB0A09
|
||||
GDI_PSo = 0x00FC008A
|
||||
GDI_PSDnoo = 0x00FD0A0A
|
||||
GDI_DPSoo = 0x00FE02A9
|
||||
GDI_WHITENESS = 0x00FF0062
|
||||
GDI_GLYPH_ORDER = 0xFFFFFFFF
|
||||
)
|
||||
|
||||
var Rop3CodeTable = map[int]string{
|
||||
GDI_BLACKNESS: "0",
|
||||
GDI_DPSoon: "DPSoon",
|
||||
GDI_DPSona: "DPSona",
|
||||
GDI_PSon: "PSon",
|
||||
GDI_SDPona: "SDPona",
|
||||
GDI_DPon: "DPon",
|
||||
GDI_PDSxnon: "PDSxnon",
|
||||
GDI_PDSaon: "PDSaon",
|
||||
GDI_SDPnaa: "SDPnaa",
|
||||
GDI_PDSxon: "PDSxon",
|
||||
GDI_DPna: "DPna",
|
||||
GDI_PSDnaon: "PSDnaon",
|
||||
GDI_SPna: "SPna",
|
||||
GDI_PDSnaon: "PDSnaon",
|
||||
GDI_PDSonon: "PDSonon",
|
||||
GDI_Pn: "Pn",
|
||||
GDI_PDSona: "PDSona",
|
||||
GDI_NOTSRCERASE: "DSon",
|
||||
GDI_SDPxnon: "SDPxnon",
|
||||
GDI_SDPaon: "SDPaon",
|
||||
GDI_DPSxnon: "DPSxnon",
|
||||
GDI_DPSaon: "DPSaon",
|
||||
GDI_PSDPSanaxx: "PSDPSanaxx",
|
||||
GDI_SSPxDSxaxn: "SSPxDSxaxn",
|
||||
GDI_SPxPDxa: "SPxPDxa",
|
||||
GDI_SDPSanaxn: "SDPSanaxn",
|
||||
GDI_PDSPaox: "PDSPaox",
|
||||
GDI_SDPSxaxn: "SDPSxaxn",
|
||||
GDI_PSDPaox: "PSDPaox",
|
||||
GDI_DSPDxaxn: "DSPDxaxn",
|
||||
GDI_PDSox: "PDSox",
|
||||
GDI_PDSoan: "PDSoan",
|
||||
GDI_DPSnaa: "DPSnaa",
|
||||
GDI_SDPxon: "SDPxon",
|
||||
GDI_DSna: "DSna",
|
||||
GDI_SPDnaon: "SPDnaon",
|
||||
GDI_SPxDSxa: "SPxDSxa",
|
||||
GDI_PDSPanaxn: "PDSPanaxn",
|
||||
GDI_SDPSaox: "SDPSaox",
|
||||
GDI_SDPSxnox: "SDPSxnox",
|
||||
GDI_DPSxa: "DPSxa",
|
||||
GDI_PSDPSaoxxn: "PSDPSaoxxn",
|
||||
GDI_DPSana: "DPSana",
|
||||
GDI_SSPxPDxaxn: "SSPxPDxaxn",
|
||||
GDI_SPDSoax: "SPDSoax",
|
||||
GDI_PSDnox: "PSDnox",
|
||||
GDI_PSDPxox: "PSDPxox",
|
||||
GDI_PSDnoan: "PSDnoan",
|
||||
GDI_PSna: "PSna",
|
||||
GDI_SDPnaon: "SDPnaon",
|
||||
GDI_SDPSoox: "SDPSoox",
|
||||
GDI_NOTSRCCOPY: "Sn",
|
||||
GDI_SPDSaox: "SPDSaox",
|
||||
GDI_SPDSxnox: "SPDSxnox",
|
||||
GDI_SDPox: "SDPox",
|
||||
GDI_SDPoan: "SDPoan",
|
||||
GDI_PSDPoax: "PSDPoax",
|
||||
GDI_SPDnox: "SPDnox",
|
||||
GDI_SPDSxox: "SPDSxox",
|
||||
GDI_SPDnoan: "SPDnoan",
|
||||
GDI_PSx: "PSx",
|
||||
GDI_SPDSonox: "SPDSonox",
|
||||
GDI_SPDSnaox: "SPDSnaox",
|
||||
GDI_PSan: "PSan",
|
||||
GDI_PSDnaa: "PSDnaa",
|
||||
GDI_DPSxon: "DPSxon",
|
||||
GDI_SDxPDxa: "SDxPDxa",
|
||||
GDI_SPDSanaxn: "SPDSanaxn",
|
||||
GDI_SRCERASE: "SDna",
|
||||
GDI_DPSnaon: "DPSnaon",
|
||||
GDI_DSPDaox: "DSPDaox",
|
||||
GDI_PSDPxaxn: "PSDPxaxn",
|
||||
GDI_SDPxa: "SDPxa",
|
||||
GDI_PDSPDaoxxn: "PDSPDaoxxn",
|
||||
GDI_DPSDoax: "DPSDoax",
|
||||
GDI_PDSnox: "PDSnox",
|
||||
GDI_SDPana: "SDPana",
|
||||
GDI_SSPxDSxoxn: "SSPxDSxoxn",
|
||||
GDI_PDSPxox: "PDSPxox",
|
||||
GDI_PDSnoan: "PDSnoan",
|
||||
GDI_PDna: "PDna",
|
||||
GDI_DSPnaon: "DSPnaon",
|
||||
GDI_DPSDaox: "DPSDaox",
|
||||
GDI_SPDSxaxn: "SPDSxaxn",
|
||||
GDI_DPSonon: "DPSonon",
|
||||
GDI_DSTINVERT: "Dn",
|
||||
GDI_DPSox: "DPSox",
|
||||
GDI_DPSoan: "DPSoan",
|
||||
GDI_PDSPoax: "PDSPoax",
|
||||
GDI_DPSnox: "DPSnox",
|
||||
GDI_PATINVERT: "DPx",
|
||||
GDI_DPSDonox: "DPSDonox",
|
||||
GDI_DPSDxox: "DPSDxox",
|
||||
GDI_DPSnoan: "DPSnoan",
|
||||
GDI_DPSDnaox: "DPSDnaox",
|
||||
GDI_DPan: "DPan",
|
||||
GDI_PDSxa: "PDSxa",
|
||||
GDI_DSPDSaoxxn: "DSPDSaoxxn",
|
||||
GDI_DSPDoax: "DSPDoax",
|
||||
GDI_SDPnox: "SDPnox",
|
||||
GDI_SDPSoax: "SDPSoax",
|
||||
GDI_DSPnox: "DSPnox",
|
||||
GDI_SRCINVERT: "DSx",
|
||||
GDI_SDPSonox: "SDPSonox",
|
||||
GDI_DSPDSonoxxn: "DSPDSonoxxn",
|
||||
GDI_PDSxxn: "PDSxxn",
|
||||
GDI_DPSax: "DPSax",
|
||||
GDI_PSDPSoaxxn: "PSDPSoaxxn",
|
||||
GDI_SDPax: "SDPax",
|
||||
GDI_PDSPDoaxxn: "PDSPDoaxxn",
|
||||
GDI_SDPSnoax: "SDPSnoax",
|
||||
GDI_PDSxnan: "PDSxnan",
|
||||
GDI_PDSana: "PDSana",
|
||||
GDI_SSDxPDxaxn: "SSDxPDxaxn",
|
||||
GDI_SDPSxox: "SDPSxox",
|
||||
GDI_SDPnoan: "SDPnoan",
|
||||
GDI_DSPDxox: "DSPDxox",
|
||||
GDI_DSPnoan: "DSPnoan",
|
||||
GDI_SDPSnaox: "SDPSnaox",
|
||||
GDI_DSan: "DSan",
|
||||
GDI_PDSax: "PDSax",
|
||||
GDI_DSPDSoaxxn: "DSPDSoaxxn",
|
||||
GDI_DPSDnoax: "DPSDnoax",
|
||||
GDI_SDPxnan: "SDPxnan",
|
||||
GDI_SPDSnoax: "SPDSnoax",
|
||||
GDI_DPSxnan: "DPSxnan",
|
||||
GDI_SPxDSxo: "SPxDSxo",
|
||||
GDI_DPSaan: "DPSaan",
|
||||
GDI_DPSaa: "DPSaa",
|
||||
GDI_SPxDSxon: "SPxDSxon",
|
||||
GDI_DPSxna: "DPSxna",
|
||||
GDI_SPDSnoaxn: "SPDSnoaxn",
|
||||
GDI_SDPxna: "SDPxna",
|
||||
GDI_PDSPnoaxn: "PDSPnoaxn",
|
||||
GDI_DSPDSoaxx: "DSPDSoaxx",
|
||||
GDI_PDSaxn: "PDSaxn",
|
||||
GDI_SRCAND: "DSa",
|
||||
GDI_SDPSnaoxn: "SDPSnaoxn",
|
||||
GDI_DSPnoa: "DSPnoa",
|
||||
GDI_DSPDxoxn: "DSPDxoxn",
|
||||
GDI_SDPnoa: "SDPnoa",
|
||||
GDI_SDPSxoxn: "SDPSxoxn",
|
||||
GDI_SSDxPDxax: "SSDxPDxax",
|
||||
GDI_PDSanan: "PDSanan",
|
||||
GDI_PDSxna: "PDSxna",
|
||||
GDI_SDPSnoaxn: "SDPSnoaxn",
|
||||
GDI_DPSDPoaxx: "DPSDPoaxx",
|
||||
GDI_SPDaxn: "SPDaxn",
|
||||
GDI_PSDPSoaxx: "PSDPSoaxx",
|
||||
GDI_DPSaxn: "DPSaxn",
|
||||
GDI_DPSxx: "DPSxx",
|
||||
GDI_PSDPSonoxx: "PSDPSonoxx",
|
||||
GDI_SDPSonoxn: "SDPSonoxn",
|
||||
GDI_DSxn: "DSxn",
|
||||
GDI_DPSnax: "DPSnax",
|
||||
GDI_SDPSoaxn: "SDPSoaxn",
|
||||
GDI_SPDnax: "SPDnax",
|
||||
GDI_DSPDoaxn: "DSPDoaxn",
|
||||
GDI_DSPDSaoxx: "DSPDSaoxx",
|
||||
GDI_PDSxan: "PDSxan",
|
||||
GDI_DPa: "DPa",
|
||||
GDI_PDSPnaoxn: "PDSPnaoxn",
|
||||
GDI_DPSnoa: "DPSnoa",
|
||||
GDI_DPSDxoxn: "DPSDxoxn",
|
||||
GDI_PDSPonoxn: "PDSPonoxn",
|
||||
GDI_PDxn: "PDxn",
|
||||
GDI_DSPnax: "DSPnax",
|
||||
GDI_PDSPoaxn: "PDSPoaxn",
|
||||
GDI_DPSoa: "DPSoa",
|
||||
GDI_DPSoxn: "DPSoxn",
|
||||
GDI_DSTCOPY: "D",
|
||||
GDI_DPSono: "DPSono",
|
||||
GDI_SPDSxax: "SPDSxax",
|
||||
GDI_DPSDaoxn: "DPSDaoxn",
|
||||
GDI_DSPnao: "DSPnao",
|
||||
GDI_DPno: "DPno",
|
||||
GDI_PDSnoa: "PDSnoa",
|
||||
GDI_PDSPxoxn: "PDSPxoxn",
|
||||
GDI_SSPxDSxox: "SSPxDSxox",
|
||||
GDI_SDPanan: "SDPanan",
|
||||
GDI_PSDnax: "PSDnax",
|
||||
GDI_DPSDoaxn: "DPSDoaxn",
|
||||
GDI_DPSDPaoxx: "DPSDPaoxx",
|
||||
GDI_SDPxan: "SDPxan",
|
||||
GDI_PSDPxax: "PSDPxax",
|
||||
GDI_DSPDaoxn: "DSPDaoxn",
|
||||
GDI_DPSnao: "DPSnao",
|
||||
GDI_MERGEPAINT: "DSno",
|
||||
GDI_SPDSanax: "SPDSanax",
|
||||
GDI_SDxPDxan: "SDxPDxan",
|
||||
GDI_DPSxo: "DPSxo",
|
||||
GDI_DPSano: "DPSano",
|
||||
GDI_MERGECOPY: "PSa",
|
||||
GDI_SPDSnaoxn: "SPDSnaoxn",
|
||||
GDI_SPDSonoxn: "SPDSonoxn",
|
||||
GDI_PSxn: "PSxn",
|
||||
GDI_SPDnoa: "SPDnoa",
|
||||
GDI_SPDSxoxn: "SPDSxoxn",
|
||||
GDI_SDPnax: "SDPnax",
|
||||
GDI_PSDPoaxn: "PSDPoaxn",
|
||||
GDI_SDPoa: "SDPoa",
|
||||
GDI_SPDoxn: "SPDoxn",
|
||||
GDI_DPSDxax: "DPSDxax",
|
||||
GDI_SPDSaoxn: "SPDSaoxn",
|
||||
GDI_SRCCOPY: "S",
|
||||
GDI_SDPono: "SDPono",
|
||||
GDI_SDPnao: "SDPnao",
|
||||
GDI_SPno: "SPno",
|
||||
GDI_PSDnoa: "PSDnoa",
|
||||
GDI_PSDPxoxn: "PSDPxoxn",
|
||||
GDI_PDSnax: "PDSnax",
|
||||
GDI_SPDSoaxn: "SPDSoaxn",
|
||||
GDI_SSPxPDxax: "SSPxPDxax",
|
||||
GDI_DPSanan: "DPSanan",
|
||||
GDI_PSDPSaoxx: "PSDPSaoxx",
|
||||
GDI_DPSxan: "DPSxan",
|
||||
GDI_PDSPxax: "PDSPxax",
|
||||
GDI_SDPSaoxn: "SDPSaoxn",
|
||||
GDI_DPSDanax: "DPSDanax",
|
||||
GDI_SPxDSxan: "SPxDSxan",
|
||||
GDI_SPDnao: "SPDnao",
|
||||
GDI_SDno: "SDno",
|
||||
GDI_SDPxo: "SDPxo",
|
||||
GDI_SDPano: "SDPano",
|
||||
GDI_PDSoa: "PDSoa",
|
||||
GDI_PDSoxn: "PDSoxn",
|
||||
GDI_DSPDxax: "DSPDxax",
|
||||
GDI_PSDPaoxn: "PSDPaoxn",
|
||||
GDI_SDPSxax: "SDPSxax",
|
||||
GDI_PDSPaoxn: "PDSPaoxn",
|
||||
GDI_SDPSanax: "SDPSanax",
|
||||
GDI_SPxPDxan: "SPxPDxan",
|
||||
GDI_SSPxDSxax: "SSPxDSxax",
|
||||
GDI_DSPDSanaxxn: "DSPDSanaxxn",
|
||||
GDI_DPSao: "DPSao",
|
||||
GDI_DPSxno: "DPSxno",
|
||||
GDI_SDPao: "SDPao",
|
||||
GDI_SDPxno: "SDPxno",
|
||||
GDI_SRCPAINT: "DSo",
|
||||
GDI_SDPnoo: "SDPnoo",
|
||||
GDI_PATCOPY: "P",
|
||||
GDI_PDSono: "PDSono",
|
||||
GDI_PDSnao: "PDSnao",
|
||||
GDI_PSno: "PSno",
|
||||
GDI_PSDnao: "PSDnao",
|
||||
GDI_PDno: "PDno",
|
||||
GDI_PDSxo: "PDSxo",
|
||||
GDI_PDSano: "PDSano",
|
||||
GDI_PDSao: "PDSao",
|
||||
GDI_PDSxno: "PDSxno",
|
||||
GDI_DPo: "DPo",
|
||||
GDI_PATPAINT: "DPSnoo",
|
||||
GDI_PSo: "PSo",
|
||||
GDI_PSDnoo: "PSDnoo",
|
||||
GDI_DPSoo: "DPSoo",
|
||||
GDI_WHITENESS: "1",
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -383,8 +383,6 @@ func (c *Client) recvPDU(s []byte) {
|
||||
p := up.Udata
|
||||
if up.UpdateType == FASTPATH_UPDATETYPE_BITMAP {
|
||||
c.Emit("bitmap", p.(*BitmapUpdateDataPDU).Rectangles)
|
||||
} else if up.UpdateType == FASTPATH_UPDATETYPE_ORDERS {
|
||||
c.Emit("orders", p.(*FastPathOrdersPDU).OrderPdus)
|
||||
}
|
||||
}
|
||||
if d.Header.PDUType2 == PDUTYPE2_SAVE_SESSION_INFO {
|
||||
@@ -445,8 +443,6 @@ func (c *Client) RecvFastPath(secFlag byte, s []byte) {
|
||||
c.Emit("bitmap", p.Data.(*FastPathBitmapUpdateDataPDU).Rectangles)
|
||||
} else if updateCode == FASTPATH_UPDATETYPE_COLOR {
|
||||
c.Emit("color", p.Data.(*FastPathColorPdu))
|
||||
} else if updateCode == FASTPATH_UPDATETYPE_ORDERS {
|
||||
c.Emit("orders", p.Data.(*FastPathOrdersPDU).OrderPdus)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,457 +0,0 @@
|
||||
// rfb.go
|
||||
package rfb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/des"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"github.com/lunixbochs/struc"
|
||||
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/core"
|
||||
"github.com/shadow1ng/fscan/mylib/grdp/emission"
|
||||
"github.com/shadow1ng/fscan/mylib/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) 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 %d", 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())
|
||||
}
|
||||
Reference in New Issue
Block a user