Python volatility.win32.tasks.get_kdbg() Examples

The following are 30 code examples of volatility.win32.tasks.get_kdbg(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module volatility.win32.tasks , or try the search function .
Example #1
Source File: bigpagepools.py    From aumfor with GNU General Public License v3.0 5 votes vote down vote up
def generate_suggestions(self):
        """The nt!PoolBigPageTable and nt!PoolBigPageTableSize
        are found relative to nt!PoolTrackTable"""

        track_table = tasks.get_kdbg(self.obj_vm).PoolTrackTable

        for pair in self.distance:
            table_base = obj.Object("address", 
                offset = track_table - pair[0], 
                vm = self.obj_vm)

            table_size = obj.Object("address", 
                offset = track_table - pair[1], 
                vm = self.obj_vm)

            if table_size != 0 and self.obj_vm.is_valid_address(table_base):
                break

        debug.debug("Distance Map: {0}".format(repr(self.distance)))
        debug.debug("PoolTrackTable: {0:#x}".format(track_table))
        debug.debug("PoolBigPageTable: {0:#x} => {1:#x}".format(table_base.obj_offset, table_base))
        debug.debug("PoolBigPageTableSize: {0:#x} => {1:#x}".format(table_size.obj_offset, table_size))
        yield table_base, table_size

#--------------------------------------------------------------------------------
# Big Page Pool Scanner
#-------------------------------------------------------------------------------- 
Example #2
Source File: callbacks.py    From volatility with GNU General Public License v2.0 5 votes vote down vote up
def get_bugcheck_callbacks(addr_space):
        """
        Enumerate generic Bugcheck callbacks.

        Note: These structures don't exist in tagged pools, but you can find 
        them via KDDEBUGGER_DATA64 on all versions of Windows.
        """

        kdbg = tasks.get_kdbg(addr_space)
        list_head = kdbg.KeBugCheckCallbackListHead.dereference_as('_KBUGCHECK_CALLBACK_RECORD')

        for l in list_head.Entry.list_of_type("_KBUGCHECK_CALLBACK_RECORD", "Entry"):
            yield "KeBugCheckCallbackListHead", l.CallbackRoutine, l.Component.dereference() 
Example #3
Source File: idt.py    From volatility with GNU General Public License v2.0 5 votes vote down vote up
def calculate(self):
        addr_space = utils.load_as(self._config)

        # Currently we only support x86. The x64 does still have a GDT 
        # but hooking is prohibited and results in bugcheck. 
        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")

        for kpcr in tasks.get_kdbg(addr_space).kpcrs():
            for i, entry in kpcr.gdt_entries():
                yield i, entry 
Example #4
Source File: psxview.py    From volatility with GNU General Public License v2.0 5 votes vote down vote up
def check_pspcid(self, addr_space):
        """Enumerate processes by walking the PspCidTable"""
        ret = dict()

        # Follow the pointers to the table base
        kdbg = tasks.get_kdbg(addr_space)
        PspCidTable = kdbg.PspCidTable.dereference().dereference()

        # Walk the handle table
        for handle in PspCidTable.handles():
            if handle.get_object_type() == "Process":
                process = handle.dereference_as("_EPROCESS")
                ret[process.obj_vm.vtop(process.obj_offset)] = process

        return ret 
Example #5
Source File: bigpagepools.py    From volatility with GNU General Public License v2.0 5 votes vote down vote up
def generate_suggestions(self):
        """The nt!PoolBigPageTable and nt!PoolBigPageTableSize
        are found relative to nt!PoolTrackTable"""

        track_table = tasks.get_kdbg(self.obj_vm).PoolTrackTable

        for pair in self.distance:
            table_base = obj.Object("address", 
                offset = track_table - pair[0], 
                vm = self.obj_vm)

            table_size = obj.Object("address", 
                offset = track_table - pair[1], 
                vm = self.obj_vm)

            if table_size != 0 and self.obj_vm.is_valid_address(table_base):
                break

        debug.debug("Distance Map: {0}".format(repr(self.distance)))
        debug.debug("PoolTrackTable: {0:#x}".format(track_table))
        debug.debug("PoolBigPageTable: {0:#x} => {1:#x}".format(table_base.obj_offset, table_base))
        debug.debug("PoolBigPageTableSize: {0:#x} => {1:#x}".format(table_size.obj_offset, table_size))
        yield table_base, table_size

#--------------------------------------------------------------------------------
# Big Page Pool Scanner
#-------------------------------------------------------------------------------- 
Example #6
Source File: modules.py    From volatility with GNU General Public License v2.0 5 votes vote down vote up
def lsmod(addr_space):
    """ A Generator for modules """

    for m in tasks.get_kdbg(addr_space).modules():
        yield m 
Example #7
Source File: callbacks.py    From DAMM with GNU General Public License v2.0 5 votes vote down vote up
def get_bugcheck_callbacks(addr_space):
        """
        Enumerate generic Bugcheck callbacks.

        Note: These structures don't exist in tagged pools, but you can find 
        them via KDDEBUGGER_DATA64 on all versions of Windows.
        """

        kdbg = tasks.get_kdbg(addr_space)
        list_head = kdbg.KeBugCheckCallbackListHead.dereference_as('_KBUGCHECK_CALLBACK_RECORD')

        for l in list_head.Entry.list_of_type("_KBUGCHECK_CALLBACK_RECORD", "Entry"):
            yield "KeBugCheckCallbackListHead", l.CallbackRoutine, l.Component.dereference() 
Example #8
Source File: idt.py    From DAMM with GNU General Public License v2.0 5 votes vote down vote up
def calculate(self):
        addr_space = utils.load_as(self._config)

        # Currently we only support x86. The x64 does still have a GDT 
        # but hooking is prohibited and results in bugcheck. 
        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")

        for kpcr in tasks.get_kdbg(addr_space).kpcrs():
            for i, entry in kpcr.gdt_entries():
                yield i, entry 
Example #9
Source File: psxview.py    From DAMM with GNU General Public License v2.0 5 votes vote down vote up
def check_pspcid(self, addr_space):
        """Enumerate processes by walking the PspCidTable"""
        ret = dict()

        # Follow the pointers to the table base
        kdbg = tasks.get_kdbg(addr_space)
        PspCidTable = kdbg.PspCidTable.dereference().dereference()

        # Walk the handle table
        for handle in PspCidTable.handles():
            if handle.get_object_type() == "Process":
                process = handle.dereference_as("_EPROCESS")
                ret[process.obj_vm.vtop(process.obj_offset)] = process

        return ret 
Example #10
Source File: bigpagepools.py    From DAMM with GNU General Public License v2.0 5 votes vote down vote up
def generate_suggestions(self):
        """The nt!PoolBigPageTable and nt!PoolBigPageTableSize
        are found relative to nt!PoolTrackTable"""

        track_table = tasks.get_kdbg(self.obj_vm).PoolTrackTable

        for pair in self.distance:
            table_base = obj.Object("address", 
                offset = track_table - pair[0], 
                vm = self.obj_vm)

            table_size = obj.Object("address", 
                offset = track_table - pair[1], 
                vm = self.obj_vm)

            if table_size != 0 and self.obj_vm.is_valid_address(table_base):
                break

        debug.debug("Distance Map: {0}".format(repr(self.distance)))
        debug.debug("PoolTrackTable: {0:#x}".format(track_table))
        debug.debug("PoolBigPageTable: {0:#x} => {1:#x}".format(table_base.obj_offset, table_base))
        debug.debug("PoolBigPageTableSize: {0:#x} => {1:#x}".format(table_size.obj_offset, table_size))
        yield table_base, table_size

#--------------------------------------------------------------------------------
# Big Page Pool Scanner
#-------------------------------------------------------------------------------- 
Example #11
Source File: modules.py    From DAMM with GNU General Public License v2.0 5 votes vote down vote up
def lsmod(addr_space):
    """ A Generator for modules """

    for m in tasks.get_kdbg(addr_space).modules():
        yield m 
Example #12
Source File: malfind.py    From vortessence with GNU General Public License v2.0 5 votes vote down vote up
def _scan_kernel_memory(self, addr_space, rules):
        # Find KDBG so we know where kernel memory begins. Do not assume
        # the starting range is 0x80000000 because we may be dealing with
        # an image with the /3GB boot switch. 
        kdbg = tasks.get_kdbg(addr_space)

        start = kdbg.MmSystemRangeStart.dereference_as("Pointer")

        # Modules so we can map addresses to owners
        mods = dict((addr_space.address_mask(mod.DllBase), mod)
                    for mod in modules.lsmod(addr_space))
        mod_addrs = sorted(mods.keys())

        # There are multiple views (GUI sessions) of kernel memory.
        # Since we're scanning virtual memory and not physical, 
        # all sessions must be scanned for full coverage. This 
        # really only has a positive effect if the data you're
        # searching for is in GUI memory. 
        sessions = []

        for proc in tasks.pslist(addr_space):
            sid = proc.SessionId
            # Skip sessions we've already seen 
            if sid == None or sid in sessions:
                continue

            session_space = proc.get_process_address_space()
            if session_space == None:
                continue

            sessions.append(sid)
            scanner = DiscontigYaraScanner(address_space = session_space,
                                           rules = rules)

            for hit, address in scanner.scan(start_offset = start):
                module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(address))
                yield (module, address, hit, session_space.zread(address - self._config.REVERSE, self._config.SIZE)) 
