8.4 PE文件节的特征提取

节中包含事实上真正运行的代码,所以也是特征提取的一个重点。

1.节头信息

节头中需要提取特征的信息列举如下。

节的个数:


len(binary.sections)

长度为0的节的个数:


sum(1 for s in binary.sections if s.size == 0)

名称为空的节的个数:


sum(1 for s in binary.sections if s.name == "")

可读可执行的节的个数。可读可执行,在lief中表示为:


lief.PE.SECTION_CHARACTERISTICS.MEM_READ
lief.PE.SECTION_CHARACTERISTICS.MEM_EXECUTE

统计可读可执行的节的个数的方法为:


sum(1 for s in binary.sections if s.has_characteristic(lief.PE.SECTION_CHARAC TERISTICS. MEM_READ)
    and s.has_characteristic(lief.PE.SECTION_CHARACTERISTICS.MEM_EXECUTE))

可写的节的个数:


sum(1 for s in binary.sections if s.has_characteristic(
    lief.PE.SECTION_CHARACTERISTICS.MEM_WRITE))

2.节大小

节的大小包括两部分:一个是节在物理文件中的大小,一个是节在内存中的大小。


section_sizes = [(s.name, len(s.content)) for s in binary.sections]
section_vsize = [(s.name, s.virtual_size) for s in binary.sections]

然后使用FeatureHasher均转换成维度为50的向量:


FeatureHasher(50, input_type="pair", dtype=self.dtype).transform(
    [section_sizes]).toarray(),
FeatureHasher(50, input_type="pair", dtype=self.dtype).transform(
    [section_entropy]).toarray(),
FeatureHasher(50, input_type="pair", dtype=self.dtype).transform(
    [section_vsize]).toarray()

3.节的熵

统计节的熵:并使用FeatureHasher均转换成维度为50的向量:


section_entropy = [(s.name, s.entropy) for s in binary.sections]
FeatureHasher(50, input_type="pair", dtype=self.dtype).transform(
    [section_entropy]).toarray()

4.节的入口点名称和属性

根据节的入口点(entry point),找到入口点的名称和属性。


entry = binary.section_from_offset(binary.entrypoint)
if entry is not None:
    entry_name = [entry.name]
    entry_characteristics = [str(c)
    for c in entry.characteristics_lists]
else:
    entry_name = []
    entry_characteristics = []

将入口点的名称和属性使用FeatureHasher转换成维度为50的向量:


FeatureHasher(50, input_type="string", dtype=self.dtype).transform(
 [entry_name]).toarray()
FeatureHasher(50, input_type="string", dtype=self.dtype).transform([entry_characteristics]).toarray()

将节的特征组成一个特征向量:


return np.concatenate([
    np.atleast_2d(np.asarray(general, dtype=self.dtype)),
    FeatureHasher(50, input_type="pair", dtype=self.dtype).transform(
        [section_sizes]).toarray(),
    FeatureHasher(50, input_type="pair", dtype=self.dtype).transform(
        [section_entropy]).toarray(),
    FeatureHasher(50, input_type="pair", dtype=self.dtype).transform(
        [section_vsize]).toarray(),
    FeatureHasher(50, input_type="string", dtype=self.dtype).transform(
        [entry_name]).toarray(),
    FeatureHasher(50, input_type="string", dtype=self.dtype).transform([entry_characteristics]).toarray()
    ], axis=-1).flatten().astype(self.dtype)