All Projects → S3cur3Th1sSh1t → SharpLigolo

S3cur3Th1sSh1t / SharpLigolo

Licence: other
C# wrapper for ligolo

Programming Languages

C#
18002 projects

SharpLigolo

C# Wrapper of Ligolo from https://github.com/sysdream/ligolo

I did this mainly to experiment for myself with embedding golang binaries in C#.

This C# wrapper has no certificates embedded. So you can only run it with the -skipverify option which is not recommended:

alt text

To stay on the safe side build the binary for yourself with embedded certificates.

This technique has one big disadvantage. It writes the dll to appdata on runtime. Therefore it's easy to spot for defenders.

The main.go file was changed like this before compilation:

package main

import (
	"bytes"
	"crypto/sha256"
	"crypto/tls"
	"encoding/hex"
	"flag"
	"fmt"
	"github.com/armon/go-socks5"
	"github.com/hashicorp/yamux"
	"github.com/sirupsen/logrus"
	"io"
	"net"
	"strings"
	"time"
	"C"
)

var tlsFingerprint string

var (
	ErrInvalidServerCert = fmt.Errorf("invalid TLS server certificate")
	ErrInvalidPinnedCert = fmt.Errorf("invalid TLS pinned certificate")
)


//maindel :
//export maindel
func maindel(charargs *C.char) {
    var stringargs string
	stringargs = C.GoString(charargs)
	arrayargs := strings.Fields(stringargs)
    fmt.Println(arrayargs)
	
	fmt.Print(`
██╗     ██╗ ██████╗  ██████╗ ██╗      ██████╗ 
██║     ██║██╔════╝ ██╔═══██╗██║     ██╔═══██╗
██║     ██║██║  ███╗██║   ██║██║     ██║   ██║
██║     ██║██║   ██║██║   ██║██║     ██║   ██║
███████╗██║╚██████╔╝╚██████╔╝███████╗╚██████╔╝
╚══════╝╚═╝ ╚═════╝  ╚═════╝ ╚══════╝ ╚═════╝
              Local Input - Go - Local Output

`)

	bypassVerify := flag.Bool("skipverify", false, "Skip TLS certificate pinning verification")

	targetServer := flag.String("targetserver", "", "The destination server (a RDP client, SSH server, etc.) - when not specified, Ligolo starts a socks5 proxy server")
	relayServer := flag.String("relayserver", "127.0.0.1:5555", "The relay server (the connect-back address)")
	autoRestart := flag.Bool("autorestart", false, "Attempt to reconnect in case of an exception")

	flag.Parse()

	if tlsFingerprint == "" && *bypassVerify == false {
		logrus.Fatal("TLS Fingerprint is missing ! Use -skipverify option to bypass TLS verification")
	}
	for {
		err := StartLigolo(*relayServer, *targetServer, *bypassVerify)
		if err != nil {
			if *autoRestart {
				logrus.Error(err)
			} else {
				logrus.Fatal(err)
			}
		}
		logrus.Warning("Restarting Ligolo...")
		time.Sleep(10 * time.Second)
	}

}
func main() {

}

func StartLigolo(relayServer string, targetServer string, skipVerify bool) error {
	var socks *socks5.Server
	logrus.Infoln("Connecting to relay server...")
	config := &tls.Config{InsecureSkipVerify: true}
	conn, err := tls.Dial("tcp", relayServer, config)
	if err != nil {
		return err
	}

	if !skipVerify {
		err := verifyTlsCertificate(conn.ConnectionState())
		if err != nil {
			logrus.WithFields(logrus.Fields{"remoteaddr": conn.RemoteAddr().String()}).Error(err)
			return err
		}
	}

	if targetServer == "" {
		socks, err = startSocksProxy()
		if err != nil {
			logrus.Error("Could not start SOCKS5 proxy !")
			return err
		}
	}

	session, err := yamux.Client(conn, nil)
	if err != nil {
		return err
	}

	logrus.Infoln("Waiting for connections....")

	for {
		stream, err := session.Accept()
		if err != nil {
			return err
		}
		logrus.WithFields(logrus.Fields{"active_sessions": session.NumStreams()}).Println("Accepted new connection !")
		// When no targetServer are specified, starts a socks5 proxy
		if targetServer == "" {
			go socks.ServeConn(stream)
		} else {
			proxyConn, err := net.Dial("tcp", targetServer)
			if err != nil {
				logrus.Errorf("Error creating Proxy TCP connection ! Error : %s\n", err)
				return err
			}
			go handleRelay(stream, proxyConn)
		}

	}
}

func startSocksProxy() (*socks5.Server, error) {
	conf := &socks5.Config{}
	socks, err := socks5.New(conf)
	if err != nil {
		logrus.Error("Could not start SOCKS5 proxy !")
		return nil, err
	}
	return socks, nil
}

func verifyTlsCertificate(connState tls.ConnectionState) error {
	valid := false
	pinnedCert := strings.Replace(tlsFingerprint, ":", "", -1)
	pinnedCertBytes, err := hex.DecodeString(pinnedCert)
	if err != nil {
		return ErrInvalidPinnedCert
	}
	for _, peerCert := range connState.PeerCertificates {
		hash := sha256.Sum256(peerCert.Raw)
		if bytes.Compare(hash[:], pinnedCertBytes) == 0 {
			valid = true
		}
	}
	if !valid {
		return ErrInvalidServerCert
	}
	return nil
}

func handleRelay(src net.Conn, dst net.Conn) {
	stop := make(chan bool, 2)

	go relay(src, dst, stop)
	go relay(dst, src, stop)

	select {
	case <-stop:
		return
	}
}

func relay(src net.Conn, dst net.Conn, stop chan bool) {
	io.Copy(dst, src)
	dst.Close()
	src.Close()
	stop <- true
	return
}

Credit to shantanu561993 for writing the following blog post:

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].