
    Zis[                     2   S r SSKJr  SrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKr\	R                  R                  \	R                  R                  \	R                  R                  \5      5      5      r\	R                  R                  \	R                  R%                  \S5      5      r\\R                  ;  a  \R                  R)                  S\5        SSKJr  SSKJrJrJrJrJrJr  SSKJr  SS	K J!r!  \RD                  " S
5      r# " S S\$5      r%\%RL                  S\%RN                  S\%RP                  S\%RR                  S\%RT                  S\%RV                  S\%RX                  S0r-S r. " S S\$5      r/ " S S\$5      r0S r1\2S:X  a  \1" 5         gg)aT  
oleid.py

oleid is a script to analyze OLE files such as MS Office documents (e.g. Word,
Excel), to detect specific characteristics that could potentially indicate that
the file is suspicious or malicious, in terms of security (e.g. malware).
For example it can detect VBA macros, embedded Flash objects, fragmentation.
The results is displayed as ascii table (but could be returned or printed in
other formats like CSV, XML or JSON in future).

oleid project website: http://www.decalage.info/python/oleid

oleid is part of the python-oletools package:
http://www.decalage.info/python/oletools
    )print_functionz0.60.1Nz..)tablestream)cryptoftguessolevbamraptoroleobjooxml)
log_helper)get_codepage_nameoleidc                   4    \ rS rSrSrSrSrSrSrSr	Sr
S	rS
rg)RISKo   z
Constants for risk levels
HIGHMediumlownoneinfoUnknownError N)__name__
__module____qualname____firstlineno____doc__r   MEDIUMLOWNONEINFOUNKNOWNERROR__static_attributes__r       h/var/www/eduai.edurigo.com/question_generate/ques_gen_env/lib/python3.13/site-packages/oletools/oleid.pyr   r   o   s,     DF
CDDGEr%   r   redyellowwhitegreencyanc                    / n[         R                  " SU 5       H  nUR                  5       nUS-   [        U 5      :  a  M'  XUS-    n[        R
                  " SXS-   US-    5      S   nUS:  a  MX  [        R
                  " SXS-   US-    5      S   nX6-   [        U 5      :  d  US	:  a  M  XX6-    nS
nSU;   a  SnUSS n	 [        R                  " U	5        UR                  X6U45        M     U$ ! [         a     M  f = f)a  
Detect Flash objects (SWF files) within a binary string of data
return a list of (start_index, length, compressed) tuples, or [] if nothing
found.

Code inspired from xxxswf.py by Alexander Hanel (but significantly reworked)
http://hooked-on-mnemonics.blogspot.nl/2011/12/xxxswfpy.html
s   CWS|FWS      z<b   r      z<ii   Fs   CWSTN)
refinditerstartlenstructunpackzlib
decompress	Exceptionappend)
datafoundmatchr3   headerversizeswf
compressedcompressed_datas
             r&   detect_flashrD      s!    EZ.7SY E!G$mmD$QwuQw"78; 8}}T4aa#89!<:D	!TD[ $
VJ "!"gO0
 	e:./G /J L  s   C22
D ?D c                   B    \ rS rSrSrS\SS\R                  S4S jrSr	g)	Indicator   z
Piece of information of an :py:class:`OleID` object.

Contains an ID, value, type, name and description. No other functionality.
NTc                 p    Xl         X l        X0l        X@l        US :X  a  Xl        XPl        X`l        Xpl        g )N)idvaluetypenamedescriptionriskhide_if_false)self_idrJ   _typerL   rM   rN   rO   s           r&   __init__Indicator.__init__   s3    
		4<I&	*r%   )rM   rO   rI   rL   rN   rK   rJ   )
r   r   r   r   r   boolr   r"   rS   r$   r   r%   r&   rF   rF      s      #'d!D
+r%   rF   c                   R    \ rS rSrSrSS jrS rS rS rS r	S	 r
S
 rS rS rSrg)OleID   z
Summary of information about an OLE file (and a few other MS Office formats)

Call :py:meth:`OleID.check` to gather all info on a given file or run one
of the `check_` functions to just get a specific piece of info.
Nc                    Uc  Uc  [        S5      eSU l        Uc2  SU l        [        US5       nUR                  5       U l        SSS5        OX l        [
        R                  " U R                  5      U l        [        U[        R                  5      (       a  Xl        SU l        OXl        SU l        / U l        SU l        g! , (       d  f       N|= f)a  
Create an OleID object

This does not run any checks yet nor open the file.

Can either give just a filename (as str), so OleID will check whether
that is a valid OLE file and create a :py:class:`olefile.OleFileIO`
object for it. Or you can give an already opened
:py:class:`olefile.OleFileIO` as argument to avoid re-opening (e.g. if
called from other oletools).

If filename is given, only :py:meth:`OleID.check` opens the file. Other
functions will return None
Nz7OleID requires either a file path or file data, or bothFTrb)
ValueErrorfile_on_diskopenreadr;   ioBytesIOdata_bytesio
isinstanceolefile	OleFileIOolefilename
indicatorssuminfo_data)rP   rf   r;   fs       r&   rS   OleID.__init__   s     VWW!< $Dh%FFH	 &% IJJtyy1h 1 122H DM$MDH  &%s   C
Cc                     U R                    Vs/ s H  nUR                  U:X  d  M  UPM     nnU(       a  US   $ gs  snf )z:Helper function: returns an indicator if present (or None)r   N)rg   rI   )rP   indicator_id	indicatorresults       r&   get_indicatorOleID.get_indicator   sB    -1__ 3_	\\\1 _ 3!93s   <<c           	      <   [         R                  " U R                  U R                  S9U l        U R                  R
                  nU R                  R                  [         R                  R                  :X  a;  SR                  U R                  R                  U R                  R                  5      nOSn[        SUR                  [        S[        R                   US9nU R"                  R%                  U5        [        SUR&                  [        S[        R                   S	S9nU R"                  R%                  U5        U R                  R&                  [         R(                  R*                  :X  a  U R                  R,                  U l        U R1                  5         U R3                  5         U R5                  5         U R7                  5         U R9                  5         U R;                  5         U R.                  b  U R.                  R=                  5         U R"                  $ )
z[
Open file and run all checks on it.

:returns: list of all :py:class:`Indicator`s created
)filepathr;   z*Unrecognized OLE file. Root CLSID: {} - {} ftypezFile format)rJ   rR   rL   rN   rM   	containerzContainer formatzContainer type)r   FileTypeGuesserrf   r;   ftgrt   filetypeFTYPEGENERIC_OLEformat
root_clsidroot_clsid_namerF   longnamestrr   r!   rg   r:   ru   	CONTAINEROLErc   re   check_propertiescheck_encryptedcheck_macroscheck_external_relationshipscheck_object_poolcheck_flashclose)rP   rt   rM   ftcts        r&   checkOleID.check  s    **DMM		R88 9 99FMM##TXX%=%=?K KwennCmZ^ZcZc#.0r"{%//K]dhdmdm#35r" 88!2!2!6!66xx''DH 	))+ 88HHNNr%   c           	      h   U R                   (       d  gU R                   R                  5       n[        SUR                  [        SS[
        R                  S9nU R                  R                  U5        SnUR                  b/  SR                  UR                  [        UR                  5      5      n[        SU[        SS	[
        R                  S9nU R                  R                  U5        [        S
UR                  [        SS[
        R                  S9nU R                  R                  U5        X$U4$ )z
Read summary information required for other check_* functions

:returns: 2 :py:class:`Indicator`s (for presence of summary info and
            application name) or None if file was not opened
NappnamezApplication namez'Application name declared in propertiesrR   rL   rM   rN   z{}: {}codepagezProperties code pagezCode page used for propertiesauthorAuthorzAuthor declared in properties)re   get_metadatarF   creating_applicationr   r   r!   rg   r:   r   r{   r   r   )rP   metar   codepage_namer   r   s         r&   r   OleID.check_properties3  s     xxxx$$&It'@'@!3Aj!%, 	w'==$$OODMM;LT]];[\MZc1?^99& 	x(8T[[#1P99& 	v&&((r%   c           	         [        SSS[        R                  SSS9nU R                  R	                  U5        U R
                  (       d  g [        R                  " U R
                  5      (       a#  SUl        [        R                  Ul
        SUl        U$ ! [         a=  nS	Ul        [        R                  Ul
        S
R                  U5      Ul         SnAU$ SnAff = f)z
Check whether this file is encrypted.

:returns: :py:class:`Indicator` for encryption or None if file was not
          opened
	encryptedF	EncryptedzThe file is not encrypted)rL   rN   rM   rO   NTz@The file is encrypted. It may be decrypted with msoffcrypto-toolr   zKmsoffcrypto-tool raised an error when checking if the file is encrypted: {})rF   r   r    rg   r:   re   r   is_encryptedrJ   r   rN   rM   r9   r#   r{   )rP   r   	exceptions      r&   r   OleID.check_encryptedN  s     k5{#'99*E,13	 	y)xx		D""488,,"&	!%	(j	%   	D%IO!ZZIN$q$x$x  zC  %DI!!	Ds   AB 
C2CCc           
      z   [        SSS[        [        R                  SSS9nU R                  R                  U5        U R                  R                  5       (       d  U$ [        5       n[        R                  " U R                  5      n[        R                  " U5       HO  u  pE[        R                  SR!                  XE5      5        UR#                  U5        U=R$                  S-  sl        MQ     UR$                  S:  a:  S	R!                  S
R'                  U5      5      Ul        [        R*                  Ul        U$ )zy
Check whether this file has external relationships (remote template, OLE object, etc).

:returns: :py:class:`Indicator`
ext_relsr   zExternal RelationshipszHExternal relationships such as remote templates, remote OLE objects, etcF)rL   rR   rN   rM   rO   z(External relationship: type={} target={}   z9External relationships found: {} - use oleobj for detailsz, )rF   intr   r    rg   r:   rw   
is_openxmlsetr
   	XmlParserra   r	   find_external_relationshipslogdebugr{   addrJ   joinrM   r   rN   )rP   r   	rel_types	xmlparserrel_typetargets         r&   r   "OleID.check_external_relationshipsj  s     Z1IQT#'99*t,13 	x(xx""$$OE	OOD$5$56	 & B B9 MHII@GGYZMM(#NNaN !N >>A#^#e#e		)$$&H  IIHMr%   c                    [        SSSS[        R                  S9nU R                  R	                  U5        U R
                  (       d  gU R
                  R                  S5      (       a  SUl        [        R                  Ul	        U$ )z
Check whether this file contains an ObjectPool stream.

Such a stream would be a strong indicator for embedded objects or files.

:returns: :py:class:`Indicator` for ObjectPool stream or None if file
          was not opened

ObjectPoolFzlContains an ObjectPool stream, very likely to contain embedded OLE objects or files. Use oleobj to check it.)rL   rM   rN   NT)
rF   r   r    rg   r:   re   existsrJ   r   rN   )rP   objpools     r&   r   OleID.check_object_pool  sl     %lQ	
 	w'xx88??<(( GM88GL r%   c           
      D   [        SS[        SS[        R                  SS9nU R                  R                  U5        [        SS[        SS	[        R                  SS9nU R                  R                  U5        U R                  R                  [        R                  R                  :X  a  S
Ul        SUl        X4$ Sn [        R                  " U R                  U R                  S9nUR!                  5       (       a  SUl        [        R$                  Ul        SUl        UR)                  5       n[*        R,                  " U5      nUR/                  5         UR0                  (       a#  SUl        [        R2                  Ul        SUl        Ub  UR9                  5         SnU R                  R;                  5       (       a  U R<                  (       am   [        R                  " U R                  S9nUR?                  5       (       a#  SUl        [        R$                  Ul        SUl        Ub  UR9                  5         X4$ [        R@                  Ul        SUl        SUl        X4$ ! [4         a:  n[        R6                  Ul        SUl        S[        U5      -  Ul         SnAGNSnAff = f! Ub  UR9                  5         Snf = f! [4         a9  n[        R6                  Ul        SUl        S[        U5      -  Ul         SnANSnAff = f! Ub  UR9                  5         f f = f)za
Check whether this file contains macros (VBA and XLM/Excel 4).

:returns: :py:class:`Indicator`
vbaNoz
VBA Macrosz&This file does not contain VBA macros.F)rQ   rJ   rR   rL   rM   rN   rO   xlmz
XLM Macrosz.This file does not contain Excel 4/XLM macros.z#RTF files cannot contain VBA macrosz#RTF files cannot contain XLM macrosN)rf   r;   YeszeThis file contains VBA macros. No suspicious keyword was found. Use olevba and mraptor for more info.zYes, suspiciouszdThis file contains VBA macros. Suspicious keywords were found. Use olevba and mraptor for more info.r   z#Error while checking VBA macros: %s)rf   z:This file contains XLM macros. Use olevba to analyse them.z#Error while checking XLM macros: %sr   zIFor now, XLM macros can only be detected for files on disk, not in memory)!rF   r   r   r    rg   r:   rw   rx   r   ry   RTFrM   r   
VBA_Parserrf   r;   detect_vba_macrosrJ   r   rN   get_vba_code_all_modulesr   MacroRaptorscan
suspiciousr   r9   r#   r   is_excelr\   detect_xlm_macrosr"   )rP   vba_indicatorxlm_indicator
vba_parservba_codemes          r&   r   OleID.check_macros  s    "e4s.V'+yyG 	}-!e4s.^'+yyG 	}-88 1 11(MM%(MM% //
	**DMM		RJ++--&+#%)[[" -T)%>>@''1<<*;M')-M& 1WM- %  "J88   +!'!2!2DMM!JJ!3355.3+-1[[*4p1 "-"((* ++	 &*\\"&/#,w)++?  	W!%M")M(MPSTUPV(VM%%	W
 %  "J ! _)-M&*1M'0UX[\]X^0^M--_
 "-"((* .sV   ?CI" AK "
J&,/J!J) !J&&J) )K 
L/L<L	 LL	 	Lc           	         [        SS[        SS[        R                  S9nU R                  R                  U5        U R                  (       d  gU R                  R                  5        HU  nU R                  R                  U5      R                  5       n[        U5      nU=R                  [        U5      -  sl        MW     UR                  S:  a  [        R                  Ul        U$ )z
Check whether this file contains flash objects

:returns: :py:class:`Indicator` for count of flash objects or None if
          file was not opened
flashr   zFlash objectszvNumber of embedded Flash objects (SWF files) detected in OLE streams. Not 100% accurate, there may be false positives.r   N)rF   r   r   r    rg   r:   re   listdir
openstreamr^   rD   rJ   r4   r   rN   )rP   r   streamr;   r<   s        r&   r   OleID.check_flash  s     Qc%  	u%xxhh&&(F88&&v.335D &EKK3u:%K	 ) ;;?EJr%   )r;   ra   r\   rf   rw   rg   re   rh   )NN)r   r   r   r   r   rS   ro   r   r   r   r   r   r   r   r$   r   r%   r&   rW   rW      s8     !D.`)6882A,Fr%   rW   c            	      b   [        S[        -  5        [        S5        [        S5        [        S5        [        R                  " [        S9n U R                  S[        SSS	S
9  U R                  5       n[        UR                  5      S:X  a  U R                  5         g[        R                  " 5         UR                   H  n[        SU5        [        U5      nUR                  5       n[        R                   " / SQ/ SQ[        R"                  S9nU H  nUR$                  (       a  UR&                  (       d  M'  [(        R+                  UR,                  S5      nUR/                  UR0                  UR&                  UR,                  UR2                  4XwUS4S9  M     UR5                  5         M     g)zFCalled when running this file as script. Shows all info on input file.z(oleid %s - http://decalage.info/oletoolsz3THIS IS WORK IN PROGRESS - Check updates regularly!zGPlease report any issue at https://github.com/decalage2/oletools/issuesrs   )rM   input*FILEzName of files to process)rK   nargsmetavarhelpr   Nz	Filename:)r0   r0   
      )rF   ValueRiskDescription)
header_rowstyle)colors)print__version__argparseArgumentParserr   add_argumentr   
parse_argsr4   r   
print_helpr   enable_loggingrW   r   r   TableStreamTableStyleSlimSeprO   rJ   
risk_colorgetrN   	write_rowrL   rM   r   )parserargsrf   r   rg   tablerm   colors           r&   mainr      s\    

4{
BC	
?@	 9 :	"I$$9F
cf7  9 D 4::!JJk8$h[[]
''(83`.9.K.KM $I++IOOO"y~~t<)..R[RgRg h(-eT'B   D	 $ 	 r%   __main__)3r   
__future__r   r   r   sysr1   r7   r5   osr_   rc   pathnormpathabspathdirname__file___thismodule_dirr   _parent_dirinsertoletools.thirdparty.tablestreamr   oletoolsr   r   r   r   r	   r
   oletools.common.log_helperr   oletools.common.codepagesr   get_or_create_silent_loggerr   objectr   r   r   r   r    r!   r"   r#   r   rD   rF   rW   r   r   r   r%   r&   <module>r     sI  V &$ * / . . .  ''""277??277??83L#MNggrww||OTBCchhHHOOA{# 7 D D 1 7 ,,W5
6 
 	IIuKKHHgIIwIIvLL$JJ
0j+ +(kF k`	'R zF r%   