Can I turn a raw memory dump (ReadProcessMemory) into a MiniDump file?

409 Views Asked by At

I have the following powershell code to dump the process memory from a given process. In this case, cmd.exe.

It opens the given process with PROCESS_ALL_ACCESS and uses VirtualQueryEx to list all the memory regions. For each memory region it finds, it calls ReadProcessMemory and writes the bytes read to a file.

$typeDefinition = @"
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

public static partial class MemApi
{
    [StructLayout(LayoutKind.Sequential)]
    public struct MEMORY_BASIC_INFORMATION64
    {
        public ulong BaseAddress;
        public ulong AllocationBase;
        public int AllocationProtect;
        public int __alignment1;
        public ulong RegionSize;
        public int State;
        public int Protect;
        public int Type;
        public int __alignment2;
    }

    [Flags]
    public enum ProcessAccessFlags : uint
    {
        VM_READ = 0x00000010,
        PROCESS_ALL_ACCESS = 0x001F0FFF
    }
    [DllImport("kernel32.dll")]
    public static extern uint GetLastError();

    [DllImport("kernel32.dll", CharSet=CharSet.Auto)]
    public static extern IntPtr OpenProcess(
        ProcessAccessFlags dwAccess,
        [MarshalAs(UnmanagedType.Bool)]
        bool bInheritHandle,
        int dwProcId
    );

    [DllImport("kernel32.dll", CharSet=CharSet.Auto)]
    public static extern int VirtualQueryEx(
        IntPtr hProc,
        IntPtr lpAddr,
        out MEMORY_BASIC_INFORMATION64 lpBuf,
        int dwLen
    );

    public static List<MEMORY_BASIC_INFORMATION64> ListMemoryRegions(
        IntPtr hProc
    )
    {
        long maxAddr = 0x00007FFFFFFFFFFF;
        long addr = 0;
        List<MEMORY_BASIC_INFORMATION64> regions = new List<MEMORY_BASIC_INFORMATION64>();

        do
        {
            MEMORY_BASIC_INFORMATION64 m;

            int result = VirtualQueryEx(hProc, (IntPtr)addr, out m, (int)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION64)));

            if (addr == (long)m.BaseAddress + (long)m.RegionSize)
                break;

            addr = (long)m.BaseAddress + (long)m.RegionSize;

            regions.Add(m);
        } while (addr <= maxAddr);

        return regions;
    }

    [DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    public static extern Boolean ReadProcessMemory(
        IntPtr hProc,
        IntPtr lpBaseAddr,
        byte[] lpBuf,
        UInt32 nSize,
        ref UInt32 lpNBytes
    );
}
"@

Add-Type -TypeDefinition $typeDefinition -Language CSharp

$cmd = Get-Process -Name cmd

$handle = [MemApi]::OpenProcess(0x1F0FFF, $false, $cmd.Id)
$regions = [MemApi]::ListMemoryRegions($handle)
$fileStream = [System.IO.File]::OpenWrite("$env:TEMP\cmd.DMP")


Write-Host "$($regions.Count) memory segments have been found"

for ($i = 0; $i -lt $regions.Count; $i++)
{
    Write-Host "Exporting memory region $("{0:d4}/{1:d4}" -f $i, ($regions.Count + 1)) ($("0x{0:X16} - 0x{1:X16}" -f $regions[$i].BaseAddress, ($regions[$i].BaseAddress + $regions[$i].RegionSize)))..."
    
    try
    {
        $read = 0
        $buff = New-Object byte[] $regions[$i].RegionSize

        if ([MemApi]::ReadProcessMemory($handle, [System.IntPtr]::new($regions[$i].BaseAddress), $buff, $buff.Length, [ref]$read) -eq $true)
        {
            $fileStream.Write($buff, 0, $buff.Length)
        }
    } catch { } finally { }
}
    
$fileStream.Close()

I would like to avoid using dbghelp.dll to do this, but is there a way I can create a MiniDump file out of this raw memory? Would I need to change the code at all or is there an external tool that can convert this?

I've tried to take a look into the MiniDumpWriteDump function to see if I can replicate it at all but I've had no luck.

I've also tried volatility's raw2dmp function, but this has not worked unfortunately.

Apologies if this is completely on the wrong tracks!

Any help would be much appreciated - Merry Christmas!

0

There are 0 best solutions below