Memory Forensics With Volatility

February 23, 2017 | Author: scudette | Category: N/A
Share Embed Donate


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

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF