如何检测(或清点)所有不使用 ASLR 的 DLL?

信息安全 记忆 零日 aslr IE浏览器
2021-08-26 06:33:04

基于这个 IE 零日,我有兴趣列出我们系统中所有已编译为不能与 ASLR 一起使用的 DLL。

理想情况下,我想分析一个静态文件而不是将其加载到内存中以检测它是否在没有 ASLR 保护的情况下编译。

最后,一旦我有一个与 ASLR 不兼容的文件列表,我能做些什么来防止或控制它们加载而不是卸载它?

3个回答

如果您只想知道一个 DLL 是否支持 ASLR,则将其加载到CFF Explorer中,转到 Optional Header 部分,然后单击该DllCharacteristics行。如果选中“DLL 可以移动”,那么它启用了 ASLR,否则不是。

如果你想做很多,我会编写一个 Python 脚本来枚举目标目录中的所有 DLL,然后使用pefile模块检查它们。这使您可以访问各种信息,包括DllCharacteristicsPE 标头的字段,您可以检查它是否IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE已设置。这会告诉你它是否启用了 ASLR。

在防止它们加载方面,您无能为力。但是,您可以使用 EMET 在进程上设置强制 ASLR,以强制加载的每个 DLL 都启用 ASLR,无论它是否在 PE 文件中设置。

感谢 @Polynomial 提供的出色pefile模块建议。我拼凑了一个快速的python脚本来做到这一点。可能还有改进的余地,但它似乎工作得很好。

import argparse
import os
import pefile


class DllCharacteristics():
    def __init__(self):
        self.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = False
        self.IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = False
        self.IMAGE_DLLCHARACTERISTICS_NO_BIND = False
        self.IMAGE_DLLCHARACTERISTICS_NO_SEH = False
        self.IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = False
        self.IMAGE_DLLCHARACTERISTICS_NX_COMPAT = False
        self.IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = False
        self.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = False


def get_dll_characteristics(path):
    foo = DllCharacteristics()

    pe = pefile.PE(path, fast_load=True)
    dll_characteristics = pe.OPTIONAL_HEADER.DllCharacteristics

    if dll_characteristics > 0:
        if dll_characteristics >= 32768:
            foo.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = True
            dll_characteristics -= 32768

        if dll_characteristics >= 8192:
            foo.IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = True
            dll_characteristics -= 8192

        if dll_characteristics == 2048 or dll_characteristics > 2080:
            foo.IMAGE_DLLCHARACTERISTICS_NO_BIND = True
            dll_characteristics -= 2048

        if dll_characteristics == 1024 or dll_characteristics > 1056:
            foo.IMAGE_DLLCHARACTERISTICS_NO_SEH = True
            dll_characteristics -= 1024

        if dll_characteristics == 512 or dll_characteristics > 544:
            foo.IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = True
            dll_characteristics -= 512

        if dll_characteristics == 256 or dll_characteristics > 288:
            foo.IMAGE_DLLCHARACTERISTICS_NX_COMPAT = True
            dll_characteristics -= 256

        if dll_characteristics >= 128:
            foo.IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = True
            dll_characteristics -= 128

        if dll_characteristics == 64:
            foo.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = True
            dll_characteristics -= 64

    return foo


if __name__ == '__main__':

    parser = argparse.ArgumentParser()
    parser.add_argument('dir', help='Directory to scan')
    args = parser.parse_args()

    dep_enabled = []
    dep_disabled = []

    aslr_enabled = []
    aslr_disabled = []

    for root, dirs, files in os.walk(args.dir):
        for f in files:
            bar = get_dll_characteristics(os.path.join(root, f))

            if bar.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE:
                aslr_enabled.append(f)
            else:
                aslr_disabled.append(f)

            if bar.IMAGE_DLLCHARACTERISTICS_NX_COMPAT:
                dep_enabled.append(f)
            else:
                dep_disabled.append(f)

    print "ASLR Enabled: "
    print "=============="
    for i in aslr_enabled:
        print i
    print ""

    print "ASLR Disabled: "
    print "==============="
    for i in aslr_disabled:
        print i
    print ""

    print "DEP Enabled: "
    print "============="
    for i in dep_enabled:
        print i
    print ""

    print "DEP Disabled: "
    print "=============="
    for i in dep_disabled:
        print i
    print ""

5 年后,我修改了@Ayrx 提供的代码,使用&运算符来测试@avakar 建议的标志。现在它可以正常工作了:

import argparse
import os
import pefile

class DllCharacteristics():
    def __init__(self):
        self.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = False
        self.IMAGE_DLLCHARACTERISTICS_GUARD_CF = False
        self.IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = False
        self.IMAGE_DLLCHARACTERISTICS_APPCONTAINER = False
        self.IMAGE_DLLCHARACTERISTICS_NO_BIND = False
        self.IMAGE_DLLCHARACTERISTICS_NO_SEH = False
        self.IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = False
        self.IMAGE_DLLCHARACTERISTICS_NX_COMPAT = False
        self.IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = False
        self.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = False
        self.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = False

def has_flag(value, flag):
    return value & flag == flag

def get_dll_characteristics(path):
    dc = DllCharacteristics()

    pe = pefile.PE(path, fast_load=True)
    dll_characteristics = pe.OPTIONAL_HEADER.DllCharacteristics

    if dll_characteristics > 0:
        dc.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = has_flag(dll_characteristics, 0x8000)
        dc.IMAGE_DLLCHARACTERISTICS_GUARD_CF = has_flag(dll_characteristics, 0x4000)
        dc.IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = has_flag(dll_characteristics, 0x2000)
        dc.IMAGE_DLLCHARACTERISTICS_APPCONTAINER = has_flag(dll_characteristics, 0x1000)
        dc.IMAGE_DLLCHARACTERISTICS_NO_BIND = has_flag(dll_characteristics, 0x0800)
        dc.IMAGE_DLLCHARACTERISTICS_NO_SEH = has_flag(dll_characteristics, 0x0400)
        dc.IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = has_flag(dll_characteristics, 0x0200)
        dc.IMAGE_DLLCHARACTERISTICS_NX_COMPAT = has_flag(dll_characteristics, 0x0100)
        dc.IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = has_flag(dll_characteristics, 0x0080)
        dc.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = has_flag(dll_characteristics, 0x0040)
        dc.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = has_flag(dll_characteristics, 0x0020)

    return dc


if __name__ == '__main__':

    parser = argparse.ArgumentParser()
    parser.add_argument('dir', help='Directory to scan')
    args = parser.parse_args()

    dep_enabled = []
    dep_disabled = []

    aslr_enabled = []
    aslr_disabled = []

    for root, dirs, files in os.walk(args.dir):
        for f in files:
            flags = get_dll_characteristics(os.path.join(root, f))

            if flags.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE:
                aslr_enabled.append(f)
            else:
                aslr_disabled.append(f)

            if flags.IMAGE_DLLCHARACTERISTICS_NX_COMPAT:
                dep_enabled.append(f)
            else:
                dep_disabled.append(f)

    print "ASLR Enabled: "
    print "=============="
    for i in aslr_enabled:
        print i
    print ""

    print "ASLR Disabled: "
    print "==============="
    for i in aslr_disabled:
        print i
    print ""

    print "DEP Enabled: "
    print "============="
    for i in dep_enabled:
        print i
    print ""

    print "DEP Disabled: "
    print "=============="
    for i in dep_disabled:
        print i
    print ""