Closed aus closed 5 years ago
Currently, donut doesn't support unmanaged EXE/DLL files without relocation information (.reloc). There should have been a check for the PE directory before building the shell code, which is now present. If you try building shellcode from PE file with no .reloc information, you'll receive the following error.
[ Error : This file has no relocation information required for in-memory execution.
Callback addresses in the TLS directory are absolute and are relatively simple to get working without .reloc information. However, code in the actual callback function may also use absolute addresses for data variables, and this is what causes the EXE file to crash the host process. To support relocating the code without .reloc information embedded in the PE file would require a built-in disassembler :) Perhaps it can be implemented in future, because it's certainly doable.
The TLS callbacks for DLL are only executed when the process begins and not for a new thread or when the process ends, which is required. For the moment, I've disabled support for PE files that do not contain relocation information. DLL files will still load, although there are likely to be issues supporting TLS.
was using x86 runsc against x64 DLL payload.bin. doh! DLL works. 😄 see this comment's revision history for a full look at my stupidity. thanks @odzhan for setting me straight.
No problem! I've done it myself many times during development :grin:
For those seeking more information about Go and donut, @odzhan added some checks to ensure the target PE has a .reloc section. Go EXEs do not normally build with .relocs (but Go DLLs do). donut will reject PEs without .relocs, thus Go EXEs do not work without some extra steps.
To get Go EXEs to work with donut, you'll need to build your executable with -buildmode=pie
. Unfortunately, this buildmode is not supported on windows/x86
and windows/amd64
unless you build with this patched version of Go. With this patched version of Go, you can just do a go build -buildmode=pie
and donut should now accept the EXE since it will have a .reloc section.
update: Go 1.15 supports buildmode=pie
by default for Windows executables.
If someone faces the same problem with gcc compiled executables -> Add those flags to the compiler
-Wl,--dynamicbase,--export-all-symbols
https://stackoverflow.com/questions/19451652/mingw-relocation-table
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
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 frommain()
.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
Instance Run
Result: This works as expected popping message boxes for
init()
andFunctionA()
.However, payload.bin does not work when run through
runsc.exe
.Run Shellcode
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()
andFunctionA()
.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
Instance run
Result: No message boxes. Execution terminates seemingly without error.
Run shellcode
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!