Memory Forensics With Volatility
February 23, 2017 | Author: scudette | Category: N/A
Short Description
Download Memory Forensics With Volatility...
Description
Memory Forensics With Volatility Michael Cohen Software Engineer - Google Inc.
Acknowledgements Many great researchers in the memory forensics field (and Volatility Contributors): ● Aaron Walters. ● Brendan Dolan-Gavitt. ● Andreas Schuster. ● Michael Hale Ligh. ● Andrew Case. ● Jamie Levy. ● Mike Auty. ● ... and many others!
References Malware Analyst's Cookbook Michael Hale Ligh, Steven Adair, Blake Hartstein, Matthew Richard http://code.google.com/p/malwarecookbook/
Module 1 - Introduction ● Why memory forensics? ● What can Volatility do for me? ● Symbols and debugging information. ○ How does Volatility support multiple operating systems and versions.
● Memory imaging ○ Linux. ○ Windows.
Memory Forensics - Why? ● Live response. ○ Can quickly triage a system.
● Capture of memory freezes system state. ○ As memory is volatile we can minimize interference with memory. ○ Analysis does not use the system APIs.
● Memory analysis technology evolves with time. ○ We used to only have grep :-) ○ NIST reference image: xp-laptop-2005-06-25.img: ■ Registry dump ■ Passwords ■ Screenshots
The Volatility Memory Forensics Framework. ● Current release on google code: http://code.google.com/p/volatility/ ○ Supports 64 bit windows up to windows 7.
● Volatility technology preview (TP): ○ Major refactoring/code rewriting - lots of new features. ○ Ease of use as a library. ○ Interface uses IPython - interactive console. ○ Memory acquisition drivers included.
● We will be using both but mainly Volatility TP. ○ Check with the volatility site for an upcoming release.
A short Volatility Demo
Types and debugging Information. ● Operating systems are generally written in C typedef unsigned char uchar; enum { It is generally not possible to predict the memory layout of a C struct without knowing OPT1, external factors: ● Alignment OPT2 ● Endianess ● Bit size } options; ● Compiler ●
struct foobar { enum options flags; short int bar; uchar *foo; }
Optimizations etc
Unless packed structs.
Types and debugging Information DWARF. $ readelf --debug-dump=info module.ko : Abbrev Number: 28 (DW_TAG_structure_type)
DW_AT_name
: (indirect string, offset: 0x7d7e): task_struct
DW_AT_byte_size
: 5864
DW_AT_decl_file
: 17
DW_AT_decl_line
: 7
DW_AT_sibling
:
: Abbrev Number: 32 (DW_TAG_member)
DW_AT_name
: (indirect string, offset: 0x254): state
DW_AT_decl_file
: 18
DW_AT_decl_line
: 1221
DW_AT_type
:
DW_AT_data_member_location: 2 byte block: 23 0
(DW_OP_plus_uconst: 0)
: Abbrev Number: 32 (DW_TAG_member)
DW_AT_name
: (indirect string, offset: 0xb200): stack
DW_AT_decl_file
: 18
DW_AT_decl_line
: 1222
DW_AT_type
:
DW_AT_data_member_location: 2 byte block: 23 8
(DW_OP_plus_uconst: 8)
Types and debugging Information PDB.
Types and debugging Information The Volatility Type system - Profiles. ● A compilation unit is a self consistent unit of compiled
●
code which uses the same memory layout for structs. ○ For example, a .obj file or a dll. ○ It is important to note that the same struct may have different layout in different dlls. For example: ■ 32 bit processes running on a 64bit operating system have different definitions for integers. ■ Microsoft exports _EPROCESS in the kernel and in userspace but these are different. VTypes is a special language for specifying memory layout of structs and other objects using python data structures.
User Space/Kernel Space
Types and debugging Information The Volatility Type system - Profiles. Struct Name
'_EPROCESS' : [ 0x4d0, {
Struct Size
'Pcb' : [ 0x0, ['_KPROCESS']],
Member Offset
'ProcessLock' : [ 0x160, ['_EX_PUSH_LOCK']], 'CreateTime' : [ 0x168, ['_LARGE_INTEGER']],
Member Type
'ExitTime' : [ 0x170, ['_LARGE_INTEGER']], 'RundownProtect' : [ 0x178, ['_EX_RUNDOWN_REF']], 'UniqueProcessId' : [ 0x180, ['pointer64', ['void']]], 'ActiveProcessLinks' : [ 0x188, ['_LIST_ENTRY']], 'ProcessQuotaUsage' : [ 0x198, ['array', 2, ['unsigned
Special support for array and pointers long long']]], (legacy).
'ProcessQuotaPeak' : [ 0x1a8, ['array', 2, ['unsigned long long']]], 'CommitCharge' : [ 0x1b8, ['unsigned long long']], 'QuotaBlock' : [ 0x1c0, ['pointer64', ['_EPROCESS_QUOTA_BLOCK']]], 'CpuQuotaBlock' : [ 0x1c8, ['pointer64', ['_PS_CPU_QUOTA_BLOCK']]], 'PeakVirtualSize' : [ 0x1d0, ['unsigned long long']], 'VirtualSize' : [ 0x1d8, ['unsigned long long']], 'SessionProcessLinks' : [ 0x1e0, ['_LIST_ENTRY']], 'DebugPort' : [ 0x1f0, ['pointer64', ['void']]], .....
Types and debugging Information The Volatility Type system - Profiles. ● VTypes are autogenerated from debugging symbols: ○ Linux: a special module is compiled with debugging symbols and the DWARF information is extracted. ■ Uses pyelftools or dwarfdump. ○ Windows: the pdb files are downloaded from the microsoft symbol server and parsed. ■ Uses pdbdump by Brendan Dolan-Gavit.
● VTypes are not enough though! ○ Debug information fails to convey semantic meaning. ○ PDB files may be incomplete or not exist - then we need to reverse engineer the struct members.
Types and debugging Information The Volatility Type system - Profiles. ● The volatility object system is built on the vtypes definition language to present an object oriented, automatic parsing system. ○ Everything is an object extending obj.BaseObject() ○ Definitions are layered: Object classes Overlays VType definition.
Types and debugging Information The Volatility Type system - Profiles. ● An Overlay is a partial vtype structure with "holes" signified by None which overlays on top of the original VType definition. ○ This is used to "correct" the original vtype, while allowing some aspect of the previous definitions to come through. '_EPROCESS' : [ 0x4d0, { 'Pcb' : [ 0x0, ['_KPROCESS']], 'ProcessLock' : [ 0x160, ['_EX_PUSH_LOCK']], 'CreateTime' : [ 0x168, '_LARGE_INTEGER']], 'ExitTime' : [ 0x170, ['_LARGE_INTEGER']], ..... }],
VType
'_EPROCESS' : [ None, { 'CreateTime' : [ None, ['WinTimeStamp', {}]]], 'ExitTime' : [ None, ['WinTimeStamp', {}]], ..... }],
Overlay
Types and debugging Information The Volatility Type system - Profiles. ● The overlay can apply to wide range of operating system versions ○ The exact offsets are controlled by the debugging symbols, but the semantic meaning is given by the overlay. '_EPROCESS' : [ 0x4d0, { 'Pcb' : [ 0x0, ['_KPROCESS']], 'ProcessLock' : [ 0x160, ['_EX_PUSH_LOCK']], 'CreateTime' : [ 0x168, '_LARGE_INTEGER']], 'ExitTime' : [ 0x170, ['_LARGE_INTEGER']], ..... }],
VType
'_EPROCESS' : [ None, { 'CreateTime' : [ None, ['WinTimeStamp', {}]]], 'ExitTime' : [ None, ['WinTimeStamp', {}]], ..... }],
Overlay
Types and debugging Information The Volatility Type system - Profiles. ● Behaviors can be attached to objects via defining specialized classes. ○ The VType system instantiates a named class with the given arguments when a struct member is dereferenced. ○ The class instance can provide extra methods. '_EPROCESS' : [ 0x4d0, { 'Pcb' : [ 0x0, ['_KPROCESS']], 'ProcessLock' : [ 0x160, ['_EX_PUSH_LOCK']], 'CreateTime' : [ 0x168, '_LARGE_INTEGER']], 'ExitTime' : [ 0x170, ['_LARGE_INTEGER']], ..... }],
VType
'_EPROCESS' : [ None, { 'CreateTime' : [ None, ['WinTimeStamp', {}]]], 'ExitTime' : [ None, ['WinTimeStamp', {}]], ..... }],
Overlay
Types and debugging Information The Volatility Type system - Profiles. This is an object representing the _EPROCESS struct. In [1]: task = session.profile._EPROCESS(0xFA8000ACAB30) Out[1]: [_EPROCESS _EPROCESS] @ 0xFA8000ACAB30 There is a CreateTime member which is an instance of the WinTimeStamp class. In [2]: type(task.CreateTime) Out[2]: volatility.plugins.overlays.basic.WinTimeStamp The WinTimeStamp class knows how to print itself nicely. In [3]: print task.CreateTime 2012-02-22 11:28:59 The WinTimeStamp class offers more functionality related to timestamp conversions. In [4]: print task.CreateTime.as_windows_timestamp() 129743837397084000
Types and debugging Information The Volatility Type system - Profiles. ● A Profile is an internally consistent collection of vtypes and definitions. ○ Strictly a profile represents a single compilation unit. ○ Volatility 2.0 has one global profile ■ Can not represent multiple, contradictory compilation units (e.g. 32bit process on 64bit OS).
● Volatility TP has domain specific profiles. ○ A profile therefore represents an internal implementation of a specialized parser. For example the registry parser consists of vtypes, overlays and classes together forming an API for handling the windows registry.
Supporting multiple operating system versions. ● For windows we have pre-computed profiles from different versions of ntoskrnl.exe. ○ Must specify the correct profile to use using the session.profile variable. (or --profile command line).
● For linux we must generate vtypes to specific kernel version we are analysing. ○ This is because the struct layouts vary depending on kernel configuration. (There are #ifdefs in the middle of the structs). ○ We generate a profile_file which is a zip containing: ■ System.map-2.6.32-40-generic ■ A special module.ko built with symbols.
Memory Imaging. Take a permanent copy of physical memory: ● Lots of techniques to do this: ○ Hardware based ■ Firewire. ■ Cold Boot attack. ■ Tribble ○ Software base ■ Hibernation ■ Crash dumps ■ Inserting a special driver. ■ Debugger APIs.
Hibernation ● When a system hibernates it copies its memory state to disk. ○ Volatility can analyse this image. ○ Pros ■ Easy to obtain image. ■ No prior preparation needed. ○ Cons ■ Prior to hibernation, an ACPI pnp event is transmitted to all drivers: ● ●
Network sockets are removed. Malware may cleanup.
■ Windows only copies in use pages to the hibernation file.
Crashdump - Windows BSOD. ● A crashdump is a standard mechanism for windows debugging. ○ Pros: ■ The system stops most running threads during the dump - atomicity is best. ■ Can attach the windows debugger (windbg) to the crash dump. Raw image can be converted to crash dump too. ○ Cons: ■ Usually must be pre-configured. ■ Only dumps memory used by the kernel (e.g. not bios areas - page 0). ■ System can not resume - so we can not do differential analysis.
Memory Acquisition tools. ● Volatility TP comes with the winpmem acquisition driver (Experimental): ○ For 64 bit windows these must be signed. ○ The winpmem driver makes physical memory accessible via the \\.\pmem device. ■ This means you can run Volatility TP directly on the raw memory device. ■ Can produce a crash dump via raw2dmp plugin.
● Other popular options: ○ windd by moonsols http://www.moonsols.com/windows-memory-toolkit/ ■ Can produce crashdumps etc. ■ Only writes image from kernel space and therefore not suitable for live memory analysis.
Windows acquisition - Example Driver reports CR3 and valid memory ranges
Imager pads gaps with zeros for raw image.
Memory Acquisition tools - Linux. ● Volatility TP comes with a Linux driver pmem.ko ○ Must be compiled for the exact kernel version that should be imaged (this is a Linux requirement). ○ Provides a new device in /dev/pmem. ○ Can use Volatility TP to analyse the running system.
● Kernel driver normally has to be compiled to the kernel version. ○ The linux kernel has symbol versioning. When loading a module with insmod the kernel ensures the module is compiled for the same version. ○ Not very convenient from an incident response point of view.
Memory acquisition - Linux scudette@scudette:~/volatility/svn/tools/linux$ sudo apt-get install linux-image-3.0.022-generic linux-headers-3.0.0-22-generic Reading package lists... Done Building dependency tree
This is the target kernel image version.
Reading state information... Done linux-image-3.0.0-22-generic is already the newest version. linux-headers-3.0.0-22-generic is already the newest version. 0 upgraded, 0 newly installed, 0 to remove and 12 not upgraded. scudette@scudette:~/volatility/svn/tools/linux$ make KVER=3.0.0-22-generic make -C //lib/modules/3.0.0-22-generic/build CONFIG_DEBUG_INFO=y M=/home/scudette/volatility/svn/tools/linux modules make[1]: Entering directory `/usr/src/linux-headers-3.0.0-22-generic' CC [M]
/home/scudette/volatility/svn/tools/linux/module.o
CC [M]
/home/scudette/volatility/svn/tools/linux/pmem.o
....
Driver creates a new device Copy to the target machine and then: # insmod pmem.ko # dd if=/dev/pmem of=myimage.dd # rmmod pmem
Patching linux kernel modules ● Ideally we want to have a binary kernel module we can insert to any kernel version. ○ This can only work if the structs used are stable across versions. ■ The pmem driver is very simple - all real work is done in userspace so kernel space code is minimized and remains stable across versions. ○ Must bypass the linux kernel's module versioning checks. ○ Andreas Moser has implemented a live module patcher. ■ Search the system for other kernel modules. ■ Copy the symbol versions to pmem.ko
Patching kernel module - Example scudette@scudette:~/volatility/svn/tools/linux$ sudo insmod ./module.ko insmod: error inserting './module.ko': -1 Invalid module format scudette@scudette:~/volatility/svn/tools/linux$ python ko_patcher.py module.ko patched_module.ko INFO:root:Module version is 2.6.32-21-generic, kernel version is 2.6.32-40-generic. INFO:root:All imports found, gathered data from 1 modules. INFO:root:Checksum mismatch for module_layout. INFO:root:Kernel Object patched. scudette@scudette:~/volatility/svn/tools/linux$ sudo insmod ./patched_module.ko scudette@scudette:~/volatility/svn/tools/linux$
Virtual Machine Imaging Taking a memory image from a virtual machine is most reliable: e.g. Virtual Box: VBoxManage debugvm dumpguestcore --filename
Summary for Module 1 ● Introduction to memory forensics and Volatility ○ ○ ○ ○
Symbols types and memory layout. The Volatility type system. What are Profiles. Generating profiles for Linux.
● Memory Imaging ○ ○ ○ ○
Different types of images. How to image Windows systems. How to image Linux systems. Live memory analysis with volatility.
Module 2 - Virtual Memory and Paging ● How does virtual memory work? ● We can see a string in the image - where does it come from? ● Why do I get a 2gb file when I dump out a single process address space?
Virtual Memory and Paging. Pages
Frames
Virtual Address
Shared Memory
Overcommited
Physical Address
Backed Mem Paged out
Backed Mem
Physical Memory
Page File Process A Virtual Memory
Process B Virtual Memory
Virtual Memory and Paging. ● Paging allows different processes to have their own unique view of physical memory: ○ Physical memory can be shared between processes at different virtual addresses. ○ Physical memory can be assigned to a specific process's use without being accessible from other processes. ○ Processes can request memory to be mapped into their virtual address space which is not yet backed by physical memory (overcommitted). ○ A process's memory can be paged out to disk. ○ A process may map a file into its address space the kernel will automatically read from the file when a page fault occurs.
Paging in 32 bit model. Virtual Address Page Directory Index CR3
Page Table Index
Byte Index
Directory Table Base (DTB)
Page Frame
PTN
PTE
Page Directory
Page Tables
Physical Memory
The CR3 register. ● Paging is done automatically by the MMU in hardware. ○ All the CPU has to do is store the address of the current Page directory table in the CR3 register. ○ When the kernel switches task context (to another process), a new value of CR3 is loaded to point at new page tables. ○ The value of CR3 is key to make sense of a physical memory image. ○ Some imaging tools also capture CR3.
Page Table Entry. Prototype
Large Page
Valid Page Frame number
U
P
Cw
Gl
L
D
A
Cd
Wt
O
W
V
Page Faults ● When bit 1 in the PTE is set to 0 (invalid), any access to this page will generate a page fault. ○ Note that all other bits of PTE are ignored in this case. So the PTE can be technically used for OS private data. ○ Page fault handler is a kernel routine which handles the page fault: ■ Page may be fetched from page file. ■ Page is in transition if Prototype bit is also set. ●
A page is transition is waiting to be paged out, but is actually valid still. A page fault here can return it into the working set immediately.
■ Page may be overcommitted and kernel will allocate physical memory for it.
Volatility Address Spaces ● An address space is an object which satisfies read requests. ○ Many address spaces satisfy their reads from another address space - Address Spaces stack. An address space can be sparse - i.e. read() to some regions will fail. The address space should implement get_available_addresses() to assist in scanning. read() zread() can be used to pad invalid regions with 0.
MmapFileAddressSpace IA32PagedMemory
Volatility Address Spaces ● By default, most plugins will invoke the load_as() plugin. ○ This uses an automated voting algorithm to figure out the correct layering of address spaces (it will call the find_dtb() scanner). ○ loas_as() will populate the session with the physical and kernel address spaces. ● A profile is applied onto an address space in order to instantiate a vtype object: task = session.profile._EPROCESS(vm=self.kernel_address_space, offset=0x12345) print task.ImageFileName
How to find the Kernel DTB Windows ● Many imaging tools already capture the DTB. ● Can deduce DTB from any process: ○ When the kernel schedules a process, it must restore CR3 to the process DTB - hence the process DTB is stored in the process struct (task.Pcb. DirectoryTableBase): ○ Every process maps the kernel! '_EPROCESS' : [ 0x260, { Typically scan for 'Pcb' : [ 0x0, ['_KPROCESS']], "Idle" 'ImageFileName' : [ 0x174, ['array', 16, ['unsigned char']]], }] '_KPROCESS' : [ 0x6c, { 'Header' : [ 0x0, ['_DISPATCHER_HEADER']], 'ProfileListHead' : [ 0x10, ['_LIST_ENTRY']], 'DirectoryTableBase' : [ 0x18, ['array', 2, ['unsigned long']]],
In [15]: find_dtb? find_dtb: A plugin to search for the Directory Table Base for windows systems. Scans the image for the Idle process. ... In [16]: find_dtb -------> find_dtb() _EPROCESS (P) DTB 0x02813140 0x00187000 0x1179b7dc 0x00490050
How does imaging work? Linux In Linux it is more efficient to implement devices through mmap: static int pmem_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { loff_t offset = vmf->pgoff pgoff); /* Faulting page */ struct page *page; /* Map the real page here. */ page = pfn_to_page(pfn); get_page(page); vmf->page = page; return 0; } static struct vm_operations_struct pmem_vm_ops = { .fault = pmem_vma_fault, };
Listing processes - Linux. ● In linux processes are represented by task_struct structures: 'task_struct': [5864, 'tasks': [576, ['list_head']], }] 'list_head': [16, { 'next': [0, ['pointer', ['list_head']]], 'prev': [8, ['pointer', ['list_head']]]}]
○ All tasks are connected in a list. ○ The init task is always alive and its address is hard coded into the kernel symbols.
Listing processes - Linux.
Init Task
next
next
next
prev
prev
prev
The Kernel Debugger Block Windows KDBG. KDBG Block
PsActiveProcessHead
Flink
Flink
Flink
Flink
Blink
Blink
Blink
Blink
The Kernel Debugger Block Windows KDBG. ● The kernel debugger uses the KDBG to store information important for debugging. ○ The PsActiveProcessHead is a pointer to the list head of the active processes.
● The KDBG is not critical to the operation of the system, so malware can easily corrupt it. ● You can always list the processes by finding a single _EPROCESS object and following the list around. ○ The PsActiveProcessHead is not a real process, so will need to discard that.
Scanning for the KDBG $ python vol.py -f ~/images/xp-laptop-2005-06-25.img --profile WinXPSP3x86 kdbgscan Volatile Systems Volatility Framework 2.1_alpha ************************************************** Instantiating KDBG using: Kernel AS WinXPSP2x86 (5.1.0 32bit) Offset (V)
: 0x8054c060
Offset (P)
: 0x54c060
KDBG owner tag check
: True
Profile suggestion (KDBGHeader): WinXPSP3x86 Version64
: 0x8054c038 (Major: 15, Minor: 2600)
Service Pack (CmNtCSDVersion) : 2 Build string (NtBuildLab)
: 2600.xpsp_sp2_gdr.050301-1519
PsActiveProcessHead
: 0x805604d8 (47 processes)
PsLoadedModuleList
: 0x8055a420 (127 modules)
KernelBase
: 0x804d7000 (Matches MZ: True)
Major (OptionalHeader)
: 5
Minor (OptionalHeader)
: 1
KPCR
: 0xffdff000 (CPU 0)
Listing processes - Windows. $ ./vol.py -f ~/images/win7_trial_64bit.raw --profile=Win7SP0x64 --logging info In [1]: pslist ------> pslist() INFO:root:Autodetected physical address space WindowsCrashDumpSpace64 INFO:root:Autodetected virtual address space AMD64PagedMemory@0x00187000 (Kernel AS@0x187000) INFO:root:KDBG not provided - Volatility will try to automatically scan for it now using plugin.kdbgscan. INFO:root:Found a KDBG hit [_KDDEBUGGER_DATA64 _KDDEBUGGER_DATA64] @ 0xF80002803070. Hope it works. If not try setting it manually. Offset (V)
Name
PID
PPID
Thds
Hnds
Sess
Wow64 Start
Exit
-------------- -------------------- ------ ------ ------ -------- ------ ------ --------------------------------------0xfa80004b09e0 System
4
0
78
489 ------
False 2012-02-22 19:58:20
-
0xfa8000ce97f0 smss.exe
208
4
2
29 ------
False 2012-02-22 19:58:20
-
0xfa8000c006c0 csrss.exe
296
288
9
385
0
False 2012-02-22 19:58:24
-
0xfa8000c92300 wininit.exe
332
288
3
74
0
False 2012-02-22 19:58:30
-
Finding hidden processes - psxview ● Combines the output from several plugins ○ ○ ○ ○ ○
_EPROCESS list traversal Pool tag scanning. CSRSS handles Thread scanning. Kernel debugger PspCidTable
● Results are always inconsistent ○ Some processes just do not show up on some sources.
In [5]: psxview ------> psxview() Offset(P)
Name
PID pslist
psscan
thrdproc pspcdid csrss
---------- -------------------- ------ ------- ------- -------- ------- ------0x01f67500 TaskSwitch.exe
1952 True
True
True
True
True
0x02000980 wmiprvse.exe
4080 True
True
True
False
False
0x02025608 atiptaxx.exe
2040 True
True
True
True
True
0x12cd3020 smss.exe
448 False
True
False
False
False
0x0fe5f8e0 snmp.exe
1424 False
True
False
False
False
528 True
True
True
True
True
2624 True
True
True
True
True
944 True
True
True
True
True
0x01ed76b0 PluckTray.exe
2740 True
True
True
True
True
0x01f48da0 tcpsvcs.exe
1400 True
True
True
True
True
0x01f6db28 msdtc.exe
1076 True
True
True
True
True
580 True
True
True
True
True
1960 False
True
False
False
False
876 True
True
True
True
True
0x01f8eb10 winlogon.exe 0x02079c18 cmd.exe 0x02218020 PluckSvr.exe
0x020e0da0 services.exe 0x1a192a90 Fast.exe 0x01fa8240 Smc.exe
Volatility TP as a library #!/usr/bin/python from volatility import session s = session.Session() s.filename = "MyImage.raw" s.profile = "Win7SP1x64"
A session is an object which holds all analysis results for the current session.
pslist = s.plugins.pslist() The module is available from the session object. A module exports methods which we can call. for task in pslist.list_eprocess(): print task.UniqueProcessId, task.ImageFileName
Normally the vol() helper calls the render() method of the module, but many modules export many other methods.
What could go wrong? BH Europe 2012: One-byte Modification for Breaking Memory Forensic Analysis specifically attacks these processes: 1. Virtual address translation in kernel space. a. Corrupt the header of Idle process. 2. Guessing OS version and Architecture. a. Change the PE header of kernel. 3. Getting kernel objects a. traversing linked lists or binary trees b. object carving i. Corrupts the pool tags. The overall effect is that it does not work out of the box!
DKOM Very old technique for unlinking _EPROCESS objects: Works because KDBG Block
PsActiveProcessHe ad
Flink Blink
the scheduler uses threads
Flink Blink
Flink Blink
Flink Blink
http://i159.photobucket.com/albums/t141/sovietweasel/hideproc-vmware.jpg
Summary of module 2 ● Virtual paging ○ Volatility Address spaces
● Analysis techniques ○ List following
● Some antiforensic techniques ○ DKOM ○ Signature subversion.
Module 3 Windows internals: ● The PE File format. ○ Finding PE files in memory.
● Scanning for kernel objects in memory. ○ psscan, filescan, driverscan
PE Executables ● The PE file format is specifically designed to allow fast and efficient loading of executables into memory. ○ The structure of executables on disk is similar to their structure in memory. ○ Imports and Exports are resolved at load time.
PE Overview
http://code.google.com/p/corkami/downloads/detail?name=pe-20110117.pdf
Example of PE Parsing from memory In [5]: from volatility.plugins.overlays.windows import pe_vtypes In [6]: pe = pe_vtypes.PE(address_space=session.kernel_address_space, image_base= session.kdbg.KernBase) In [7]: p pe.nt_header [_IMAGE_NT_HEADERS _IMAGE_NT_HEADERS] @ 0x804D70E8 0x00 Signature 0x04 FileHeader
This is the address of ntoskrnl.exe
[unsigned long:Signature]: 0x00004550 [_IMAGE_FILE_HEADER FileHeader] @ 0x804D70EC
0x18 OptionalHeader [_IMAGE_OPTIONAL_HEADER OptionalHeader] @ 0x804D7100 0xF8 Sections
In [8]: p pe.nt_header.OptionalHeader [_IMAGE_OPTIONAL_HEADER OptionalHeader] @ 0x804D7100 0x1C ImageBase
[unsigned long:ImageBase]: 0x00400000
0x20 SectionAlignment
[unsigned long:SectionAlignment]: 0x00000080
0x24 FileAlignment
[unsigned long:FileAlignment]: 0x00000080
0x28 MajorOperatingSystemVersion 0x00000005
[unsigned short:MajorOperatingSystemVersion]:
0x2A MinorOperatingSystemVersion 0x00000001
[unsigned short:MinorOperatingSystemVersion]:
Version 5.1= Windows XP SP 2
Listing Sections of PE Files In [42]: for section in pe.Sections(): print section ('xr-',
[String:Name]: '.text\x00\x00\x00',
('xr-',
[String:Name]: 'INITKDBG',
('xr-',
[String:Name]: 'POOLMI\x00\x00',
('xr-',
[String:Name]: 'POOLCODE',
('xrw',
[String:Name]: 'RWEXEC\x00\x00',
[unsigned long:VirtualAddress]: 0x001A6000, 1728512)
('-r-',
[String:Name]: '.rdata\x00\x00',
[unsigned long:VirtualAddress]: 0x001A7000, 1980928)
('-rw',
[String:Name]: '.data\x00\x00\x00',
('-r-',
[String:Name]: '.pdata\x00\x00',
.....
[unsigned long:VirtualAddress]: 0x00001000, 1689600)
[unsigned long:VirtualAddress]: 0x0019D000, 1706496) [unsigned long:VirtualAddress]: 0x001A1000, 1715200)
[unsigned long:VirtualAddress]: 0x001A3000, 1728512)
[unsigned long:VirtualAddress]: 0x001E4000, 2046976)
[unsigned long:VirtualAddress]: 0x00278000, 2783744)
The peinfo plugin In [11]: peinfo? peinfo: Print information about a PE binary. Dump a PE binary from memory. Status is shown for each exported function: - M: The function is mapped into memory. Parameter
Documentation
------------------------------ ---------------------------------------------------------------------address_space
The address space which contains the PE image.
image_base
The address of the image base (dos header).
The peinfo plugin In [3]: peinfo session.kernel_address_space, session.kdbg.KernBase Machine
TimeDateStamp
-------------------- ------------Machine
IMAGE_FILE_MACHINE_AMD64
TimeDateStamp
2009-07-13 23:40:48 UTC+0000
Characteristics
IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE
.... Sections (Relative to 0xFFFFF8000261A000): Perm Name
VMA
Size
---- -------- -------------- -------------xr-
.text
0x000000001000 0x00000019b800
xr-
INITKDBG 0x00000019d000 0x000000003a00
xr-
POOLMI
0x0000001a1000 0x000000001c00
.... Data Directories: -
VMA
Size
---------------------------------------- -------------- -------------IMAGE_DIRECTORY_ENTRY_EXPORT
0xfffff80002b43000 0x000000010962
IMAGE_DIRECTORY_ENTRY_IMPORT
0xfffff80002bbccec 0x000000000078
IMAGE_DIRECTORY_ENTRY_RESOURCE
0xfffff80002bbe000 0x000000035d34
...
Other PE Files - Processes In [12]: eprocess = session.profile._EPROCESS(vm=session.kernel_address_space, offset=0x0000fa8000aa0b30) In [5]: eprocess.Peb.ImageBaseAddress Out[5]:
This is the address of a process that comes from pslist
The process Environment Block
In [14]: pe = pe_vtypes.PE(address_space=eprocess.get_process_address_space(), image_base=eproc ImageBaseAddress) In [16]: for section in pe.Sections(): print section ('xr-',
[String:Name]: '.text\x00\x00\x00',
('-r-',
[String:Name]: '.rdata\x00\x00',
('-rw',
[String:Name]: '.data\x00\x00\x00',
('-r-',
[String:Name]: '.pdata\x00\x00',
('-r-',
[String:Name]: '.rsrc\x00\x00\x00',
('-r-',
[String:Name]: '.reloc\x00\x00',
[unsigned long:VirtualAddress]: 0x00001000, The PE file is mapped 33228
into the process address [unsigned long:VirtualAddress]: 0x00052000, 455168)
space [unsigned long:VirtualAddress]: 0x00070000, 46848
[unsigned long:VirtualAddress]: 0x00073000, 499712)
[unsigned long:VirtualAddress]: 0x0007A000, 60211
[unsigned long:VirtualAddress]: 0x00093000, 606208)
DLLs ● The _EPROCESS object has 3 lists of dlls loaded: ○ eprocess.Peb.Ldr.InInitializationOrderModuleList ○ eprocess.Peb.Ldr.InLoadOrderModuleList ○ eprocess.Peb.Ldr.InMemoryOrderModuleList
● Unfortunately these are located in the process address space. ○ A malicious process can easily unlink their dlls from these lists.
Process Loaded DLL lists. In [10]: for x in eprocess.get_load_modules(): print x.FullDllName, hex(x.DllBase) C:\Windows\system32\SearchIndexer.exe 0xff120000 C:\Windows\SYSTEM32\ntdll.dll 0x76d40000 C:\Windows\system32\kernel32.dll 0x76b20000 C:\Windows\system32\KERNELBASE.dll 0x7fefcd50000 C:\Windows\system32\ADVAPI32.dll 0x7fefd110000 In [11]: for x in eprocess.get_init_modules(): print x.FullDllName, hex(x.DllBase) C:\Windows\SYSTEM32\ntdll.dll 0x76d40000 C:\Windows\system32\KERNELBASE.dll 0x7fefcd50000 C:\Windows\system32\kernel32.dll 0x76b20000 In [12]: for x in eprocess.get_mem_modules(): print x.FullDllName, hex(x.DllBase) C:\Windows\system32\SearchIndexer.exe 0xff120000 C:\Windows\SYSTEM32\ntdll.dll 0x76d40000 C:\Windows\system32\kernel32.dll 0x76b20000 C:\Windows\system32\KERNELBASE.dll 0x7fefcd50000
DLLs are PE files too. In [16]: for version in pe.VersionInformation(): print version ( [UnicodeString:Key]: u'CompanyName\x00', Corporation\x00')
[UnicodeString:Value]: u'Microsoft
( [UnicodeString:Key]: u'FileDescription\x00', Natural Language Server Data and Code\x00') ( [UnicodeString:Key]: u'FileVersion\x00', (win7_rtm.090713-1255)\x00') ( [UnicodeString:Key]: u'InternalName\x00',
[UnicodeString:Value]: u'Microsoft English
[UnicodeString:Value]: u'6.1.7600.16385
[UnicodeString:Value]: u'NlsData0009\x00')
Dumping a PE file from memory def WritePEFile(self, fd, address_space, image_base): dos_header = self.pe_profile._IMAGE_DOS_HEADER(offset=image_base, vm=address_space) image_base = dos_header.obj_offset
The PE Image is located in memory.
nt_header = dos_header.NTHeader
# First copy the PE file header, then copy the sections. data = dos_header.obj_vm.zread(image_base, nt_header.OptionalHeader.SizeOfHeaders) fd.seek(0) fd.write(data)
Copy the headers.
for section in nt_header.Sections: data = section.obj_vm.zread(section.VirtualAddress + image_base, section.SizeOfRawData) fd.seek(section.PointerToRawData, 0) fd.write(data)
Copy each section.
PE Dumping from memory ● Can be done using a bunch of plugins: ○ procdump - Dumps _EPROCESS images using PID. ○ dlldump - Dumps DLLs. ○ pedump - Generic PE dumper that is used by the other modules.
● Potential problems: ○ Rootkits can easily change the in-memory PE headers. (e.g. Section description etc). ■ It is possible to corrupt the headers so the tool blows up - too much data, huge executables. ○ Import Address Table is not patched. ○ Not all sections are fully mapped into memory (e.g. . rsrc not always mapped in).
Dumping packed binaries. ● Normal binaries contain two import thunks:
Packed binaries ● Packed binaries have a very small IAT on disk (just enough for the unpacker). ○ The real import table is built in memory ○ but does not contain any function names - only dll 1 function pointers. dll 1 IAT on disk IAT in memory Binary Code Section
export table
code
dll 1 export table
dll 1 code
dll 1 export table
dll 1 code
impscan - Reconstruct IATs 1. Scan all the dlls in the process address space, and enumerate their exports. 2. We disassemble the code segment of the binary, looking for indirect calls through the IAT. 3. Match up these calls with the known dll exports. 4. Create a report or IDAC code to inform IDA about the exports.
Example In [2]: impscan pid=2236 ------> impscan(pid=2236) ************************************************** Process conhost.exe PID 2236 IAT
Call
Module
Function
-------------- -------------- -------------------- -------0x0000ffddf000 0x07fefd7c2520 GDI32.dll
CreateRectRgn
0x0000ffddf018 0x07fefd7c1090 GDI32.dll
DeleteObject
0x0000ffddf030 0x07fefd7c1860 GDI32.dll
SelectObject
0x0000ffddf038 0x07fefd7c6274 GDI32.dll
SelectPalette
0x0000ffddf048 0x07fefd7c222c GDI32.dll
DeleteDC
0x0000ffddf070 0x07fefd7c103c GDI32.dll
GetStockObject
0x0000ffddf078 0x07fefd7c14a0 GDI32.dll
PolyPatBlt
Module 3 Summary ● The PE executable format. ○ Relation between PE in memory and PE on disk. ○ Dumping out PE from memory. ○ Different types of PE files: ■ Processes. ■ DLLs. ■ Kernel Drivers.
Module 4: Memory Management ● The windows kernel Object Manager. ○ ○ ○ ○
Allocation strategy - Pool tags Scanning for objects. Back references to _EPROCESS objects. Scanning vs. List following.
● Process memory management: ○ Page File Number database. ○ VAD tree. ○ Some Malware hiding techniques.
Window Kernel Memory Allocation ● The windows kernel uses Pools to manage allocation: ○ Paged pool - can be paged to disk. ○ Non paged - For use by critical components which must not be paged (e.g. Interrupt level).
● Allocations come from the pool, and are tagged using a special identifier "Tag": ○ ExAllocatePoolWithTag ○ Tags are used to track memory owners and detect leaks.
Poolmon
Windows Kernel Objects ● The windows Object Manager is responsible for managing allocation/deallocation of objects. ○ An object is a managed data structure in the kernel. ○ There are many types of objects - basically anything we require the kernel to manage is an object. ○ Allocation functions end up delegating to ObCreateObject()
Object Allocation Scheme http://www.codemachine.com/article_objectheader.html
Number of optional headers is encoded in the Object Header
Pool Header
Optional Header
Optional Header
Object Header ObCreateObject() Object
The Volatility Scanning framework ● Specify a set of conditions which all have to match. ○ Conditions are tested in order, exit early. ○ Conditions can specify a "skipper" - i.e. can return a number of bytes to skip which can never match.
● The user of the scanner calls the scan() iterator to receive possible matches. ● Some useful scanners: ○ Discontiguous Scanner - can efficiently scan Virtual Address Space. ○ VAD Scanner - used to scan memory accessible to a process.
Discontiguous Scanners. Discontiguous Scanners
Physical Address Space Virtual Address Space
Scanning for Objects class PoolScanDriver(PoolScanFile): """ Scanner for _DRIVER_OBJECT """
Declare header allocation order.
allocation = ['_POOL_HEADER', '_OBJECT_HEADER', '_DRIVER_OBJECT', '_DRIVER_EXTENSION'] checks = [ ('PoolTagCheck', dict(tag = "Dri\xf6")),
Pool Tag
('CheckPoolSize', dict(condition = lambda x: x >= 0xf8)), ('CheckPoolType', dict(paged = True, non_paged = True, free = True)), ('CheckPoolIndex', dict(value = 0)), ]
● We can scan in the physical address space or kernel address space: ○ Physical AS can be fooled by process allocations but is slightly faster. ○ Scanning for kernel objects in kernel address space is sufficient.
Scanning for Objects ● Because the size of the object header is variable we can not just calculate the size directly: ○ Use a bottom up approach: Pool Header Optional Header
Allocation Size
Total Size of Object Optional Headers
Optional Header Object Header
Size of Object Header
Object
Size of Object (e.g. _FILE_OBJECT)
Windows 8 ● The bottom up method does not work on Windows 8: ○ Windows 8 uses a binned memory allocator: ■ Each allocation is rounded up to the next bin size. ■ Can not calculate object size from allocation size. ■ Need to iterate through all possible header configurations. ○ In addition pool tags are not unique enough ■ e.g. for EPROCESS it is "Proc"
● Pool scanning on windows 8 is slower ☹
Object Owners ● When the object manager allocates a kernel object on behalf of a process, sometimes, there is a reference to the _EPROCESS embedded into the _OBJECT_HEADER: ○ object_obj.HandleInfo.SingleEntry.Process http://computer.forensikblog.de/en/2009/04/linking-file-objects-to-processes.html In [4]: vol plugins.filescan, address_space=session.kernel_address_space Offset
#Ptr #Hnd Access Owner
OwnerPid
OwnerName
Name
------------------ ---- ---- ------ ------------------ --------- ---------------- ---0x0000f6fd40004530 15 0 RW-rw- ------------------ --------- ---------------\Users\testing\AppData\Roaming\Microsoft\Windows\Cookies\Low\index.dat 0x0000f6fd40006050 1 1 RW-r-d 0x0000fa80004b09e0 \Windows\System32\wdi\LogFiles\WdiContextLog.etl.001
4 System
0x0000fa8000514dd0 19 1 RW-r-- 0x0000fa80007d09e0 916 svchost.exe \Windows\System32\winevt\Logs\Microsoft-Windows-BranchCacheSMB%4Operational.evtx
Example: psscan vs. pslist $ vol.py --profile WinXPSP2x86 -f malwarecookbook/15/6/prolaco.vmem psscan Offset
Offset(V)
Name
PID
PPID
PDB
Time created
Time exited
---------- ---------- ---------------- ------ ------ ---------- -------------------- -------------------0x005f23a0 0xff0dd3a0 rundll32.exe
1260
1724 0x06cc0360 2010-08-11 16:50:29
0x010f7588 0x80f94588 wuauclt.exe
468
1028 0x06cc0180 2010-08-11 06:09:37
0x01122910 0x80fbf910 svchost.exe
1028
676 0x06cc0120 2010-08-11 06:06:24
0x0113f648 0x80fdc648 1_doc_RCData_61
1336
1136 0x06cc0340 2010-08-11 16:50:20
2010-08-11 16:50:42
$ vol.py --profile WinXPSP2x86 -f malwarecookbook/15/6/prolaco.vmem pslist Offset (V) Name
PID
PPID
Thds
Hnds
Sess
Wow64 Start
Exit
---------- -------------------- ------ ------ ------ -------- ------ ------ -------------------- ---------------0x810b1660 System ....
4
0
56
1136
1724
2
253 ------
False -
-
False 2010-08-11 16:50:19
-
(Not found)
0xff37a4b0 ImmunityDebugge
73
0
The Page Frame Number (PFN) database (Windows). ● The operating system maintains a database about the allocation status of every physical page in the system. ○ Since the page tables exist in the physical address space, but the OS can only reference the Virtual Address space, there must be a way to quickly access the PTEs that control a particular physical page. ○ The hardware can only do the forward mapping (Virtual to Physical). ○ Hence the operating system needs to keep track of the reverse mapping (Physical Page to PTE).
Paging in 32 bit model. Virtual Address Page Directory Index CR3
Page Table Index
Byte Index
Directory Table Base (DTB)
Page Frame
PTN
PTE
Page Directory
PFN DB Maps PFN to PTE
Page Tables
Physical Memory
The PFN Database ● An array of _MMPFN structs, one for every page of physical memory. ○ The PFN database start is referenced by kdbg. MmPfnDatabase. ○ To get the PFN of a physical address we just divide by 0x1000 (i.e. its the page number). ○ Index the array of _MMPFN structs (aka the PFN database) to read the PFN record.
● The PFN record contains important information about the physical page. ○ In use/Valid/Paged ○ Virtual Address of the PTE which controls this page.
Page Frame Number [_MMPFN MmPfnDatabase[200264] ] @ 0xFA800092AD80 0x00 Type
[ValueEnumeration:Type]: 0x00000006 (ActiveAndValid)
0x00 u1
[__unnamed_152d u1] @ 0xFA800092AD80
0x08 u2
[__unnamed_152f u2] @ 0xFA800092AD88
0x10 Lock
Page is valid.
0x10 PteAddress
[long:Lock]: 0x40018718
0x10 PteLong
0x10 VolatilePteAddress
[unsigned long long:PteLong]: 0xFFFFF6FC40018718
u3] @ 0xFA800092AD98 The [__unnamed_1534 PTE UsedPageTableEntries [unsigned short:UsedPageTableEntries]: address in VaType [unsigned Kernel Addresschar:VaType]: 0x00000000 ViewCount [unsigned char:ViewCount]: 0x00000000 Space
0x18 u3 0x1C 0x1E 0x1F
0x20 AweReferenceCount
0x00000000
[long:AweReferenceCount]: 0x00000080
0x20 OriginalPte
[_MMPTE OriginalPte] @ 0xFA800092ADA0
0x28 u4
[__unnamed_153c u4] @ 0xFA800092ADA8
[__unnamed_153c u4] @ 0xFA800092ADA8 0x00 PrototypePte
[BitField:PrototypePte]: 0x00000000
0x00 PteFrame
[BitField:PteFrame]: 0x00019A18
0x00 Unused
[BitField:Unused]: 0x00000000
The physical page containing the PTE.
Physical to Virtual mapping ● Can use the PFN database to map from physical address to virtual address. ○ Find the Virtual PTE address for the physical address. (e.g. 0xF6FC40018718) ○ Find the PteFrame (This is the physical address for the PTE). (e.g. 0x00019A18) ○ PTE Physical address is then 0x00019A18718. ○ Because there is a virtual mapping to the PTE itself, we can repeat the process to find the PTE controlling this PTE (i.e. the PDE). ■ Use the PFN database to locate the PDE, PDPDTE, PML4E and DTB, in turn.
Example In [36]: vtop 0xf880030e3000 -------> vtop(0xf880030e3000) Virtual 0xF880030E3000, Page Directory 0x00187000 pml4e@ 0x00187F88 = 0x2E004863 pdpte@ 0x2E004000 = 0x2E003863 pde@ 0x2E0030C0 = 0x19A18863 pte@ 0x19A18718 = 0x30E48963 PTE mapped@ 0x19A18718 = 0x30E48000
Physical Address In [37]: ptov 0x30E48000 -------> ptov(0x30E48000) Physical Address 0x0000000030E48000 => Virtual Address 0x0000F880030E3000 DTB @ 0x0000000000187000 PML4E @ 0x0000000000187F88 PDPDE @ 0x000000002E004000 PDE @ 0x000000002E0030C0 PTE @ 0x0000000019A18718
DTB for this page is found.
PFN DB is used to connect all the levels.
In [35]: pfn 0x30E48 -------> pfn(0x30E48) PFN 0x00030E48 at kernel address 0x0000FA800092AD80 flink
00000000
blink / share count 0000000000000001
pteaddress (VAS) 0x0000F6FC40018718 reference count 0001
color 0
containing page
0x00019A18
Modified
(Phys AS) 0x0000000019A18718 ActiveAndValid
M
Finding hidden processes using PFN ● Every process has its own address space. ○ Hence every process has its own DTB. ○ Perform the physical to virtual mapping of all the physical pages, and find all the DTBs. ○ Compare to the DTBs of known processes.
● This is actually very hard for a rootkit to hide.
Finding hidden processes using PFN $ python vol.py -f ~/images/win7_trial_64bit.dmp --profile=Win7SP0x64 dtbscan DTB
_EPROCESS
Image Name
-------------- -------------- ---------0x000000187000 0xfa800096a9e0 System 0x00001f915000 0xfa8001d4b630 svchost.exe 0x0000209de000 0xfa8000bbdb30
�&�.exe
0x00001b2c8000 0xfa8001ea5b30 spoolsv.exe 0x0000211a4000 0xfa8001dbfb30 svchost.exe 0x00002ceb9000 0xfa8000a2d060 svchost.exe 0x00002178b000 0xfa8001db5b30 svchost.exe 0x000022e75000 0xfa8000bbd060 conhost.exe 0x000022192000 0xfa8001d03ac0 lsm.exe 0x000019295000 0xfa80020bfb30 sppsvc.exe 0x00001d3a2000 0xfa8001fd9890 svchost.exe 0x00002573b000 0xfa8001974630 winlogon.exe -0x00000001000 -------------- Process not Found! 0x000021533000 0xfa8001e905b0 svchost.exe 0x00001d5c7000 0xfa8001dd7800 explorer.exe .....
Process Memory management - The Vad Tree. ● Windows manages process memory through 2 mechanisms: ○ Ultimately pages are assigned through the page tables and the PFN database. ○ The Virtual Memory Address Descriptors (VAD) maintain a high level overview of the pages assigned to a process. ○ A binary tree in memory of virtual memory assigned to a process. ○ The kernel uses the VAD tree to manage the page tables for this process.
The VAD tree: A process-eye view of physical memory - Brendan Dolan-Gavitt digitalinvestigation 4S (2007) S62–S64
Inspecting the VAD In [2]: vad pid=4012 ------> vad(pid=4012) Pid: 4012 dd.exe VAD
lev
start
end
com -
-
Protect
Filename
---------- --- ---------- ---------- ---- ------- ------ -------------------- -------0x81edc7e0
0
0x30
0x12f
3 Private
READWRITE
0x8220fad0
1
0x10
0x10
1 Private
READWRITE
0x81ff0398
2
0x20
0x20
1 Private
READWRITE
0x820ee328
1
0x400
0x40d
2 Mapped
0x82068e78
2
0x140
0x23f
12 Private
0x81f1b548
3
0x130
0x132
0 Mapped
READONLY
0x81f338b0
3
0x250
0x25f
0 Mapped
READWRITE
0x81ffa408
4
0x240
0x24f
6 Private
READWRITE
0x81eef6d8
6
0x2c0
0x300
0 Mapped
READONLY
0xff94a1d0
6
0x330
0x332
0 Mapped
READONLY
0x8220e848
7
0x320
0x32f
8 Private
READWRITE
0x8136f140
10
0x37f
0x37f
0 Mapped
READONLY
0x82216830
2
0x7c900
0x7c9af
5 Mapped
Exe
EXECUTE_WRITECOPY
\WINDOWS\system32\ntdll.dll
0x820c9308
3
0x7c800
0x7c8f3
5 Mapped
Exe
EXECUTE_WRITECOPY
\WINDOWS\system32\kernel32.dll
0x81f16390
4
0x10000
0x10005
2 Mapped
Exe
EXECUTE_WRITECOPY
\dd\UnicodeRelease\getopt.dll
Exe
EXECUTE_WRITECOPY
\dd\UnicodeRelease\dd.exe
READWRITE
Mapped DLLs are shared between \WINDOWS\system32\sortkey.nls \WINDOWS\system32\ctype.nls processes.
vadinfo $ vol.py -f xp-laptop-2005-06-25.img --profile WinXPSP2x86 --pid 4012 vadinfo .... VAD node @ 0x820c9308 Start 0x7c800000 End 0x7c8f3fff Tag Vad Flags: CommitCharge: 5, ImageMap: 1, Protection: 7 Protection: PAGE_EXECUTE_WRITECOPY ControlArea @820e24b8 Segment e165b3d8 Dereference list: Flink 00000000, Blink 00000000 NumberOfSectionReferences:
119
41 NumberOfUserReferences:
42
NumberOfMappedViews:
1 NumberOfPfnReferences:
WaitingForDeletion Event:
00000000
Control Flags: Accessed: 1, File: 1, HadUserReference: 1, Image: 1 FileObject @821745e0 FileBuffer @ e17c2460
, Name: \WINDOWS\system32\kernel32.dll
First prototype PTE: e165b410 Last contiguous PTE: fffffffc Flags2: Inherit: 1
Using the VAD to find hidden files. $ vol.py --profile WinXPSP2x86 -f malwarecookbook/15/6/prolaco.vmem Welcome to the volatility interactive shell! In [1]: psscan Offset
Offset(V)
Name
PID
PPID
PDB
Time created
Time exited
---------- ---------- ---------------- ------ ------ ---------- -------------------- -------------------0x005f23a0This 0xff0dd3a0 rundll32.exe is the hidden
1260
1724 0x06cc0360 2010-08-11 16:50:29
0x010f7588process. 0x80f94588 wuauclt.exe
468
1028 0x06cc0180 2010-08-11 06:09:37
0x01122910 0x80fbf910 svchost.exe
1028
676 0x06cc0120 2010-08-11 06:06:24
0x0113f648 0x80fdc648 1_doc_RCData_61
1336
1136 0x06cc0340 2010-08-11 16:50:20
2010-08-11 16:50:42
... In [2]: vad eprocess=0x80fdc648 Pid: 1336 1_doc_RCData_61 VAD
lev
start
end
com -
-
Protect
Filename
---------- --- ---------- ---------- ---- ------- ------ -------------------- --------
The original
0xff1418a8 0 0x400 0x454 48 Mapped Exe EXECUTE_WRITECOPY Executable location. Settings\Administrator\Desktop\1_doc_RCData_612.exe 0x80fddab0
1
0x10
0x10
1 Private
READWRITE
0xff277bc8
2
0x20
0x20
1 Private
READWRITE
0xff083310
3
0x30
0x22f
4 Private
READWRITE
0xff149fa8
4
0x230
0x232
0 Mapped
READONLY
\Documents and
Using the vad to double check loaded dlls. ● As we mentioned previously there are 3 lists of loaded dlls in the Peb: ○ In loaded order. ○ In Init order. ○ In Memory order.
● Malware can easily unlink a module from these lists, but its harder to manipulate the VAD.
How can we get an executable area without being in the module lists and not having file mapping?
The ldrmodules plugin.
$ vol.py --profile WinXPSP2x86 -f malwarecookbook/stuxnet.vmem --pid 680 --verbose ldrmodules Pid
Process
Base
InLoad InInit InMem MappedPath
-------- -------------------- ---------- ------ ------ ----- ---------1928
lsass.exe
0x00080000
False
False False -
1928
lsass.exe
0x7c900000
True
True
True
\WINDOWS\system32\ntdll.dll
1928
lsass.exe
0x77c00000
True
True
True
\WINDOWS\system32\version.dll
1928
lsass.exe
0x01000000
True
False True
-
1928
lsass.exe
0x5b860000
True
True
True
\WINDOWS\system32\netapi32.dll
1928
lsass.exe
0x76bf0000
True
True
True
\WINDOWS\system32\psapi.dll
1928
lsass.exe
0x77c10000
True
True
True
\WINDOWS\system32\msvcrt.dll
1928
lsass.exe
0x77dd0000
True
True
True
\WINDOWS\system32\advapi32.dll
1928
lsass.exe
0x7c9c0000
True
True
True
\WINDOWS\system32\shell32.dll
1928
lsass.exe
0x00870000
True
True
True
-
1928
lsass.exe
0x76f20000
True
True
True
\WINDOWS\system32\dnsapi.dll
1928
lsass.exe
0x5d090000
True
True
True
\WINDOWS\system32\comctl32.dll
1928
lsass.exe
0x71aa0000
True
True
True
\WINDOWS\system32\ws2help.dll
1928
lsass.exe
0x77b20000
True
True
True
\WINDOWS\system32\msasn1.dll
Process Hollowing ● Malware can attempt to hide by using process hollowing: 1. Create a new process using a legitimate executable, but do not start it. 2. Free the memory section that contains the ImageBase from the executable. 3. Allocate a new memory region in the new process, and copy malicious code into it. a. VirtualAllocEx, WriteProcessMemory
4. Resume the start thread from the new executable.
Malware Analyst's Cookbook - Michael Hale Ligh, Steven Adair, Blake Hartstein, Matthew Richard
How does that look in memory? $ vol.py --profile WinXPSP2x86 -f malwarecookbook/stuxnet.vmem In [1]: pslist pid=868 Offset (V) Name
PID
PPID
Thds
Hnds
Sess
Wow64 Start
Exit
---------- -------------------- ------ ------ ------ -------- ------ ------ -------------------- -----0x81c498c8 lsass.exe
868
668
2
23
0
False 2011-06-03 04:26:55
-
In [3]: vad eprocess=0x81c498c8 Pid: 868 lsass.exe VAD
lev
start
end
com -
-
Protect
Filename
---------- --- ---------- ---------- ---- ------- ------ -------------------- -------0x81f459d0
0
0x210
0x21f
0 Mapped
READWRITE
0x822e7e70
1
0x80
0xf9
0 Mapped
0x81fc8520
2
0x10
0x10
1 Private
0x8209b818
3
0x200
0x20f
0x8209c3d0
1
0x7c900
0x7c9ae
0x81f1ef08
2
0x1000
0x1005
0x81fa64b0
3
0x240
0x280
0 Mapped
READONLY
\WINDOWS\system32\locale.
0x81c970a8
4
0x220
0x235
0 Mapped
READONLY
\WINDOWS\system32\unicod
Exe
EXECUTE_READWRITE READWRITE
...
Executable 6 Private memory READWRITE which is not backed 5 Mapped Exe EXECUTE_WRITECOPY by a file???? 2 Mapped Exe EXECUTE_READWRITE
\WINDOWS\system32\ntdll.d
In [7]: task = session.profile._EPROCESS(vm=session.kernel_address_space, offset=0x81c498c8) In [8]: dump task.get_process_address_space(), 0x80000 ------> dump(task.get_process_address_space(), 0x80000) 0x00080000
4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00
MZ..............
0x00080010
b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00
........@.......
0x00080020
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
................
0x00080030
00 00 00 00 00 00 00 00 00 00 00 00 08 01 00 00
................
0x00080040
0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68
........!..L.!Th
0x00080050
69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f
is.program.canno
0x00080060
74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20
t.be.run.in.DOS.
0x00080070
6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00
mode....$.......
0x00080080
c7 1c 48 b9 83 7d 26 ea 83 7d 26 ea 83 7d 26 ea
..H..}&..}&..}&.
0x00080090
a4 bb 4b ea 81 7d 26 ea 9d 2f a2 ea 88 7d 26 ea
..K..}&../...}&.
Module 4: Summary ● Scanning for objects in kernel memory. ○ Discontiguous scanners.
● Examining the PFN database ○ dtbscan ○ physical to virtual mapping.
● The VAD tree ○ Finding evidence of VirtualAllocEx and WritePrecessMemory. ○ Dll injections, process hollowing.
Module 5: Hooking ● Hooking means to change the flow control of execution to take control of certain code paths. ○ Malware uses hooking to monitor and filter various operations. ○ e.g. File operations can be subverted to prevent security software from seeing malware specific files. ○ HTTP traffic can be intercepted even prior to encryption - used for credential stealing etc.
● Security software has similar goals - hence many security applications also hook.
Kernel hooking - ssdt ● The system dispatcher table is used to control what driver can service requests from userspace. ○ Not really useful on new versions of windows due to patchguard.
● ssdt plugin: Entry 0x0073: 0x8060bc6c (NtOpenEventPair) owned by ntoskrnl.exe Entry 0x0074: 0x8056e26a (NtOpenFile) owned by ntoskrnl.exe Entry 0x0075: 0x8056bab6 (NtOpenIoCompletion) owned by ntoskrnl.exe Entry 0x0076: 0x805ca2ac (NtOpenJobObject) owned by ntoskrnl.exe Entry 0x0077: 0x80619f68 (NtOpenKey) owned by ntoskrnl.exe Entry 0x0078: 0x8060c064 (NtOpenMutant) owned by ntoskrnl.exe Entry 0x0079: 0x805e8fcc (NtOpenObjectAuditAlarm) owned by ntoskrnl.exe Entry 0x007a: 0xfca2953e (NtOpenProcess) owned by lanmandrv.sys Entry 0x007b: 0x805e229e (NtOpenProcessToken) owned by ntoskrnl.exe Entry 0x007c: 0x805e1ea4 (NtOpenProcessTokenEx) owned by ntoskrnl.exe
Kernel hooking - Drivers. ● In windows IO operations on a device are sent to a driver in an IO Request Packet (IRP): ○ The IRP contains the data for the IO operation as well as a completion routine. ○ The user space program is free to continue with other tasks while waiting for the IO. ○ The IRP is sent to the driver, and is services asyncronously.
● There are several types of IRPs - each type is handled by a different dispatch routing in the driver.
Kernel hooking - Drivers.
Scan for drivers in the kernel address space.
● The windows _DRIVER_OBJECT: In [10]: driverscan address_space=session.kernel_address_space Offset(P)
#Ptr #Hnd
Start
Size
Service Key
Name
Driver Name
---------- ---- ---- ---------- ---------- -------------------- ------------ ----------0x81e97b28
3
Instantiate 0 0xf8711000
a 0x8900 _DRIVER_OBJECT at Gpc this address.0x10e00 PSched 0xf819f000
Gpc
\Driver\Gpc
0x81e97f38
7
0
PSched
\Driver\PSched
0x81f7dda0
3
0 0xf88f9000
Msfs
\FileSystem\Msfs
0x4a80 Msfs
In [11]: d = session.profile._DRIVER_OBJECT(0x81f7dda0) In [12]: p d [_DRIVER_OBJECT _DRIVER_OBJECT] @ 0x81F7DDA0 0x1C DriverName
[_UNICODE_STRING DriverName] @ 0x81F7DDBC
0x38 MajorFunction
In [13]: p d.MajorFunction 0x0000 0x0002 0x0003 0x0004
Each element of this array points to a different function.
Kernel hooking - Drivers. ● When an IO Request Packet (IRP) is created by the kernel for this device, the kernel uses the MajorFunction table to pass the IRP to the driver for processing. ● A couple of ways for subversion ○ Malware can install their own handler for this device so it legitimately receives the IRP for processing (layered model). ○ A malicious driver can insert a detour in another driver to intercept IRPs intended for the legitimate driver.
IRP IRP
IRP
Malicious Driver Malicious Driver
Driver 1
Driver 1
Driver 1 Driver 2
Driver 2 Driver 2
Driver 3
Driver 3 Driver 3
Normal handling of IRP
Attaching to device as a filter driver.
Detour hooking through the Major Function Table
Kernel hooking - driverirp ● driverirp scans for drivers and enumerates their major functions. These functions are then located in their respective driver. In [15]: driverirp .... ************************************************** DriverName: Teefer DriverStart: 0xf837d000 DriverSize: 0x1d000
This driver only handles some IRPs
DriverStartIo: 0x0 Func Name
Func Addr
Module
---- ------------------------------------ ---------- -----------------------------0 IRP_MJ_CREATE
0xf83852c0 Teefer.sys
1 IRP_MJ_CREATE_NAMED_PIPE
0x805031be \WINDOWS\system32\ntoskrnl.exe
2 IRP_MJ_CLOSE
0xf8385380 Teefer.sys
3 IRP_MJ_READ
0xf8386e40 Teefer.sys
4 IRP_MJ_WRITE
0xf8386e10 Teefer.sys
5 IRP_MJ_QUERY_INFORMATION
0x805031be \WINDOWS\system32\ntoskrnl.exe
6 IRP_MJ_SET_INFORMATION
0x805031be \WINDOWS\system32\ntoskrnl.exe
Usermode hooks ● Malware can intercept functions used by user mode programs. Malware Code dll 1 code Legitimate process IAT in memory
Malware Code
Binary Code Section dll 1 code
Detour/ Trampoline
FinFisher - A commercial rootkit. https://citizenlab. org/2012/07/from-bahrainwith-love-finfishers-spy-kitexposed/
Trampoline hook installed
https://citizenlab.org/wp-content/uploads/2012/07/image29-500.png
Hijack code is located in an injected memory region
Registry Dumping ● The windows registry is a central location for configuration data. ○ A rich source of evidence in a digital investigation. ○ There are many tools that can analyse registry files.
● The registry is cached in memory ○ Registry data is stored in hives. ○ Hives are divided into HBins. ○ HBins are cached in memory.
● Volatility has a full registry parser and a bunch of modules to deal with registry. Forensic Analysis of the Windows Registry in Memory. - Brendan Dolan-Gavitt. DFRWS 2008
Registry in Memory _CMHIVE: System
_CMHIVE: Software
Linked list
Hive.Storage.Map[].Directory[].Table[].BlockAddress
HBIN
HBIN
HBIN
Not resident
Structure is very similar to a page table which refers to HBINS. If a HBIN is not frequently used it will be paged out (i.e. not memory resident). When a program attempts to read a key which is contained in this HBIN - the HBIN will be paged into memory.
Registry in Memory In [5]: hivescan ------> hivescan() Offset(V)
Offset(P)
Name
0xe102e008 0x02837008 [no name] @ 0xe102e008 0xe1035b60 0x0283db60 \Device\HarddiskVolume1\WINDOWS\system32\config\system @ 0xe1035b60 0xe1558578 0x02d63578 [no name] @ 0xe1558578 ..... In [9]: printkey key="Software" Legend: (S) = Stable
(V) = Volatile
---------------------------Registry: \Device\HarddiskVolume1\Documents and Settings\NetworkService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat @ 0xe1bf1b60 Key name: Software (S) Last updated: 2005-03-18 21:42:02 Subkeys: (S) Microsoft ....
Registry analysis from memory. ● There are some excellent forensic tools for registry analysis: ○ Regripper ○ Registry Decoder ○ Encase/FTK and other commercial tools
● But these tools typically only work with registry files... ○ So we need to dump out the registry into files.
Dumping out the registry In [11]: regdump? regdump: Dump all registry hives into a dump directory. Parameter
Documentation
------------------------------ ----------------------------------------------------hive_offset
A list of hive offsets as found by hivelist (virtual address). If not provided we call hivescan ourselves and dump all hives found.
dump_dir
Directory in which to dump hive files.
In [12]: regdump dump_dir="/tmp/" ************************************************** Dumping \Device\HarddiskVolume1\WINDOWS\system32\config\system @ 0xe1035b60 into "/tmp/system @ 0xe1035b60" Dumped 5312512 bytes ************************************************** Dumping \Device\HarddiskVolume1\Documents and Settings\Sarah\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat @ 0xe1ecd008 into "/tmp/UsrClass_dat @ 0xe1ecd008" Dumped 8192 bytes
Domain Specific Profiles ● Memory analysis of modules other than the kernel. ○ Usually we do not have symbols for applications. ○ We often need different profiles for applications than the kernel.
● Still a lot of research to do in this area.
Example: svcscan ● Windows drivers are loaded through the service control manager (SCM). ○ The SCM is a process (services.exe) which keeps additional accounting on which services are currently registered. ○ The process memory can be analysed. ○ We can carve the process memory for tag signatures of _SERVICE_RECORD objects. ■ Use the VadScanner to only look at the process memory. ○ A malicious kernel driver may remove itself from the module list but will remain in the SCM internal lists.
svcscan In [14]: svcscan Offset: 0x6e1e90 Order: 1 Process ID: Service Name: Abiosdsk Display Name: Abiosdsk Service Type: SERVICE_KERNEL_DRIVER Service State: SERVICE_STOPPED Binary Path: Offset: 0x6e1f20 Order: 2 Process ID: Service Name: abp480n5 Display Name: abp480n5 Service Type: SERVICE_KERNEL_DRIVER Service State: SERVICE_STOPPED Binary Path: -
Netscan - tcpip.sys ● The windows TCP/IP stack is implemented by tcpip.sys ○ No public symbols available. ○ However... Reverse engineering shows basic structures: ■ _TCP_ENDPOINT ■ _UDP_ENDPOINT ■ _TCP_LISTENER ○ These have well recognized pool tags. ○ We can scan for these but structs must be reversed for each version of windows. ○ Information is mostly private to the tcpip.sys module.
Windows 7: netscan In [7]: netscan Offset(P)
Proto
Local Address
Remote Address
State
Pid Owner
Created
-------------- -------- -------------------- -------------------- ---------------- ----- -------------- ------0x00000f882a30 TCPv4
0.0.0.0:135
0.0.0.0:0
LISTENING
628 svchost.exe
-
0x00001121b7b0 TCPv6
:::135
:::0
LISTENING
628 svchost.exe
-
0x000017de8980 TCPv4
0.0.0.0:49153
0.0.0.0:0
LISTENING
444 lsass.exe
-
0x000017de8980 TCPv6
:::49153
:::0
LISTENING
444 lsass.exe
-
0x000017f35240 TCPv4
0.0.0.0:49155
0.0.0.0:0
LISTENING
880 svchost.exe
-
0x000017f362b0 TCPv4
0.0.0.0:49155
0.0.0.0:0
LISTENING
880 svchost.exe
-
0x000017f362b0 TCPv6
:::49155
:::0
LISTENING
880 svchost.exe
-
0x00001725d010 TCPv4
:49359
93.184.220.20:80
CLOSED
2820 iexplore.exe
-
0x000017270530 TCPv4
10.0.2.15:49363
173.194.35.38:80
ESTABLISHED
2820 iexplore.exe
-
0x000017285010 TCPv4
:49341
82.165.218.111:80
CLOSED
2820 iexplore.exe
-
0x000017288a90 TCPv4
10.0.2.15:49254
74.125.31.157:80
CLOSE_WAIT
2820 iexplore.exe
-
0x00001728f6b0 TCPv4
10.0.2.15:49171
204.245.34.130:80
ESTABLISHED
2820 iexplore.exe
-
0x000017291ba0 TCPv4
10.0.2.15:49347
173.194.35.36:80
CLOSE_WAIT
2820 iexplore.exe
-
0x000017292cf0 TCPv4
:49369
82.165.218.111:80
CLOSED
1892 iexplore.exe
-
0x0000174e2cf0 TCPv4
:49368
82.165.218.111:80
CLOSED
2820 iexplore.exe
-
0x0000174f9440 TCPv4
10.0.2.15:49296
74.125.127.148:80
CLOSE_WAIT
2820 iexplore.exe
-
0x000017527cf0 TCPv4
:49358
93.184.220.20:80
CLOSED
2820 iexplore.exe
-
0x0000175288b0 TCPv4
:49373
82.165.218.111:80
CLOSED
2820 iexplore.exe
Windows XP: connections and sockets In [3]: connections Offset (V) Local Address
Remote Address
Pid
---------- ------------------------- ------------------------- -----0x820869b0 127.0.0.1:1055
127.0.0.1:1056
2160
0xffa2baf0 127.0.0.1:1056
127.0.0.1:1055
2160
0x8220c008 192.168.2.7:1077
64.62.243.144:80
2392
0x81f11e70 192.168.2.7:1082
205.161.7.134:80
2392
0x8220d6b8 192.168.2.7:1066
199.239.137.200:80
2392
In [4]: sockets Offset (V)
PID
Port
Proto Protocol
Address
Create Time
---------- ------ ------ ------ --------------- --------------- ----------0x82004e98
984
1027
17 UDP
0.0.0.0
2005-06-25 16:48:02
0x82052e98
4
138
17 UDP
192.168.2.7
2005-06-25 16:47:48
0x821cad08
1400
19
17 UDP
0.0.0.0
2005-06-25 16:48:00
0x81341308
4
0
47 GRE
0.0.0.0
2005-06-25 16:48:13
0x82036008
1948
1030
6 TCP
0.0.0.0
2005-06-25 16:48:05
0x81fdf968
592
500
17 UDP
0.0.0.0
2005-06-25 16:47:59
Summary for Module 5 - Detecting malware. ● Kernel Hooking ● Userspace Hooking ● Domain specific profiles: ○ Registry Dumping ○ Service Control Manager ○ Network connections.
View more...
Comments