
    XfM                     ^   d Z ddlZddlZddlZddlZddlmZmZmZm	Z	m
Z
mZmZmZmZ ddlmZmZmZmZ ddlmZ ddlmZmZ ddlmZ ddlmZ ed	k    r~ddlZej                             ej        !                    ej        !                    ej        !                    ej        !                    e"                                                    ej#        e          Z$ee%e&ee%eee'e%e&f                  f         f         Z(e	ee%ef                  Z) G d
 dej*        j+                  Z,dS )aY  A module for scanning translation layers looking for Windows PDB records
from loaded PE files.

This module contains a standalone scanner, and also a :class:`~volatility3.framework.interfaces.layers.ScannerInterface`
based scanner for use within the framework by calling :func:`~volatility3.framework.interfaces.layers.DataLayerInterface.scan`.
    N)	AnyCallableDictIterableListOptionalSetTupleUnion)	constants
exceptions
interfaceslayers)requirements)intelscanners)native)
PDBUtility__main__c                      e Zd ZdZdZdZddgZdej        j	        de
dej        j        d	ee
         fd
Z	 d$dej        j	        dedej        d	dfdZdej        j	        ded	dfdZd Z	 d$dej        j	        dej        j        dej        d	ee         fdZ	 d$dej        j	        dej        j        dej        d	ee         fdZ	 	 	 d%dej        j	        dej        j        dedededej        d	ee         fdZ	 d$dej        j	        dej        j        dededej        d	ee         fdZ 	 d$dej        j	        dej        j        dej        d	ee         fdZ!	 d$dej        j	        dej        j        dej        d	ee         fdZ"	 d$dej        j	        dej        j        dedej        d	ee         f
d Z#e"e!eegZ$	 d$dej        j	        d!ee
         dej        d	ee         fd"Z%	 d$dej        j	        de
dej        j        dej        d	df
d#Z&dS )&KernelPDBScannerar  Windows symbol loader based on PDB signatures.

    An Automagic object that looks for all Intel translation layers and scans each of them for a pdb signature.
    When found, a search for a corresponding Intermediate Format data file is carried out and if found an appropriate
    symbol space is automatically loaded.

    Once a specific kernel PDB signature has been found, a virtual address for the loaded kernel is determined
    by one of two methods.  The first method assumes a specific mapping from the kernel's physical address to its
    virtual address (typically the kernel is loaded at its physical location plus a specific offset).  The second method
    searches for a particular structure that lists the kernel module's virtual address, its size (not checked) and the
    module's name.  This value is then used if one was not found using the previous method.
       i  @ linuxmaccontextconfig_pathrequirementreturnc                    t           j                            ||j                  }g }t	          |t
          j                  r|j                            |d          }|j                            t           j                            |d          d          }|r,|r*|j	        |         }t	          |t          j                  r|g}n6|j                                        D ]}	||                     |||	          z  }|S )aQ  Traverses the requirement tree, rooted at `requirement` looking for
        virtual layers that might contain a windows PDB.

        Returns a list of possible layers

        Args:
            context: The context in which the `requirement` lives
            config_path: The path within the `context` for the `requirement`'s configuration variables
            requirement: The root of the requirement tree to search for :class:~`volatility3.framework.interfaces.layers.TranslationLayerRequirement` objects to scan

        Returns:
            A list of (layer_name, scan_results)
        Nmemory_layer)r   configuration	path_joinname
isinstancer   TranslationLayerRequirementconfiggetr   r   Intelvaluesfind_virtual_layers_from_req)
selfr   r   r   sub_config_pathresultsvirtual_layer_name
layer_namememlayersubreqs
             Y/home/panchajanya/Development/work/volatility3/volatility3/framework/automagic/pdbscan.pyr*   z-KernelPDBScanner.find_virtual_layers_from_req5   s   & %2<<)
 
  k<#KLL 	 ")!3!3OT!J!J ++(22?NSS J  30 3">*<=h44 312G%299;;  4<<_f       Nvalid_kernelprogress_callbackc           
      J   | j         D ]\  }}|ry|\  }}}t          |d         t                    rt          |d         t                    st          d          t	          j        ||d         |d         |d         d||           t                              d           dS )	a  Fulfills the SymbolTableRequirements in `self._symbol_requirements`
        found by the `recurse_symbol_requirements`.

        This pass will construct any requirements that may need it in the context it was passed

        Args:
            context: Context on which to operate
            valid_kernel: A list of offsets where valid kernels have been found
            progress_callback: Means of providing the user with feedback during long processes
        pdb_nameGUIDz#PDB name or GUID not a string valueagezBvolatility3.framework.symbols.windows.WindowsKernelIntermedSymbols)r   guidr9   r7   symbol_table_classr   r5   z&No suitable kernel pdb signature foundN)_symbol_requirementsr$   str	TypeErrorr   load_windows_symbol_tablevollogdebug)	r+   r   r4   r5   r,   r   virtual_layer_kvokernels	            r2   recurse_symbol_fulfillerz)KernelPDBScanner.recurse_symbol_fulfiller`   s      -1,E 	G 	G(O[  G.:+tV!&"4c:: K*6NCC C K $$IJJJ4#u#J/'k /&7     EFFFF+	G 	Gr3   c                     |rn|\  }}}|ht           j                            |j        |         j        d          }||j        |<   t                              dt          |                      dS dS dS )aX  Traverses the requirement tree, looking for kernel_virtual_offset
        values that may need setting and sets it based on the previously
        identified `valid_kernel`.

        Args:
            context: Context on which to operate and provide the kernel virtual offset
            valid_kernel: List of valid kernels and offsets
        Nkernel_virtual_offsetz!Setting kernel_virtual_offset to )	r   r!   r"   r   r   r&   r@   rA   hex)r+   r   r4   rB   kvorD   kvo_paths          r2   set_kernel_virtual_offsetz*KernelPDBScanner.set_kernel_virtual_offset   s      	M)5&M3%3==N=1=?V  ,/x(KSKKLLLLL	M 	M r3   c                 ~    |j                             t          j                            |j        d          d           S )Nr    )r&   r'   r   r!   r"   r   )r+   r   vlayers      r2   get_physical_layer_namez(KernelPDBScanner.get_physical_layer_name   s8    ~!!$..v/A>RRTX
 
 	
r3   rM   c                 F   dt           dt          t           t          f         dt          t                   fd}t
                              d           |                     |||dd|          }||S t
                              d           |                     |||dd|          S )	Nr.   rD   r   c                 b    |d         t          |d         t                    sd S ||d         |fS )N	mz_offset)r$   int)physical_layer_namer.   rD   s      r2   test_virtual_kernelz>KernelPDBScanner.method_slow_scan.<locals>.test_virtual_kernel   s;     k"**VK=PRU2V2V*t&{(;VDDr3   z8Kernel base determination - optimized scan virtual layerTFz3Kernel base determination - slow scan virtual layerr=   r   r   r   ValidKernelTyper@   rA   _method_layer_pdb_scan)r+   r   rM   r5   rT   r4   s         r2   method_slow_scanz!KernelPDBScanner.method_slow_scan   s    	E58	EBFsCx.	Eo&	E 	E 	E 	E 	OPPP22V0$?P
 
 #JKKK**V0%@Q
 
 	
r3   c           	          dt           dt           dt          t           t          f         dt          t                   ffd}t
                              d           |                     ||dd|          S )	NrS   r.   rD   r   c           
          d         t          d         t                    sd S j        dk    rKd         dt          t          j        t          j        j        dz                       dz
            z  z   }nd         dj        dz
  z  z   }	                     |d          }t           fd|D                       r||fS t          
                    d                    t          |                               n?# t          j        $ r- t          
                    d	t          |                      Y nw xY wd S )
