TheWover / donut

Generates x86, x64, or AMD64+x86 position-independent shellcode that loads .NET Assemblies, PE files, and other Windows payloads from memory and runs them with parameters
BSD 3-Clause "New" or "Revised" License
3.61k stars 637 forks source link

SetCommandLineW seems to work only at first invocation #88

Closed phra closed 1 year ago

phra commented 3 years ago

Hello, I am doing some experiments with donut and reflective execution. I noticed in my tests that if you inject multiple times a payload with a different command line, only the first invocation of SetCommandLineW seems to work while the later ones seem to not have any effect at all. For example, if I inject mimikatz with the options '"coffee" "exit"' and run it I would get the correct output, but if I regenerate the payload with '"answer" "exit"' and re-inject it in the very same process I would still get the coffee ascii picture. Of course, if I inject the payload in different, untouched process, I would get the correct 42 answer. Any idea of what can cause its behaviour and how to eventually fix it?

Thanks!

phra commented 3 years ago

i am trying to debug the issue but on linux but I am having some difficulties to generate a debug build of the loader with mingw (after generating the debug loader and transform it to a C header file with exe2h, I could not get any output at all when injected)

to debug it I have initially used the following executable to inject and to confirm that the command line was not updating after the first injection:

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    LPWSTR *szArgList;
    int argCount;

     szArgList = CommandLineToArgvW(GetCommandLine(), &argCount);
     if (szArgList == NULL)
     {
         MessageBox(NULL, L"Unable to parse command line", L"Error", MB_OK);
         return 10;
     }

     for(int i = 0; i < argCount; i++)
     {
         MessageBox(NULL, szArgList[i], L"Arglist contents", MB_OK);
     }

     LocalFree(szArgList);
     return 0;
}
phra commented 3 years ago

i can confirm that the issue is present in the last release v0.9.2, but it was fixed in the dev branch. in particular, I compiled donut using the following commit https://github.com/TheWover/donut/commit/b70467ef75bcb836b7730d9fe9c48c4094bd214f and the problem disappeared.