Example #13
Source File: callbacks.py    From vortessence with GNU General Public License v2.0 5 votes vote down vote up
def get_bugcheck_callbacks(addr_space):
        """
        Enumerate generic Bugcheck callbacks.

        Note: These structures don't exist in tagged pools, but you can find 
        them via KDDEBUGGER_DATA64 on all versions of Windows.
        """

        kdbg = tasks.get_kdbg(addr_space)
        list_head = kdbg.KeBugCheckCallbackListHead.dereference_as('_KBUGCHECK_CALLBACK_RECORD')

        for l in list_head.Entry.list_of_type("_KBUGCHECK_CALLBACK_RECORD", "Entry"):
            yield "KeBugCheckCallbackListHead", l.CallbackRoutine, l.Component.dereference() 
Example #14
Source File: idt.py    From vortessence with GNU General Public License v2.0 5 votes vote down vote up
def calculate(self):
        addr_space = utils.load_as(self._config)

        # Currently we only support x86. The x64 does still have a GDT 
        # but hooking is prohibited and results in bugcheck. 
        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")

        for kpcr in tasks.get_kdbg(addr_space).kpcrs():
            for i, entry in kpcr.gdt_entries():
                yield i, entry 
Example #15
Source File: psxview.py    From vortessence with GNU General Public License v2.0 5 votes vote down vote up
def check_pspcid(self, addr_space):
        """Enumerate processes by walking the PspCidTable"""
        ret = dict()

        # Follow the pointers to the table base
        kdbg = tasks.get_kdbg(addr_space)
        PspCidTable = kdbg.PspCidTable.dereference().dereference()

        # Walk the handle table
        for handle in PspCidTable.handles():
            if handle.get_object_type() == "Process":
                process = handle.dereference_as("_EPROCESS")
                ret[process.obj_vm.vtop(process.obj_offset)] = process

        return ret 
Example #16
Source File: bigpagepools.py    From vortessence with GNU General Public License v2.0 5 votes vote down vote up
def generate_suggestions(self):
        """The nt!PoolBigPageTable and nt!PoolBigPageTableSize
        are found relative to nt!PoolTrackTable"""

        track_table = tasks.get_kdbg(self.obj_vm).PoolTrackTable

        for pair in self.distance:
            table_base = obj.Object("address", 
                offset = track_table - pair[0], 
                vm = self.obj_vm)

            table_size = obj.Object("address", 
                offset = track_table - pair[1], 
                vm = self.obj_vm)

            if table_size != 0 and self.obj_vm.is_valid_address(table_base):
                break

        debug.debug("Distance Map: {0}".format(repr(self.distance)))
        debug.debug("PoolTrackTable: {0:#x}".format(track_table))
        debug.debug("PoolBigPageTable: {0:#x} => {1:#x}".format(table_base.obj_offset, table_base))
        debug.debug("PoolBigPageTableSize: {0:#x} => {1:#x}".format(table_size.obj_offset, table_size))
        yield table_base, table_size

#--------------------------------------------------------------------------------
# Big Page Pool Scanner
#-------------------------------------------------------------------------------- 
Example #17
Source File: modules.py    From vortessence with GNU General Public License v2.0 5 votes vote down vote up
def lsmod(addr_space):
    """ A Generator for modules """

    for m in tasks.get_kdbg(addr_space).modules():
        yield m 
Example #18
Source File: malfind.py    From volatility with GNU General Public License v2.0 5 votes vote down vote up
def _scan_kernel_memory(self, addr_space, rules):
        # Find KDBG so we know where kernel memory begins. Do not assume
        # the starting range is 0x80000000 because we may be dealing with
        # an image with the /3GB boot switch. 
        kdbg = tasks.get_kdbg(addr_space)

        start = kdbg.MmSystemRangeStart.dereference_as("Pointer")

        # Modules so we can map addresses to owners
        mods = dict((addr_space.address_mask(mod.DllBase), mod)
                    for mod in modules.lsmod(addr_space))
        mod_addrs = sorted(mods.keys())

        # There are multiple views (GUI sessions) of kernel memory.
        # Since we're scanning virtual memory and not physical, 
        # all sessions must be scanned for full coverage. This 
        # really only has a positive effect if the data you're
        # searching for is in GUI memory. 
        sessions = []

        for proc in tasks.pslist(addr_space):
            sid = proc.SessionId
            # Skip sessions we've already seen 
            if sid == None or sid in sessions:
                continue

            session_space = proc.get_process_address_space()
            if session_space == None:
                continue

            sessions.append(sid)
            scanner = DiscontigYaraScanner(address_space = session_space,
                                           rules = rules)

            for hit, address in scanner.scan(start_offset = start):
                module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(address))
                yield (module, address - self._config.REVERSE, hit, session_space.zread(address - self._config.REVERSE, self._config.SIZE)) 
Example #19
Source File: callbacks.py    From volatility with GNU General Public License v2.0 5 votes vote down vote up
def get_bugcheck_callbacks(addr_space):
        """
        Enumerate generic Bugcheck callbacks.

        Note: These structures don't exist in tagged pools, but you can find 
        them via KDDEBUGGER_DATA64 on all versions of Windows.
        """

        kdbg = tasks.get_kdbg(addr_space)
        list_head = kdbg.KeBugCheckCallbackListHead.dereference_as('_KBUGCHECK_CALLBACK_RECORD')

        for l in list_head.Entry.list_of_type("_KBUGCHECK_CALLBACK_RECORD", "Entry"):
            yield "KeBugCheckCallbackListHead", l.CallbackRoutine, l.Component.dereference() 
Example #20
Source File: idt.py    From volatility with GNU General Public License v2.0 5 votes vote down vote up
def calculate(self):
        addr_space = utils.load_as(self._config)

        # Currently we only support x86. The x64 does still have a GDT 
        # but hooking is prohibited and results in bugcheck. 
        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")

        for kpcr in tasks.get_kdbg(addr_space).kpcrs():
            for i, entry in kpcr.gdt_entries():
                yield i, entry 
Example #21
Source File: psxview.py    From volatility with GNU General Public License v2.0 5 votes vote down vote up
def check_pspcid(self, addr_space):
        """Enumerate processes by walking the PspCidTable"""
        ret = dict()

        # Follow the pointers to the table base
        kdbg = tasks.get_kdbg(addr_space)
        PspCidTable = kdbg.PspCidTable.dereference().dereference()

        # Walk the handle table
        for handle in PspCidTable.handles():
            if handle.get_object_type() == "Process":
                process = handle.dereference_as("_EPROCESS")
                ret[PsXview.get_file_offset(process)] = process

        return ret 
Example #22
Source File: modules.py    From aumfor with GNU General Public License v3.0 5 votes vote down vote up
def lsmod(addr_space):
    """ A Generator for modules """

    for m in tasks.get_kdbg(addr_space).modules():
        yield m 