NrQ   @            r   c                 @    g | ]\  }}}}}|d          k    o|k    S )rQ    ).0_pr/   rD   rS   s       r2   
<listcomp>zWKernelPDBScanner.method_fixed_mapping.<locals>.test_physical_kernel.<locals>.<listcomp>   sH       4Q1a f[11WjDW6W  r3   zDPotential kernel_virtual_offset did not map to expected location: {}z5Potential kernel_virtual_offset caused a page fault: )r$   rR   bits_per_registermathceillog2maximum_addressmappinganyr@   rA   formatrH   r   InvalidAddressException)rS   r.   rD   rI   kvprM   s   ` `  r2   test_physical_kernelzCKernelPDBScanner.method_fixed_mapping.<locals>.test_physical_kernel   s    k"**VK=PRU2V2V*t'2--[)#di	&2H12L(M(MNNQRRSSS [)Q63Ka3O-PQnnS!,,    8;     /V<<LL^eeHH    
 5   VCPSHHVV     4s   6D :D 9EEz6Kernel base determination - testing fixed base addressFTrU   )r+   r   rM   r5   ro   s     `  r2   method_fixed_mappingz%KernelPDBScanner.method_fixed_mapping   s     	!$ 	:= 	GKCQTH~ 	o& 	  	  	  	  	  	D 	MNNN**V15$@Q
 
 	
r3   FTtest_kernel	optimizedphysicalc                 2   d }|j         }|                     ||          }	|	}
|s|}
d}|r|s|j        |
         j        j        dv rd}d t
          j        j        D             }t          j	        ||
||j
        ||          }|D ]} ||	||          }| n|S )Nr   )Intel64l        ` c                 4    g | ]}t          |d z   d          S z.pdbzutf-8bytesra   r#   s     r2   rd   z;KernelPDBScanner._method_layer_pdb_scan.<locals>.<listcomp>  6     
 
 
 $-))
 
 
r3   )ctxr/   start	page_size	pdb_namesr5   )r#   rN   r   metadataarchitecturer   windowsKERNEL_MODULE_NAMESr   pdbname_scanr~   )r+   r   rM   rq   rr   rs   r5   r4   r.   rS   layer_to_scanstart_scan_addresskernel_pdb_nameskernelsrD   s                  r2   rW   z'KernelPDBScanner._method_layer_pdb_scan   s    #["::7FKK+ 	/.M	-	- }-6C{RR "-
 
!)=
 
 
 )$$&&/
 
 
  	 	F&;':<NPVWWL' (r3   patternresult_offsetc                    t                               d           d}|                     ||          }|j        |         }|                    |t          j        |          |          }	t                      }
|	D ]]}|                    d||z   |          }||j	        z  }||
v r,|

                    |           |                     ||||          }|r n^|S )zLMethod for finding a suitable kernel offset based on a module
        table.zAKernel base determination - searching layer module list structureN)r5   zpdbscan!unsigned long long)offsetr/   )r@   rA   rN   r   scanr   BytesScannersetobjectaddress_maskaddcheck_kernel_offset)r+   r   rM   r   r   r5   r4   rS   physical_layerr-   seenresultpointeraddresss                 r2   _method_offsetzKernelPDBScanner._method_offset  s    	O	
 	
 	
 37"::7FKK (;< %%X*733GX & 
 
  	 	Fnn,.. %  G
  33G$HHW33*; L  r3   c           
      d    |                      ||ddt          |j        dz            z
  |          S )Ns   \SystemRoot\system32\nti   )r   rR   re   r+   r   rM   r5   s       r2   method_module_offsetz%KernelPDBScanner.method_module_offsetC  s@     "")#f.2333
 
 	
r3   c                 4    |                      ||dd|          S )Ns   KDBGr   )r   r   s       r2   method_kdbg_offsetz#KernelPDBScanner.method_kdbg_offsetQ  s!     ""7FGQ@QRRRr3   r   c                 |   d}d t           j        j        D             }|j        }t	          j        t          j                  5  |                    |d          dk    rGt          t          j        ||j        |j        ||||| j        z                       }|r|||d         f}ddd           n# 1 swxY w Y   |S )zScans a virtual address.Nc                 4    g | ]}t          |d z   d          S rw   rx   rz   s     r2   rd   z8KernelPDBScanner.check_kernel_offset.<locals>.<listcomp>d  r{   r3      s   MZ)r|   r/   r~   r   r5   r}   endr   )r   r   r   r#   
contextlibsuppressr   rm   readlistr   r   r~   max_pdb_size)	r+   r   rM   r   r5   r4   r   r.   ress	            r2   r   z$KernelPDBScanner.check_kernel_offsetY  s4    37
 
