Hi,
I know there has been some discussion in the Bloodhound Slack on regarding donut and Go binaries. After a short conversation with @TheWover, I wanted to post some findings.
I'm working with the following Go code. It's a simple application that pops message boxes at various points of execution. Hopefully, the code is fairly straight forward.
Test Go Code
// +build windows,cgo
// build dll:
// go build -buildmode=c-shared -o msgbox.dll msgbox.go
// build exe:
// go build -o msgbox.exe msgbox.go
package main
import (
"C"
"fmt"
"runtime"
"syscall"
"unsafe"
)
func abort(funcname string, err error) {
panic(fmt.Sprintf("%s failed: %v", funcname, err))
}
var (
kernel32, _ = syscall.LoadLibrary("kernel32.dll")
getModuleHandle, _ = syscall.GetProcAddress(kernel32, "GetModuleHandleW")
user32, _ = syscall.LoadLibrary("user32.dll")
messageBox, _ = syscall.GetProcAddress(user32, "MessageBoxW")
)
const (
MB_OK = 0x00000000
MB_OKCANCEL = 0x00000001
MB_ABORTRETRYIGNORE = 0x00000002
MB_YESNOCANCEL = 0x00000003
MB_YESNO = 0x00000004
MB_RETRYCANCEL = 0x00000005
MB_CANCELTRYCONTINUE = 0x00000006
MB_ICONHAND = 0x00000010
MB_ICONQUESTION = 0x00000020
MB_ICONEXCLAMATION = 0x00000030
MB_ICONASTERISK = 0x00000040
MB_USERICON = 0x00000080
MB_ICONWARNING = MB_ICONEXCLAMATION
MB_ICONERROR = MB_ICONHAND
MB_ICONINFORMATION = MB_ICONASTERISK
MB_ICONSTOP = MB_ICONHAND
MB_DEFBUTTON1 = 0x00000000
MB_DEFBUTTON2 = 0x00000100
MB_DEFBUTTON3 = 0x00000200
MB_DEFBUTTON4 = 0x00000300
)
func MessageBox(caption, text string, style uintptr) (result int) {
var nargs uintptr = 4
ret, _, callErr := syscall.Syscall9(uintptr(messageBox),
nargs,
0,
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text))),
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(caption))),
style,
0,
0,
0,
0,
0)
if callErr != 0 {
abort("Call MessageBox", callErr)
}
result = int(ret)
return
}
func GetModuleHandle() (handle uintptr) {
var nargs uintptr = 0
if ret, _, callErr := syscall.Syscall(uintptr(getModuleHandle), nargs, 0, 0, 0); callErr != 0 {
abort("Call GetModuleHandle", callErr)
} else {
handle = ret
}
return
}
func main() {
defer syscall.FreeLibrary(kernel32)
defer syscall.FreeLibrary(user32)
MessageBox("MessageBox", trace(), MB_OK)
}
// simple function to reveal current scope
func trace() (name string) {
pc := make([]uintptr, 10) // at least 1 entry needed
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
return "Hello from " + f.Name()
}
func init() {
MessageBox("MessageBox", trace(), MB_OK)
}
// No parameters (MessageBox might be started minimized)
// example: rundll32.exe msgbox.dll,FunctionA
//export FunctionA
func FunctionA() {
MessageBox("MessageBox", trace(), MB_OK)
}
// rundll32 with parameters (MessageBox might be started minimized)
// example: rundll32.exe msgbox.dll,FunctionB foo
//export FunctionB
func FunctionB(handle C.int, instance C.int, p *C.char, nCmdShow C.int) {
msg := fmt.Sprintf("msg: %s\nparm: %v", trace(), C.GoString(p))
MessageBox("MessageBox", msg, MB_OK)
}
The above code can be built as an EXE or a DLL.
When run as an EXE, the code will pop two message boxes: one from init()
and another from main()
.
When run as a DLL, you can invoke with the following:
rundll32.exe msgbox.dll,FunctionA
rundll32.exe msgbox.dll,FunctionB foo
I've tried inputting msgbox.dll and msgbox.exe into donut using various combinations. Here some results:
Go DLL
Build payload
> donut/donut.exe -f msgbox.dll -m FunctionA
[ Donut shellcode generator v0.9.2
[ Copyright (c) 2019 TheWover, Odzhan
DEBUG: donut.c:835:DonutCreate(): Entering.
DEBUG: donut.c:837:DonutCreate(): Validating configuration and path of file PDONUT_CONFIG: 000000000066EDB0
DEBUG: donut.c:853:DonutCreate(): Validating instance type 1
DEBUG: donut.c:893:DonutCreate(): Validating architecture
DEBUG: donut.c:903:DonutCreate(): Validating AMSI/WDLP bypass option
DEBUG: donut.c:287:get_file_info(): Entering.
DEBUG: donut.c:296:get_file_info(): Checking extension of msgbox.dll
DEBUG: donut.c:303:get_file_info(): Extension is ".dll"
DEBUG: donut.c:330:get_file_info(): Module is DLL
DEBUG: donut.c:337:get_file_info(): Mapping msgbox.dll into memory
DEBUG: donut.c:231:map_file(): Reading size of file : msgbox.dll
DEBUG: donut.c:240:map_file(): Opening msgbox.dll
DEBUG: donut.c:250:map_file(): Mapping 3369360 bytes for msgbox.dll
DEBUG: donut.c:346:get_file_info(): Checking DOS header
DEBUG: donut.c:352:get_file_info(): Checking NT header
DEBUG: donut.c:358:get_file_info(): Checking IMAGE_DATA_DIRECTORY
DEBUG: donut.c:366:get_file_info(): Checking characteristics
DEBUG: donut.c:405:get_file_info(): Leaving.
DEBUG: donut.c:924:DonutCreate(): Validating architecture 3 for DLL/EXE 2
DEBUG: donut.c:939:DonutCreate(): Validating DLL function "FunctionA" for DLL
DEBUG: donut.c:419:is_dll_export(): Entering.
DEBUG: donut.c:424:is_dll_export(): EAT VA : 192000
DEBUG: donut.c:427:is_dll_export(): Offset = 170000
DEBUG: donut.c:431:is_dll_export(): Number of exported functions : dbb
DEBUG: donut.c:441:is_dll_export(): Found API
DEBUG: donut.c:450:is_dll_export(): Leaving.
DEBUG: donut.c:966:DonutCreate(): Creating module
DEBUG: donut.c:528:CreateModule(): Entering.
DEBUG: donut.c:532:CreateModule(): Allocating 3375792 bytes of memory for DONUT_MODULE
DEBUG: donut.c:578:CreateModule(): DLL function : FunctionA
DEBUG: donut.c:622:CreateModule(): Leaving.
DEBUG: donut.c:973:DonutCreate(): Creating instance
DEBUG: donut.c:633:CreateInstance(): Entering.
DEBUG: donut.c:636:CreateInstance(): Allocating space for instance
DEBUG: donut.c:643:CreateInstance(): The size of module is 3375792 bytes. Adding to size of instance.
DEBUG: donut.c:655:CreateInstance(): Generating random key for instance
DEBUG: donut.c:661:CreateInstance(): Generating random key for module
DEBUG: donut.c:667:CreateInstance(): Generating random string to verify decryption
DEBUG: donut.c:673:CreateInstance(): Generating random IV for Maru hash
DEBUG: donut.c:678:CreateInstance(): Generating hashes for API using IV: 8f2c56dd7702db68
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : LoadLibraryA = 56B5339166F47DBA
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : GetProcAddress = 780AA8DAFA96AB39
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : GetModuleHandleA = F88453504A1FBC21
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : VirtualAlloc = B6E30F9DD64E472
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : VirtualFree = 27A160551E14E870
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : VirtualQuery = 49321C4C74407C1B
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : VirtualProtect = 2CED87B46E96C342
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : Sleep = CFA6CCD93C33E2AF
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : MultiByteToWideChar = B1937A2D00692354
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : GetUserDefaultLCID = 182053287B04E6E6
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SafeArrayCreate = B20B22790275829E
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SafeArrayCreateVector = 3E1ABB8A0061FC61
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SafeArrayPutElement = 18CEC67128EE1427
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SafeArrayDestroy = 778E7F9F5D9D2306
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SafeArrayGetLBound = BFCDF4DE062D0F4
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SafeArrayGetUBound = 83D7ABADC6660895
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SysAllocString = E2E0937BD44E0364
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SysFreeString = 192D367F894E6662
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : LoadTypeLib = 8DA50ABDFFC4B997
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : InternetCrackUrlA = 89F714D822BF70F6
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : InternetOpenA = 4C6E78015F4188DC
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : InternetConnectA = CC035229E65BBF2F
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : InternetSetOptionA = D435392CD1EB137E
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : InternetReadFile = BB2628E6825E2FCB
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : InternetCloseHandle = 8580FD167321B2F6
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : HttpOpenRequestA = 83A501F1EDAD723
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : HttpSendRequestA = 313E7D35F02FD434
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : HttpQueryInfoA = 4EFC4CF7D50FD4CC
DEBUG: donut.c:691:CreateInstance(): Hash for mscoree.dll : CorBindToRuntime = 6BEE295E647536C5
DEBUG: donut.c:691:CreateInstance(): Hash for mscoree.dll : CLRCreateInstance = EB5561BE5F0EDCAF
DEBUG: donut.c:691:CreateInstance(): Hash for ole32.dll : CoInitializeEx = 5E40CDDA0A0ACC99
DEBUG: donut.c:691:CreateInstance(): Hash for ole32.dll : CoCreateInstance = 5CC4C072B8648E8E
DEBUG: donut.c:691:CreateInstance(): Hash for ole32.dll : CoUninitialize = 7B421153367387DE
DEBUG: donut.c:804:CreateInstance(): Copying module data to instance
DEBUG: donut.c:809:CreateInstance(): encrypting instance
DEBUG: donut.c:821:CreateInstance(): Leaving.
DEBUG: donut.c:981:DonutCreate(): Saving instance to file
DEBUG: donut.c:1014:DonutCreate(): PIC size : 3400231
DEBUG: donut.c:1021:DonutCreate(): Inserting opcodes
DEBUG: donut.c:1057:DonutCreate(): Copying 16111 bytes of x86 + amd64 shellcode
DEBUG: donut.c:268:unmap_file(): Unmapping
DEBUG: donut.c:271:unmap_file(): Closing
DEBUG: donut.c:1083:DonutCreate(): Leaving.
[ Instance type : PIC
[ Module file : "msgbox.dll"
[ File type : DLL
[ Function : FunctionA
[ Target CPU : x86+AMD64
[ AMSI/WDLP : continue
[ Shellcode : "payload.bin"
DEBUG: donut.c:1091:DonutDelete(): Entering.
DEBUG: donut.c:1110:DonutDelete(): Leaving.
Instance Run
> donut/payload/payload.exe instance
Running...
DEBUG: payload.c:46:ThreadProc(): Maru IV : 8F2C56DD7702DB68
DEBUG: payload.c:49:ThreadProc(): Resolving address for VirtualAlloc() : B6E30F9DD64E472
DEBUG: payload.c:53:ThreadProc(): Resolving address for VirtualAlloc() : 27A160551E14E870
DEBUG: payload.c:62:ThreadProc(): VirtualAlloc : 00007FFB2B809D80 VirtualFree : 00007FFB2B809DA0
DEBUG: payload.c:64:ThreadProc(): Allocating 3384088 bytes of RW memory
DEBUG: payload.c:71:ThreadProc(): Copying 3384088 bytes of data to memory 0000000000C80000
DEBUG: payload.c:75:ThreadProc(): Zero initializing PDONUT_ASSEMBLY
DEBUG: payload.c:83:ThreadProc(): Decrypting 3384088 bytes of instance
DEBUG: payload.c:90:ThreadProc(): Generating hash to verify decryption
DEBUG: payload.c:92:ThreadProc(): Instance : bb830fb9f9552c5c | Result : bb830fb9f9552c5c
DEBUG: payload.c:99:ThreadProc(): Resolving LoadLibraryA
DEBUG: payload.c:105:ThreadProc(): Loading ole32.dll ...
DEBUG: payload.c:105:ThreadProc(): Loading oleaut32.dll ...
DEBUG: payload.c:105:ThreadProc(): Loading wininet.dll ...
DEBUG: payload.c:105:ThreadProc(): Loading mscoree.dll ...
DEBUG: payload.c:109:ThreadProc(): Resolving 33 API
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 780AA8DAFA96AB39
DEBUG: payload.c:112:ThreadProc(): Resolving API address for F88453504A1FBC21
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 0B6E30F9DD64E472
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 27A160551E14E870
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 49321C4C74407C1B
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 2CED87B46E96C342
DEBUG: payload.c:112:ThreadProc(): Resolving API address for CFA6CCD93C33E2AF
DEBUG: payload.c:112:ThreadProc(): Resolving API address for B1937A2D00692354
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 182053287B04E6E6
DEBUG: payload.c:112:ThreadProc(): Resolving API address for B20B22790275829E
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 3E1ABB8A0061FC61
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 18CEC67128EE1427
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 778E7F9F5D9D2306
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 0BFCDF4DE062D0F4
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 83D7ABADC6660895
DEBUG: payload.c:112:ThreadProc(): Resolving API address for E2E0937BD44E0364
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 192D367F894E6662
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 8DA50ABDFFC4B997
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 89F714D822BF70F6
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 4C6E78015F4188DC
DEBUG: payload.c:112:ThreadProc(): Resolving API address for CC035229E65BBF2F
DEBUG: payload.c:112:ThreadProc(): Resolving API address for D435392CD1EB137E
DEBUG: payload.c:112:ThreadProc(): Resolving API address for BB2628E6825E2FCB
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 8580FD167321B2F6
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 083A501F1EDAD723
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 313E7D35F02FD434
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 4EFC4CF7D50FD4CC
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 6BEE295E647536C5
DEBUG: payload.c:112:ThreadProc(): Resolving API address for EB5561BE5F0EDCAF
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 5E40CDDA0A0ACC99
DEBUG: peb.c:87:FindExport(): 5e40cdda0a0acc99 is forwarded to api-ms-win-core-com-l1-1-0.CoInitializeEx
DEBUG: peb.c:110:FindExport(): Trying to load api-ms-win-core-com-l1-1-0.dll
DEBUG: peb.c:114:FindExport(): Calling GetProcAddress(CoInitializeEx)
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 5CC4C072B8648E8E
DEBUG: peb.c:87:FindExport(): 5cc4c072b8648e8e is forwarded to api-ms-win-core-com-l1-1-0.CoCreateInstance
DEBUG: peb.c:110:FindExport(): Trying to load api-ms-win-core-com-l1-1-0.dll
DEBUG: peb.c:114:FindExport(): Calling GetProcAddress(CoCreateInstance)
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 7B421153367387DE
DEBUG: peb.c:87:FindExport(): 7b421153367387de is forwarded to api-ms-win-core-com-l1-1-0.CoUninitialize
DEBUG: peb.c:110:FindExport(): Trying to load api-ms-win-core-com-l1-1-0.dll
DEBUG: peb.c:114:FindExport(): Calling GetProcAddress(CoUninitialize)
DEBUG: payload.c:128:ThreadProc(): Using module embedded in instance
DEBUG: bypass.c:111:DisableAMSI(): Length of AmsiScanBufferStub is 37 bytes.
DEBUG: bypass.c:121:DisableAMSI(): Overwriting AmsiScanBuffer
DEBUG: bypass.c:136:DisableAMSI(): Length of AmsiScanStringStub is 37 bytes.
DEBUG: bypass.c:146:DisableAMSI(): Overwriting AmsiScanString
DEBUG: payload.c:139:ThreadProc(): DisableAMSI OK
DEBUG: bypass.c:325:DisableWLDP(): Length of WldpQueryDynamicCodeTrustStub is 23 bytes.
DEBUG: bypass.c:349:DisableWLDP(): Length of WldpIsClassInApprovedListStub is 37 bytes.
DEBUG: payload.c:145:ThreadProc(): DisableWLDP OK
DEBUG: inmem_pe.c:89:RunPE(): Using module embedded in instance
DEBUG: inmem_pe.c:111:RunPE(): Allocating 3358720 (0x334000) bytes of RWX memory for file
DEBUG: inmem_pe.c:120:RunPE(): Copying Headers
DEBUG: inmem_pe.c:123:RunPE(): Copying each section to RWX memory 0000000002B60000
DEBUG: inmem_pe.c:135:RunPE(): Processing the Import Table
DEBUG: inmem_pe.c:143:RunPE(): Loading KERNEL32.dll
DEBUG: inmem_pe.c:143:RunPE(): Loading msvcrt.dll
DEBUG: inmem_pe.c:209:RunPE(): Applying Relocations
DEBUG: inmem_pe.c:234:RunPE(): Processing TLS directory
DEBUG: inmem_pe.c:241:RunPE(): Calling 0000000002BF5110
DEBUG: inmem_pe.c:241:RunPE(): Calling 0000000002BF50E0
DEBUG: inmem_pe.c:249:RunPE(): Executing entrypoint of DLL
DEBUG: inmem_pe.c:255:RunPE(): Resolving address of FunctionA
DEBUG: inmem_pe.c:263:RunPE(): IMAGE_EXPORT_DIRECTORY.NumberOfNames : 3515
DEBUG: inmem_pe.c:286:RunPE(): Calling FunctionA via code stub.
DEBUG: inmem_pe.c:292:RunPE(): Erasing code stub
DEBUG: inmem_pe.c:319:RunPE(): Releasing memory
DEBUG: payload.c:188:ThreadProc(): Erasing RW memory for instance
DEBUG: payload.c:191:ThreadProc(): Releasing RW memory for instance
Result: This works as expected popping message boxes for init()
and FunctionA()
.
However, payload.bin does not work when run through runsc.exe
.
Run Shellcode
> ./runsc.exe -f payload.bin -x
[ run shellcode v0.2
[ reading code from payload.bin
[ executing code...OK!
Result: No message boxes.
oops... was using a x86 version of runsc trying to run x64 DLL.
Result: This works as expected popping message boxes for init()
and FunctionA()
.
Go EXE
I get different results here. The instance run ends at DEBUG: inmem_pe.c:234:RunPE(): Processing TLS directory
without error, but does not continue or pop message boxes.
Build Payload
> donut/donut.exe -f msgbox.exe
[ Donut shellcode generator v0.9.2
[ Copyright (c) 2019 TheWover, Odzhan
DEBUG: donut.c:835:DonutCreate(): Entering.
DEBUG: donut.c:837:DonutCreate(): Validating configuration and path of file PDONUT_CONFIG: 000000000066EDB0
DEBUG: donut.c:853:DonutCreate(): Validating instance type 1
DEBUG: donut.c:893:DonutCreate(): Validating architecture
DEBUG: donut.c:903:DonutCreate(): Validating AMSI/WDLP bypass option
DEBUG: donut.c:287:get_file_info(): Entering.
DEBUG: donut.c:296:get_file_info(): Checking extension of msgbox.exe
DEBUG: donut.c:303:get_file_info(): Extension is ".exe"
DEBUG: donut.c:325:get_file_info(): Module is EXE
DEBUG: donut.c:337:get_file_info(): Mapping msgbox.exe into memory
DEBUG: donut.c:231:map_file(): Reading size of file : msgbox.exe
DEBUG: donut.c:240:map_file(): Opening msgbox.exe
DEBUG: donut.c:250:map_file(): Mapping 3210015 bytes for msgbox.exe
DEBUG: donut.c:346:get_file_info(): Checking DOS header
DEBUG: donut.c:352:get_file_info(): Checking NT header
DEBUG: donut.c:358:get_file_info(): Checking IMAGE_DATA_DIRECTORY
DEBUG: donut.c:366:get_file_info(): Checking characteristics
DEBUG: donut.c:405:get_file_info(): Leaving.
DEBUG: donut.c:924:DonutCreate(): Validating architecture 3 for DLL/EXE 2
DEBUG: donut.c:966:DonutCreate(): Creating module
DEBUG: donut.c:528:CreateModule(): Entering.
DEBUG: donut.c:532:CreateModule(): Allocating 3216447 bytes of memory for DONUT_MODULE
DEBUG: donut.c:622:CreateModule(): Leaving.
DEBUG: donut.c:973:DonutCreate(): Creating instance
DEBUG: donut.c:633:CreateInstance(): Entering.
DEBUG: donut.c:636:CreateInstance(): Allocating space for instance
DEBUG: donut.c:643:CreateInstance(): The size of module is 3216447 bytes. Adding to size of instance.
DEBUG: donut.c:655:CreateInstance(): Generating random key for instance
DEBUG: donut.c:661:CreateInstance(): Generating random key for module
DEBUG: donut.c:667:CreateInstance(): Generating random string to verify decryption
DEBUG: donut.c:673:CreateInstance(): Generating random IV for Maru hash
DEBUG: donut.c:678:CreateInstance(): Generating hashes for API using IV: eb4a78958abbbafe
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : LoadLibraryA = 2DF95594CD608906
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : GetProcAddress = FAB0AE969B017E0B
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : GetModuleHandleA = D724A33874DB7868
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : VirtualAlloc = EC3A34FF852C8DA6
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : VirtualFree = 122563EE3D349FCB
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : VirtualQuery = B5DA04ECC4AB476
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : VirtualProtect = 1AC0FE9F635C58DC
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : Sleep = BEA29614205E7C70
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : MultiByteToWideChar = 63647A06DD8F3549
DEBUG: donut.c:691:CreateInstance(): Hash for kernel32.dll : GetUserDefaultLCID = 89F58D639D1DCC36
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SafeArrayCreate = 67E1E7A184D3F769
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SafeArrayCreateVector = 9E4807E146DFB7DE
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SafeArrayPutElement = 595648A793AAC0F5
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SafeArrayDestroy = 3C95DAE96B9AA7C7
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SafeArrayGetLBound = 43A289E081CEE4DA
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SafeArrayGetUBound = 4D7F534264432B27
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SysAllocString = 67B14B010317DA88
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : SysFreeString = 82AC3F71770BB511
DEBUG: donut.c:691:CreateInstance(): Hash for oleaut32.dll : LoadTypeLib = 13BA13DAA3578E1A
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : InternetCrackUrlA = E325E512127959C8
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : InternetOpenA = 861FF063A79DD483
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : InternetConnectA = 9263EC0B9739E72D
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : InternetSetOptionA = 41C02E589751D1DF
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : InternetReadFile = FCD711CD0BAA4B19
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : InternetCloseHandle = ADCBEADC713F7C66
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : HttpOpenRequestA = D6E2A37B11777014
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : HttpSendRequestA = 51786C66F73C6F70
DEBUG: donut.c:691:CreateInstance(): Hash for wininet.dll : HttpQueryInfoA = 56AF03D19CD82713
DEBUG: donut.c:691:CreateInstance(): Hash for mscoree.dll : CorBindToRuntime = DCC59EDA1DEAD734
DEBUG: donut.c:691:CreateInstance(): Hash for mscoree.dll : CLRCreateInstance = 4C8B3175B83FB0F8
DEBUG: donut.c:691:CreateInstance(): Hash for ole32.dll : CoInitializeEx = B654CBED3853909B
DEBUG: donut.c:691:CreateInstance(): Hash for ole32.dll : CoCreateInstance = 28E28E9A7F4F53EB
DEBUG: donut.c:691:CreateInstance(): Hash for ole32.dll : CoUninitialize = 3202CF1D21697E7F
DEBUG: donut.c:804:CreateInstance(): Copying module data to instance
DEBUG: donut.c:809:CreateInstance(): encrypting instance
DEBUG: donut.c:821:CreateInstance(): Leaving.
DEBUG: donut.c:981:DonutCreate(): Saving instance to file
DEBUG: donut.c:1014:DonutCreate(): PIC size : 3240886
DEBUG: donut.c:1021:DonutCreate(): Inserting opcodes
DEBUG: donut.c:1057:DonutCreate(): Copying 16111 bytes of x86 + amd64 shellcode
DEBUG: donut.c:268:unmap_file(): Unmapping
DEBUG: donut.c:271:unmap_file(): Closing
DEBUG: donut.c:1083:DonutCreate(): Leaving.
[ Instance type : PIC
[ Module file : "msgbox.exe"
[ File type : EXE
[ Target CPU : x86+AMD64
[ AMSI/WDLP : continue
[ Shellcode : "payload.bin"
DEBUG: donut.c:1091:DonutDelete(): Entering.
DEBUG: donut.c:1110:DonutDelete(): Leaving.
Instance run
> donut/payload/payload.exe instance
Running...
DEBUG: payload.c:46:ThreadProc(): Maru IV : EB4A78958ABBBAFE
DEBUG: payload.c:49:ThreadProc(): Resolving address for VirtualAlloc() : EC3A34FF852C8DA6
DEBUG: payload.c:53:ThreadProc(): Resolving address for VirtualAlloc() : 122563EE3D349FCB
DEBUG: payload.c:62:ThreadProc(): VirtualAlloc : 00007FFB2B809D80 VirtualFree : 00007FFB2B809DA0
DEBUG: payload.c:64:ThreadProc(): Allocating 3224743 bytes of RW memory
DEBUG: payload.c:71:ThreadProc(): Copying 3224743 bytes of data to memory 0000000000D50000
DEBUG: payload.c:75:ThreadProc(): Zero initializing PDONUT_ASSEMBLY
DEBUG: payload.c:83:ThreadProc(): Decrypting 3224743 bytes of instance
DEBUG: payload.c:90:ThreadProc(): Generating hash to verify decryption
DEBUG: payload.c:92:ThreadProc(): Instance : 4dfa180a90ced2eb | Result : 4dfa180a90ced2eb
DEBUG: payload.c:99:ThreadProc(): Resolving LoadLibraryA
DEBUG: payload.c:105:ThreadProc(): Loading ole32.dll ...
DEBUG: payload.c:105:ThreadProc(): Loading oleaut32.dll ...
DEBUG: payload.c:105:ThreadProc(): Loading wininet.dll ...
DEBUG: payload.c:105:ThreadProc(): Loading mscoree.dll ...
DEBUG: payload.c:109:ThreadProc(): Resolving 33 API
DEBUG: payload.c:112:ThreadProc(): Resolving API address for FAB0AE969B017E0B
DEBUG: payload.c:112:ThreadProc(): Resolving API address for D724A33874DB7868
DEBUG: payload.c:112:ThreadProc(): Resolving API address for EC3A34FF852C8DA6
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 122563EE3D349FCB
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 0B5DA04ECC4AB476
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 1AC0FE9F635C58DC
DEBUG: payload.c:112:ThreadProc(): Resolving API address for BEA29614205E7C70
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 63647A06DD8F3549
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 89F58D639D1DCC36
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 67E1E7A184D3F769
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 9E4807E146DFB7DE
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 595648A793AAC0F5
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 3C95DAE96B9AA7C7
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 43A289E081CEE4DA
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 4D7F534264432B27
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 67B14B010317DA88
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 82AC3F71770BB511
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 13BA13DAA3578E1A
DEBUG: payload.c:112:ThreadProc(): Resolving API address for E325E512127959C8
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 861FF063A79DD483
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 9263EC0B9739E72D
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 41C02E589751D1DF
DEBUG: payload.c:112:ThreadProc(): Resolving API address for FCD711CD0BAA4B19
DEBUG: payload.c:112:ThreadProc(): Resolving API address for ADCBEADC713F7C66
DEBUG: payload.c:112:ThreadProc(): Resolving API address for D6E2A37B11777014
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 51786C66F73C6F70
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 56AF03D19CD82713
DEBUG: payload.c:112:ThreadProc(): Resolving API address for DCC59EDA1DEAD734
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 4C8B3175B83FB0F8
DEBUG: payload.c:112:ThreadProc(): Resolving API address for B654CBED3853909B
DEBUG: peb.c:87:FindExport(): b654cbed3853909b is forwarded to api-ms-win-core-com-l1-1-0.CoInitializeEx
DEBUG: peb.c:110:FindExport(): Trying to load api-ms-win-core-com-l1-1-0.dll
DEBUG: peb.c:114:FindExport(): Calling GetProcAddress(CoInitializeEx)
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 28E28E9A7F4F53EB
DEBUG: peb.c:87:FindExport(): 28e28e9a7f4f53eb is forwarded to api-ms-win-core-com-l1-1-0.CoCreateInstance
DEBUG: peb.c:110:FindExport(): Trying to load api-ms-win-core-com-l1-1-0.dll
DEBUG: peb.c:114:FindExport(): Calling GetProcAddress(CoCreateInstance)
DEBUG: payload.c:112:ThreadProc(): Resolving API address for 3202CF1D21697E7F
DEBUG: peb.c:87:FindExport(): 3202cf1d21697e7f is forwarded to api-ms-win-core-com-l1-1-0.CoUninitialize
DEBUG: peb.c:110:FindExport(): Trying to load api-ms-win-core-com-l1-1-0.dll
DEBUG: peb.c:114:FindExport(): Calling GetProcAddress(CoUninitialize)
DEBUG: payload.c:128:ThreadProc(): Using module embedded in instance
DEBUG: bypass.c:111:DisableAMSI(): Length of AmsiScanBufferStub is 37 bytes.
DEBUG: bypass.c:121:DisableAMSI(): Overwriting AmsiScanBuffer
DEBUG: bypass.c:136:DisableAMSI(): Length of AmsiScanStringStub is 37 bytes.
DEBUG: bypass.c:146:DisableAMSI(): Overwriting AmsiScanString
DEBUG: payload.c:139:ThreadProc(): DisableAMSI OK
DEBUG: bypass.c:325:DisableWLDP(): Length of WldpQueryDynamicCodeTrustStub is 23 bytes.
DEBUG: bypass.c:349:DisableWLDP(): Length of WldpIsClassInApprovedListStub is 37 bytes.
DEBUG: payload.c:145:ThreadProc(): DisableWLDP OK
DEBUG: inmem_pe.c:89:RunPE(): Using module embedded in instance
DEBUG: inmem_pe.c:111:RunPE(): Allocating 3186688 (0x30a000) bytes of RWX memory for file
DEBUG: inmem_pe.c:120:RunPE(): Copying Headers
DEBUG: inmem_pe.c:123:RunPE(): Copying each section to RWX memory 0000000002C10000
DEBUG: inmem_pe.c:135:RunPE(): Processing the Import Table
DEBUG: inmem_pe.c:143:RunPE(): Loading KERNEL32.dll
DEBUG: inmem_pe.c:143:RunPE(): Loading msvcrt.dll
DEBUG: inmem_pe.c:234:RunPE(): Processing TLS directory
Result: No message boxes. Execution terminates seemingly without error.
Run shellcode
./runsc.exe -f payload.bin -x
[ run shellcode v0.2
[ reading code from payload.bin
[ executing code...OK!
Result: No message boxes
Go DLL with Dllmain
At one point, I had a Go DLL working as donut shellcode. By placing the function call in Dllmain on the ON_PROCESS_ATTACH
. However, I cannot reproduce. (This was over a week ago, so a few commits back.)
I'm still debugging, but hopefully this helps!