Disassembling
You can disassemble in WinDbg at any memory address, e.g.
0:067> db 000007fe`ff4d0000
000007fe`ff4d0000 4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00 MZ..............
000007fe`ff4d0010 b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00 ........@.......
000007fe`ff4d0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
000007fe`ff4d0030 00 00 00 00 00 00 00 00-00 00 00 00 e0 00 00 00 ................
000007fe`ff4d0040 0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68 ........!..L.!Th
000007fe`ff4d0050 69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f is program canno
000007fe`ff4d0060 74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20 t be run in DOS
000007fe`ff4d0070 6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00 mode....$.......
0:067> u 000007fe`ff4d0000 L1
advapi32!WmipBuildReceiveNotification <PERF> (advapi32+0x0):
000007fe`ff4d0000 4d5a pop r10
But as you can see, this is more or less useless (in my example useless to disassemble the MZ
magic bytes of a DLL's header).
So, finding the right starting place for a disassembly is the critical part.
Finding code as part of DLLs
Code should mainly be in DLLs or EXEs (called images or modules in WinDbg). To find them in a memory dump (kernel or user mode), you can run the WinDbg command
.imgscan
From WinDbg help:
The .imgscan command scans virtual memory for image headers.
The .imgscan command displays any image headers that it finds and the header type. Header types include Portable Executable (PE) headers and Microsoft MS-DOS MZ headers.
I was able to verify this in user mode, but with the only Windows XP kernel mode dump I currently have, it does not output anything.
Example output from a user mode dump:
MZ at 000007fe`ff4d0000, prot 00000004, type 00020000 - size db000
Name: ADVAPI32.dll
So all the necessary information to get the DLL is available. In case of a user mode dump I have used
.writemem <FileName> <Range>
to write the DLL to disk and analyze later.
<Range>
is according the address and range syntax, e.g.
.writemem advapi32.dll 000007fe`ff4d0000 Ldb000
This probably won't work for kernel mode dumps because parts of the module may have been swapped to disk, so the DLL in memory is no longer complete.
This approach will also not find code that was generated on the fly.
Finding potentially executable code
Code that can be executed must reside in a memory block that has the executable
flag set.
Unfortunately the command
!address -f:<filter>
is broken in WinDbg 6.2.9200. It should work in user mode dumps and output a list of start and end addresses that are executable.
At the moment I only get
0:067> !address -f:PAGE_EXECUTE
BaseAddress EndAddress+1 RegionSize Type State Protect Usage
------------------------------------------------------------------------------------------------------------------------
0:067> !address -f:PAGE_EXECUTE_READ
Invalid filter arguments. Type !address -? to get the list of supported parameters
0:067> !address -f:PAGE_EXECUTE_READWRITE
Invalid filter arguments. Type !address -? to get the list of supported parameters
0:067> !address -f:PAGE_EXECUTE_WRITECOPY
Invalid filter arguments. Type !address -? to get the list of supported parameters
Although I have a full memory dump
0:067> .dumpdebug
...
Flags 40002
0002 MiniDumpWithFullMemory
40000 MiniDumpWithTokenInformation
But you get the idea and might be able to apply it to other tools.