!)=
 
 

 $[ !CDD 	I 	I{{7C((E11+##);"("2"2*;%#d&77  
 
  I$6Q#HL	I 	I 	I 	I 	I 	I 	I 	I 	I 	I 	I 	I 	I 	I 	I s   A"B11B58B5potential_layersc                     d}|D ]X}|j                             |d          }t          |t           j        j                  r| j        D ]} || |||          }|r nY|st                              d           |S )aa  Runs through the identified potential kernels and verifies their
        suitability.

        This carries out a scan using the pdb_signature scanner on a physical layer.  It uses the
        results of the scan to determine the virtual offset of the kernel.  On early windows implementations
        there is a fixed mapping between the physical and virtual addresses of the kernel.  On more recent versions
        a search is conducted for a structure that will identify the kernel's virtual offset.

        Args:
            context: Context on which to operate
            potential_layers: List of layer names that the kernel might live at
            progress_callback: Function taking a percentage and optional description to be called during expensive computations to indicate progress

        Returns:
            A dictionary of valid kernels
        Nz(No suitable kernels found during pdbscan)r   r'   r$   r   r(   methodsr@   info)r+   r   r   r5   r4   r.   rM   methods           r2   determine_valid_kernelz'KernelPDBScanner.determine_valid_kernel  s    , 37"2 	 	^''(:DAAF&&,"455 "l  F#)6$AR#S#SL#  	DKKBCCCr3   c                 b   |                     ||          rd|j        vr7|j                            t          j        dt          j                             |                     |||t          j                  | _	        | 
                    |||          }| j	        D ]\  }}t          j                            |          }|                     ||          rF|                     |||          }	|	r-|                     ||	           |                     ||	|           | |dd           d S d S )Npdbscan)r   r   r   d   zPDB scanning finished)unsatisfiedsymbol_spaceappendr   NativeTable
std_ctypesfind_requirementsr   SymbolTableRequirementr<   r*   r   r!   parent_pathr   rK   rE   )
r+   r   r   r   r5   r   r,   
symbol_reqr   r4   s
             r2   __call__zKernelPDBScanner.__call__  ss    ""7K88 	 444$++&y&2CDD   )-(>(>k<3V) )D%  $@@[k  A     04/H 
 
+(6BB?SS))';?? #'#>#>!13D$ $L $ 66wMMM55#\3D   (c#:;;;;; )(r3   )N)FTN)'__name__
__module____qualname____doc__priorityr   exclusion_listr   r   ContextInterfacer=   r!   RequirementInterfacer   r*   rV   r   ProgressCallbackrE   rK   rN   r   r   r(   r   rX   rp   r   boolrW   ry   rR   r   r   r   r   r   r   r   r`   r3   r2   r   r   #   s         HLu%N)#4) )  -B	)
 
c) ) ) )^ 9=	%G %G#4%G &%G %5	%G
 
%G %G %G %GNM#4M &M 
	M M M M.
 
 
 9=	
 
#4
 "
 %5	

 
/	"
 
 
 
> 9=	+
 +
#4+
 "+
 %5	+

 
/	"+
 +
 +
 +
d  8<+ +#4+ "+ 	+
 + + %5+ 
/	"+ + + +f 9=) )#4) ") 	)
 ) %5) 
/	") ) ) )^ 9=	
 
#4
 "
 %5	

 
/	"
 
 
 
$ 9=	S S#4S "S %5	S
 
/	"S S S S 9=   #4  "  	 
 %5  
/	"       H 		G 9=	   #4  s)  %5	 
 
/	"       N 9= <  <#4 <  <  -B	 <
 %5 < 
 <  <  <  <  <  <r3   r   )-r   r   loggingrf   ostypingr   r   r   r   r   r   r	   r
   r   volatility3.frameworkr   r   r   r   #volatility3.framework.configurationr   volatility3.framework.layersr   r   volatility3.framework.symbolsr   -volatility3.framework.symbols.windows.pdbutilr   r   syspathr   dirname__file__	getLoggerr@   r=   rR   ry   rV   KernelsType	automagicAutomagicInterfacer   r`   r3   r2   <module>r      s          				 S S S S S S S S S S S S S S S S S S S S S S K K K K K K K K K K K K < < < < < < 8 8 8 8 8 8 8 8 0 0 0 0 0 0 D D D D D DzJJJHOO
8Q8Q(R(RSSTT   
	8	$	$S$sHU5#s?5K,L'L"MMNtCH~&b< b< b< b< b<z+> b< b< b< b< b<r3   