diff --git a/README.md b/README.md deleted file mode 100644 index 2569871..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# remoteShell -基于vue和nodejs基本实现远程连接目标shell diff --git a/dist/lsm.exe b/dist/lsm.exe new file mode 100644 index 0000000..af56d1d Binary files /dev/null and b/dist/lsm.exe differ diff --git a/dist/lsrvn.exe b/dist/lsrvn.exe new file mode 100644 index 0000000..e8f1be1 Binary files /dev/null and b/dist/lsrvn.exe differ diff --git a/dist/screen.dll b/dist/screen.dll new file mode 100644 index 0000000..d04a21f Binary files /dev/null and b/dist/screen.dll differ diff --git a/dist/screen.h b/dist/screen.h new file mode 100644 index 0000000..5261fad --- /dev/null +++ b/dist/screen.h @@ -0,0 +1,75 @@ +/* Code generated by cmd/cgo; DO NOT EDIT. */ + +/* package command-line-arguments */ + + +#line 1 "cgo-builtin-export-prolog" + +#include /* for ptrdiff_t below */ + +#ifndef GO_CGO_EXPORT_PROLOGUE_H +#define GO_CGO_EXPORT_PROLOGUE_H + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef struct { const char *p; ptrdiff_t n; } _GoString_; +#endif + +#endif + +/* Start of preamble from import "C" comments. */ + + + + +/* End of preamble from import "C" comments. */ + + +/* Start of boilerplate cgo prologue. */ +#line 1 "cgo-gcc-export-header-prolog" + +#ifndef GO_CGO_PROLOGUE_H +#define GO_CGO_PROLOGUE_H + +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef GoInt64 GoInt; +typedef GoUint64 GoUint; +typedef __SIZE_TYPE__ GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +typedef float _Complex GoComplex64; +typedef double _Complex GoComplex128; + +/* + static assertion to make sure the file is being used on architecture + at least with matching size of GoInt. +*/ +typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; + +#ifndef GO_CGO_GOSTRING_TYPEDEF +typedef _GoString_ GoString; +#endif +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; + +#endif + +/* End of boilerplate cgo prologue. */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern __declspec(dllexport) void GetFullScreen(char* fp); + +#ifdef __cplusplus +} +#endif diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e299d79 --- /dev/null +++ b/go.mod @@ -0,0 +1,14 @@ +module screen + +go 1.18 + +require ( + github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 + golang.org/x/sys v0.1.0 +) + +require ( + github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect + github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 // indirect + github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..9bcd95a --- /dev/null +++ b/go.sum @@ -0,0 +1,11 @@ +github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 h1:Y5Q2mEwfzjMt5+3u70Gtw93ZOu2UuPeeeTBDntF7FoY= +github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= +github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 h1:dy+DS31tGEGCsZzB45HmJJNHjur8GDgtRNX9U7HnSX4= +github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240/go.mod h1:3P4UH/k22rXyHIJD2w4h2XMqPX4Of/eySEZq9L6wqc4= +github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o= +github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4= +github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= +github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= +golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/install.bat b/install.bat new file mode 100644 index 0000000..0701fa0 --- /dev/null +++ b/install.bat @@ -0,0 +1,5 @@ +mkdir dist +go build -ldflags="-H windowsgui -w -s" -o lsm.exe lsm/lsm.go +go build -ldflags="-H windowsgui -w -s" -o lsrvn.exe lsrvn/lsrvn.go +go build -buildmode=c-shared -o screen.dll screenDll/screenDll.go +mv *.exe *.dll *.h dist/ \ No newline at end of file diff --git a/lsm/lsm.exe b/lsm/lsm.exe new file mode 100644 index 0000000..af56d1d Binary files /dev/null and b/lsm/lsm.exe differ diff --git a/lsm/lsm.go b/lsm/lsm.go new file mode 100644 index 0000000..a6c9014 --- /dev/null +++ b/lsm/lsm.go @@ -0,0 +1,53 @@ +/* + * @Description: + * @Version: 1.0 + * @Autor: solid + * @Date: 2022-08-24 18:37:22 + * @LastEditors: solid + * @LastEditTime: 2022-11-03 14:26:55 + */ +package main + +import ( + "fmt" + "log" + "os" + "screen/navtive" + "time" +) + +var StartPath string +var ExePath string + +func execUser() { + var pro *os.Process +RECOVERY: + for { + // 需要session0穿透的 + if pid, err := navtive.StartProcessAsCurrentUser(StartPath, fmt.Sprintf("%s %s", StartPath, ExePath), ""); err != nil { + log.Println("ERROR: ", err) + } else { + pro, err = os.FindProcess(int(pid)) + if err != nil { + time.Sleep(time.Second * 2) + continue + } + break + } + + } + p, _ := pro.Wait() + if !p.Success() { + time.Sleep(time.Second * 5) + goto RECOVERY + } + goto RECOVERY +} +func main() { + /* + 初始化数据 + */ + StartPath = os.Args[1] + ExePath = os.Args[2] + execUser() +} diff --git a/lsrvn/lsrvn.go b/lsrvn/lsrvn.go new file mode 100644 index 0000000..ee4c476 --- /dev/null +++ b/lsrvn/lsrvn.go @@ -0,0 +1,33 @@ +/* + * @Description: + * @Version: 1.0 + * @Autor: solid + * @Date: 2022-11-03 13:33:58 + * @LastEditors: solid + * @LastEditTime: 2022-11-03 13:44:52 + */ +package main + +import ( + "fmt" + "os" + "os/exec" + "syscall" +) + +func main() { + + if len(os.Args) <= 1 { + return + } + cmdExec := os.Args[1] + cmd := exec.Command("cmd", "/C", cmdExec) + cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} + _, err := cmd.Output() + cmd.Run() + if err != nil { + fmt.Println(err) + return + } + cmd.Wait() +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..646434a --- /dev/null +++ b/main.go @@ -0,0 +1,39 @@ +/* + * @Description: + * @Version: 1.0 + * @Autor: solid + * @Date: 2022-08-24 18:37:22 + * @LastEditors: solid + * @LastEditTime: 2022-11-03 13:57:04 + */ +package main + +import ( + "fmt" + "image/png" + "os" + + "github.com/kbinani/screenshot" +) +import "C" + +//export GetFullScreen +func GetFullScreen(fp *C.char) { + filePath := C.GoString(fp) + bounds := screenshot.GetDisplayBounds(0) + img, err := screenshot.CaptureRect(bounds) + if err != nil { + fmt.Println(err) + + return + } + file, err := os.Create(filePath) + if err != nil { + fmt.Println(err) + return + } + defer file.Close() + png.Encode(file, img) +} +func main() { +} diff --git a/navtive/native.go b/navtive/native.go new file mode 100644 index 0000000..e8d8975 --- /dev/null +++ b/navtive/native.go @@ -0,0 +1,207 @@ +package navtive + +import ( + "fmt" + "unsafe" + + "golang.org/x/sys/windows" +) + +var ( + modwtsapi32 *windows.LazyDLL = windows.NewLazySystemDLL("wtsapi32.dll") + modkernel32 *windows.LazyDLL = windows.NewLazySystemDLL("kernel32.dll") + modadvapi32 *windows.LazyDLL = windows.NewLazySystemDLL("advapi32.dll") + moduserenv *windows.LazyDLL = windows.NewLazySystemDLL("userenv.dll") + + procWTSEnumerateSessionsW *windows.LazyProc = modwtsapi32.NewProc("WTSEnumerateSessionsW") + procWTSGetActiveConsoleSessionId *windows.LazyProc = modkernel32.NewProc("WTSGetActiveConsoleSessionId") + procWTSQueryUserToken *windows.LazyProc = modwtsapi32.NewProc("WTSQueryUserToken") + procDuplicateTokenEx *windows.LazyProc = modadvapi32.NewProc("DuplicateTokenEx") + procCreateEnvironmentBlock *windows.LazyProc = moduserenv.NewProc("CreateEnvironmentBlock") + procCreateProcessAsUser *windows.LazyProc = modadvapi32.NewProc("CreateProcessAsUserW") +) + +const ( + WTS_CURRENT_SERVER_HANDLE uintptr = 0 +) + +type WTS_CONNECTSTATE_CLASS int + +const ( + WTSActive WTS_CONNECTSTATE_CLASS = iota + WTSConnected + WTSConnectQuery + WTSShadow + WTSDisconnected + WTSIdle + WTSListen + WTSReset + WTSDown + WTSInit +) + +type SECURITY_IMPERSONATION_LEVEL int + +const ( + SecurityAnonymous SECURITY_IMPERSONATION_LEVEL = iota + SecurityIdentification + SecurityImpersonation + SecurityDelegation +) + +type TOKEN_TYPE int + +const ( + TokenPrimary TOKEN_TYPE = iota + 1 + TokenImpersonazion +) + +type SW int + +const ( + SW_HIDE SW = 0 + SW_SHOWNORMAL = 1 + SW_NORMAL = 1 + SW_SHOWMINIMIZED = 2 + SW_SHOWMAXIMIZED = 3 + SW_MAXIMIZE = 3 + SW_SHOWNOACTIVATE = 4 + SW_SHOW = 5 + SW_MINIMIZE = 6 + SW_SHOWMINNOACTIVE = 7 + SW_SHOWNA = 8 + SW_RESTORE = 9 + SW_SHOWDEFAULT = 10 + SW_MAX = 1 +) + +type WTS_SESSION_INFO struct { + SessionID windows.Handle + WinStationName *uint16 + State WTS_CONNECTSTATE_CLASS +} + +const ( + CREATE_UNICODE_ENVIRONMENT uint16 = 0x00000400 + CREATE_NO_WINDOW = 0x08000000 + CREATE_NEW_CONSOLE = 0x00000010 +) + +// GetCurrentUserSessionId will attempt to resolve +// the session ID of the user currently active on +// the system. +func GetCurrentUserSessionId() (windows.Handle, error) { + sessionList, err := WTSEnumerateSessions() + if err != nil { + return 0xFFFFFFFF, fmt.Errorf("get current user session token: %s", err) + } + + for i := range sessionList { + if sessionList[i].State == WTSActive { + return sessionList[i].SessionID, nil + } + } + + if sessionId, _, err := procWTSGetActiveConsoleSessionId.Call(); sessionId == 0xFFFFFFFF { + return 0xFFFFFFFF, fmt.Errorf("get current user session token: call native WTSGetActiveConsoleSessionId: %s", err) + } else { + return windows.Handle(sessionId), nil + } +} + +// WTSEnumerateSession will call the native +// version for Windows and parse the result +// to a Golang friendly version +func WTSEnumerateSessions() ([]*WTS_SESSION_INFO, error) { + var ( + sessionInformation windows.Handle = windows.Handle(0) + sessionCount int = 0 + sessionList []*WTS_SESSION_INFO = make([]*WTS_SESSION_INFO, 0) + ) + + if returnCode, _, err := procWTSEnumerateSessionsW.Call(WTS_CURRENT_SERVER_HANDLE, 0, 1, uintptr(unsafe.Pointer(&sessionInformation)), uintptr(unsafe.Pointer(&sessionCount))); returnCode == 0 { + return nil, fmt.Errorf("call native WTSEnumerateSessionsW: %s", err) + } + + structSize := unsafe.Sizeof(WTS_SESSION_INFO{}) + current := uintptr(sessionInformation) + for i := 0; i < sessionCount; i++ { + sessionList = append(sessionList, (*WTS_SESSION_INFO)(unsafe.Pointer(current))) + current += structSize + } + + return sessionList, nil +} + +// DuplicateUserTokenFromSessionID will attempt +// to duplicate the user token for the user logged +// into the provided session ID +func DuplicateUserTokenFromSessionID(sessionId windows.Handle) (windows.Token, error) { + var ( + impersonationToken windows.Handle = 0 + userToken windows.Token = 0 + ) + + if returnCode, _, err := procWTSQueryUserToken.Call(uintptr(sessionId), uintptr(unsafe.Pointer(&impersonationToken))); returnCode == 0 { + return 0xFFFFFFFF, fmt.Errorf("call native WTSQueryUserToken: %s", err) + } + + if returnCode, _, err := procDuplicateTokenEx.Call(uintptr(impersonationToken), 0, 0, uintptr(SecurityImpersonation), uintptr(TokenPrimary), uintptr(unsafe.Pointer(&userToken))); returnCode == 0 { + return 0xFFFFFFFF, fmt.Errorf("call native DuplicateTokenEx: %s", err) + } + + if err := windows.CloseHandle(impersonationToken); err != nil { + return 0xFFFFFFFF, fmt.Errorf("close windows handle used for token duplication: %s", err) + } + + return userToken, nil +} + +func StartProcessAsCurrentUser(appPath, cmdLine, workDir string) (uint32, error) { + var ( + sessionId windows.Handle + userToken windows.Token + envInfo windows.Handle + + startupInfo windows.StartupInfo + processInfo windows.ProcessInformation + + commandLine uintptr = 0 + workingDir uintptr = 0 + + err error + ) + + if sessionId, err = GetCurrentUserSessionId(); err != nil { + return 0, err + } + + if userToken, err = DuplicateUserTokenFromSessionID(sessionId); err != nil { + return 0, fmt.Errorf("get duplicate user token for current user session: %s(, sessionID: %v)", err, sessionId) + } + + if returnCode, _, err := procCreateEnvironmentBlock.Call(uintptr(unsafe.Pointer(&envInfo)), uintptr(userToken), 0); returnCode == 0 { + return 0, fmt.Errorf("create environment details for process: %s", err) + } + + creationFlags := CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE + // creationFlags := CREATE_NO_WINDOW + startupInfo.ShowWindow = SW_SHOW + // startupInfo.ShowWindow = uint16(SW_HIDE) + startupInfo.Desktop = windows.StringToUTF16Ptr("winsta0\\default") + + if len(cmdLine) > 0 { + commandLine = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(cmdLine))) + } + if len(workDir) > 0 { + workingDir = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(workDir))) + } + if returnCode, _, err := procCreateProcessAsUser.Call( + uintptr(userToken), uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(appPath))), commandLine, 0, 0, 0, + uintptr(creationFlags), uintptr(envInfo), workingDir, uintptr(unsafe.Pointer(&startupInfo)), uintptr(unsafe.Pointer(&processInfo)), + ); returnCode == 0 { + return 0, fmt.Errorf("create process as user: %s", err) + } + + return processInfo.ProcessId, nil +} diff --git a/screenDll/screenDll.go b/screenDll/screenDll.go new file mode 100644 index 0000000..8a6a230 --- /dev/null +++ b/screenDll/screenDll.go @@ -0,0 +1,39 @@ +/* + * @Description: + * @Version: 1.0 + * @Autor: solid + * @Date: 2022-08-24 18:37:22 + * @LastEditors: solid + * @LastEditTime: 2022-11-03 14:22:55 + */ +package main + +import ( + "fmt" + "image/png" + "os" + + "github.com/kbinani/screenshot" +) +import "C" + +//export GetFullScreen +func GetFullScreen(fp *C.char) { + filePath := C.GoString(fp) + bounds := screenshot.GetDisplayBounds(0) + img, err := screenshot.CaptureRect(bounds) + if err != nil { + fmt.Println(err) + + return + } + file, err := os.Create(filePath) + if err != nil { + fmt.Println(err) + return + } + defer file.Close() + png.Encode(file, img) +} +func main() { +}