Example #23
Source File: bigpagepools.py    From volatility with GNU General Public License v2.0 5 votes vote down vote up
def generate_suggestions(self):
        """The nt!PoolBigPageTable and nt!PoolBigPageTableSize
        are found relative to nt!PoolTrackTable"""

        track_table = tasks.get_kdbg(self.obj_vm).PoolTrackTable

        for pair in self.distance:
            table_base = obj.Object("address", 
                offset = track_table - pair[0], 
                vm = self.obj_vm)

            table_size = obj.Object("address", 
                offset = track_table - pair[1], 
                vm = self.obj_vm)
                
            if (table_base % 0x1000 == 0 and
                    self.obj_vm.is_valid_address(table_base) and
                    table_size != 0 and 
                    table_size % 0x1000 == 0 and 
                    table_size < 0x1000000):
                break

        debug.debug("Distance Map: {0}".format(repr(self.distance)))
        debug.debug("PoolTrackTable: {0:#x}".format(track_table))
        debug.debug("PoolBigPageTable: {0:#x} => {1:#x}".format(table_base.obj_offset, table_base))
        debug.debug("PoolBigPageTableSize: {0:#x} => {1:#x}".format(table_size.obj_offset, table_size))
        yield table_base, table_size

#--------------------------------------------------------------------------------
# Big Page Pool Scanner
#-------------------------------------------------------------------------------- 
Example #24
Source File: modules.py    From volatility with GNU General Public License v2.0 5 votes vote down vote up
def lsmod(addr_space):
    """ A Generator for modules """

    for m in tasks.get_kdbg(addr_space).modules():
        yield m 
Example #25
Source File: malfind.py    From aumfor with GNU General Public License v3.0 5 votes vote down vote up
def _scan_kernel_memory(self, addr_space, rules):
        # Find KDBG so we know where kernel memory begins. Do not assume
        # the starting range is 0x80000000 because we may be dealing with
        # an image with the /3GB boot switch. 
        kdbg = tasks.get_kdbg(addr_space)

        start = kdbg.MmSystemRangeStart.dereference_as("Pointer")

        # Modules so we can map addresses to owners
        mods = dict((addr_space.address_mask(mod.DllBase), mod)
                    for mod in modules.lsmod(addr_space))
        mod_addrs = sorted(mods.keys())

        # There are multiple views (GUI sessions) of kernel memory.
        # Since we're scanning virtual memory and not physical, 
        # all sessions must be scanned for full coverage. This 
        # really only has a positive effect if the data you're
        # searching for is in GUI memory. 
        sessions = []

        for proc in tasks.pslist(addr_space):
            sid = proc.SessionId
            # Skip sessions we've already seen 
            if sid == None or sid in sessions:
                continue

            session_space = proc.get_process_address_space()
            if session_space == None:
                continue

            sessions.append(sid)
            scanner = DiscontigYaraScanner(address_space = session_space,
                                           rules = rules)

            for hit, address in scanner.scan(start_offset = start):
                module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(address))
                yield (module, address, hit, session_space.zread(address - self._config.REVERSE, self._config.SIZE)) 
Example #26
Source File: psxview.py    From aumfor with GNU General Public License v3.0 5 votes vote down vote up
def check_pspcid(self, addr_space):
        """Enumerate processes by walking the PspCidTable"""
        ret = dict()

        # Follow the pointers to the table base
        kdbg = tasks.get_kdbg(addr_space)
        PspCidTable = kdbg.PspCidTable.dereference().dereference()

        # Walk the handle table
        for handle in PspCidTable.handles():
            if handle.get_object_type() == "Process":
                process = handle.dereference_as("_EPROCESS")
                ret[PsXview.get_file_offset(process)] = process

        return ret 
Example #27
Source File: callbacks.py    From aumfor with GNU General Public License v3.0 5 votes vote down vote up
def get_bugcheck_callbacks(addr_space):
        """
        Enumerate generic Bugcheck callbacks.

        Note: These structures don't exist in tagged pools, but you can find 
        them via KDDEBUGGER_DATA64 on all versions of Windows.
        """

        kdbg = tasks.get_kdbg(addr_space)
        list_head = kdbg.KeBugCheckCallbackListHead.dereference_as('_KBUGCHECK_CALLBACK_RECORD')

        for l in list_head.Entry.list_of_type("_KBUGCHECK_CALLBACK_RECORD", "Entry"):
            yield "KeBugCheckCallbackListHead", l.CallbackRoutine, l.Component.dereference() 
Example #28
Source File: idt.py    From aumfor with GNU General Public License v3.0 5 votes vote down vote up
def calculate(self):
        addr_space = utils.load_as(self._config)

        # Currently we only support x86. The x64 does still have a GDT 
        # but hooking is prohibited and results in bugcheck. 
        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")

        for kpcr in tasks.get_kdbg(addr_space).kpcrs():
            for i, entry in kpcr.gdt_entries():
                yield i, entry 
