Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated shellcode does not work #45

Open
lesnuages opened this issue Mar 23, 2020 · 15 comments
Open

Generated shellcode does not work #45

lesnuages opened this issue Mar 23, 2020 · 15 comments
Assignees
Labels
bug Something isn't working
Milestone

Comments

@lesnuages
Copy link

What's wrong ?

The generated loader.bin shellcode does not seem to work on a specific system configuration. It makes the host process crash when loaded.

System configuration

  • Windows 10.0.18362 N/A Build 18362
  • .NET Framework installed on the host:
    • v4.0.0.0
    • v4.8.03752
  • Anti-Virus: Windows Defender is installed by default, but all options have been disabled
  • Donut: latest version built from master as of 03/23/2020

What did you try to do ?

Use donut.exe to generate a shellcode based on the DemoCreateProcess assembly with the following command:

.\donut.exe -e 1 -b 1 -z 1 -c TestClass -m RunProcess -p "calc.exe calc.exe" C:\Users\lab\source\repos\donut\DemoCreateProcess\bin\Release\DemoCreateProcess.dll

Then converted the shellcode to a base64 string using the following powershell snippet:

 [System.Convert]::ToBase64String([IO.File]::ReadAllBytes("path\to\loader.bin")) | clip

Finally, replaced the base64 string in the DonutTest project, line 13. Then, I compiled the DonutTest project, started a new notepad.exe process (pid 5824), and ran:

.\DonutTest.exe 5824

What did you expect ?

calc.exe should be running as a child of notepad.exe (process 5824)

What happened ?

The notepad process crashed.

More information

I initially had the issue with another assembly, and another shellcode injector, but even trying with the ones provided within the donut repo, I am able to reproduce this behavior. Building and using a debug version of donut results in the same behavior, although running .\loader64.exe .\instance on the generated instance file works well. So my best guess would be that something is wrong in the loader embedded in the final shellcode, but I have honestly no clue about what.

Here are the log files for the debug build:
https://gist.github.com/lesnuages/f27ef9b33676ac4f0e882c738ed0fb10

@TheWover
Copy link
Owner

Thanks for the issue. Will test and see if I can reproduce.

@TheWover TheWover self-assigned this Mar 23, 2020
@TheWover TheWover added the bug Something isn't working label Mar 23, 2020
@odzhan
Copy link
Collaborator

odzhan commented Mar 25, 2020

For what it's worth, I used the same options and file, then injected loader.bin into notepad. Two instances of calc.exe were created, so I'm not sure what the problem is. EDIT: Did you build from master yourself? Did you use MSVC 2019 for this?

@lesnuages
Copy link
Author

I built from master on Linux, using make debug -f Makefile.mingw.

Here's the version I have

x86_64-w64-mingw32-gcc -v
Using built-in specs.
COLLECT_GCC=x86_64-w64-mingw32-gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-w64-mingw32/9.2.1/lto-wrapper
Target: x86_64-w64-mingw32
Configured with: ../configure --prefix=/usr --bindir=/usr/bin --includedir=/usr/include --mandir=/usr/share/man --infodir=/usr/share/info --datadir=/usr/share --build=x86_64-redhat-linux-gnu --host=x86_64-redhat-linux-gnu --with-gnu-as --with-gnu-ld --verbose --without-newlib --disable-multilib --disable-plugin --with-system-zlib --disable-nls --without-included-gettext --disable-win32-registry --enable-languages=c,c++,objc,obj-c++,fortran --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-threads=posix --with-cloog --enable-libgomp --target=x86_64-w64-mingw32 --with-sysroot=/usr/x86_64-w64-mingw32/sys-root --with-gxx-include-dir=/usr/x86_64-w64-mingw32/sys-root/mingw/include/c++
Thread model: posix
gcc version 9.2.1 20190827 (Fedora MinGW 9.2.1-1.fc31) (GCC)

@odzhan
Copy link
Collaborator

odzhan commented Mar 25, 2020

Any chance you can attach loader.bin generated with DemoCreateProcess.dll ?

@lesnuages
Copy link
Author

Sure, here you go:
loader.bin.zip

@odzhan
Copy link
Collaborator

odzhan commented Mar 25, 2020

It's some problem related to compiling with MingW that I haven't noticed before. Looking into it.

@lesnuages
Copy link
Author

Well I had the same issues using the generated shellcode from donut on Linux, if that ever helps.

@TheWover
Copy link
Owner

For what it's worth, I'm having a similar problem. Using the dev branch and the same .NET Assembly (DemoCreateProcess), generating shellcode on Windows works fine while shellcode generated on Linux crashes the host process.

I have a very different version of mingw than @lesnuages , though.


COLLECT_GCC=x86_64-w64-mingw32-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-w64-mingw32/7.3-win32/lto-wrapper
Target: x86_64-w64-mingw32
Configured with: ../../src/configure --build=x86_64-linux-gnu --prefix=/usr --includedir='/usr/include' --mandir='/usr/share/man' --infodir='/usr/share/info' --sysconfdir=/etc --localstatedir=/var --disable-silent-rules --libdir='/usr/lib/x86_64-linux-gnu' --libexecdir='/usr/lib/x86_64-linux-gnu' --disable-maintainer-mode --disable-dependency-tracking --prefix=/usr --enable-shared --enable-static --disable-multilib --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --libdir=/usr/lib --enable-libstdcxx-time=yes --with-tune=generic --with-headers=/usr/x86_64-w64-mingw32/include --enable-version-specific-runtime-libs --enable-fully-dynamic-string --enable-libgomp --enable-languages=c,c++,fortran,objc,obj-c++,ada --enable-lto --with-plugin-ld --enable-threads=win32 --program-suffix=-win32 --program-prefix=x86_64-w64-mingw32- --target=x86_64-w64-mingw32 --with-as=/usr/bin/x86_64-w64-mingw32-as --with-ld=/usr/bin/x86_64-w64-mingw32-ld --enable-libatomic --enable-libstdcxx-filesystem-ts=yes
Thread model: win32
gcc version 7.3-win32 20180312 (GCC) 

@odzhan
Copy link
Collaborator

odzhan commented Mar 26, 2020

I'm not sure what the problem is at the moment. This is what I have on Debian, installed from packages.

Using built-in specs.
COLLECT_GCC=x86_64-w64-mingw32-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-w64-mingw32/6.3-win32/lto-wrapper
Target: x86_64-w64-mingw32
Configured with: ../../src/configure --build=x86_64-linux-gnu --prefix=/usr --includedir='/usr/include' --mandir='/usr/share/man' --infodir='/usr/share/info' --sysconfdir=/etc --localstatedir=/var --disable-silent-rules --libdir='/usr/lib/x86_64-linux-gnu' --libexecdir='/usr/lib/x86_64-linux-gnu' --disable-maintainer-mode --disable-dependency-tracking --prefix=/usr --enable-shared --enable-static --disable-multilib --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --libdir=/usr/lib --enable-libstdcxx-time=yes --with-tune=generic --enable-version-specific-runtime-libs --enable-fully-dynamic-string --enable-libgomp --enable-languages=c,c++,fortran,objc,obj-c++ --enable-lto --with-plugin-ld --enable-threads=win32 --program-suffix=-win32 --program-prefix=x86_64-w64-mingw32- --target=x86_64-w64-mingw32 --with-as=/usr/bin/x86_64-w64-mingw32-as --with-ld=/usr/bin/x86_64-w64-mingw32-ld --enable-libatomic
Thread model: win32
gcc version 6.3.0 20170516 (GCC)

It works fine with my version of MingW, so I'm wondering about the build of GCC you both have installed. Was it built from source/repo? When I debugged the loader uploaded by @lesnuages RtlInitUnicodeString was initialized instead of RtlExitUserProcess.

That leads me to think it's related to the size of ULONG_PTR or..the structure is not aligned by 8 bytes even though -fpack-struct=8 is specified.

len is defined as uint32_t at the start of the DONUT_INSTANCE structure in include/donut.h. What happens if you change this to uint64_t and recompile everything? I'll try getting the version you have installed.

@odzhan
Copy link
Collaborator

odzhan commented Mar 27, 2020

Try compiling and running this against the loader you generated.
dumpcfg.c.gz

Here's what I get:

c:\donut>dumpcfg loader.bin
Length : 8576
Key : 00000000000000000000000000000000
CTR : 00000000000000000000000000000000
Maru IV : 0
Exit Opt : 1
OEP : 0000000000000000
API Count : 52
00 => 8322A3F655D252A0 is the hash for kernel32.dll!LoadLibraryA : OK
01 => 5F9A2F5A70159AF7 is the hash for kernel32.dll!GetProcAddress : OK
02 => ECEC2E0F77C1DF79 is the hash for kernel32.dll!GetModuleHandleA : OK
03 => 52622E8E2A03836A is the hash for kernel32.dll!VirtualAlloc : OK
04 => A0F99483877BBCC4 is the hash for kernel32.dll!VirtualFree : OK
05 => A6B3DEBBBD52F776 is the hash for kernel32.dll!VirtualQuery : OK
06 => E0206318E83E16F4 is the hash for kernel32.dll!VirtualProtect : OK
07 => 29407C7E01077DEF is the hash for kernel32.dll!Sleep : OK
08 => B2D46685A8D6CC8F is the hash for kernel32.dll!MultiByteToWideChar : OK
09 => 3D28AFB2AD9197E5 is the hash for kernel32.dll!GetUserDefaultLCID : OK
10 => C45F651AAFFB410B is the hash for kernel32.dll!WaitForSingleObject : OK
11 => A88D8A63D7D17933 is the hash for kernel32.dll!CreateThread : OK
12 => EDBBC13672C19CE4 is the hash for kernel32.dll!GetThreadContext : OK
13 => 6A2447B1BECC189C is the hash for kernel32.dll!GetCurrentThread : OK
14 => E6E2D0AA08292200 is the hash for kernel32.dll!GetCommandLineA : OK
15 => 1C7CF9F57FA86E3D is the hash for kernel32.dll!GetCommandLineW : OK
16 => F3848EC570838A21 is the hash for shell32.dll!CommandLineToArgvW : OK
17 => DFBD47E13EE13B10 is the hash for oleaut32.dll!SafeArrayCreate : OK
18 => BD77AF2569689C8A is the hash for oleaut32.dll!SafeArrayCreateVector : OK
19 => 8AD71499A1140B4D is the hash for oleaut32.dll!SafeArrayPutElement : OK
20 => 2082D640CCFD441B is the hash for oleaut32.dll!SafeArrayDestroy : OK
21 => 7046B02E03CE7D0C is the hash for oleaut32.dll!SafeArrayGetLBound : OK
22 => C1EB0C113A5660BA is the hash for oleaut32.dll!SafeArrayGetUBound : OK
23 => F3AC45C203C14CE0 is the hash for oleaut32.dll!SysAllocString : OK
24 => 733CE6F644E27222 is the hash for oleaut32.dll!SysFreeString : OK
25 => 3E3F0153FB195BEB is the hash for oleaut32.dll!LoadTypeLib : OK
26 => 908B117CC2EF66F9 is the hash for wininet.dll!InternetCrackUrlA : OK
27 => A146D290F7863A30 is the hash for wininet.dll!InternetOpenA : OK
28 => 57777DD39940F617 is the hash for wininet.dll!InternetConnectA : OK
29 => 9395C00826DDF250 is the hash for wininet.dll!InternetSetOptionA : OK
30 => D388820170E23FB1 is the hash for wininet.dll!InternetReadFile : OK
31 => 6A0E5F83356BF090 is the hash for wininet.dll!InternetCloseHandle : OK
32 => F66DD0723A6E8482 is the hash for wininet.dll!HttpOpenRequestA : OK
33 => 0B43C51621CD164B is the hash for wininet.dll!HttpSendRequestA : OK
34 => B872B6B717BFF247 is the hash for wininet.dll!HttpQueryInfoA : OK
35 => 957235ACDB519818 is the hash for mscoree.dll!CorBindToRuntime : OK
36 => 60111C8D1049452E is the hash for mscoree.dll!CLRCreateInstance : OK
37 => 121D46593E41D827 is the hash for ole32.dll!CoInitializeEx : OK
38 => 2D5F94E307433D52 is the hash for ole32.dll!CoCreateInstance : OK
39 => E9A80D05EE05D859 is the hash for ole32.dll!CoUninitialize : OK
40 => 453737D2E7D0F769 is the hash for ntdll.dll!RtlEqualUnicodeString : OK
41 => 439713CC2F516036 is the hash for ntdll.dll!RtlEqualString : OK
42 => C7B512E9E2D2F84F is the hash for ntdll.dll!RtlUnicodeStringToAnsiString : OK
43 => 2992DE171F478173 is the hash for ntdll.dll!RtlInitUnicodeString : OK
44 => 8C914E01296AFCA9 is the hash for ntdll.dll!RtlExitUserThread : OK
45 => B2038712DAAC1A44 is the hash for ntdll.dll!RtlExitUserProcess : OK
46 => 8EDF30B20BC8A076 is the hash for ntdll.dll!RtlCreateUnicodeString : OK
47 => 5FD236D633BA0134 is the hash for ntdll.dll!RtlGetCompressionWorkSpaceSize : OK
48 => 0CF4EFF0BA940F2B is the hash for ntdll.dll!RtlDecompressBuffer : OK
49 => B0C67F05012616EC is the hash for ntdll.dll!NtContinue : OK
50 => 2B187C9F4F529D96 is the hash for kernel32.dll!AddVectoredExceptionHandler : OK
51 => 0989367F9B2F00CE is the hash for kernel32.dll!RemoveVectoredExceptionHandler : OK
sizeof(DONUT_INSTANCE) : 3664
sizeof(ULONG_PTR) : 8
RtlExitUserProcess index : 45
Hashes match OK

