Announcement

Collapse
No announcement yet.

Dumping process module from memory to disk

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

  • Wayne Diamond
    replied
    Steve, I can now successfully dump in NT/2K! ... the secret was to use the AttachThreadInput API first! I would not have been able to discover that if it wasn't for your help, so I return today stoked that I can at least partially return your kind favour.
    Many thanks again!
    PS. Upgrade to NT! <grin>


    ------------------

    Leave a comment:


  • Wayne Diamond
    replied
    Steve, I just realised that you do your work on 95/98 and not NT as I do - I finally was able to try your code on a 98 box tonight and it works perfectly for ALL the processes that I tried, so youre code is spot on ! ! im puzzled why it's only able to dump a minority of NT/2K processes though :/, but some is better than none
    Again, many thanks for all your help with this issue Steve, ive learnt a lot from your postings and should be able to go on from this!


    ------------------

    Leave a comment:


  • Steve Hutchesson
    replied
    Wayne,

    There can be a number of reasons, 400000h works on most PE EXE files but
    it will not work on a DLL, they are dynamically loaded by the operating
    system loader at different addresses in the application's address space
    depending on the address range available. From memory, there is an API
    call designed to get a DLL starting address (Module handle).

    There are of course a number of tricks used as both anti-debugging and
    anti-hacking measures that will stop a successful image dump. Another
    consideration is that from memory, this process cannot be used on non-PE
    files. The original function I posted was designed to work on programs
    started with CreateProcess and it seems to do the job on the PE EXE files
    that I have used it with but for serious image analysis, I have mainly
    seen guys using SICE for NT with an add-on called Icedump.

    Set a breakpoint at the program entry point then dump the PE image. There
    are specialised techniques to defeat this method but there are as many
    trick around it.

    Regards,

    [email protected]


    ------------------

    Leave a comment:


  • Wayne Diamond
    replied
    Steve or Florent or anyone! have you had any luck in getting all processes to dump ok? im still only able to get a few to dump! would this be because the base address may not be &H400000 ? i can only dump about one in five processes though, so that doesnt seem to be it?


    ------------------

    Leave a comment:


  • Wayne Diamond
    replied
    thought this may be of interest while you were mentioning smallest exe files ... http://ntsecurity.nu/toolbox/tini/
    It is a remote access trojan server that is a standalone total exe of 3072 bytes. It works on 95, 98, NT, and 2000, and gives anyone who connects to it (tcp 7777) a command prompt - now thats fat-free programming :-)

    ------------------

    Leave a comment:


  • Wayne Diamond
    replied
    Steve and Florent, thanks very much for your help! It is much appreciated as i am swimming in deep water here and Im not wearing floaties :-)
    Im getting closer to what I want to do (which is just dump a processes main module to a file), and its working on some , but not others...
    Steve i modified the example you supplied up the top so that it can dump from an already-running process rather than having to start one up (parsing the process id)
    Code:
    FUNCTION GetPEimage(ProcID AS LONG, BYVAL LoadAdr AS DWORD) AS STRING
          LOCAL hMem  AS DWORD
          LOCAL bRead AS DWORD
          LOCAL EndIm AS DWORD
          LOCAL hProc AS DWORD
          LOCAL bSize AS DWORD
          LOCAL tSize AS DWORD
          LOCAL fl    AS DWORD
          LOCAL pi    AS PROCESS_INFORMATION
          LOCAL si    AS STARTUPINFO
          LOCAL buffer$
          LOCAL hWnd AS LONG
          hProc = OpenProcess(%PROCESS_VM_READ,%TRUE,ProcID)
          bSize = 2000000 'almost 2 megs to dump
          tbuffer$ = "  "
          buffer$ = STRING$(bSize,"x")
          IF LoadAdr = 0 THEN
            LoadAdr = &H400000   'default 4 meg load address
          END IF
          hMem = ReadProcessMemory(hProc,LoadAdr,BYVAL STRPTR(buffer$),bSize,BYVAL VARPTR(bRead))
          EndIm = INSTR(buffer$,"xxxxxxxxxxxx") 'locate the end of the buffer
          ! dec EndIm
          CloseHandle hProc
          FUNCTION = LEFT$(buffer$,EndIm)
      END FUNCTION
    so that part is basically working perfectly on Windows 95, 98, NT , _AND_ 2000 so Steve I am over the moon that you have helped me get that far
    but I am getting a headache from this base address issue. Im assuming that the reason it can only dump some processes and not all is because the base address isnt the default

    I also tried scanning for the string "This program" (eg. for "This program cannot run in DOS") starting at 1 and working my way up to 256mb yet was unable to locate it even in processes such as Notepad. Scanning in that way should have worked with a process such as Notepad, i would've thought? even if it wouldn't work with an exe that has been "header-munted" by Steve's other example
    getting there!

    ------------------

    Leave a comment:


  • Steve Hutchesson
    replied
    Florent,

    It did not run here either on win95b, incorrent alignment so I had a look
    at it in a hex editor and it does not have a valid MZ header. I think both
    NT4 and 9x will not run a file with an invalid MZ header or that is aligned
    below 512 bytes.

    From my experience, the smallest I have been able to get a valid PE file
    is 1024 bytes with a test piece in MASM. It normally builds at 1536 bytes
    but by merging the 2 sections with the /MERGE linker option, it drops in
    size by a single 512 byte alignment.

    Also thanks for posting the rebase code, it will be very useful.

    Regards,

    [email protected]

    ------------------

    Leave a comment:


  • Florent Heyworth
    replied
    Hi Hutch

    very interesting info - I used the pe_map.exe to dump
    hello.exe and got a nice informative report. I'll study
    the LUEVESMEYER source as soon as I have time.

    I read pe.txt which is very informative. I very much liked the
    section where he shows making hello.exe executable. Can you
    run Hello.exe on your system? On mine, NT 4.0 SP6 I get a
    critical error message box telling me hello.exe is not a valid
    NT application.

    Cheers

    Florent


    [This message has been edited by Florent Heyworth (edited September 10, 2000).]

    Leave a comment:


  • Steve Hutchesson
    replied
    Here are the two files I have as PE reference,
    www.pbq.com.au/home/hutch/pefiles/pe1.zip

    LUEVELSMEYER's example has a C program and a good text file
    with it to explain the PE file format.
    www.pbq.com.au/home/hutch/pefiles/winf10.zip

    The PDF file originated from the Intel site a couple of years
    ago and is a very comprehensive document on PE format.

    [email protected]

    ------------------

    Leave a comment:


  • Steve Hutchesson
    replied
    Wayne,

    Below is the include file that I am using to work on PE files. I have
    slightly renamed the structures so that the names do not clash with the
    ones in the standard include file with PB6. This is are a straight port
    from my MASM32 include file and it tests OK in PowerBASIC.

    I will try and post some decent reference material on PE files, there
    is a reasonably good text file by LUEVELSMEYER and a very comprehensive
    PDF file called WINF10.PDF but neither seems to be readily available on
    the Internet at the moment.

    For dumping a PE image, probably the only safe way is to get the header
    information from the disk file as it can be modified by the application.

    I have not had a chance to have a look at Semen code but I just had a
    quick look at the code posted by Florent for rebasing DLLs which is very
    good and this stuff, particularly the imagehlp.dll functions should be
    very useful to you.

    Regards,

    [email protected]

    Code:
      ' ************************************
      ' Structures for PE file manipulation
      ' ************************************
      
      %IMAGE_SIZEOF_SECTION_HEADER      = 40
      
      ' ---------------------------------
      ' original name "IMAGE_DOS_HEADER"
      ' ---------------------------------
      TYPE IMAGE_DOS_HDR
        e_magic                       as WORD
        e_cblp                        as WORD
        e_cp                          as WORD
        e_crlc                        as WORD
        e_cparhdr                     as WORD
        e_minalloc                    as WORD
        e_maxalloc                    as WORD
        e_ss                          as WORD
        e_sp                          as WORD
        e_csum                        as WORD
        e_ip                          as WORD
        e_cs                          as WORD
        e_lfarlc                      as WORD
        e_ovno                        as WORD
        e_res(3)                      as WORD '  4 member WORD array
        e_oemid                       as WORD
        e_oeminfo                     as WORD
        e_res2(9)                     as WORD ' 10 member WORD array
        e_lfanew                      as LONG
      END TYPE
      
      ' ----------------------------------
      ' original name "IMAGE_FILE_HEADER"
      ' ----------------------------------
      TYPE IMAGE_FILE_HDR
        Machine                       as WORD
        NumberOfSections              as WORD
        TimeDateStamp                 as DWORD
        PointerToSymbolTable          as DWORD
        NumberOfSymbols               as DWORD
        SizeOfOptionalHeader          as WORD
        Characteristics               as WORD
      END TYPE
      
      ' --------------------------------------
      ' original name "IMAGE_DATA_DIRECTORY"
      ' --------------------------------------
      TYPE IMAGE_DATA_DIR
        VirtualAddress                as DWORD
        isize                         as DWORD
      END TYPE
      
      ' --------------------------------------
      ' original name "IMAGE_OPTIONAL_HEADER32"
      ' --------------------------------------
      TYPE IMAGE_OPTIONAL_HDR
        Magic                         as WORD 
        MajorLinkerVersion            as BYTE 
        MinorLinkerVersion            as BYTE 
        SizeOfCode                    as DWORD
        SizeOfInitializedData         as DWORD
        SizeOfUninitializedData       as DWORD
        AddressOfEntryPoint           as DWORD
        BaseOfCode                    as DWORD
        BaseOfData                    as DWORD
        ImageBase                     as DWORD
        SectionAlignment              as DWORD
        FileAlignment                 as DWORD
        MajorOperatingSystemVersion   as WORD 
        MinorOperatingSystemVersion   as WORD 
        MajorImageVersion             as WORD 
        MinorImageVersion             as WORD 
        MajorSubsystemVersion         as WORD 
        MinorSubsystemVersion         as WORD 
        Win32VersionValue             as DWORD
        SizeOfImage                   as DWORD
        SizeOfHeaders                 as DWORD
        CheckSum                      as DWORD
        Subsystem                     as WORD 
        DllCharacteristics            as WORD 
        SizeOfStackReserve            as DWORD
        SizeOfStackCommit             as DWORD
        SizeOfHeapReserve             as DWORD
        SizeOfHeapCommit              as DWORD
        LoaderFlags                   as DWORD
        NumberOfRvaAndSizes           as DWORD
        DataDirectory(15)             as IMAGE_DATA_DIR   ' 16 member array of structures
      END TYPE
      
      ' ---------------------------------
      ' original name "IMAGE_NT_HEADERS"
      ' ---------------------------------
      TYPE IMAGE_NT_HDR
        Signature                     as DWORD
        FileHeader                    as IMAGE_FILE_HDR
        OptionalHeader                as IMAGE_OPTIONAL_HDR
      END TYPE
      
      ' ---------------------------------------
      ' original name "IMAGE_EXPORT_DIRECTORY"
      ' ---------------------------------------
      TYPE IMAGE_EXPORT_DIR
        Characteristics               as DWORD
        TimeDateStamp                 as DWORD
        MajorVersion                  as WORD
        MinorVersion                  as WORD
        nName                         as DWORD
        nBase                         as DWORD
        NumberOfFunctions             as DWORD
        NumberOfNames                 as DWORD
        AddressOfFunctions            as DWORD
        AddressOfNames                as DWORD
        AddressOfNameOrdinals         as DWORD
      END TYPE
      
      UNION MISC
        PhysicalAddress               as DWORD
        VirtualSize                   as DWORD
      END UNION
      
      ' ---------------------------------------
      ' original name "IMAGE_SECTION_HEADER"
      ' ---------------------------------------
      TYPE IMAGE_SECTION_HDR
        Name1                         as STRING * 8
        Property                      as MISC
        VirtualAddress                as DWORD
        SizeOfRawData                 as DWORD
        PointerToRawData              as DWORD
        PointerToRelocations          as DWORD
        PointerToLinenumbers          as DWORD
        NumberOfRelocations           as WORD
        NumberOfLinenumbers           as WORD
        Characteristics               as DWORD
      END TYPE


    ------------------

    Leave a comment:


  • Florent Heyworth
    replied
    hi wayne

    the example you posted while very interesting is very long and
    does not correctly retrieve the base address of the open process.

    i don't have the time to translate it pb at the moment - however
    i posted some code a little while ago for a rebase utility which
    correctly retrieves the base address of a executable/dll.

    you can find it at: http://www.powerbasic.com/support/pb...ad.php?t=22797

    extract what you need from the code and look at semen's code which
    shows how to retrieve all running processes - this will get you
    the processes' handles.

    you can find it at: http://www.powerbasic.com/support/pb...ead.php?t=2521

    combine that with hutch's code and you've got a winner

    cheers

    florent



    ------------------

    Leave a comment:


  • Steve Hutchesson
    replied
    Wayne,

    The only safe way to get the starting address in an EXE file is to read
    it from the disk file and even this is subject to possible change.

    The hInstance passed to an EXE file is the address of the beginning of
    the PE image so in your own EXE files, dumping the PE image to disk is
    easy, just read from hInstance for as much as you need.

    I have yet to find a PE EXE that has a different load address to &H400000
    and any that I have tried to rebase will not run but the capacity exists
    so it is worth chasing what you are after.

    The API you are using is not available in win9x and my MSDN does not have
    it either so I don't have any way of testing what it will return.

    I have had to write my own set of PE image headers from my MASM include
    file to get a reliable set of structures to work on PE files and this
    gives reasonably straight forward access to the information stored in the
    different headers in a PE file.

    Regards,

    [email protected]

    ------------------

    Leave a comment:


  • Wayne Diamond
    replied
    there is an example with C++ source at http://msdn.microsoft.com/library/pe...7/hood0197.htm and i am
    sure this is the solution (at least under NT), but Im having a lot of
    trouble converting C++ to PB ,as i dont write in C/C++ .. can you embed C in PB code? (i read on one forum here that you could, but i was only aware of basic and asm?), or is someone wise and kind enough to translate it to PB?


    ------------------

    Leave a comment:


  • Wayne Diamond
    replied
    Glenfiddich it is ! (- ive still got half a bottle )
    im in Perth by the way - good luck with the games, i hope it doesn't invade your suburb :-)

    I have one final question regarding processes/memory before I can carry on fluently with the rest of my project. I am trying to determine the base address... you are defaulting to &H400000, but I am trying to determine this value the proper way, however that may be :-)

    This is what ive got... it compiles, but i dont think im calling things right... (is this the right call to make to determine base address?)
    naturally i am calling it after using OpenProcess, and parsing the handle over to NtQueryInformationProcess
    [code]

    DECLARE FUNCTION QueryInformationProcess LIB "ntdll.dll" ALIAS "NtQueryInformationProcess" (BYVAL ProcessHandle AS LONG, BYVAL inProcInfoClass AS LONG, BYVAL pBuffer AS ANY, PROCLENGTH AS LONG) AS LONG

    FUNCTION QUERYBASEADDRESS() AS LONG
    DIM xRes AS LONG
    DIM iProc AS PROCESS_BASIC_INFORMATION
    DIM oProc AS PROCESS_BASIC_INFORMATION
    DIM xLen AS LONG
    xLen = 255
    DIM xMyInfo AS ProcessBasicInformation
    xInfoType = xMyInfo
    xRes = QueryInformationProcess(BYVAL hProc, BYVAL xInfoType, BYVAL VARPTR(iProc), xLen)
    END FUNCTION



    ------------------

    Leave a comment:


  • Steve Hutchesson
    replied
    Wayne,

    I just got an answer from one of the authors of ProcdumpNT, it reconstructs
    the sections in a PE file directly from the disk file so the process of
    overwriting the PE header does not effect its capacity to get a complete PE
    image.

    It is in fact the only way to do it unless the unpacker wants to try a
    heuristic technique of reading the complete image and calculating where the
    addresses start.

    Regards,

    [email protected]

    PS, next time you are in Sydney, I am a pure malt man so you can shout me a
    nip of Glenfiddich.

    ------------------

    Leave a comment:


  • Wayne Diamond
    replied
    Steve, youre sure I cant buy you a drink or anything?
    Your "rather crude" technique works SUPERBLY under Windows NT (havent tested 95/98, but i dont see why they wouldnt work after success on NT and you developing it under 98)
    Its unfortunate I can't dump processes that are already running, but this is still a huge step forward in my learning! Thankyou very very much
    Drinks on me (!)



    ------------------

    Leave a comment:


  • Steve Hutchesson
    replied
    Wayne,

    Following is a rather crude technique for getting a loaded PE image from
    another process. It allocates a buffer that is much larger than the
    expected loaded image size which is filled with a single character. I have
    done it this way to avoid reading the section data from the PE header as
    it can be destroyed by various protection schemes.

    It reads from hex 400000 (&H400000) which is the normal start address and
    continues to read until the OS denies access to any further read.

    You then search the buffer for the first occurrence of a long repeat of
    the fill character which gives you the end of the loaded image.

    Point a non loaded disk file name at the function and write the return
    string to disk and you have a raw PE memory dump. NOTE that it will not
    run in this form.

    This function is valid for Win95b and it uses documented access but with
    the endless changes in 32 bit windows, there is no garrantee that it will
    run on either NT4 or WIN2K.

    Regards,

    [email protected]

    Code:
    '##########################################################################
      
      FUNCTION GetPEimage(fname$,ByVal LoadAdr as DWORD) as STRING
      
          LOCAL hMem  as DWORD
          LOCAL bRead as DWORD
          LOCAL EndIm as DWORD
          LOCAL hProc as DWORD
          LOCAL bSize as DWORD
          LOCAL fl    as DWORD
          LOCAL pi    as PROCESS_INFORMATION
          LOCAL si    as STARTUPINFO
          LOCAL buffer$
      
          Open fname$ for Binary as #1
            fl = lof(1)
            Get$ #1,1000, a$
            If instr(a$,"PE"+chr$(0,0)) = 0 Then
              MessageBox hWnd,"Cannot find PE signature in header", _
                              "Not PE file",%MB_OK
              FUNCTION = ""
              Exit FUNCTION
            End If
          Close #1
      
          rvP& = CreateProcess(ByVal StrPtr(fname$), _
                               ByVal %NULL, _
                               ByVal %NULL, _
                               ByVal %NULL, _
                               %FALSE, _
                               %DETACHED_PROCESS, _
                               ByVal %NULL, _
                               ByVal %NULL, _
                               ByVal VarPtr(si), _
                               ByVal VarPtr(pi))
      
          hProc = OpenProcess(%PROCESS_VM_READ,%TRUE,pi.dwProcessId)
      
          bSize = fl * 6
      
          buffer$ = string$(bSize,"x")
      
          If LoadAdr = 0 Then
            LoadAdr = &H400000   ' default 4 meg load address
          End If
      
          hMem = ReadProcessMemory(hProc,LoadAdr,ByVal StrPtr(buffer$), _
                                   bSize,ByVal VarPtr(bRead))
      
          EndIm = instr(buffer$,"xxxxxxxxxxxx") ' locate the end of the buffer
      
          ! dec EndIm
      
          CloseHandle hProc
      
          FUNCTION = left$(buffer$,EndIm)
      
      END FUNCTION
      
    ' #########################################################################
    ------------------

    Leave a comment:


  • Wayne Diamond
    replied
    I rephrase my question - I'll pay for somebody to write me the source code to dump process modules from memory to disk. Normally i like coding everything myself but there are some things i dont think i'd be able to achieve in a reasonable timeframe due to the research id have to put in beforehand
    perhaps there should be a Jobs forum for questions like this? If anybody is interested, could they please reply here or mail to [email protected]
    Thankyou!


    ------------------

    Leave a comment:


  • Wayne Diamond
    started a topic Dumping process module from memory to disk

    Dumping process module from memory to disk

    Steve Hutchesson, you may be the person to answer this but all feedback is welcome! How do programs such as ProcDump dump modules from memory to disk? Is this an accomplishable task in PB, and are there any examples of this nature?



    ------------------
Working...
X