Example #29
Source File: malfind.py    From volatility with GNU General Public License v2.0 4 votes vote down vote up
def calculate(self):

        if not has_yara:
            debug.error("Please install Yara from https://plusvic.github.io/yara/")

        addr_space = utils.load_as(self._config)

        rules = self._compile_rules()

        if self._config.KERNEL:

            # Find KDBG so we know where kernel memory begins. Do not assume
            # the starting range is 0x80000000 because we may be dealing with
            # an image with the /3GB boot switch. 
            kdbg = tasks.get_kdbg(addr_space)

            start = kdbg.MmSystemRangeStart.dereference_as("Pointer")

            # Modules so we can map addresses to owners
            mods = dict((addr_space.address_mask(mod.DllBase), mod)
                        for mod in modules.lsmod(addr_space))
            mod_addrs = sorted(mods.keys())

            # There are multiple views (GUI sessions) of kernel memory.
            # Since we're scanning virtual memory and not physical, 
            # all sessions must be scanned for full coverage. This 
            # really only has a positive effect if the data you're
            # searching for is in GUI memory. 
            sessions = []

            for proc in tasks.pslist(addr_space):
                sid = proc.SessionId
                # Skip sessions we've already seen 
                if sid == None or sid in sessions:
                    continue

                session_space = proc.get_process_address_space()
                if session_space == None:
                    continue

                sessions.append(sid)
                scanner = DiscontigYaraScanner(address_space = session_space,
                                               rules = rules)

                for hit, address in scanner.scan(start_offset = start):
                    module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(address))
                    yield (module, address, hit, session_space.zread(address - self._config.REVERSE, self._config.SIZE))

        else:
            for task in self.filter_tasks(tasks.pslist(addr_space)):
                scanner = VadYaraScanner(task = task, rules = rules)
                for hit, address in scanner.scan():
                    yield (task, address, hit, scanner.address_space.zread(address - self._config.REVERSE, self._config.SIZE)) 
Example #30
Source File: pooltracker.py    From aumfor with GNU General Public License v3.0 4 votes vote down vote up
def calculate(self):
        kernel_space = utils.load_as(self._config)

        if not self.is_valid_profile(kernel_space.profile):
            debug.error("Windows XP/2003 does not track pool tags")

        knowntags = {}
        if self._config.TAGFILE and os.path.isfile(self._config.TAGFILE):
            taglines = open(self._config.TAGFILE).readlines()
            for tag in taglines:
                tag = tag.strip()
                if tag.startswith("rem") or tag.startswith(" ") or tag == "":
                    continue
                info = tag.split("-", 2)
                try:
                    key = info[0].strip()
                    driver = info[1].strip()
                    reason = info[2].strip()
                except IndexError:
                    continue
                knowntags[key] = (driver, reason)

        track_table = tasks.get_kdbg(kernel_space).PoolTrackTable

        # not really an address, this is just a trick to get 
        # a 32bit number on x86 and 64bit number on x64. the
        # size is always directly before the pool table. 
        table_size = obj.Object("address", offset = 
            track_table - kernel_space.profile.get_obj_size("address"), 
            vm = kernel_space
            )

        track_table = track_table.dereference_as("address")

        if not kernel_space.is_valid_address(track_table) or table_size > 100000:
            debug.error("Cannot find the table or its size is unexpected: {0}".format(table_size))

        entries = obj.Object("Array", targetType = "_POOL_TRACKER_TABLE", 
            offset = track_table, count = table_size, 
            vm = kernel_space
            )

        if self._config.TAGS:
            tags = [tag for tag in self._config.TAGS.split(",")]
        else:
            tags = []

        for entry in entries:

            if not self._config.SHOW_FREE:
                if entry.PagedBytes == 0 and entry.NonPagedBytes == 0:
                    continue

            if not tags or entry.Key in tags:
                try:
                    (driver, reason) = knowntags[str(entry.Key).strip()]
                    if self._config.WHITELIST:
                        continue
                except KeyError:
                    (driver, reason) = ("", "")
                yield entry, driver, reason