@odzhan
Copy link
Collaborator

odzhan commented Mar 27, 2020

Here's the output of debugging your loader. First API should be VirtualAlloc.

debug1

No problem there. Second should be VirtualFree

debug2

No problem there either. The third API should be RtlExitUserProcess (B2038712DAAC1A44), but as you can see, the hash for RtlInitUnicodeString (2992de171f478173) is used instead.

debug3

I have seen this kind of behavior in the past and it was usually the result of the donut generator and the loader using different structures. They were not in sync. That's what this looks like, but obviously that isn't the case here if you both experience the same problem.

I'll try get my hands on the version of MingW you're using, but right now I've no solution.

@lesnuages
Copy link
Author

Thanks for the investigation @odzhan, I'll try to have a look this weekend. I'm compiling from a Fedora 31, gcc installed from the Fedora repos, version is:

gcc --version
gcc (GCC) 9.2.1 20190827 (Red Hat 9.2.1-1)
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

MinGW is also installed from the Fedora repos. I'll test the dumpcfg bin when I get sometime this weekend.

@lesnuages
Copy link
Author

Here you go:

PS C:\Users\lab\Desktop> .\dumpcfg.exe .\donut\loader.bin
Length    : 8576
Key       : 00000000000000000000000000000000
CTR       : 00000000000000000000000000000000
Maru IV   : 0
Exit Opt  : 1
OEP       : 0000000000000000
API Count : 52
00 => 8322A3F655D252A0 is the hash for kernel32.dll!LoadLibraryA : OK
01 => 5F9A2F5A70159AF7 is the hash for kernel32.dll!GetProcAddress : OK
02 => ECEC2E0F77C1DF79 is the hash for kernel32.dll!GetModuleHandleA : OK
03 => 52622E8E2A03836A is the hash for kernel32.dll!VirtualAlloc : OK
04 => A0F99483877BBCC4 is the hash for kernel32.dll!VirtualFree : OK
05 => A6B3DEBBBD52F776 is the hash for kernel32.dll!VirtualQuery : OK
06 => E0206318E83E16F4 is the hash for kernel32.dll!VirtualProtect : OK
07 => 29407C7E01077DEF is the hash for kernel32.dll!Sleep : OK
08 => B2D46685A8D6CC8F is the hash for kernel32.dll!MultiByteToWideChar : OK
09 => 3D28AFB2AD9197E5 is the hash for kernel32.dll!GetUserDefaultLCID : OK
10 => C45F651AAFFB410B is the hash for kernel32.dll!WaitForSingleObject : OK
11 => A88D8A63D7D17933 is the hash for kernel32.dll!CreateThread : OK
12 => EDBBC13672C19CE4 is the hash for kernel32.dll!GetThreadContext : OK
13 => 6A2447B1BECC189C is the hash for kernel32.dll!GetCurrentThread : OK
14 => E6E2D0AA08292200 is the hash for kernel32.dll!GetCommandLineA : OK
15 => 1C7CF9F57FA86E3D is the hash for kernel32.dll!GetCommandLineW : OK
16 => F3848EC570838A21 is the hash for shell32.dll!CommandLineToArgvW : OK
17 => DFBD47E13EE13B10 is the hash for oleaut32.dll!SafeArrayCreate : OK
18 => BD77AF2569689C8A is the hash for oleaut32.dll!SafeArrayCreateVector : OK
19 => 8AD71499A1140B4D is the hash for oleaut32.dll!SafeArrayPutElement : OK
20 => 2082D640CCFD441B is the hash for oleaut32.dll!SafeArrayDestroy : OK
21 => 7046B02E03CE7D0C is the hash for oleaut32.dll!SafeArrayGetLBound : OK
22 => C1EB0C113A5660BA is the hash for oleaut32.dll!SafeArrayGetUBound : OK
23 => F3AC45C203C14CE0 is the hash for oleaut32.dll!SysAllocString : OK
24 => 733CE6F644E27222 is the hash for oleaut32.dll!SysFreeString : OK
25 => 3E3F0153FB195BEB is the hash for oleaut32.dll!LoadTypeLib : OK
26 => 908B117CC2EF66F9 is the hash for wininet.dll!InternetCrackUrlA : OK
27 => A146D290F7863A30 is the hash for wininet.dll!InternetOpenA : OK
28 => 57777DD39940F617 is the hash for wininet.dll!InternetConnectA : OK
29 => 9395C00826DDF250 is the hash for wininet.dll!InternetSetOptionA : OK
30 => D388820170E23FB1 is the hash for wininet.dll!InternetReadFile : OK
31 => 6A0E5F83356BF090 is the hash for wininet.dll!InternetCloseHandle : OK
32 => F66DD0723A6E8482 is the hash for wininet.dll!HttpOpenRequestA : OK
33 => 0B43C51621CD164B is the hash for wininet.dll!HttpSendRequestA : OK
34 => B872B6B717BFF247 is the hash for wininet.dll!HttpQueryInfoA : OK
35 => 957235ACDB519818 is the hash for mscoree.dll!CorBindToRuntime : OK
36 => 60111C8D1049452E is the hash for mscoree.dll!CLRCreateInstance : OK
37 => 121D46593E41D827 is the hash for ole32.dll!CoInitializeEx : OK
38 => 2D5F94E307433D52 is the hash for ole32.dll!CoCreateInstance : OK
39 => E9A80D05EE05D859 is the hash for ole32.dll!CoUninitialize : OK
40 => 453737D2E7D0F769 is the hash for ntdll.dll!RtlEqualUnicodeString : OK
41 => 439713CC2F516036 is the hash for ntdll.dll!RtlEqualString : OK
42 => C7B512E9E2D2F84F is the hash for ntdll.dll!RtlUnicodeStringToAnsiString : OK
43 => 2992DE171F478173 is the hash for ntdll.dll!RtlInitUnicodeString : OK
44 => 8C914E01296AFCA9 is the hash for ntdll.dll!RtlExitUserThread : OK
45 => B2038712DAAC1A44 is the hash for ntdll.dll!RtlExitUserProcess : OK
46 => 8EDF30B20BC8A076 is the hash for ntdll.dll!RtlCreateUnicodeString : OK
47 => 5FD236D633BA0134 is the hash for ntdll.dll!RtlGetCompressionWorkSpaceSize : OK
48 => 0CF4EFF0BA940F2B is the hash for ntdll.dll!RtlDecompressBuffer : OK
49 => B0C67F05012616EC is the hash for ntdll.dll!NtContinue : OK
50 => 2B187C9F4F529D96 is the hash for kernel32.dll!AddVectoredExceptionHandler : OK
51 => 0989367F9B2F00CE is the hash for kernel32.dll!RemoveVectoredExceptionHandler : OK
sizeof(DONUT_INSTANCE) : 3664
sizeof(ULONG_PTR)      : 8
RtlExitUserProcess index : 45
Hashes match OK

