File size: 2,142 Bytes
bdcd51c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import lief
import numpy as np
import json

def extract_features(pe_path):
    """Extract static features from a PE file using lief."""
    features = {}

    try:
        binary = lief.parse(pe_path)
    except Exception as e:
        return None, f"Failed to parse PE file: {e}"

    if binary is None:
        return None, "Not a valid PE file"

    # Header features
    features['has_debug'] = int(binary.has_debug)
    features['has_relocations'] = int(binary.has_relocations)
    features['has_resources'] = int(binary.has_resources)
    features['has_signature'] = int(binary.has_signatures)
    features['has_tls'] = int(binary.has_tls)
    features['has_configuration'] = int(binary.has_configuration)

    # Section features
    features['num_sections'] = len(binary.sections)
    section_sizes = [s.size for s in binary.sections]
    section_entropies = [s.entropy for s in binary.sections]
    features['section_mean_entropy'] = float(np.mean(section_entropies)) if section_entropies else 0.0
    features['section_max_entropy'] = float(np.max(section_entropies)) if section_entropies else 0.0
    features['section_mean_size'] = float(np.mean(section_sizes)) if section_sizes else 0.0

    # Import features
    if binary.has_imports:
        features['num_imports'] = sum(len(lib.entries) for lib in binary.imports)
        features['num_import_libs'] = len(binary.imports)
    else:
        features['num_imports'] = 0
        features['num_import_libs'] = 0

    # Export features
    if binary.has_exports:
        features['num_exports'] = len(binary.get_export().entries)
    else:
        features['num_exports'] = 0

    # Optional header
    oh = binary.optional_header
    features['virtual_size'] = oh.sizeof_image
    features['num_rva_and_sizes'] = oh.numberof_rva_and_size

    return features, None


if __name__ == "__main__":
    import sys
    if len(sys.argv) < 2:
        print("Usage: python extract_features.py <path_to_exe>")
        sys.exit(1)

    path = sys.argv[1]
    feats, err = extract_features(path)
    if err:
        print(f"Error: {err}")
    else:
        print(json.dumps(feats, indent=2))