How to get the output from a reflected loaded dll via anonymous pipes?

Hi, I don’t know if this is the right place to ask but I have a problem that I want to solve. I want to get the output of a reflective loaded DLL from my child’s process via anonymous pipes.

Here is the code I wrote to spawn a process and inject a reflective DLL into it.

DWORD SpawnDll(LPVOID lpDllBuffer, DWORD dwDllLength, const char* cpCommandLine , DWORD dwProcessArch) {  
  
#ifdef DEBUG  
    printf("\n\n[DEBUG] SpawnDll(0x0%p, %d, %s, %d)\n",  
           lpDllBuffer, dwDllLength, cpCommandLine, dwProcessArch);  
#endif  
  
 	if (lpDllBuffer == NULL) {  
 		free(lpDllBuffer);  
        return 0;  
    }  
  
 	BOOL bSuccess = FALSE;  
  
    HANDLE hStdInPipeRead = NULL;  
    HANDLE hStdInPipeWrite = NULL;  
    HANDLE hStdOutPipeRead = NULL;  
    HANDLE hStdOutPipeWrite = NULL;  
  
    SECURITY_ATTRIBUTES sa = {  
 		.nLength = sizeof(SECURITY_ATTRIBUTES),  
        .lpSecurityDescriptor = NULL,  
        .bInheritHandle = FALSE,  
    };  
  
    bSuccess = CreatePipe(&hStdInPipeRead, &hStdInPipeWrite, &sa, 0);  
    if (bSuccess == FALSE)  
 		return ERROR_FAILED_INPUT_PIPE;  
  
    if (!SetHandleInformation(hStdInPipeWrite, HANDLE_FLAG_INHERIT, 0)) {  
 		DEBUGF("Stdin SetHandleInformation");  
        goto Cleanup;  
    }  
  
 	bSuccess = CreatePipe(&hStdOutPipeRead, &hStdOutPipeWrite, &sa, 0);  
    if (bSuccess == FALSE)  
 		return ERROR_FAILED_OUTPUT_PIPE;  
  
    if (!SetHandleInformation(hStdOutPipeRead, HANDLE_FLAG_INHERIT, 0)) {  
 		DEBUGF("Stdout SetHandleInformation");  
        goto Cleanup;  
    }  
  
 	STARTUPINFOEXA sInfo = {  
 			.StartupInfo.cb = sizeof(STARTUPINFO),  
            .StartupInfo.dwFlags = STARTF_USESTDHANDLES,  
            .StartupInfo.hStdError = hStdOutPipeWrite,  
            .StartupInfo.hStdOutput = hStdOutPipeWrite,  
            .StartupInfo.hStdInput = hStdInPipeRead,  
    };  
  
    PROCESS_INFORMATION pInfo = { 0 };  
  
    CreateThread(NULL, 0, ReadFromPipe, hStdOutPipeRead, 0, NULL);  
  
    if (dwProcessArch == PROCESS_ARCH_X64) {  
 		bSuccess = CreateProcessA(NULL, (char*) "C:\\Windows\\System32\\rundll32.exe" , NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &sInfo, &pInfo);  
#ifdef DEBUG  
        printf("[DEBUG] Started Process :: C:\\Windows\\System32\\rundll32.exe\n");  
#endif  
 	} else {  
 		bSuccess = CreateProcessA(NULL, (char*) "C:\\Windows\\SysWOW64\\rundll32.exe", NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &sInfo, &pInfo);  
#ifdef DEBUG  
        printf("[DEBUG] Started Process :: C:\\Windows\\SysWOW64\\rundll32.exe\n");  
#endif  
 	}  
  
 	if (!bSuccess)  
 		goto Cleanup;  
  
    InjectDLL( pInfo.dwProcessId, lpDllBuffer, dwDllLength, cpCommandLine, dwProcessArch );  
  
#ifdef DEBUG  
    printf("[DEBUG] injected dll\n");  
#endif  
  
 	ResumeThread(pInfo.hThread);  
    CloseHandle(pInfo.hThread);  
  
    WaitForSingleObject(pInfo.hProcess, INFINITE);  
  
    Cleanup:  
        CloseHandle(hStdOutPipeRead);  
        CloseHandle(hStdOutPipeWrite);  
        CloseHandle(hStdInPipeWrite);  
        CloseHandle(hStdInPipeRead);  
  
    return 0;  
}

The InjectDll function is straight-up copied from pupy rat reflected dll injection.

The ReadPipe function looks like that.

#define MAX_OUTPUT 1024
void ReadFromPipe(HANDLE hSTD_OUT_Read) {  
 	char	chBuf[MAX_OUTPUT + 1] = { 0 };  
    BOOL    bSuccess = FALSE;  
    DWORD   dwRead = 0;  
  
    DEBUGF("Started Reading from Pipe")  
 	bSuccess = ReadFile(hSTD_OUT_Read, chBuf, MAX_OUTPUT, &dwRead, NULL);  

    DEBUGF("Starting do while loop...")  
 	do {  
 		chBuf[dwRead] = '\0';  
#ifdef DEBUG  
        printf("[%s] dwRead :: %d\n", __FUNCTION__ , dwRead);  
#endif
 		if (dwRead != 0) printf("%s\n",chBuf);  
 		memset(chBuf, '\0', sizeof(chBuf));  
        bSuccess = ReadFile(hSTD_OUT_Read, chBuf, MAX_OUTPUT, &dwRead, NULL);
    } while (bSuccess == TRUE);  
    return;  
}

reflective Dll Source code based on stephenfewer’s dll:

//===============================================================================================//  
// This is a stub for the actual functionality of the DLL.  
//===============================================================================================//  
#include "ReflectiveLoader.h"  
#include <stdio.h>  
  
// Note: REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR and REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN are  
// defined in the project properties (Properties->C++->Preprocessor) so as we can specify our own  
// DllMain and use the LoadRemoteLibraryR() API to inject this DLL.  
  
// You can use this value as a pseudo hinstDLL value (defined and set via ReflectiveLoader.c)  
extern HINSTANCE hAppInstance;  
//===============================================================================================//  
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )  
{  
 BOOL bReturnValue = TRUE;  
    switch( dwReason ) {  
 		case DLL_QUERY_HMODULE:  
            if( lpReserved != NULL )  
 				*(HMODULE *)lpReserved = hAppInstance;  
            break;  
        case DLL_PROCESS_ATTACH:  
            hAppInstance = hinstDLL;  
            puts("[DEBUG] Hello from DllMain");  
            MessageBoxA( NULL, "Hello from DllMain!", "Reflective Dll Injection", MB_OK );  
            break;  
        case DLL_PROCESS_DETACH:  
        case DLL_THREAD_ATTACH:  
        case DLL_THREAD_DETACH:  
            break;  
    }  
 return bReturnValue;  
}

The injection part works because I see Message Box popping up for a second but then closing itself.

image

I already searched the internet and didn’t really found anything (or i am to dump to search for it…)

Thank you guys for the help and answers : )

1 Like