Files
MemProcFS-plugins/files/vmmpy_example.py
2018-11-18 19:50:41 +01:00

429 lines
17 KiB
Python

# vmmpy_example.py
#
# Example showcase file displaying how it is possible to interface the Memory
# Process File System / Virtual Memory Manager - VMM.DLL / VmmPy / VmmPyC with
# user created python programs.
#
# Requirement: Memory Dump file from Windows 7 x64 or later with a logged in
# user that have the process 'explorer.exe' running.
#
# To start example run:
# from vmmpy_example import *
# VmmPy_Example("<filename_of_windows_memory_dump_file>")
# where <filename_of_windows_memory_dump_file> is the file name and path of a
# Windows dump file of a 64-bit Windows operating system - Windows 7 or later.
#
# To start example how to conveniently parse the PE header structs by using
# the dissect.cstruct library and VmmPy please run the example:
# from vmmpy_example import *
# VmmPy_Example_ParsePE(<filename_of_windows_memory_dump_file>)
#
# https://github.com/ufrisk/
#
# (c) Ulf Frisk, 2018
# Author: Ulf Frisk, pcileech@frizk.net
#
from vmmpy import *
from io import BytesIO
from dissect import cstruct
# Examples:
#
# VmmPy_Example("c:\\temp\\win10.raw")
# VmmPy_Example_ParsePE("c:\\temp\\win10.raw")
def VmmPy_Example(dump_file_name):
print("--------------------------------------------------------------------")
print("Welcome to the VmmPy Example showcase / test cases. This will demo ")
print("how it is possible to use VmmPy to access memory dump files in a ")
print("convenient way. Please ensure that the VmmPy requirements about the ")
print("python version (such as Python 3.6) is met before starting ... ")
# INIITALIZE
print("--------------------------------------------------------------------")
print("Initialize VmmPy with the dump file specified. ")
input("Press Enter to continue...")
print("CALL: VmmPy_InitializeFile()")
VmmPy_InitializeFile(dump_file_name)
print("SUCCESS: VmmPy_InitializeFile()")
# GET CONFIG
print("--------------------------------------------------------------------")
print("Retrieve configuration value for: VMMPY_OPT_CORE_MAX_NATIVE_ADDRESS.")
input("Press Enter to continue...")
print("CALL: VmmPy_ConfigGet()")
result = VmmPy_ConfigGet(VMMPY_OPT_CORE_MAX_NATIVE_ADDRESS)
print("SUCCESS: VmmPy_ConfigGet()")
print(result)
# SET CONFIG
print("--------------------------------------------------------------------")
print("Set configuration value for: VMMPY_OPT_CORE_PRINTF_ENABLE. ")
input("Press Enter to continue...")
print("CALL: VmmPy_ConfigSet()")
VmmPy_ConfigSet(VMMPY_OPT_CORE_PRINTF_ENABLE, 1)
print("SUCCESS: VmmPy_ConfigSet()")
# MEM READ
print("--------------------------------------------------------------------")
print("Read 0x100 bytes of memory from the physical address 0x1000 ")
input("Press Enter to continue...")
print("CALL: VmmPy_MemRead()")
result = VmmPy_MemRead(-1, 0x1000, 0x100)
print("SUCCESS: VmmPy_MemRead()")
print(result)
# MEM READ + FillHexAscii
print("--------------------------------------------------------------------")
print("Read 0x100 bytes of memory from the physical address 0x1000 ")
input("Press Enter to continue...")
print("CALL: VMMPYC_UtilFillHexAscii(VmmPy_MemRead())")
result = VmmPy_UtilFillHexAscii(VmmPy_MemRead(-1, 0x1000, 0x100))
print("SUCCESS: VMMPYC_UtilFillHexAscii(VmmPy_MemRead())")
print(result)
# MEM READ SCATTER
print("--------------------------------------------------------------------")
print("Read 2 non-contigious (scatter) memory from the physical addresses: ")
print("0x1000 and 0x3000. ")
input("Press Enter to continue...")
print("CALL: VmmPy_MemReadScatter()")
result = VmmPy_MemReadScatter(-1, [0x1000, 0x3000])
print("SUCCESS: VmmPy_MemReadScatter()")
print(result)
# PID
print("--------------------------------------------------------------------")
print("Retrieve the process identifier pid for the process 'explorer.exe'. ")
input("Press Enter to continue...")
print("CALL: VmmPy_PidGetFromName()")
result = VmmPy_PidGetFromName("explorer.exe")
print("SUCCESS: VmmPy_PidGetFromName()")
print(result)
pid = result
# PIDs
print("--------------------------------------------------------------------")
print("List the process identifier pids of the processes in the system. ")
input("Press Enter to continue...")
print("CALL: VmmPy_PidList()")
result = VMMPYC_PidList()
print("SUCCESS: VmmPy_PidList()")
print(result)
# PROCESS INFORMATION GET
print("--------------------------------------------------------------------")
print("Get the process information about the earlier explorer.exe process. ")
input("Press Enter to continue...")
print("CALL: VmmPy_ProcessGetInformation()")
result = VmmPy_ProcessGetInformation(pid)
print("SUCCESS: VmmPy_ProcessGetInformation()")
print(result)
# PROCESS INFORMATION LIST
print("--------------------------------------------------------------------")
print("Get the process information for all process in a dict by pid. ")
input("Press Enter to continue...")
print("CALL: VmmPy_ProcessListInformation()")
result = VmmPy_ProcessListInformation()
print("SUCCESS: VmmPy_ProcessListInformation()")
print(result)
# MODULE INFORMATION
print("--------------------------------------------------------------------")
print("Get module information about the explorer.exe module in the process.")
input("Press Enter to continue...")
print("CALL: VmmPy_ProcessGetModuleFromName()")
result = VmmPy_ProcessGetModuleFromName(pid, "explorer.exe")
print("SUCCESS: VmmPy_ProcessGetModuleFromName()")
print(result)
va = result['va']
# MEM MAP
print("--------------------------------------------------------------------")
print("Get the memory map of 'explorer.exe' by walking the page table. ")
input("Press Enter to continue...")
print("CALL: VmmPy_ProcessGetMemoryMap()")
result = VmmPy_ProcessGetMemoryMap(pid, True)
print("SUCCESS: VmmPy_ProcessGetMemoryMap()")
print(result)
# MEM MAP ENTRY
print("--------------------------------------------------------------------")
print("Get the PE base of 'explorer.exe' in the 'explorer.exe' process. ")
input("Press Enter to continue...")
print("CALL: VmmPy_ProcessGetMemoryMapEntry()")
result = VmmPy_ProcessGetMemoryMapEntry(pid, va, True)
print("SUCCESS: VmmPy_ProcessGetMemoryMapEntry()")
print(result)
# MEM VIRTUAL2PHYSICAL
print("--------------------------------------------------------------------")
print("Get physical address of the PE virtual address of 'explorer.exe'. ")
input("Press Enter to continue...")
print("CALL: VmmPy_MemVirt2Phys()")
result = VmmPy_MemVirt2Phys(pid, va)
print("SUCCESS: VmmPy_MemVirt2Phys()")
print(result)
# MEM READ
print("--------------------------------------------------------------------")
print("Read 0x100 bytes of memory from 'explorer.exe' PE base. ")
input("Press Enter to continue...")
print("CALL: VmmPy_MemRead()")
result = VmmPy_UtilFillHexAscii(VmmPy_MemRead(pid, va, 0x100))
print("SUCCESS: VmmPy_MemRead()")
print(result)
# PE EAT
print("--------------------------------------------------------------------")
print("Get the Export Address Table given 'explorer.exe'/'kernel32.dll' ")
input("Press Enter to continue...")
print("CALL: VmmPy_ProcessGetEAT()")
result = VmmPy_ProcessGetEAT(pid, "kernel32.dll")
print("SUCCESS: VmmPy_ProcessGetEAT()")
print(result)
# PE IAT
print("--------------------------------------------------------------------")
print("Get the Import Address Table given 'explorer.exe'/'kernel32.dll' ")
input("Press Enter to continue...")
print("CALL: VmmPy_ProcessGetIAT()")
result = VmmPy_ProcessGetIAT(pid, "kernel32.dll")
print("SUCCESS: VmmPy_ProcessGetIAT()")
print(result)
# PE DATA DIRECTORIES
print("--------------------------------------------------------------------")
print("Get the PE Data Directories from 'explorer.exe'/'kernel32.dll' ")
input("Press Enter to continue...")
print("CALL: VmmPy_ProcessGetDirectories()")
result = VmmPy_ProcessGetDirectories(pid, "kernel32.dll")
print("SUCCESS: VmmPy_ProcessGetDirectories()")
print(result)
# PE SECTIONS
print("--------------------------------------------------------------------")
print("Get the PE Data Directories from 'explorer.exe'/'kernel32.dll' ")
input("Press Enter to continue...")
print("CALL: VmmPy_ProcessGetSections()")
result = VmmPy_ProcessGetSections(pid, "kernel32.dll")
print("SUCCESS: VmmPy_ProcessGetSections()")
print(result)
# VFS LIST /
print("--------------------------------------------------------------------")
print("Retrieve the file list of the virtual file system from the root path")
input("Press Enter to continue...")
print("CALL: VmmPy_VfsList()")
result = VmmPy_VfsList('/')
print("SUCCESS: VmmPy_VfsList()")
print(result)
# VFS LIST /name
print("--------------------------------------------------------------------")
print("Retrieve the file list of the virtual file system from the name path")
input("Press Enter to continue...")
print("CALL: VmmPy_VfsList()")
result = VmmPy_VfsList('/name')
print("SUCCESS: VmmPy_VfsList()")
print(result)
# VFS READ
print("--------------------------------------------------------------------")
print("Read from a file in the virtual file system (/pmem at offset 0x1000)")
input("Press Enter to continue...")
print("CALL: VmmPy_VfsRead()")
result = VmmPy_UtilFillHexAscii(VmmPy_VfsRead('/pmem', 0x100, 0x1000))
print("SUCCESS: VmmPy_VfsRead()")
print(result)
PE_STRUCT_DEFINITIONS = """
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_DOS_HEADER
{
WORD e_magic;
WORD e_cblp;
WORD e_cp;
WORD e_crlc;
WORD e_cparhdr;
WORD e_minalloc;
WORD e_maxalloc;
WORD e_ss;
WORD e_sp;
WORD e_csum;
WORD e_ip;
WORD e_cs;
WORD e_lfarlc;
WORD e_ovno;
WORD e_res[4];
WORD e_oemid;
WORD e_oeminfo;
WORD e_res2[10];
LONG e_lfanew;
} IMAGE_DOS_HEADER;
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER;
typedef struct _IMAGE_DATA_DIRECTORY {
ULONG VirtualAddress;
ULONG Size;
} IMAGE_DATA_DIRECTORY;
typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER;
typedef struct _IMAGE_OPTIONAL_HEADER64 {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
ULONGLONG ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
ULONGLONG SizeOfStackReserve;
ULONGLONG SizeOfStackCommit;
ULONGLONG SizeOfHeapReserve;
ULONGLONG SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER64;
typedef struct _IMAGE_SECTION_HEADER {
char Name[IMAGE_SIZEOF_SHORT_NAME];
ULONG VirtualSize;
ULONG VirtualAddress;
ULONG SizeOfRawData;
ULONG PointerToRawData;
ULONG PointerToRelocations;
ULONG PointerToLinenumbers;
USHORT NumberOfRelocations;
USHORT NumberOfLinenumbers;
ULONG Characteristics;
} IMAGE_SECTION_HEADER;
"""
def VmmPy_Example_ParsePE(dump_file_name):
# INIITALIZE
print("--------------------------------------------------------------------")
print("Initialize VmmPy with the dump file specified. ")
input("Press Enter to continue...")
print("CALL: VmmPy_InitializeFile()")
VmmPy_InitializeFile(dump_file_name)
print("SUCCESS: VmmPy_InitializeFile()")
#
# EXAMPLE BELOW USE THE FOX-IT DISSECT CSTRUCT PYTHON MODULE TO PARSE THE
# THE PE HEADER OF 'ntdll.dll' in 'explorer.exe'
#
print("--------------------------------------------------------------------")
print("Parse the PE header of 'explorer.exe'/'ntdll.dll' by using a VmmPy ")
print("custom version of the dissect.cstruct parsing library from fox-it. ")
print("dissect.cstruct: https://github.com/fox-it/dissect.cstruct ")
input("Press Enter to continue...")
# Call VmmPy to retrieve the actual 0x1000 page containing the PE header.
print("CALL: VmmPy*")
mz_pid = VmmPy_PidGetFromName('explorer.exe')
mz_va = VmmPy_ProcessGetModuleFromName(mz_pid, "ntdll.dll")['va']
mz_bytes = VmmPy_MemRead(mz_pid, mz_va, 0x1000)
print("SUCCESS: VmmPy*")
# Create a stream for convenience
mz_stream = BytesIO(mz_bytes)
# Set up dissect.cstruct
print("INITIALIZING dissect.cstruct and parsing PE header structures ... ")
pestruct = cstruct.cstruct()
pestruct.load(PE_STRUCT_DEFINITIONS)
# Load the MZ stream into dissect.struct. NB! loading mz_bytes will work as
# well but will not be as convenient since the 'file pointer' won't move on
# struct reads automatically...
struct_mz = pestruct.IMAGE_DOS_HEADER(mz_stream)
if struct_mz.e_magic != 0x5a4d:
print("MZ HEADER DOES NOT MATCH - ABORTING")
return
print(struct_mz)
print(cstruct.dumpstruct(struct_mz, None, 0, False, True))
# Seek towards the PE signature / magic value and check that it is correct.
mz_stream.seek(struct_mz.e_lfanew)
signature = pestruct.uint32(mz_stream)
if signature != 0x4550:
print("PE HEADER DOES NOT MATCH")
return
# Parse and display the PE file_header struct.
struct_file_header = pestruct.IMAGE_FILE_HEADER(mz_stream)
print(struct_file_header)
print(cstruct.dumpstruct(struct_file_header, None, 0, False, True))
# Parse and display the PE struct_optional_header struct.
struct_optional_header = pestruct.IMAGE_OPTIONAL_HEADER64(mz_stream) if struct_file_header.Machine == 0x8664 else pestruct.IMAGE_OPTIONAL_HEADER(mz_stream)
print(struct_optional_header)
print(cstruct.dumpstruct(struct_optional_header, None, 0, False, True))
# Parse and display the PE sections.
struct_sections = [pestruct.IMAGE_SECTION_HEADER(mz_stream) for _ in range(struct_file_header.NumberOfSections)]
for struct_section in struct_sections:
print(cstruct.dumpstruct(struct_section, None, 0, False, True))