
    Xf<a                     F   d dl Z d dlZd dlmZmZmZmZ d dlZd dlm	Z	m
Z
mZ d dl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 d d
lmZ d dlmZ d dlmZmZ 	 d dlZdZ  ejD                  e#      Z$ G d de	jJ                  jL                        Z'y# e!$ r dZ Y ;w xY w)    N)IterableTupleListOptional)
interfacessymbols
exceptions)	renderers	constants)requirements)scanners)utility)format_hints)intermed)pdbutil)pe)pslistvadinfoTFc                   ^   e Zd ZdZdZed        Zdededede	j                  fdZd	ej                  j                  d
ededefdZd	ej                  j                  dededefdZdededej$                  j&                  dej$                  j&                  fdZdedej$                  j&                  ded
edeej                  j                  eeef   f
dZdej$                  j.                  deded
efdZdedeej$                  j.                  ef   fdZdej$                  j.                  deeef   fdZdedej$                  j&                  d
ededeej                  j                  eef   f
dZdefdZd ed!edej$                  j&                  dedeej                  j                     f
d"Z dedej$                  j&                  d
edeej                  j                     fd#Z!dedej$                  j&                  d
edede"ej$                  j&                     f
d$Z#d% Z$d& Z%d' Z&y())Skeleton_Key_Checkz'Looks for signs of Skeleton Key malware)      r   c                    t        j                  ddddg      t        j                  dt        j                  d      t        j                  d	t
        j                  d      t        j                  d
t        j                  d      gS )NkernelzWindows kernelIntel32Intel64)namedescriptionarchitecturesr   )r   r   r   )r   	componentversionr   r   )   r   r   )	r   ModuleRequirementVersionRequirementr   PsListr   VadInfor   
PDBUtility)clss    j/home/panchajanya/Development/work/volatility3/volatility3/framework/plugins/windows/skeleton_key_check.pyget_requirementsz#Skeleton_Key_Check.get_requirements.   s}     **,()4
 ++	 ++'//9 ++'*<*<i
 	
    pe_table_name
layer_namebase_addressreturnc                    t        j                         }	 | j                  j                  |t        j
                  z   dz   ||      }|j                         D ]'  \  }}|j                  |       |j                  |       ) t        j                  |j                         d      }|S # t        j                  $ r t        j                  d       d}Y |S w xY w)aJ  
        Attempts to pefile object from the bytes of the PE file

        Args:
            pe_table_name: name of the pe types table
            layer_name: name of the lsass.exe process layer
            base_address: base address of cryptdll.dll in lsass.exe

        Returns:
            the constructed pefile object
        _IMAGE_DOS_HEADER)offsetr-   T)data	fast_loadz,Unable to reconstruct cryptdll.dll in memoryN)ioBytesIOcontextobjectr   BANGreconstructseekwritepefilePEgetvaluer	   InvalidAddressExceptionvollogdebug)	selfr,   r-   r.   pe_data
dos_headerr2   r3   pe_rets	            r)   _get_pefile_objz"Skeleton_Key_Check._get_pefile_objB   s     **,	,,	.1DD#% - J !+ 6 6 8 $V$d#$ YYG$4$4$6$GF 	 11 	LLGHF		s   BB) )*CCcsystemcryptdll_basecryptdll_sizec                 ~    ||j                   cxk  xr ||z   k  nc xr ||j                  cxk  xr	 ||z   k   S c  S )a  
        Checks if Initialize and/or Decrypt is hooked by determining if
        these function pointers reference addresses inside of the cryptdll VAD

        Args:
            csystem: The RC4HMAC KERB_ECRYPT instance
            cryptdll_base: Base address of the cryptdll.dll VAD
            cryptdll_size: Size of the VAD
        Returns:
            bool: if a skeleton key hook is present
        
InitializeDecrypt)rC   rH   rI   rJ   s       r)   _check_for_skeleton_key_vadz.Skeleton_Key_Check._check_for_skeleton_key_vade   sO    $ g00QMM4QQ T'//R]]5RR
 	
R
 	
r+   rc4HmacInitializerc4HmacDecryptc                 B    |j                   |k7  xs |j                  |k7  S )a  
        Uses the PDB information to specifically check if the csystem for RC4HMAC
        has an initialization pointer to rc4HmacInitialize and a decryption pointer
        to rc4HmacDecrypt.

        Args:
            csystem: The RC4HMAC KERB_ECRYPT instance
            rc4HmacInitialize: The expected address of csystem Initialization function
            rc4HmacDecrypt: The expected address of the csystem Decryption function

        Returns:
            bool: if a skeleton key hook was found
        rL   )rC   rH   rP   rQ   s       r)   _check_for_skeleton_key_symbolsz2Skeleton_Key_Check._check_for_skeleton_key_symbols{   s&    ( "33Xw.7X	
r+   array_startcountcryptdll_typesc                     	 |j                  d||j                  d      |d      }|S # t        j                  $ r* t        j                  dj                  |             d}Y |S w xY w)a=  
        Attempts to construct an array of _KERB_ECRYPT structures

        Args:
            array_start: starting virtual address of the array
            count: how many elements are in the array
            cryptdll_types: the reverse engineered types

        Returns:
            The instantiated array
        array_KERB_ECRYPTT)object_typer2   subtyperU   absolutez8Unable to construct cSystems array at given offset: {:x}N)r8   get_typer	   r@   rA   rB   format)rC   rT   rU   rV   rX   s        r)   _construct_ecrypt_arrayz*Skeleton_Key_Check._construct_ecrypt_array   s}    $	"))#"&//? * E   11 	LLJQQ
 E	s   %) 9A&%A&cryptdll_symbolsproc_layer_namec                    | j                   j                  |||      }|j                  d      }|j                  d      }|j                  d      j                  }	 |j                  d|      }	|j                  d      }
| j                  |
|	|      }|t        j                  d	       |||fS # t        j                  $ r d}	Y Ww xY w)
aa  
        Finds the CSystems array through use of PDB symbols

        Args:
            cryptdll_symbols: The symbols table from the PDB file
            cryptdll_types: The types from cryptdll binary analysis
            proc_layer_name: The lsass.exe process layer name
            cryptdll_base: Base address of cryptdll.dll inside of lsass.exe

        Returns:
            Tuple of:
            array: The cSystems array
            rc4HmacInitialize: The runtime address of the expected initialization function
            rc4HmacDecrypt: The runtime address of the expected decryption function
        )r-   r2   rP   rQ   	cCSystemszunsigned long)rZ   r2      CSystemszHThe CSystem array is not present in memory. Stopping PDB based analysis.)r7   moduleget_absolute_symbol_address
get_symboladdressr8   r	   r@   r_   rA   rB   )rC   r`   rV   ra   rI   cryptdll_modulerP   rQ   count_addressrU   rT   rX   s               r)   _find_array_with_pdb_symbolsz/Skeleton_Key_Check._find_array_with_pdb_symbols   s    , ,,-- . 
 ,GG
 )DDEUV'22;?GG	"))+M * E &AA*M,,[%P=LLZ '77 11 	E	s   B0 0CCr7   config_pathc                     | j                   j                  | j                  d      }d|j                  i}t        j
                  j                  ||dd|      }|j                  |||      S )aY  
        Builds a symbol table from the cryptdll types generated after binary analysis

        Args:
            context: the context to operate upon
            config:
            config_path:
            proc_layer_name: name of the lsass.exe process layer
            cryptdll_base: base address of cryptdll.dll inside of lsass.exe
        r   
nt_symbolswindowskerb_ecrypt)r7   rm   sub_pathfilenametable_mapping)r2   )r7   modulesconfigsymbol_table_namer   IntermediateSymbolTablecreaterf   )	rC   r7   rv   rm   ra   rI   r   rt   cryptdll_symbol_tables	            r)   _get_cryptdll_typesz&Skeleton_Key_Check._get_cryptdll_types   s|    $ %%dkk(&;<%v'?'?@ ( @ @ G G#"' !H !
 ~~!?=  
 	
r+   	proc_listc           	      
   |D ]$  }	 |j                   }|j                         }||fc S  y# t        j                  $ rD}t        j                  dj                  |j                  |j                               Y d}~zd}~ww xY w)aI  
        Walks the process list and returns the first valid lsass instances.
        There should be only one lsass process, but malware will often use the
        process name to try and blend in.

        Args:
            proc_list: The process list generator

        Return:
            The process object for lsass
        z*Process {}: invalid address {} in layer {}NNN)	UniqueProcessIdadd_process_layerr	   r@   rA   rB   r^   invalid_addressr-   )rC   r|   procproc_idra   excps         r)   _find_lsass_procz#Skeleton_Key_Check._find_lsass_proc  s      	D.."&"8"8":_,,	  55 @GG!5!5t s   +B:A==B
lsass_procc                    |j                         j                         D ]f  }|j                         }t        |t              s$|j                         j                  d      sD|j                         }||j                         fc S  y)a:  
        Finds the base address of cryptdll.dll inside of lsass.exe

        Args:
            lsass_proc: the process object for lsass.exe

        Returns:
            A tuple of:
            cryptdll_base: the base address of cryptdll.dll
            crytpdll_size: the size of the VAD for cryptdll.dll
        zcryptdll.dllr~   )	get_vad_roottraverseget_file_name
isinstancestrlowerendswith	get_startget_size)rC   r   vadrs   bases        r)   _find_cryptdllz!Skeleton_Key_Check._find_cryptdll-  sr     **,557 	,C((*H(C(X^^-=-F-F~-V}}S\\^++	, r+   c                 t   	 t         j                  j                  | j                  t        j
                  j                  | j                  d      |d||      }| j                  ||||      \  }}}|t        j                  d       |||fS # t        j                  $ r t        j                  d       Y yw xY w)a  
        Attempts to find CSystems and the expected address of the handlers.
        Relies on downloading and parsing of the cryptdll PDB file.

        Args:
            proc_layer_name: the name of the lsass.exe process layer
            cryptdll_types: The types from cryptdll binary analysis
            cryptdll_base: the base address of cryptdll.dll
            crytpdll_size: the size of the VAD for cryptdll.dll

        Returns:
            A tuple of:
            array: An initialized Volatility array of _KERB_ECRYPT structures
            rc4HmacInitialize: The expected address of csystem Initialization function
            rc4HmacDecrypt: The expected address of the csystem Decryption function
        cryptdllzcryptdll.pdbzDUnable to use the cryptdll PDB. Stopping PDB symbols based analysis.)NNNzPThe CSystem array is not present in memory. Stopping PDB symbols based analysis.)r   r'   symbol_table_from_pdbr7   r   configuration	path_joinrm   r	   VolatilityExceptionrA   rB   rl   )	rC   ra   rV   rI   rJ   r`   rX   rP   rQ   s	            r)   _find_csystems_with_symbolsz.Skeleton_Key_Check._find_csystems_with_symbolsD  s    .	$&11GG((2243C3CZP  483T3Tno}4
0 . =LLb '77 -- 	$LLV $		$s   AB (B76B7c                 V   	 |j                   d   }|j                  t        j                  j
                  k7  ry|j                  |j                  j                        dk7  ry|j                  |j                  z   |j                  j                  z   S # t        j                  $ r Y yw xY w)aP  
        Returns the target address of a RIP-relative instruction.

        These instructions contain the offset of a target address
        relative to the current instruction pointer.

        Args:
            inst: A capstone instruction instance

        Returns:
            None or the target address of the instruction
        r"   Nrip)operandscapstoneCsErrortypex86
X86_OP_MEMreg_namememr   ri   sizedisp)rC   instopnds      r)   _get_rip_relative_targetz+Skeleton_Key_Check._get_rip_relative_targetu  s    	==#D 99///=='50||dii'$((--77  		s   B B('B(function_bytesfunction_startc                 &   d}d}d}t        j                  t         j                  t         j                        }d|_        |j                  ||      D ]  }	|	j                  dk(  r n|	j                  dk(  rY|r&| j                  |	      }
|
r>t        j                  | j                  j                  |   j                  |
d      d      }nd}d}||	j                  d	k(  s| j                  |	      }
|
r|
} n |r|r| j                  |||      }|S d}|S )
a  
        Performs static analysis on CDLocateCSystem to find the instructions that
        reference CSystems as well as cCsystems

        Args:
            function_bytes: the instruction bytes of CDLocateCSystem
            function_start: the address of CDLocateCSystem
            proc_layer_name: the name of the lsass.exe process layer

        Return:
            The cSystems array of ecrypt instances
        FNTint3movr   littlerd   lea)r   CsCS_ARCH_X86
CS_MODE_64detaildisasmmnemonicr   int
from_bytesr7   layersreadr_   )rC   r   r   rV   ra   found_countrT   rU   mdr   target_addressrX   s               r)   _analyze_cdlocatecsystemz+Skeleton_Key_Check._analyze_cdlocatecsystem  s    &  [[--x/B/BC	IInn= 	D}}& %'"%)%B%B4%HN & # LL//@EE . %	! !#"&K%'!%!>!>t!D!"0K ?	B 500e^TE  Er+   c                    t         st        j                  d       yt        j                  d       t        j                  j                  | j                  | j                  ddt        j                        }| j                  |||      }|sy|j                  t        j                  d   g       t        |d	      sy|j                  j                   D ]y  }|j"                  d
k7  r||j$                  z   }	 | j                  j&                  |   j)                  |d      }	| j/                  |	|||      }
|
t        j                  d       |
c S  y# t*        j,                  $ r t        j                  d       Y  yw xY w)a  
        Uses export table analysis to locate CDLocateCsystem
        This function references CSystems and cCsystems

        Args:
            proc_layer_name: The lsass.exe process layer name
            cryptdll_types: The types from cryptdll binary analysis
            cryptdll_base: Base address of cryptdll.dll inside of lsass.exe
            _: unused in this source
        Returns:
            The cSystems array
        zGcapstone is not installed so cannot fall back to export table analysis.NzTUnable to perform analysis using PDB symbols, falling back to export table analysis.rp   r   )class_typesIMAGE_DIRECTORY_ENTRY_EXPORT)directoriesDIRECTORY_ENTRY_EXPORTs   CDLocateCSystemP   zgThe CDLocateCSystem function is not present in the lsass address space. Stopping export based analysis.zKThe CSystem array is not present in memory. Stopping export based analysis.)has_capstonerA   rB   r   rx   ry   r7   rm   r   r   rG   parse_data_directoriesr=   DIRECTORY_ENTRYhasattrr   r   r   ri   r   r   r	   r@   r   )rC   ra   rV   rI   _r,   r   exportr   r   rX   s              r)   _find_csystems_with_exportz-Skeleton_Key_Check._find_csystems_with_export  s   ( LLY b	
 !88??LL$**It @ 
 ''V''//0NOP 	( 	
 x!9: 55== 	F{{00*V^^;N!%!4!4_!E!J!J"D" 11E }a L1	4 ! 55 }  !s   8)E(E>=E>c                    g }||z   }| j                   j                  |   }|j                  d      j                  }|j	                  | j                   t        j                  d      ||fg      D ]l  }	|j                  |	|      s|j                  d|	d      }
||
j                  cxk  r|k  s@n C||
j                  cxk  r|k  sYn \|j                  |
       n |S )a  
        Performs scanning to find potential RC4 HMAC csystem instances

        This function may return several values as it cannot validate which is the active one

        Args:
            proc_layer_name: the lsass.exe process layer name
            cryptdll_types: the types from cryptdll binary analysis
            cryptdll_base: base address of cryptdll.dll inside of lsass.exe
            cryptdll_size: size of the VAD
        Returns:
            A list of csystem instances
        rY   s         )sectionsT)r2   r\   )r7   r   r]   r   scanr   BytesScanneris_validr8   EncryptFinishappend)rC   ra   rV   rI   rJ   csystemscryptdll_end
proc_layerecrypt_sizeri   kerbs              r)   _find_csystems_with_scanningz/Skeleton_Key_Check._find_csystems_with_scanning  s    * $}4\\((9
$--n=BB
 "LL!!"EF$m45 ' 
 	&G &&w<!((RV(WD ;|;:l:%!	&$ r+   c           	   #   t  K   | j                   j                  | j                  d      }t        j                  | j                   |j
                        st        j                  d       y| j                  |      \  }}|st        j                  d       y| j                  |      \  }}|st        j                  d       y| j                  | j                   | j                  | j                  ||      }| j                  ||||      \  }}	}
|.| j                  | j                  g}|D ]  } |||||      }| n |t        j                  d       y|D ]  }| j                   j                  |   j!                  |j"                  j$                  |j"                  j&                        sU|j(                  dk7  re|	r|
r| j+                  ||	|
      }n| j-                  |||      }d|j.                  d	|t1        j2                  |j4                        t1        j2                  |j6                        ff  yw)
z
        Finds instances of the RC4 HMAC CSystem structure

        Returns whether the instances are hooked as well as the function handler addresses

        Args:
            procs: the process list filtered to lsass.exe instances
        r   z6This plugin only supports 64bit Windows memory samplesNzpUnable to find a valid lsass.exe process in the process list. This should never happen. Analysis cannot proceed.zYUnable to find the location of cryptdll.dll inside of lsass.exe. Analysis cannot proceed.zHUnable to find CSystems inside of cryptdll.dll. Analysis cannot proceed.   r   	lsass.exe)r7   ru   rv   r   symbol_table_is_64bitrw   rA   infor   r   r{   rm   r   r   r   r   r   volr2   r   EncryptionTyperS   rO   r   r   HexrM   rN   )rC   procsr   r   ra   rI   rJ   rV   r   rP   rQ   fallback_sourcessourcerH   skeleton_key_presents                  r)   
_generatorzSkeleton_Key_Check._generatorO  sE     %%dkk(&;<,,T\\6;S;STKKPQ&*&;&;E&B#
OKK C '+':'::'F$}KKk  11LL$++t'7'7-

 7;6V6V^]M7
3#^ //11 
 + !#^]M ' KKZ  	G<<&&7@@""GKK$4$4  %%- !^'+'K'K.($ (,'G'G]M($ **$  !3!34  1  )	s   D6H89C?H8c                 J    t        j                  |j                        }|dk7  S )z
        Used to filter to only lsass.exe processes

        There should only be one of these, but malware can/does make lsass.exe
        named processes to blend in or uses lsass.exe as a process hollowing target
        r   )r   array_to_stringImageFileName)rC   r   process_names      r)   _lsass_proc_filterz%Skeleton_Key_Check._lsass_proc_filter  s%     ..t/A/AB{**r+   c                    | j                   j                  | j                  d      }t        j                  dt
        fdt        fdt        fdt        j                  fdt        j                  fg| j                  t        j                  j                  | j                   |j                  |j                  | j                                     S )Nr   PIDProcesszSkeleton Key FoundrP   rQ   )r7   r-   symbol_tablefilter_func)r7   ru   rv   r
   TreeGridr   r   boolr   r   r   r   r%   list_processesr-   rw   r   )rC   r   s     r)   runzSkeleton_Key_Check.run  s    %%dkk(&;<!!C %t,$l&6&67!<#3#34 OO,, LL%00!'!9!9 $ 7 7	 - 
 	
r+   N)'__name__
__module____qualname____doc___required_framework_versionclassmethodr*   r   r   r=   r>   rG   r   objectsObjectInterfacer   rO   rS   r7   ModuleInterfacer_   r   rl   ContextInterfacer{   r   r   r   r   r   bytesr   r   r   r   r   r   r   r    r+   r)   r   r   )   sR   1"+
 
&! !.1!AD!	!F
##33
 
 	

 

,
##33
 
 	

 

.## # #**::	#
 
			+	+#J4848 #**::48 	48
 48 
z!!113S@	A48l
##44
 	

 
 
B!	z!!22C7	8>$,,==	sCx./8/8 #**::/8 	/8
 /8 
z!!113;	</8b8 84AA A #**::	A
 A 
*$$44	5AFGG #**::G 	G 
*$$44	5GR22 #**::2 	2
 2 
j  00	12hYv	+
r+   r   )(r5   loggingtypingr   r   r   r   r=   volatility3.frameworkr   r   r	   r
   r   #volatility3.framework.configurationr   volatility3.framework.layersr   volatility3.framework.objectsr   volatility3.framework.renderersr   volatility3.framework.symbolsr   %volatility3.framework.symbols.windowsr   0volatility3.framework.symbols.windows.extensionsr   volatility3.plugins.windowsr   r   r   r   ImportError	getLoggerr   rA   pluginsPluginInterfacer   r   r+   r)   <module>r     s    
  2 2  A A 6 < 1 1 8 2 9 ? 7L 
		8	$_

++;; _

  Ls   B B B 