Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Dump process or modules image from memory to disk

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dump process or modules image from memory to disk

    A simple example of how to dump the executable image of a process or module/DLL from memory.

    Some "process dumpers" try to dump the entire image in one go, for example ...
    ReadProcessMemory (BYVAL hProc, BYVAL me32.ModBaseAddr, BYVAL STRPTR(sBuf), BYVAL me32.ModBaseSize, lBytesRead)

    That works most of the time, but sometimes it will fail, as MSDN's ReadProcessMemory documentation states: "The entire area to be read must be accessible, and if it is not accessible, the function fails."

    The solution is to simply read the image one page at a time -- GetSystemInfo(SYSTEM_INFO) ... SYSTEM_INFO.dwPageSize

    Code:
    #COMPILE EXE
    #INCLUDE "win32api.inc"
    #INCLUDE "tlhelp32.inc"
     
    FUNCTION DumpModule (BYVAL dwPID AS DWORD, szModule AS ASCIIZ, sBuf AS STRING) AS DWORD  '// Returns LEN(sBuf) if success, 0 if failed
    LOCAL hModuleSnap AS DWORD, me32 AS MODULEENTRY32, lResult AS LONG, szLModule AS ASCIIZ * %MAX_PATH, lBytesRead AS DWORD
    LOCAL dwBase AS DWORD, dwSize AS DWORD, lpSystemInfo AS SYSTEM_INFO, dwOffset AS DWORD, hProc AS DWORD, i AS DWORD
     GetSystemInfo lpSystemInfo
     szLModule = LCASE$(szModule)
     '// Now try to locate the base address and size of the target module
     hModuleSnap = CreateToolhelp32Snapshot(%TH32CS_SNAPMODULE, dwPID)
     IF hModuleSnap <> %INVALID_HANDLE_VALUE THEN
        me32.dwSize = SIZEOF(MODULEENTRY32)
        lResult = Module32First (hModuleSnap, me32)
        WHILE lResult
            IF LCASE$(me32.szExePath) = szLModule THEN
                dwBase = me32.ModBaseAddr
                dwSize = me32.ModBaseSize
                EXIT
            END IF
            lResult = Module32Next (hModuleSnap, me32)
        WEND
        CloseHandle hModuleSnap
     END IF
     IF dwBase = 0 THEN
        MSGBOX "Couldn't locate module in target process", %MB_ICONERROR + %MB_OK, "Error"
        EXIT FUNCTION
     END IF
     '// Now open the target process
     IF dwPID = GetCurrentProcessId THEN
         hProc = GetCurrentProcess
     ELSE
         hProc = OpenProcess(%PROCESS_VM_READ, %FALSE, dwPID)
         IF hProc = 0 THEN
             MSGBOX "OpenProcess failed", %MB_ICONERROR + %MB_OK, "Error"
             EXIT FUNCTION
         END IF
     END IF
     '// Read the memory one page at a time
     sBuf = STRING$(me32.ModBaseSize + lpSystemInfo.dwPageSize, 0)
     FOR i = 1 TO (me32.ModBaseSize \ lpSystemInfo.dwPageSize) + 1
        ReadProcessMemory (BYVAL hProc, BYVAL me32.ModBaseAddr + dwOffset, BYVAL STRPTR(sBuf) + dwOffset, BYVAL lpSystemInfo.dwPageSize, lBytesRead)
        dwOffset = dwOffset + lpSystemInfo.dwPageSize
     NEXT
     sBuf = LEFT$(sBuf, me32.ModBaseSize)
     FUNCTION = LEN(sBuf)
    END FUNCTION
    
    
    FUNCTION PBMAIN () AS LONG
     '// Dump a module (szModule) from a process (dwPID) into string buffer (sBuf)
     LOCAL dwPID AS DWORD, sBuf AS STRING, szModule AS ASCIIZ * %MAX_PATH
     dwPID = GetCurrentProcessID                                                     '// PID of target process
     GetModuleFilename(BYVAL GetModuleHandle(BYVAL 0), szModule, SIZEOF(szModule))   '// Module filename in target process
     IF DumpModule(BYVAL dwPID, szModule, sBuf) > 0 THEN
         MSGBOX "Success. First two bytes = " & LEFT$(sBuf,2) '// should be "MZ"
     ELSE
         MSGBOX "Failed"
     END IF
     
     '// Save the buffer to disk
     LOCAL hFile AS DWORD: hFile = FREEFILE
     OPEN szModule & "-dumped.dat" FOR BINARY ACCESS WRITE LOCK SHARED AS #hFile
      PUT #hFile, 1, sBuf
     CLOSE #hFile
    END FUNCTION
    Last edited by Wayne Diamond; 21 Jun 2008, 02:45 PM.
    -
Working...
X