Skip to content

Commit

Permalink
Improved signature generation + Added signatures to the embedded DB
Browse files Browse the repository at this point in the history
  • Loading branch information
dhondta committed Jan 20, 2024
1 parent c771c7a commit 1ccc528
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/peid/VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.0.0
2.0.1
52 changes: 32 additions & 20 deletions src/peid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,49 @@
__all__ = ["find_ep_only_signature", "identify_packer", "SignaturesDB"]


def find_ep_only_signature(*files, length=64, common_bytes_threshold=.5, logger=None):
def find_ep_only_signature(*files, minlength=16, maxlength=64, common_bytes_threshold=.5, logger=None):
""" Find a signature among the given files.
:param files: list of files to be compared in order to deduce a signature
:param length: signature length
:param mainlength: minimum signature length
:param maxlength: maximum signature length
:param common_bytes_threshold: minimal portion of bytes common to each file to be considered a valid signature
:return: signature string (PEiD format)
"""
#TODO: improve this algorithm to separate common bytes into [2-MAX] clusters of best patterns, thus yielding
# BEST_N (belongs to [2-MAX]) signatures and configurable through the MAX parameter
sig, data = [], []
# load maxlength-series of bytes for each input file
data = []
for f in files:
try:
with PE(f) as pe:
data.append(pe.read(length, pe.entrypoint_offst))
except ValueError as e:
bytes_from_ep = [f"{b:02X}" for b in list(pe.read(maxlength, pe.entrypoint_offset))[0]]
maxlength = max(min(len(bytes_from_ep), maxlength), minlength)
data.append(bytes_from_ep)
except (TypeError, ValueError) as e:
if logger:
logger.debug(f"{f}: {e}")
for i in range(length):
for d in data:
if len(sig) <= i:
sig.append(d[i])
elif d[i] != sig[-1]:
sig[-1] = "??"
if len(sig) == 0 or sig.count("??") / len(sig) > 1 - common_bytes_threshold:
if logger:
logger.warning("Could not find a suitable signature")
return
else:
raise ValueError("Could not find a suitable signature")
return " ".join(sig)
# now determine a signature
length = maxlength
while length >= minlength:
sig = []
for i in range(length):
for d in data:
if i >= len(d):
continue
if len(sig) <= i:
sig.append(d[i])
elif d[i] != sig[-1]:
sig[-1] = "??"
break
# right-strip "??" tokens up to the minimum length
while len(sig) > minlength and sig[-1] == "??":
sig = sig[:-1]
if sig.count("??") / len(sig) <= 1 - common_bytes_threshold:
# if it satisfies the condition, then right-strip remaining "??" tokens
while len(sig) > minlength and sig[-1] == "??":
sig = sig[:-1]
return " ".join(sig)
length -= 1
raise ValueError("Could not find a suitable signature")


def identify_packer(*paths, db=None, ep_only=True, sec_start_only=False, match_all=True, logger=None):
Expand Down
13 changes: 8 additions & 5 deletions src/peid/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,10 @@ def peidsig():
parser = ArgumentParser(description=descr, epilog=examples, formatter_class=RawTextHelpFormatter, add_help=False)
parser.add_argument("path", type=valid_file, nargs="+", help="path to packed portable executables")
sig = parser.add_argument_group("signature arguments")
sig.add_argument("-l", "--length", type=int, default=64, help="length of bytes to be considered for the signature"
" (default: 64)")
sig.add_argument("-m", "--min-length", type=int, default=16, help="minimum length of bytes to be considered for the"
" signature (default: 16)")
sig.add_argument("-M", "--max-length", type=int, default=64, help="maximum length of bytes to be considered for the"
" signature (default: 64)")
sig.add_argument("-t", "--bytes-threshold", type=valid_percentage, default=.5, help="proportion of common bytes"
" to be considered from the samples ; 0 <= x <= 1 (default: .5)")
opt = parser.add_argument_group("optional arguments")
Expand All @@ -110,15 +112,16 @@ def peidsig():
"formatted signature is displayed\n in addition, if --db is defined, the signature is saved")
extra = parser.add_argument_group("extra arguments")
extra.add_argument("-h", "--help", action="help", help="show this help message and exit")
extra.add_argument("--verbose", action="store_true", help="display debug information (default: False)")
args = parser.parse_args()
logging.basicConfig()
args.logger = logging.getLogger("peid")
args.logger.setLevel([logging.INFO, logging.DEBUG][args.verbose])
try:
s = find_ep_only_signature(*args.path, length=args.length, common_bytes_threshold=args.bytes_threshold,
logger=args.logger)
s = find_ep_only_signature(*args.path, minlength=args.min_length, maxlength=args.max_length,
common_bytes_threshold=args.bytes_threshold, logger=args.logger)
except ValueError:
print("[ERROR] Could not find a suitable signature")
print("[ERROR] Could not find a suitable signature\n")
return 1
if args.packer:
n = args.packer
Expand Down
31 changes: 30 additions & 1 deletion src/peid/db/userdb.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@
; - PEiDTab
; - ExeinfoPe
; - PEV
; 5587 signatures in list
; This DB also contains a few signatures based on this dataset: https://github.com/packing-box/dataset-packed-pe
; 5592 signatures in list

