1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
U
T±d¹Gã@svdZddlZddlZddlZddlZddlZddlZddlZdZ    ej
Z
dZ Gdd„de ƒZ dd„Zd    d
„Zd d „ZdS) z‚peutils, Portable Executable utilities module
 
 
Copyright (c) 2005-2023 Ero Carrera <ero.carrera@gmail.com>
 
All rights reserved.
éNz Ero Carrerazero.carrera@gmail.comc@s|eZdZdZddd„Zddd„Zddd    „Zd d d „Zd!dd„Zd"dd„Z    dd„Z
d#dd„Z d$dd„Z d%dd„Z d&dd„ZdS)'ÚSignatureDatabasea±This class loads and keeps a parsed PEiD signature database.
 
    Usage:
 
        sig_db = SignatureDatabase('/path/to/signature/file')
 
    and/or
 
        sig_db = SignatureDatabase()
        sig_db.load('/path/to/signature/file')
 
    Signature databases can be combined by performing multiple loads.
 
    The filename parameter can be a URL too. In that case the
    signature database will be downloaded from that location.
    NcCsRt dtj¡|_tƒ|_d|_tƒ|_d|_tƒ|_    d|_
d|_ |j ||ddS)Nzh\[(.*?)\]\s+?signature\s*=\s*(.*?)(\s+\?\?)*\s*ep_only\s*=\s*(\w+)(?:\s*section_start_only\s*=\s*(\w+)|)r©ÚfilenameÚdata) ÚreÚcompileÚSÚ    parse_sigÚdictÚsignature_tree_eponly_trueÚsignature_count_eponly_trueÚsignature_tree_eponly_falseÚsignature_count_eponly_falseÚsignature_tree_section_startÚsignature_count_section_startÚ    max_depthÚ_SignatureDatabase__load©Úselfrr©rú>d:\z\workplace\vscode\pyvenv\venv\Lib\site-packages\peutils.pyÚ__init__&sþzSignatureDatabase.__init__éc     Cs‚tƒ}t|jƒD]b\}}|j|kr$q|j}d||dt|jƒd dd„|jDƒ¡f}| |j    |||dd|d¡qd     |¡d    S)
aGenerates signatures for all the sections in a PE file.
 
        If the section contains any data a signature will be created
        for it. The signature name will be a combination of the
        parameter 'name' and the section number and its name.
        z%s Section(%d/%d,%s)éÚcSsg|]}|tjkr|‘qSr)ÚstringÚ    printable©Ú.0ÚcrrrÚ
<listcomp>^s
zASignatureDatabase.generate_section_signatures.<locals>.<listcomp>FT)Úep_onlyÚsection_start_onlyÚ
sig_lengthÚ
)
ÚlistÚ    enumerateÚsectionsZ SizeOfRawDataÚPointerToRawDataÚlenÚjoinÚNameÚappendÚ&_SignatureDatabase__generate_signature)    rÚpeÚnamer#Zsection_signaturesÚidxÚsectionÚoffsetZsig_namerrrÚgenerate_section_signaturesHs,
üúÿ z-SignatureDatabase.generate_section_signaturescCs"| |jj¡}|j|||d|dS)z°Generate signatures for the entry point of a PE file.
 
        Creates a signature whose name will be the parameter 'name'
        and the section number and its name.
        T)r!r#)Zget_offset_from_rvaÚOPTIONAL_HEADERÚAddressOfEntryPointr-)rr.r/r#r2rrrÚgenerate_ep_signaturensÿz'SignatureDatabase.generate_ep_signatureFc
Cs^|j|||…}d dd„|Dƒ¡}|dkr4d}nd}|dkrFd}nd}d||||f}    |    S)Nú cSsg|]}dt|ƒ‘qS)z%02x)Úordrrrrr sz:SignatureDatabase.__generate_signature.<locals>.<listcomp>TÚtrueÚfalsez9[%s]
signature = %s
ep_only = %s
section_start_only = %s
)Ú__data__r*)
rr.r2r/r!r"r#rÚsignature_bytesÚ    signaturerrrZ__generate_signature{süz&SignatureDatabase.__generate_signatureTcCs8| |||¡}|r4|dkr(dd„|DƒS|ddSdS)aMatches and returns the exact match(es).
 
        If ep_only is True the result will be a string with
        the packer name. Otherwise it will be a list of the
        form (file_offset, packer_name) specifying where
        in the file the signature was found.
        FcSs g|]}|d|ddf‘qS)rréÿÿÿÿr)rÚmatchrrrr ©sz+SignatureDatabase.match.<locals>.<listcomp>rr>N©Ú_SignatureDatabase__match©rr.r!r"Úmatchesrrrr?–s      zSignatureDatabase.matchcCs*| |||¡}|r&|dkr|S|dSdS)z+Matches and returns all the likely matches.FrNr@rBrrrÚ    match_all¯s zSignatureDatabase.match_allc
Cs|dkrPz
|j}Wn$tk
r6}z‚W5d}~XYnX|j}dd„|jDƒ}nh|dkr z | ¡}Wn$tk
rˆ}z‚W5d}~XYnX|j}|jj}|g}n|j}|j}t    t
|ƒƒ}g}    |D]0}
|  |||
|
|j …¡} | rÀ|      |
| f¡qÀ|dkr
|    r
|    dS|    S)NTcSsg|]
}|j‘qSr)r()rr1rrrr Õsz-SignatureDatabase.__match.<locals>.<listcomp>r)r;Ú    Exceptionrr'Zget_memory_mapped_imager r4r5r Úranger)Ú(_SignatureDatabase__match_signature_treerr,) rr.r!r"rZexcpÚ
signaturesÚscan_addressesÚeprCr0ÚresultrrrZ__match¿s<
  ÿ
zSignatureDatabase.__matchc
Csz|}dg}|dkr|j}n|dkr(|j}g}|D]0}| |||||j…¡}    |    r0| ||    f¡q0|dkrv|rv|dS|S)NrT)rr rGrr,)
rZ    code_datar!r"rrIrHrCr0rKrrrÚ
match_data
s$ÿzSignatureDatabase.match_datarc     Cs2tƒ}|}tdd„|DƒƒD]´\}}|dkr0qÒ| |d¡}dt| ¡ƒkrˆtƒ}    t| ¡ƒD]}
|
ddkr^|     |
d¡q^| |    ¡d|krÌ| dd¡} ||dd…} | rÌ| | | | ||d¡¡|}q|dk    r.dt| ¡ƒkr.tƒ}    t| ¡ƒD]"}
|
ddkr|     |
d¡q| |    ¡|S)a
Recursive function to find matches along the signature tree.
 
        signature_tree  is the part of the tree left to walk
        data    is the data being checked against the signature tree
        depth   keeps track of how far we have gone down the tree
        cSs"g|]}t|tƒr|nt|ƒ‘qSr)Ú
isinstanceÚintr8©rÚbrrrr Dsz<SignatureDatabase.__match_signature_tree.<locals>.<listcomp>Nrrz??)r%r&ÚgetÚvaluesÚitemsr,ÚextendrG) rZsignature_treerÚdepthZ matched_namesr?r0ÚbyteZ
match_nextÚnamesÚitemZmatch_tree_alternateZdata_remainingrrrZ__match_signature_tree6s>  
 
ÿÿ
z(SignatureDatabase.__match_signature_treecCs|j||ddS)znLoad a PEiD signature file.
 
        Invoking this method on different files combines the signatures.
        rN)rrrrrÚload~szSignatureDatabase.loadcsè|dk    r†tj |¡sNz tj |¡}| ¡}| ¡Wq„tk
rJ‚Yq„XqŠzt    |dƒ}| ¡}| ¡WqŠtk
r‚‚YqŠXn|}|s’dSdd„‰|j
  |¡}|D]6\}}}}    }
|      ¡  ¡}    | dd¡  ¡}‡fdd„| ¡Dƒ} |    dkrúd    }    nd
}    |
dkrd    }
nd
}
d } |
d    kr6|j} |jd 7_n4|    d    krV|j} |jd 7_n|j} |jd 7_t| ƒD]^\}}|d t| ƒkr¬|  |tƒ¡| |<d| ||<n|  |tƒ¡| |<| |} | d 7} qr| |jkrª| |_qªdS) NÚrtcSsd|kr |St|dƒS)Nú?é)rN)ÚvaluerrrÚto_byte¨sz)SignatureDatabase.__load.<locals>.to_bytez\nrcsg|] }ˆ|ƒ‘qSrrrO©r^rrr Àsz,SignatureDatabase.__load.<locals>.<listcomp>r9TFrr)ÚosÚpathÚexistsÚurllibÚrequestÚurlopenÚreadÚcloseÚIOErrorÚopenr    ÚfindallÚstripÚlowerÚreplaceÚsplitrrr r r rr&r)rQr
r)rrrZsig_fZsig_datarCZ packer_namer=Zsuperfluous_wildcardsr!r"r<rUÚtreer0rVrr_rZ__load†sj   
 
 
 ú 
 
 
 
zSignatureDatabase.__load)NN)r)r)FFr)TF)TF)TF)r)NN)NN)Ú__name__Ú
__module__Ú __qualname__Ú__doc__rr3r6r-r?rDrArLrGrYrrrrrrs
"
&
ÿ
 
 
K
,
H
rcCsdS)rNr)r.rrrÚis_validísrtcCs¢d}d}t|dƒrŠ|jD]p}d}|jD]`}|j|jjkrJ|jdkrRnnd}|dk    r€||jkrt|dkr€nn|d7}|j}q&qd}| ¡}|rž|dS)zp
    unusual locations of import tables
    non recognized section names
    presence of long ASCII strings
    FrÚDIRECTORY_ENTRY_BASERELOCNéTr)ÚhasattrruÚentriesZrvar4r5Z get_warnings)r.Zrelocations_overlap_entry_pointZsequential_relocsZ
base_relocZlast_reloc_rvaZrelocZwarnings_while_parsingÚwarningsrrrÚ is_suspiciousòs,
 
 
$ÿþþ
 
rzcCs`t| ¡ƒ}|sdSd}d}|jD](}| ¡}t| ¡ƒ}|dkr"||7}q"||dkr\d}|S)a8Returns True is there is a high likelihood that a file is packed or contains compressed data.
 
    The sections of the PE file will be analyzed, if enough sections
    look like containing compressed data and the data makes
    up for more than 20% of the total file size, the function will
    return True.
    TFrgš™™™™™@gš™™™™™É?)r)Ztrimr'Z get_entropyÚget_data)r.Ztotal_pe_data_lengthZ)has_significant_amount_of_compressed_dataZtotal_compressed_datar1Z    s_entropyZs_lengthrrrÚis_probably_packed(s 
 
 r|)rsr`rrÚurllib.requestrcÚ urllib.parseÚ urllib.errorZpefileÚ
__author__Ú __version__Z __contact__Úobjectrrtrzr|rrrrÚ<module>s\6