@aus
Copy link

aus commented Apr 1, 2020

I'm not sure if this is the same issue, but I am able to reproduce the GCC vs MinGW issue. In my case, the shellcode created with MinGW/Windows donut.exe works but the shellcode created with GCC/Linux donut fails.

Generated via:

donut -a 2 -e 1 -s http://localhost:8080 my.dll

Build versions:

$ gcc --version
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0

$ x86_64-w64-mingw32-gcc --version
x86_64-w64-mingw32-gcc (GCC) 7.3-win32 20180312

And here's the output to dumpcfg for both versions:

PS > .\tools\dumpcfg.exe .\loader.bin.mingw
Length    : 3664
Key       : 00000000000000000000000000000000
CTR       : 00000000000000000000000000000000
Maru IV   : 0
Exit Opt  : 1
OEP       : 0000000000000000
API Count : 52
00 => 8322A3F655D252A0 is the hash for kernel32.dll!LoadLibraryA : OK
01 => 5F9A2F5A70159AF7 is the hash for kernel32.dll!GetProcAddress : OK
02 => ECEC2E0F77C1DF79 is the hash for kernel32.dll!GetModuleHandleA : OK
03 => 52622E8E2A03836A is the hash for kernel32.dll!VirtualAlloc : OK
04 => A0F99483877BBCC4 is the hash for kernel32.dll!VirtualFree : OK
05 => A6B3DEBBBD52F776 is the hash for kernel32.dll!VirtualQuery : OK
06 => E0206318E83E16F4 is the hash for kernel32.dll!VirtualProtect : OK
07 => 29407C7E01077DEF is the hash for kernel32.dll!Sleep : OK
08 => B2D46685A8D6CC8F is the hash for kernel32.dll!MultiByteToWideChar : OK
09 => 3D28AFB2AD9197E5 is the hash for kernel32.dll!GetUserDefaultLCID : OK
10 => C45F651AAFFB410B is the hash for kernel32.dll!WaitForSingleObject : OK
11 => A88D8A63D7D17933 is the hash for kernel32.dll!CreateThread : OK
12 => EDBBC13672C19CE4 is the hash for kernel32.dll!GetThreadContext : OK
13 => 6A2447B1BECC189C is the hash for kernel32.dll!GetCurrentThread : OK
14 => E6E2D0AA08292200 is the hash for kernel32.dll!GetCommandLineA : OK
15 => 1C7CF9F57FA86E3D is the hash for kernel32.dll!GetCommandLineW : OK
16 => F3848EC570838A21 is the hash for shell32.dll!CommandLineToArgvW : OK
17 => DFBD47E13EE13B10 is the hash for oleaut32.dll!SafeArrayCreate : OK
18 => BD77AF2569689C8A is the hash for oleaut32.dll!SafeArrayCreateVector : OK
19 => 8AD71499A1140B4D is the hash for oleaut32.dll!SafeArrayPutElement : OK
20 => 2082D640CCFD441B is the hash for oleaut32.dll!SafeArrayDestroy : OK
21 => 7046B02E03CE7D0C is the hash for oleaut32.dll!SafeArrayGetLBound : OK
22 => C1EB0C113A5660BA is the hash for oleaut32.dll!SafeArrayGetUBound : OK
23 => F3AC45C203C14CE0 is the hash for oleaut32.dll!SysAllocString : OK
24 => 733CE6F644E27222 is the hash for oleaut32.dll!SysFreeString : OK
25 => 3E3F0153FB195BEB is the hash for oleaut32.dll!LoadTypeLib : OK
26 => 908B117CC2EF66F9 is the hash for wininet.dll!InternetCrackUrlA : OK
27 => A146D290F7863A30 is the hash for wininet.dll!InternetOpenA : OK
28 => 57777DD39940F617 is the hash for wininet.dll!InternetConnectA : OK
29 => 9395C00826DDF250 is the hash for wininet.dll!InternetSetOptionA : OK
30 => D388820170E23FB1 is the hash for wininet.dll!InternetReadFile : OK
31 => 6A0E5F83356BF090 is the hash for wininet.dll!InternetCloseHandle : OK
32 => F66DD0723A6E8482 is the hash for wininet.dll!HttpOpenRequestA : OK
33 => 0B43C51621CD164B is the hash for wininet.dll!HttpSendRequestA : OK
34 => B872B6B717BFF247 is the hash for wininet.dll!HttpQueryInfoA : OK
35 => 957235ACDB519818 is the hash for mscoree.dll!CorBindToRuntime : OK
36 => 60111C8D1049452E is the hash for mscoree.dll!CLRCreateInstance : OK
37 => 121D46593E41D827 is the hash for ole32.dll!CoInitializeEx : OK
39 => E9A80D05EE05D859 is the hash for ole32.dll!CoUninitialize : OK
40 => 453737D2E7D0F769 is the hash for ntdll.dll!RtlEqualUnicodeString : OK
41 => 439713CC2F516036 is the hash for ntdll.dll!RtlEqualString : OK
42 => C7B512E9E2D2F84F is the hash for ntdll.dll!RtlUnicodeStringToAnsiString : OK
43 => 2992DE171F478173 is the hash for ntdll.dll!RtlInitUnicodeString : OK
44 => 8C914E01296AFCA9 is the hash for ntdll.dll!RtlExitUserThread : OK
45 => B2038712DAAC1A44 is the hash for ntdll.dll!RtlExitUserProcess : OK
46 => 8EDF30B20BC8A076 is the hash for ntdll.dll!RtlCreateUnicodeString : OK
47 => 5FD236D633BA0134 is the hash for ntdll.dll!RtlGetCompressionWorkSpaceSize : OK
48 => 0CF4EFF0BA940F2B is the hash for ntdll.dll!RtlDecompressBuffer : OK
49 => B0C67F05012616EC is the hash for ntdll.dll!NtContinue : OK
50 => 2B187C9F4F529D96 is the hash for kernel32.dll!AddVectoredExceptionHandler : OK
51 => 0989367F9B2F00CE is the hash for kernel32.dll!RemoveVectoredExceptionHandler : OK
sizeof(DONUT_INSTANCE) : 3664
sizeof(ULONG_PTR)      : 8
RtlExitUserProcess index : 45
Hashes match OK


