
    XfV                     t   d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZ d dlm	Z	m
Z
mZmZmZmZmZ d dlmZmZ d dlmZ d dlmZmZmZmZ d dlmZ d dlmZ d d	lmZ d d
l m!Z! d dl"m#Z#  ejH                  e%      Z& G d dejN                  jP                        Z) G d dejT                  jV                        Z,y)    N)PureWindowsPath)AnyDict	GeneratorListOptionalTupleUnion)parserequest)symbols)	constantscontexts
exceptions
interfaces)symbol_cache)requirements)SymbolTableRequirement)intermed)pdbconvc                      e Zd ZdZdZdZe	 	 	 d dej                  j                  de
dede
d	e
d
ej                  dee
   fd       Ze	 	 d!dej                  j                  de
dede
de
d	e
d
ej                  fd       Zedej                  j                  de
dedeee
ee
f      fd       Ze	 d"dej                  j                  de
dede
d
ej                  ddfd       Ze	 	 	 	 d#dej                  j                  de
dedee   d
ej                  dee   dee   dedeee
eeee
ef      f   ddf   fd       Ze	 	 d$dej                  j                  d	e
de
de
dedede
fd       Ze	 	 	 d%dej                  j                  d	e
de
de
dedededeee
   ee
   f   fd       Ze	 	 d$dej                  j                  d	e
de
de
dedede
fd       Zy)&
PDBUtilityzAClass to handle and manage all getting symbols based on MZ header)   r   r   )   r   r   Ncontext
layer_nameoffsetsymbol_table_classconfig_pathprogress_callbackreturnc           	         | j                  |||      }|"t        j                  dt        |              y|\  }}	}
|0t        j
                  j                  d|
j                  dd            }| j                  |||	|
|||      S )a  Produces the name of a symbol table loaded from the offset for an MZ header

        Args:
            context: The context on which to operate
            layer_name: The name of the (contiguous) layer within the context that contains the MZ file
            offset: The offset in the layer at which the MZ file begins
            symbol_table_class: The class to use when constructing the SymbolTable
            config_path: New path for the produced symbol table configuration with the config tree
            progress_callback: Callable called to update ongoing progress

        Returns:
            None if no pdb information can be determined, else returned the name of the loaded symbols for the MZ
        NzCould not get GUID for 
pdbutility._)	get_guid_from_mzvollogdebughexr   configuration	path_joinreplaceload_windows_symbol_table)clsr   r   r   r   r   r    resultguidagepdb_names              _/home/panchajanya/Development/work/volatility3/volatility3/framework/symbols/windows/pdbutil.pysymbol_table_from_offsetz#PDBUtility.symbol_table_from_offset    s    . %%gz6B>LL23v;-@A$c8$22<<h..sC8K ,,
 	
    r0   r1   r2   c           	      z   t         j                  j                  |j                  d      |j	                         dz   t        |      z         }d}	t        j                  j                  dt        j                  j                        st        j                  d       yt         j                  j                  t        j                  t        j                         }
t        j                  |
      j#                  t        j$                  j'                  |j                  d      |j	                         |      d      }|r|}	nK| j)                  ||j	                         |||       t*        j,                  j/                  d|      D ]  }|}	 n |	sgt        j                  d|        t        j1                  dj3                  |j                  d      |j	                         t        |      z                yt        j                  d	|        t4        j6                  j8                  }||j:                   ||d
      <   |	|j:                   ||d      <   t4        j6                  j=                  |      }t4        j6                  j?                  |      }tA        |d      }|jC                  ||       |j:                  |   S )z7Loads (downloading if necessary) a windows symbol table -N)r   r   r   z)Required version of SQLiteCache not foundwindowsz(Required symbol library path not found: z@The symbols can be downloaded later using pdbconv.py -p {} -g {}zUsing symbol library: classisf_urlz!PDBUtility generated symbol table)namedescription)"ospathjoinstripupperstrr   VersionRequirementmatches_requiredr   SqliteCacheversionr'   r(   r   
CACHE_PATHIDENTIFIERS_FILENAMEfind_locationWindowsIdentifiergeneratedownload_pdb_isfr   IntermediateSymbolTablefile_symbol_urlinfoformatr   r*   r+   configparent_path	path_headr   	construct)r.   r   r0   r1   r2   r   r   r    filter_stringisf_pathidentifiers_pathvaluer@   parent_config_pathrequirement_namerequirements                   r3   r-   z$PDBUtility.load_windows_symbol_tableK   sL    NN6"DJJL3$6S$A
 ..??|//77
 LLDF77<<  )"@"@
 (()9:HH**33v&

c 	
 H   sH6G "99II=  !	 LLCM?STKKRYYNN6*DJJL3s8,C
 -m_=> ''115GtK127?tK34'55AA+N%33==kJ -!/R
 	g'9:~~k**r5   c                    	 ddl }|j                  |   }|j                  |d      }|dk7  ryt        j                  d|j                  |dz   d            \  }|j                  ||z   d      }|d	k7  ryt        j                  d
|j                  ||z   dz   d            \  }	|j                  ||dz   |	z         }
|j                  |
      }|j                  j                  }|j                  ||d      }|j                  |      }|j                  j                  }|d| }|j                  D ]+  }|||j                  |j                  |j                  z    z  }- |j                  |      }t        |d      rt!        |j"                        syd}t%        t!        |j"                              D ]  }|j"                  |   j                  j&                  dk(  s*|j"                  |   }|j)                  |j                  j+                  d      |j                  j,                         |j/                          |j"                  |   j0                  } |y|j2                  j5                  d      j7                  d      }t9        |      j:                  }|j<                  }|j>                  dd }|||fS # t        $ r t        j                  d       Y yw xY w)a  Takes the offset to an MZ header, locates any available pdb headers, and extracts the guid, age and pdb_name from them

        Args:
            context: The context on which to operate
            layer_name: The name of the (contiguous) layer within the context that contains the MZ file
            offset: The offset in the layer at which the MZ file begins

        Returns:
            A tuple of the guid, age and pdb_name, or None if no PDB record can be found
        r   Nz=Get_guid_from_mz requires the following python module: pefiler      MZz<I<      s   PEz<H      )dataT)padDIRECTORY_ENTRY_DEBUGAddressOfRawDatautf-8r7       ) pefileImportErrorr'   errorlayersreadstructunpackPEOPTIONAL_HEADERSizeOfImageSizeOfHeaderssectionsVirtualAddressSizeOfRawDatahasattrlenre   rangeTypeset_dword_at_offsetget_field_absolute_offsetPointerToRawData	full_loadentryPdbFileNamedecoderA   r   r<   AgeSignature_String)r.   r   r   r   ri   layermz_signt_header_startpe_sigoptional_header_size	pe_headerpe_datamax_sizevirtual_data
sizeofHdrsphysical_datasectdebug_entryindex
debug_datar2   r1   r0   s                          r3   r&   zPDBUtility.get_guid_from_mz   s   	 z*FA& U?#]]4FTM11MNF_4a8 U?"(--%**Vo5<a@#
	 JJv'=@T'TU	)))+**66 zz&(z=))). ,,::
$[j1$$ 	D\##d&9&9D<N<N&N M	
 )))/w 78))A
  3w<<=> 	IE,,U3::??1D$::5A
++%%??@RS%%66 !!#%;;EBHH	I **11':@@H #8,11oo++CR0S(""M  	LLO 		s   J5 5KKc                 t   t         j                  j                  ||dz   t        |      z         }t        j
                  D ]   }g }t         j                  j                  |d|dz         }	d}
	 t        j                  t         j                  j                  |	      d       t        j                  |	d      5 }t        j                         j                  |t        |      z   ||      }|rt        j                  |d	
      }|j                  d	k(  st!        |j                        dk(  rJ|j#                  |       dt%        j&                  t         j                  j)                  |d               z   }n|}t        j*                  ||||      j-                         }|j/                  t1        t3        j4                  |dd      d             d}
nt6        j9                  d       ddd       	 |
s4t         j                  j;                  |	      rt        j<                  |	       |D ]  }	 t        j<                  |         y t6        j9                  d       y# 1 sw Y   vxY w# t>        $ r t6        j9                  d|        Y cw xY w# t>        $ r t6        j9                  djA                  |	             Y |
s4t         j                  j;                  |	      rt        j<                  |	       |D ]?  }	 t        j<                  |       # t>        $ r t6        j9                  d|        Y =w xY w w xY w# |
s4t         j                  j;                  |	      rt        j<                  |	       |D ]?  }	 t        j<                  |       # t>        $ r t6        j9                  d|        Y =w xY w w xY w)zpAttempts to download the PDB file, convert it to an ISF file and
        save it to one of the symbol locations.r8   r9   z.json.xzFT)exist_okw)	file_namer    file)schemer   zfile:r   )indent	sort_keysrg   zSymbol file could not be downloaded from remote server                                                                                                    Nz%Temporary file could not be removed: zBCannot write necessary symbol file, please check permissions on {}zvCannot write downloaded symbols, please add the appropriate symbols or add/modify a symbols directory that is writable)!r>   r?   r@   rC   r   __path__makedirsdirnamelzmaopenr   PdbRetreiverretreive_pdbr   urlparser   rx   appendr   pathname2urlabspath	PdbReaderget_jsonwritebytesjsondumpsr'   warningexistsremovePermissionErrorrQ   )r.   r   r0   r1   r2   r    rV   r?   	tmp_filespotential_output_filenamedata_writtenoffilenameurllocationjson_outputs                   r3   rM   zPDBUtility.download_pdb_isf   s;    XtczCH/DE$$ A	DI(*i!;)% !L5BGGOO,EFQUVYY8#> "&335BBs3x"**;  C  H
  #nnXfE::/3szz?a3G%,,X6'.1E1E "	" >2 (H (0H&-&7&7#Xx9J'"(* $ ! $

;qD Q ' (,*9@  $7P(QII78 ) H		(+mA	| NNFk ` + CH:N # X__1
  $7P(QII78 ) H		(+* CH:N $7P(QII78 ) H		(+* CH:Ns   -A
J7D.I%J*I&I#	J&!J
	J
-L8:L;7L!L10L17L88L;;<N78NN7!N2/N71N22N7ctx	page_size	pdb_namesstartendmaximum_invalid_countc	              #     K   d}	||j                   |   j                  }||j                   |   j                  }|j                   |   j                  |t	        |      ||||z
  fg      D ]  \  }
}}}d}||z  }d}t        ||	d      D ]_  }||kD  r nX|j                   |   j                  ||z  d      s|dz  }2|j                   |   j                  ||z  d      }|dk(  sZ||z  } n |}	|
|t        |d      ||d	  yw)
a  Scans through `layer_name` at `ctx` looking for RSDS headers that
        indicate one of four common pdb kernel names (as listed in
        `self.pdb_names`) and returns the tuple (GUID, age, pdb_name,
        signature_offset, mz_offset)

        .. note:: This is automagical and therefore not guaranteed to provide correct results.

        The UI should always provide the user an opportunity to specify the
        appropriate types and PDB values themselves
        Args:
            layer_name: The layer name to scan
            page_size: Size of page constant
            pdb_names: List of pdb names to scan
            progress_callback: Means of providing the user with feedback during long processes
            start: Start address to start scanning from the pdb_names
            end: Minimum address to scan the pdb_names
            maximum_invalid_count: Amount of pages that can be invalid during scanning before aborting signature search
        r   N)r    rt   r   r   r   r^   rg   )GUIDr1   r2   signature_offset	mz_offset)	rl   minimum_addressmaximum_addressscanPdbSignatureScannerry   is_validrm   rC   )r.   r   r   r   r   r    r   r   r   min_pfnr   r1   r2   r   r   sig_pfncurrent_invalid_counterirc   s                      r3   pdbname_scanzPDBUtility.pdbname_scan=  sP    < =JJz*::E;**Z(88C58ZZ
5K5P5P	*/cEk*+	 6Q 6
 	1D#x!1 I&)3G&'#7GR0 *-BBzz*-66q9}aH+q0+zz*-221y=!D5= !II G '2$4& 1	s   C!D$!Dmodule_offsetmodule_sizec                 8    | j                  ||||||      \  }}|S )a  Creates symbol table for a module in the specified layer_name.

        Searches the memory section of the loaded module for its PDB GUID
        and loads the associated symbol table into the symbol space.

        Args:
            context: The context to retrieve required elements (layers, symbol tables) from
            config_path: The config path where to find symbol files
            layer_name: The name of the layer on which to operate
            module_offset: This memory dump's module image offset
            module_size: The size of the module for this dump

        Returns:
            The name of the constructed and loaded symbol table
        _modtable_from_pdb)	r.   r   r   r   r2   r   r   r%   symbol_table_names	            r3   symbol_table_from_pdbz PDBUtility.symbol_table_from_pdb  s/    2  #55[*h{ 
 ! r5   create_modulec                 t   ||j                   |   j                  }||j                   |   j                  |z
  }t        | j	                  |||j                   |   j
                  t        |d      g|||z               }|st        j                  d| d|dd      |d   }	t        j                  d|	d	    d
|	d    d|	d           |	d	   j                  dd      }
| j                  ||	d   |	d   |	d	   d|      }d }|r3t        j                  j                  ||
||	d   |      }|j                   }||fS )Nzlatin-1)r   r   zDid not find GUID of z in module @ 0xx!r   zFound r2   z: r   r8   r1   z.pdb >volatility3.framework.symbols.intermed.IntermediateSymbolTable)r   r   )r   r   )rl   r   r   listr   r   r   r   VolatilityExceptionr'   r(   r,   r-   r   Modulecreater<   )r.   r   r   r   r2   r   r   r   guidsr0   module_namer   new_module_name
new_modules                 r3   r   zPDBUtility._modtable_from_pdb  s     #NN:6FFM!..4DD}TKz*44x+,#!K/  	
 00'zq@QQRS  Qxvd:./r$v,qeNO:&..vr:99LKL# : 
 !//K("3 0 J )ooO 111r5   c           	      <    | j                  ||||||d      \  }}|S )a  Creates a module in the specified layer_name based on a pdb name.

        Searches the memory section of the loaded module for its PDB GUID
        and loads the associated symbol table into the symbol space.

        Args:
            context: The context to retrieve required elements (layers, symbol tables) from
            config_path: The config path where to find symbol files
            layer_name: The name of the layer on which to operate
            module_offset: This memory dump's module image offset
            module_size: The size of the module for this dump

        Returns:
            The name of the constructed and loaded symbol table
        T)r   r   )	r.   r   r   r   r2   r   r   r   r%   s	            r3   module_from_pdbzPDBUtility.module_from_pdb  s:    4 // 0 
Q r5   )r   NN)r#   NN)NNNd   )NN)NNF)__name__
__module____qualname____doc___version_required_framework_versionclassmethodr   r   ContextInterfacerC   intr   ProgressCallbackr   r4   r-   r	   r&   rM   r   r   r   r   r
   r   r   boolr   r    r5   r3   r   r      s   KH"+ #c8<(
##44(
 (
 	(

  (
 (
 %55(
 
#(
 (
T  (8<G+##44G+ G+ 	G+
 G+  G+ G+ %55G+ G+R U# ((99U#GJU#TWU#	%S#&	'U# U#n  9=M##44M M 	M
 M %55M 
M M^  9=#!%(B00B B 	B
 ;B %55B }B c]B  #B 
4XeE3O&<==>dJ	KB BH  "!##44! ! 	!
 ! ! ! 
! !:  "#92##4492 92 	92
 92 92 92 92 
x}hsm+	,92 92v  "###44# # 	#
 # # # 
# #r5   r   c                        e Zd ZdZdZ	 dZ	  ej                  d      Zde	e
   ddf fdZd	e
d
edeeeee
ef   ddf   fdZ xZS )r   an  A :class:`~volatility3.framework.interfaces.layers.ScannerInterface`
    based scanner use to identify Windows PDB records.

    Args:
        pdb_names: A list of bytestrings, used to match pdb signatures against the pdb names within the records.

    .. note:: The pdb_names must be a list of byte strings, unicode strs will not match against the data scanned
    i @  Tz<16BIr   r!   Nc                 0    t         |           || _        y r   )super__init__
_pdb_names)selfr   	__class__s     r3   r   zPdbSignatureScanner.__init__  s    #r5   rc   data_offsetc              #     K   dd| j                   j                  z  z   dz   dj                  | j                  D cg c]  }t	        j
                  |       c}      z   dz   }t	        j                  ||t        j                        D ]1  }||j                  d      dz   | j                   j                  z   |j                  d      t        |j                               z   d	z
   }|| j                  v sm| j                   j                  ||j                  d      dz   |j                  d      dz   | j                   j                  z          \  }}}	}
}}}}}}}}}}}}}d
j                  |
|	||||||||||||||      }|j                  d      | j                  k  s|||||j                  d      z   f 4 y c c}w w)Ns   RSDS   .   (   |s   ) )flagsr   r`   r   z`{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X})_RSDS_formatsizer@   r   reescapefinditerDOTALLr   rx   groupro   rQ   
chunk_size)r   rc   r   r   patternmatchr2   g3g2g1g0g5g4g7g6g8g9gagbgcgdgegfar0   s                            r3   __call__zPdbSignatureScanner.__call__  s     d'',,,. iit?!1?@A 	 	 [[$bii@ &	LEA##(()+0;;q>ekkm$,%,H 4??*( %%,,A*U[[^a-?$BSBSBXBX-X% &--BBBBBBBPR ;;q>DOO3HkEKKN.JKKM&	L @s   8GF>
BG5B)G #G)r   r   r   r   overlapthread_safern   Structr   r   r   r   r   r   r	   rC   r   r  __classcell__)r   s   @r3   r   r     s     GlK A 6==)L$$u+ $$ $0L0L(+0L	5c5#-.d:	;0Lr5   r   )-r   loggingr   r>   r  rn   pathlibr   typingr   r   r   r   r   r	   r
   urllibr   r   volatility3r   volatility3.frameworkr   r   r   r   volatility3.framework.automagicr   #volatility3.framework.configurationr   0volatility3.framework.configuration.requirementsr   volatility3.framework.symbolsr   %volatility3.framework.symbols.windowsr   	getLoggerr   r'   r*   VersionableInterfacer   rl   ScannerInterfacer   r   r5   r3   <module>r-     s   
    	 	  # E E E !  M M 8 < S 2 9			8	$f))>> fREL*++<< ELr5   