[ A win32 exe packer - http://github.com/Eronana/packer ]
signature = 60 68 00 ?? ?? 00 E8 07 FC FF FF 89 45 FC 61 FF 65 FC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ep_only = true

[Alienyze -> morfal]
signature = 55 8B EC 81 EC 60 01 00 00 53 56 64 A1 30 00 00 00 89 85 70 FF FF FF 8B 8D 70 FF FF FF 8B 51 0C 89 55 AC 8B 45 AC 8B 48 0C 8B 51 28 89 55 CC C7 45 B0 00 00 00 00 C7 45 94 00 00 00 00 8B 45 B0 8B 4D CC 0F B7 14 41 85 D2 74 23 8B 45 B0 8B 4D CC 0F B7 14 41 83 FA 5C 75 09 8B 45 B0 83 C0 01 89 45 94 8B 4D B0 83 C1 01 89 4D B0 EB CF 8B 55 AC 8B 42 14 8B 08 89 4D AC 8B 55 AC 8B 02 89 85
ep_only = true

[Eronana-Packer -> morfal]
signature = 60 68 00 ?? ?? ?? E8 17 FC FF FF 89 45 FC 61 FF 65 FC
ep_only = true

[ Embarcadero Delphi compiler XE7 - 2014 sign ASL ( 64 bit exe ) ]
signature = 55 48 83 EC 20 48 8B EC 90 48 8D 0D ?? ?? FF FF E8 ?? ?? ?? FF 48 8B 05 ?? ?? ?? 00 48 8B 08 E8 ?? ?? ?? FF 48 8B 05 ?? ?? ?? 00 48 8B 08
ep_only = true
Expand Down Expand Up @@ -2030,6 +2039,10 @@ ep_only = false
signature = 80 ?? ?? ?? 83 ?? ?? ?? ?? 90 90 90
ep_only = true

[ASPack -> morfal]
signature = 60 E8 03 00 00 00 E9 EB 04 5D 45 55 C3 E8 01 00 00 00 EB 5D BB ED FF FF FF 03 DD 81 EB 00 ?? ?? ?? 83 BD 88 04 00 00 00 89 9D 88 04 00 00 0F 85 CB 03 00 00 8D 85 94 04 00 00 50 FF 95 A9 0F 00 00 89 85 8C 04 00 00 8B F0 8D 7D 51 57 56 FF 95 A5 0F 00 00 AB B0 00 AE 75 FD 38 07 75 EE 8D 45 7A FF E0 56 69 72 74 75 61 6C 41 6C 6C 6F 63 00 56 69 72 74 75 61 6C 46 72 65 65 00 56 69 72 74
ep_only = true

[Aspack v2.12 -> www.aspack.com]
signature = ?? ?8 0? ?0 00 ?? ?? ?? ?? ?D ?? ?? ?? ?? ?? ?? ?? ?? ?? 5? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 0? ?3 ?? ?? 0? ?? 0? ?? ?? ?? ?? ?? 0? ?? ?F ?? ?? ?3 0? ?? ?? 8? ?? ?? ?? ?? ?? ?? ?? ?? 0? ?0 0? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?F 95 ?? ?? ?? ?? 8? ?? ?D ?? ?? ?? ?? 5
ep_only = true
Expand Down Expand Up @@ -5042,6 +5055,10 @@ ep_only = true
signature = 46 4F 58 53 51 5A
ep_only = true

[FSG -> morfal]
signature = BB D0 01 40 00 BF 00 10 40 00 BE ?? ?? ?? ?? 53 E8 0A 00 00 00 02 D2 75 05 8A 16 46 12 D2 C3 FC B2 80 A4 6A 02 5B FF 14 24 73 F7 33 C9 FF 14 24 73 18 33 C0 FF 14 24 73 21 B3 02 41 B0 10 FF 14 24 12 C0 73 F9 75 3F AA EB DC E8 43 00 00 00 2B CB 75 10 E8 38 00 00 00 EB 28 AC D1 E8 74 41 13 C9 EB 1C 91 48 C1 E0 08 AC E8 22 00 00 00 3D 00 7D 00 00 73 0A 80 FC 05 73 06 83 F8 7F 77 02 41
ep_only = true

[FSG 1.10 -> bart/xt]
signature = BB D0 01 40 00 BF 00 10 40 00 BE ?? ?? ?? 00 53 E8 0A 00 00 00 02 D2 75 05 8A 16 46 12 D2 C3 FC B2 80 A4 6A 02 5B FF 14 24 73 F7 33 C9 FF 14 24 73 18 33 C0 FF 14 24 73 21 B3 02 41 B0 10 FF 14 24 12 C0 73 F9 75 3F AA EB DC E8 43 00 00 00 2B CB 75 10 E8 38
ep_only = false
Expand Down Expand Up @@ -6570,6 +6587,10 @@ ep_only = true
signature = ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 1A 4A 61 72 1B
ep_only = false

[JDPack -> morfal]
signature = 60 E8 00 00 00 00 5D 8B D5 81 ED C6 2B 40 00 2B 95 61 34 40 00 81 EA 06 00 00 00 89 95 65 34 40 00 83 BD 69 34 40 00 00 0F 85 BC 03 00 00 C7 85 69 34 40 00 01 00 00 00 B9 88 07 00 00 8D B5 18 2C 40 00 8A 85 60 34 40 00 8A 1E 32 C3 88 06 88 9D 60 34 40 00 46 E2 EB
ep_only = true

[JDPack]
signature = 55 8B EC 6A FF 68 ?? ?? ?? ?? 68 ?? ?? ?? ?? 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 ?? ?? ?? E8 01 00 00 00 ?? ?? ?? ?? ?? ?? 05 00 00 00 00 83 C4 0C 5D 60 E8 00 00 00 00 5D 8B D5 64 FF 35 00 00 00 00 EB
ep_only = true
Expand Down Expand Up @@ -7058,6 +7079,10 @@ ep_only = true
signature = 1E 0E 1F BA ?? ?? 81 ?? ?? ?? B4 09 CD 21 1F B4 4C CD 21
ep_only = true

[MEW -> morfal]
signature = E9 ?? ?? ?? ?? 0C ?? ?? ?? 00 00 00 00 00 00 00 00 ?? ?? ?? ?? 0C
ep_only = true

[MEW 10 - Northfox]
signature = 33 C0 E9
ep_only = true
Expand Down Expand Up @@ -21274,6 +21299,10 @@ ep_only = true
signature = ?? ?? 83 EC ?? D9 34 24 8B 44 24 ?? ?? ?? ?? BF ?? ?? ?? ?? 8A 17 ?? ?? 8B C8 81 E1 ?? ?? ?? ?? EB ?? ?? ?? 30 10 FE CA 48 49
ep_only = true

[eXPressor -> morfal]
signature = 55 8B EC 81 EC 84 02 00 00 53 56 57 83 A5 A8 FD FF FF 00 F3 EB 0C 65 58 50 72 2D 76 2E 31 2E 36 2E 00 A1 00 ?? ?? ?? 05 00 ?? ?? ?? A3 04 ?? ?? ?? A1 04 ?? ?? ?? 83 78 70 00 75 14 6A 10 68 F0 ?? ?? ?? 68 78 ?? ?? ?? 6A 00 FF 15 50 ?? ?? ?? E8 F0 FE FF FF A3 08 ?? ?? ?? 68 04 01 00 00 8D 85 D8 FD FF FF 50 FF 35 14 ?? ?? ?? FF 15 48 ?? ?? ?? 8D 84 05 D7 FD FF FF 89 85 AC FD FF FF 8B
ep_only = true

[eXPressor 1.0 beta -> CGSoftLabs]
signature = E9 35 14 00 00 E9 31 13 00 00 E9 98 12 00 00 E9 EF 0C 00 00 E9 42 13 00 00 E9 E9 02 00 00 E9 EF 0B 00 00 E9 1B 0D 00 00 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2A 70 77 20 3D 20 30 78 25 30 34 78 20 20 2A 70 64 77 20 3D 20 30 78 25 30 38 78 00 00 00 00 00 00 00 00 00 42 61 64 20 70 6F 69 6E 74 65 72 3A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2A 70 64 77 20 3D 20 30 78 25 30 38 78 00 00 00 45 72 72 6F 72 3A 00 00 54 68 65 20 25 68 73 20 66 69 6C 65 20 69 73 20 0A 6C 69 6E 6B 65 64 20 74 6F 20 6D 69 73 73 69 6E 67 20 65 78 70
ep_only = true
Expand Down

0 comments on commit 1ccc528

Please sign in to comment.