PS > .\tools\dumpcfg.exe .\loader.bin.gcc
Length    : 3664
Key       : 00000000000000000000000000000000
CTR       : 00000000000000000000000000000000
Maru IV   : 0
Exit Opt  : 1
OEP       : 0000000000000000
API Count : 52
00 => 8322A3F655D252A0 is the hash for kernel32.dll!LoadLibraryA : OK
01 => 5F9A2F5A70159AF7 is the hash for kernel32.dll!GetProcAddress : OK
02 => ECEC2E0F77C1DF79 is the hash for kernel32.dll!GetModuleHandleA : OK
03 => 52622E8E2A03836A is the hash for kernel32.dll!VirtualAlloc : OK
04 => A0F99483877BBCC4 is the hash for kernel32.dll!VirtualFree : OK
05 => A6B3DEBBBD52F776 is the hash for kernel32.dll!VirtualQuery : OK
06 => E0206318E83E16F4 is the hash for kernel32.dll!VirtualProtect : OK
07 => 29407C7E01077DEF is the hash for kernel32.dll!Sleep : OK
08 => B2D46685A8D6CC8F is the hash for kernel32.dll!MultiByteToWideChar : OK
09 => 3D28AFB2AD9197E5 is the hash for kernel32.dll!GetUserDefaultLCID : OK
10 => C45F651AAFFB410B is the hash for kernel32.dll!WaitForSingleObject : OK
11 => A88D8A63D7D17933 is the hash for kernel32.dll!CreateThread : OK
12 => EDBBC13672C19CE4 is the hash for kernel32.dll!GetThreadContext : OK
13 => 6A2447B1BECC189C is the hash for kernel32.dll!GetCurrentThread : OK
14 => E6E2D0AA08292200 is the hash for kernel32.dll!GetCommandLineA : OK
15 => 1C7CF9F57FA86E3D is the hash for kernel32.dll!GetCommandLineW : OK
16 => F3848EC570838A21 is the hash for shell32.dll!CommandLineToArgvW : OK
17 => DFBD47E13EE13B10 is the hash for oleaut32.dll!SafeArrayCreate : OK
18 => BD77AF2569689C8A is the hash for oleaut32.dll!SafeArrayCreateVector : OK
19 => 8AD71499A1140B4D is the hash for oleaut32.dll!SafeArrayPutElement : OK
20 => 2082D640CCFD441B is the hash for oleaut32.dll!SafeArrayDestroy : OK
21 => 7046B02E03CE7D0C is the hash for oleaut32.dll!SafeArrayGetLBound : OK
22 => C1EB0C113A5660BA is the hash for oleaut32.dll!SafeArrayGetUBound : OK
23 => F3AC45C203C14CE0 is the hash for oleaut32.dll!SysAllocString : OK
24 => 733CE6F644E27222 is the hash for oleaut32.dll!SysFreeString : OK
25 => 3E3F0153FB195BEB is the hash for oleaut32.dll!LoadTypeLib : OK
26 => 908B117CC2EF66F9 is the hash for wininet.dll!InternetCrackUrlA : OK
27 => A146D290F7863A30 is the hash for wininet.dll!InternetOpenA : OK
28 => 57777DD39940F617 is the hash for wininet.dll!InternetConnectA : OK
29 => 9395C00826DDF250 is the hash for wininet.dll!InternetSetOptionA : OK
30 => D388820170E23FB1 is the hash for wininet.dll!InternetReadFile : OK
31 => 6A0E5F83356BF090 is the hash for wininet.dll!InternetCloseHandle : OK
32 => F66DD0723A6E8482 is the hash for wininet.dll!HttpOpenRequestA : OK
33 => 0B43C51621CD164B is the hash for wininet.dll!HttpSendRequestA : OK
34 => B872B6B717BFF247 is the hash for wininet.dll!HttpQueryInfoA : OK
35 => 957235ACDB519818 is the hash for mscoree.dll!CorBindToRuntime : OK
36 => 60111C8D1049452E is the hash for mscoree.dll!CLRCreateInstance : OK
37 => 121D46593E41D827 is the hash for ole32.dll!CoInitializeEx : OK
38 => 2D5F94E307433D52 is the hash for ole32.dll!CoCreateInstance : OK
39 => E9A80D05EE05D859 is the hash for ole32.dll!CoUninitialize : OK
40 => 453737D2E7D0F769 is the hash for ntdll.dll!RtlEqualUnicodeString : OK
41 => 439713CC2F516036 is the hash for ntdll.dll!RtlEqualString : OK
42 => C7B512E9E2D2F84F is the hash for ntdll.dll!RtlUnicodeStringToAnsiString : OK
43 => 2992DE171F478173 is the hash for ntdll.dll!RtlInitUnicodeString : OK
44 => 8C914E01296AFCA9 is the hash for ntdll.dll!RtlExitUserThread : OK
45 => B2038712DAAC1A44 is the hash for ntdll.dll!RtlExitUserProcess : OK
46 => 8EDF30B20BC8A076 is the hash for ntdll.dll!RtlCreateUnicodeString : OK
47 => 5FD236D633BA0134 is the hash for ntdll.dll!RtlGetCompressionWorkSpaceSize : OK
48 => 0CF4EFF0BA940F2B is the hash for ntdll.dll!RtlDecompressBuffer : OK
49 => B0C67F05012616EC is the hash for ntdll.dll!NtContinue : OK
50 => 2B187C9F4F529D96 is the hash for kernel32.dll!AddVectoredExceptionHandler : OK
51 => 0989367F9B2F00CE is the hash for kernel32.dll!RemoveVectoredExceptionHandler : OK
sizeof(DONUT_INSTANCE) : 3664
sizeof(ULONG_PTR)      : 8
RtlExitUserProcess index : 45
Hashes match OK

@janedoe-lab
Copy link

janedoe-lab commented Mar 5, 2022

I suspect I am facing the same issue. From my naive attempt to debug it, I believe the problem is rooted in wrong offsets used in the generated shellcode. I was stepping through MainProc in x64dbg and noticed that some values (but not all) were not matching configuration.

Few more bits of observation:

  • When I compile donut under linux using MinGW I experience problems with offsets.
  • If I add -fPIC -fPIE into Makefile.mingw for lines compiling donut.exe, generated shellcode works as expected
  • If I compile using gcc - I experience problems with offsets
  • when building using gcc, loader_exe_*.h are not updated (I guess the only way to update them is to compile loader32/64.exe?)
  • when building using MinGW with -fPIE -fPIC, both loader_exe_*.h files changing completely
  • if I compile donut using gcc after both loader_exe_*.h files get updates, I still experience problem with offsets.
  • if I compile donut.exe using MinGW WITHOUT updated loader_exe_*.h files, I experience problem with offsets.

NOTE: I added -fPIC -fPIE only to lines that compile donut.exe, not loaders' executables.

Hopefully, it might give a clue where to look next.... I am out of ideas :)

@TheWover TheWover added this to the future milestone Feb 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants