示例#1
0
    def render_text(self, outfd, data):
        common.set_plugin_members(self)
        self.table_header(outfd, [
            ("PID", "8"),
            ("Name", "16"),
            ("Start Time", "32"),
            ("Priority", "6"),
            ("Start Function", "[addrpad]"),
            ("Function Map", ""),
        ])

        kaddr_info = common.get_handler_name_addrs(self)
        for proc in data:
            for th in proc.threads():
                func_addr = th.continuation

                (module,
                 handler_sym) = common.get_handler_name(kaddr_info, func_addr)
                if handler_sym:
                    handler = handler_sym
                elif module:
                    handler = module
                else:
                    handler = proc.find_map_path(func_addr)

                self.table_row(outfd, proc.p_pid, proc.p_comm, th.start_time(),
                               th.priority, func_addr, handler)
示例#2
0
    def render_text(self, outfd, data):
        common.set_plugin_members(self)
        self.table_header(outfd, [("PID","8"),
                                  ("Name", "16"),
                                  ("Start Time", "32"),
                                  ("Priority", "6"),
                                  ("Start Function", "[addrpad]"),
                                  ("Function Map", ""),
                                 ])
 
        kaddr_info = common.get_handler_name_addrs(self)
        for proc in data:
            for th in proc.threads():
                func_addr = th.continuation

                (module, handler_sym) = common.get_handler_name(kaddr_info, func_addr)
                if handler_sym:
                    handler = handler_sym
                elif module:
                    handler = module
                else:
                    handler = proc.find_map_path(func_addr)
                
                self.table_row(outfd, proc.p_pid, proc.p_comm, 
                    th.start_time(), 
                    th.sched_pri, 
                    func_addr, handler)
示例#3
0
    def render_text(self, outfd, data):
        common.set_plugin_members(self)
        self.table_header(
            outfd,
            [
                ("Offset", "[addrpad]"),
                ("Scope", "24"),
                ("IData", "[addrpad]"),
                ("Callback Addr", "[addrpad]"),
                ("Callback Mod", "24"),
                ("Callback Sym", ""),
            ],
        )

        kaddr_info = common.get_handler_name_addrs(self)

        for scope in data:
            scope_name = scope.ks_identifier

            for ls in scope.listeners():
                cb = ls.kll_callback.v()
                (module, handler_sym) = common.get_handler_name(kaddr_info, cb)
                self.table_row(
                    outfd,
                    ls.v(),
                    scope_name,
                    ls.kll_idata,
                    cb,
                    module,
                    handler_sym,
                )
示例#4
0
    def generator(self, data):
        kaddr_info = common.get_handler_name_addrs(self)

        for proc in data:
            for th in proc.threads():
                func_addr = th.continuation

                (module,
                 handler_sym) = common.get_handler_name(kaddr_info, func_addr)
                if handler_sym:
                    handler = handler_sym
                elif module:
                    handler = module
                else:
                    handler = proc.find_map_path(func_addr)

                yield (
                    0,
                    [
                        int(proc.p_pid),
                        str(proc.p_comm),
                        str(th.start_time()),
                        int(th.sched_pri),
                        Address(func_addr),
                        str(handler),
                    ],
                )
示例#5
0
    def _walk_opv_desc(self, kaddr_info):
        table_addr = self.addr_space.profile.get_symbol("_vfs_opv_descs")

        table = obj.Object(targetType = "unsigned long", theType = "Array", count = 32, vm = self.addr_space, offset = table_addr)

        for desc in table:
            if desc.v() == 0:
                break

            table_name = self.addr_space.profile.get_symbol_by_address("kernel", desc.v())
            if not table_name:
                table_name = "<unknown table>"

            vnodeopv_desc = obj.Object("vnodeopv_desc", offset = desc.v(), vm = self.addr_space)

            vdesc_arr = obj.Object(theType = "Array", targetType = "vnodeopv_entry_desc", offset = vnodeopv_desc.opv_desc_ops, count = 64, vm = self.addr_space)

            for vdesc in vdesc_arr: 
                ptr = vdesc.opve_impl.v()
                if ptr == 0:
                    break

                name = self.addr_space.read(vdesc.opve_op.vdesc_name.v(), 64)
                if name:
                    idx = name.find("\x00")
                    if idx != -1:
                        name = name[:idx]
                else:
                    name = "<INVALID NAME>"
                    
                name = table_name + "/" + name

                (module, handler_sym) = common.get_handler_name(kaddr_info, ptr)

                yield (vdesc.v(), name, ptr, module, handler_sym)  
示例#6
0
    def calculate(self):
        common.set_plugin_members(self)

        kaddr_info = common.get_handler_name_addrs(self)

        dict_ptr_addr = common.get_cpp_sym("sAllClassesDict",
                                           self.addr_space.profile)
        dict_addr = obj.Object("unsigned long",
                               offset=dict_ptr_addr,
                               vm=self.addr_space)

        fdict = obj.Object(self._struct_or_class("OSDictionary"),
                           offset=dict_addr.v(),
                           vm=self.addr_space)

        ents = obj.Object('Array',
                          offset=fdict.dictionary,
                          vm=self.addr_space,
                          targetType=self._struct_or_class("dictEntry"),
                          count=fdict.count)

        for ent in ents:
            if ent == None or not ent.is_valid():
                continue

            class_name = str(
                ent.key.dereference_as(self._struct_or_class("OSString")))

            osmeta = obj.Object(self._struct_or_class("OSMetaClass"),
                                offset=ent.value.v(),
                                vm=self.addr_space)

            cname = str(
                osmeta.className.dereference_as(
                    self._struct_or_class("OSString")))

            offset = 0

            if hasattr(osmeta, "metaClass"):
                arr_start = osmeta.metaClass.v()
            else:
                arr_start = obj.Object("Pointer",
                                       offset=osmeta.obj_offset,
                                       vm=self.addr_space)

            vptr = obj.Object("unsigned long",
                              offset=arr_start,
                              vm=self.addr_space)
            while vptr != 0:
                (module,
                 handler_sym) = common.get_handler_name(kaddr_info, vptr)

                yield (cname, vptr, module, handler_sym)

                offset = offset + vptr.size()

                vptr = obj.Object("unsigned long",
                                  offset=arr_start + offset,
                                  vm=self.addr_space)
示例#7
0
    def _walk_opv_desc(self, kaddr_info):
        table_addr = self.addr_space.profile.get_symbol("_vfs_opv_descs")

        table = obj.Object(
            targetType="unsigned long",
            theType="Array",
            count=32,
            vm=self.addr_space,
            offset=table_addr,
        )

        for desc in table:
            if desc.v() == 0:
                break

            table_name = self.addr_space.profile.get_symbol_by_address(
                "kernel", desc.v())
            if not table_name:
                table_name = "<unknown table>"

            vnodeopv_desc = obj.Object("vnodeopv_desc",
                                       offset=desc.v(),
                                       vm=self.addr_space)

            vdesc_arr = obj.Object(
                theType="Array",
                targetType="vnodeopv_entry_desc",
                offset=vnodeopv_desc.opv_desc_ops,
                count=64,
                vm=self.addr_space,
            )

            for vdesc in vdesc_arr:
                ptr = vdesc.opve_impl.v()
                if ptr == 0:
                    break

                name = self.addr_space.read(vdesc.opve_op.vdesc_name.v(), 64)
                if name:
                    idx = name.find(b"\x00")
                    if idx != -1:
                        name = name[:idx]
                else:
                    name = b"<INVALID NAME>"

                name = table_name + "/" + name.decode('ascii')

                (module,
                 handler_sym) = common.get_handler_name(kaddr_info, ptr)

                yield (vdesc.v(), name, ptr, module, handler_sym)
示例#8
0
    def calculate(self):
        common.set_plugin_members(self)

        nchrdev_addr = self.addr_space.profile.get_symbol("_nchrdev")
        nchrdev = obj.Object("unsigned int",
                             offset=nchrdev_addr,
                             vm=self.addr_space)

        cdevsw_addr = self.addr_space.profile.get_symbol("_cdevsw")
        cdevsw = obj.Object(
            theType="Array",
            targetType="cdevsw",
            offset=cdevsw_addr,
            vm=self.addr_space,
            count=nchrdev,
        )

        kaddr_info = common.get_handler_name_addrs(self)

        op_members = list(
            self.profile.types['cdevsw'].keywords["members"].keys())

        op_members.remove('d_ttys')
        op_members.remove('d_type')

        files = mac_list_files.mac_list_files(self._config).calculate()
        for vnode, path in files:
            if vnode.v_type.v() not in [3, 4]:
                continue

            if path.startswith("/Macintosh HD"):
                path = path[13:]

            dn = vnode.v_data.dereference_as("devnode")

            dev = dn.dn_typeinfo.dev
            major = (dev >> 24) & 0xFF

            if not (0 <= major <= nchrdev):
                continue

            cdev = cdevsw[major]

            for member in op_members:
                ptr = cdev.__getattr__(member).v()

                if ptr != 0:
                    (module,
                     handler_sym) = common.get_handler_name(kaddr_info, ptr)

                    yield (cdev.v(), path, member, ptr, module, handler_sym)
示例#9
0
    def _walk_vfstbllist(self, kaddr_info):
        table_size_ptr = self.addr_space.profile.get_symbol("_maxvfsconf")

        if table_size_ptr == None:
            table_size_ptr = self.addr_space.profile.get_symbol("_maxvfsslots")

        table_size = obj.Object("unsigned int",
                                offset=table_size_ptr,
                                vm=self.addr_space)

        table_ptr = self.addr_space.profile.get_symbol("_vfstbllist")
        table = obj.Object(
            theType="Array",
            targetType="vfstable",
            offset=table_ptr,
            count=table_size,
            vm=self.addr_space,
        )
        vfs_op_members = list(
            self.profile.types['vfsops'].keywords["members"].keys())

        if "vfs_reserved" in vfs_op_members:
            vfs_op_members.remove("vfs_reserved")

        for vfs in table:
            if not vfs.is_valid():
                continue

            name = self.addr_space.read(vfs.vfc_name.obj_offset, 16)
            if name:
                idx = name.find(b"\x00")
                if idx != -1:
                    name = name[:idx]
            else:
                name = b"<INVALID NAME>"

            if name == b"<unassigned>":
                break

            ops = vfs.vfc_vfsops

            for member in vfs_op_members:
                ptr = ops.__getattr__(member).v()

                if ptr == 0:
                    continue

                (module,
                 handler_sym) = common.get_handler_name(kaddr_info, ptr)

                yield (vfs.v(), name, ptr, module, handler_sym)
    def generator(self, data):
        kaddr_info = common.get_handler_name_addrs(self)

        for scope in data:
            cb = scope.ks_callback.v()
            (module, handler_sym) = common.get_handler_name(kaddr_info, cb)

            yield (0, [
                Address(scope.v()),
                str(scope.ks_identifier),
                Address(scope.ks_idata),
                str(len([l for l in scope.listeners()])),
                Address(cb),
                str(module),
                str(handler_sym),
            ])
示例#11
0
    def generator(self, data):
        kaddr_info = common.get_handler_name_addrs(self)

        for scope in data:
            cb = scope.ks_callback.v()
            (module, handler_sym) = common.get_handler_name(kaddr_info, cb)

            yield(0, [
                Address(scope.v()),
                str(scope.ks_identifier),
                Address(scope.ks_idata),
                int(len([l for l in scope.listeners()])),
                Address(cb),
                str(module),
                str(handler_sym),
                ])
    def generator(self, data):
        kaddr_info = common.get_handler_name_addrs(self)

        for scope in data:
            scope_name = scope.ks_identifier

            for ls in scope.listeners():
                cb = ls.kll_callback.v()
                (module, handler_sym) = common.get_handler_name(kaddr_info, cb)

                yield(0, [
                    Address(ls.v()),
                    str(scope_name),
                    Address(ls.kll_idata),
                    Address(cb),
                    str(module),
                    str(handler_sym),
                    ])
    def generator(self, data):
        kaddr_info = common.get_handler_name_addrs(self)

        for scope in data:
            scope_name = scope.ks_identifier

            for ls in scope.listeners():
                cb = ls.kll_callback.v()
                (module, handler_sym) = common.get_handler_name(kaddr_info, cb)

                yield (0, [
                    Address(ls.v()),
                    str(scope_name),
                    Address(ls.kll_idata),
                    Address(cb),
                    str(module),
                    str(handler_sym),
                ])
    def render_text(self, outfd, data):
        common.set_plugin_members(self)
        self.table_header(outfd, [("Offset", "[addrpad]"),
                          ("Scope", "24"),
                          ("IData", "[addrpad]"),
                          ("Callback Addr", "[addrpad]"),
                          ("Callback Mod", "24"),
                          ("Callback Sym", ""),])


        kaddr_info = common.get_handler_name_addrs(self)

        for scope in data:
            scope_name = scope.ks_identifier

            for ls in scope.listeners():
                cb = ls.kll_callback.v()
                (module, handler_sym) = common.get_handler_name(kaddr_info, cb)
                self.table_row(outfd, ls.v(), scope_name, ls.kll_idata, cb, module, handler_sym)
示例#15
0
    def calculate(self):
        common.set_plugin_members(self)

        kaddr_info = common.get_handler_name_addrs(self)

        real_ncpus = obj.Object("int", offset = self.addr_space.profile.get_symbol("_real_ncpus"), vm = self.addr_space)
        
        ptr = self.addr_space.profile.get_symbol("_cpu_data_ptr")
        cpu_data_ptrs = obj.Object(theType = 'Array', offset = ptr, vm = self.addr_space, targetType = "unsigned long long", count = real_ncpus)
        
        for i in range(real_ncpus):
            cpu_data = obj.Object('cpu_data', offset = cpu_data_ptrs[i], vm = self.addr_space)

            c = cpu_data.rtclock_timer
            q = c.queue
            
            ent = q.head.next
            first = ent
            seen = {}

            while ent.is_valid():
                seen[ent.v()] = 1

                timer = obj.Object("call_entry", offset = ent.v(), vm = self.addr_space)
                  
                func = timer.func.v()

                if func < 0x1000 or func == 0xffffffff00000000:
                    break

                (module, handler_sym) = common.get_handler_name(kaddr_info, func)
                
                if hasattr(timer, "entry_time"):
                    entry_time = timer.entry_time.v()
                else:
                    entry_time = -1
                
                yield func, timer.param0, timer.param1, timer.deadline, entry_time, module, handler_sym       
         
                ent = timer.q_link.next

                if ent == first or ent.v() in seen:
                    break
示例#16
0
    def _walk_vfstbllist(self, kaddr_info):
        table_size_ptr = self.addr_space.profile.get_symbol("_maxvfsconf")

        if table_size_ptr == None:
            table_size_ptr = self.addr_space.profile.get_symbol("_maxvfsslots")

        table_size = obj.Object("unsigned int", offset = table_size_ptr, vm = self.addr_space)

        table_ptr = self.addr_space.profile.get_symbol("_vfstbllist")
        table = obj.Object(theType = "Array", targetType = "vfstable", offset = table_ptr, count = table_size, vm = self.addr_space) 
        vfs_op_members = self.profile.types['vfsops'].keywords["members"].keys()
        
        if "vfs_reserved" in vfs_op_members:
            vfs_op_members.remove("vfs_reserved")

        for vfs in table:
            if not vfs.is_valid():
                continue

            name = self.addr_space.read(vfs.vfc_name.obj_offset, 16)
            if name:
                idx = name.find("\x00")
                if idx != -1:
                    name = name[:idx]
            else:
                name = "<INVALID NAME>"

            if name == "<unassigned>":
                break

            ops = vfs.vfc_vfsops

            for member in vfs_op_members:
                ptr = ops.__getattr__(member).v()

                if ptr == 0:
                    continue
                
                (module, handler_sym) = common.get_handler_name(kaddr_info, ptr)

                yield (vfs.v(), name, ptr, module, handler_sym)
示例#17
0
    def calculate(self):
        common.set_plugin_members(self)
        
        kaddr_info = common.get_handler_name_addrs(self)

        dict_ptr_addr = common.get_cpp_sym("sAllClassesDict", self.addr_space.profile)     
        dict_addr = obj.Object("unsigned long", offset = dict_ptr_addr, vm = self.addr_space)

        fdict = obj.Object(self._struct_or_class("OSDictionary"), offset = dict_addr.v(), vm = self.addr_space)
        
        ents = obj.Object('Array', offset = fdict.dictionary, 
                          vm = self.addr_space, 
                          targetType = self._struct_or_class("dictEntry"), 
                          count = fdict.count)

        for ent in ents:
            if ent == None or not ent.is_valid():
                continue
            
            class_name = str(ent.key.dereference_as(self._struct_or_class("OSString")))
           
            osmeta = obj.Object(self._struct_or_class("OSMetaClass"), offset = ent.value.v(), vm = self.addr_space)

            cname = str(osmeta.className.dereference_as(self._struct_or_class("OSString")))
            
            offset = 0

            if hasattr(osmeta, "metaClass"):
                arr_start = osmeta.metaClass.v()
            else:
                arr_start = obj.Object("Pointer", offset = osmeta.obj_offset, vm = self.addr_space)

            vptr = obj.Object("unsigned long", offset = arr_start, vm = self.addr_space)
            while vptr != 0:
                (module, handler_sym) = common.get_handler_name(kaddr_info, vptr)

                yield (cname, vptr, module, handler_sym)
                
                offset = offset + vptr.size()

                vptr = obj.Object("unsigned long", offset = arr_start + offset, vm = self.addr_space)
示例#18
0
    def calculate(self):
        common.set_plugin_members(self)

        nchrdev_addr = self.addr_space.profile.get_symbol("_nchrdev")
        nchrdev = obj.Object("unsigned int", offset = nchrdev_addr, vm = self.addr_space)

        cdevsw_addr = self.addr_space.profile.get_symbol("_cdevsw")
        cdevsw = obj.Object(theType = "Array", targetType = "cdevsw", offset = cdevsw_addr, vm = self.addr_space, count = nchrdev)

        kaddr_info = common.get_handler_name_addrs(self)

        op_members = self.profile.types['cdevsw'].keywords["members"].keys()
        
        op_members.remove('d_ttys')
        op_members.remove('d_type')

        files = mac_list_files.mac_list_files(self._config).calculate()
        for vnode, path in files:
            if vnode.v_type.v() not in [3, 4]:
                continue

            if path.startswith("/Macintosh HD"):
                path = path[13:]

            dn = vnode.v_data.dereference_as("devnode") 
 
            dev   = dn.dn_typeinfo.dev
            major = (dev >> 24) & 0xff

            if not (0 <= major <= nchrdev):
                continue
        
            cdev = cdevsw[major]
           
            for member in op_members:
                ptr = cdev.__getattr__(member).v()
        
                if ptr != 0: 
                    (module, handler_sym) = common.get_handler_name(kaddr_info, ptr)

                    yield (cdev.v(), path, member, ptr, module, handler_sym)
示例#19
0
    def render_text(self, outfd, data):
        common.set_plugin_members(self)
        
        self.table_header(outfd, [("Offset", "[addrpad]"),
                          ("Name", "24"),
                          ("IData", "[addrpad]"),
                          ("Listeners", "5"),
                          ("Callback Addr", "[addrpad]"),
                          ("Callback Mod", "24"),
                          ("Callback Sym", ""),])

        kaddr_info = common.get_handler_name_addrs(self)
        
        for scope in data:
            cb = scope.ks_callback.v()
            (module, handler_sym) = common.get_handler_name(kaddr_info, cb) 
            
            self.table_row(outfd, scope.v(),
                                  scope.ks_identifier,
                                  scope.ks_idata,
                                  len([l for l in scope.listeners()]), 
                                  cb, module, handler_sym)
示例#20
0
    def generator(self, data):
        kaddr_info = common.get_handler_name_addrs(self)

        for proc in data:
            for th in proc.threads():
                func_addr = th.continuation

                (module, handler_sym) = common.get_handler_name(kaddr_info, func_addr)
                if handler_sym:
                    handler = handler_sym
                elif module:
                    handler = module
                else:
                    handler = proc.find_map_path(func_addr)
                
                yield(0, [
                    int(proc.p_pid),
                    str(proc.p_comm),
                    str(th.start_time()),
                    str(th.priority),
                    Address(func_addr),
                    str(handler),
                    ])
示例#21
0
    def walk_reg_entry(self, reg_addr):
        regroot = obj.Object(self._struct_or_class("IORegistryEntry"), offset = reg_addr, vm = self.addr_space)
        
        fdict = regroot.fRegistryTable

        props = self.parse_properties(regroot.fPropertyTable)

        ents = obj.Object('Array', offset = fdict.dictionary, 
                          vm = self.addr_space, 
                          targetType = self._struct_or_class("dictEntry"), 
                          count = fdict.count)

        keys     = []
        children = []
        current_name = ""
        device_mem = False

        for ent in ents:
            if ent == None or not ent.is_valid():
                continue
            
            key = str(ent.key.dereference_as(self._struct_or_class("OSString")))
            
            keys.append(key)
          
            if key == "IODeviceMemory":
                current_name = str(ent.value.dereference_as(self._struct_or_class("OSString")))
                device_mem = True
 
            if key == "IOName" and device_mem == False:
                current_name = str(ent.value.dereference_as(self._struct_or_class("OSString")))

            if key == "IOServiceChildLinks":
                children.append(ent.value)

        if current_name == "":
            if "IOClass" in props:
                addr = props["IOClass"]
                s = obj.Object(self._struct_or_class("OSString"), offset = addr, vm = self.addr_space)
                current_name = "IOCLass: %s" % str(s)

        if current_name == "":
            serv = obj.Object(self._struct_or_class("IOService"), offset = reg_addr, vm = self.addr_space)
            buf  = self.addr_space.read(serv.pwrMgt.Name, 128)           
            if buf:
                idx = buf.find("\x00")
                if idx != -1:
                    buf = buf[:idx]

                current_name = buf

        prop_string = "".join(["%s=%x, " % (k,v) for (k,v) in props.items()])

        #print "%-20s | %s | %s" % (current_name, keys, prop_string)

        offset = self.addr_space.profile.get_obj_offset(self._struct_or_class("_IOServiceInterestNotifier"), "chain")

        for (k, v) in props.items():
            if k.find("nterest") != -1:
                cmd = obj.Object(self._struct_or_class("IOCommand"), offset = v, vm = self.addr_space)
                notifier_ptr = cmd.fCommandChain.next
                first_ptr = notifier_ptr

                last = 0

                while notifier_ptr.is_valid() and notifier_ptr != last:
                    notifier = obj.Object(self._struct_or_class("_IOServiceInterestNotifier"), offset = notifier_ptr - offset, vm = self.addr_space)

                    if not notifier.handler.is_valid():
                        break
   
                    last = notifier_ptr
                    notifier_ptr = notifier.chain.next

                    if notifier_ptr == first_ptr:
                        break

                    handler = notifier.handler.v()

                    (module, handler_sym) = common.get_handler_name(kaddr_info, handler)

                    yield k, handler, module, handler_sym          
 
        for child in children: 
            for k, handler, module, handler_sym in self.walk_child_links(child):
                yield k, handler, module, handler_sym
示例#22
0
    def walk_reg_entry(self, reg_addr):
        regroot = obj.Object(
            self._struct_or_class("IORegistryEntry"),
            offset=reg_addr,
            vm=self.addr_space,
        )

        fdict = regroot.fRegistryTable

        props = self.parse_properties(regroot.fPropertyTable)

        ents = obj.Object(
            'Array',
            offset=fdict.dictionary,
            vm=self.addr_space,
            targetType=self._struct_or_class("dictEntry"),
            count=fdict.count,
        )

        keys = []
        children = []
        current_name = ""
        device_mem = False

        for ent in ents:
            if ent == None or not ent.is_valid():
                continue

            key = str(ent.key.dereference_as(
                self._struct_or_class("OSString")))

            keys.append(key)

            if key == "IODeviceMemory":
                current_name = str(
                    ent.value.dereference_as(
                        self._struct_or_class("OSString")))
                device_mem = True

            if key == "IOName" and device_mem == False:
                current_name = str(
                    ent.value.dereference_as(
                        self._struct_or_class("OSString")))

            if key == "IOServiceChildLinks":
                children.append(ent.value)

        if current_name == "":
            if "IOClass" in props:
                addr = props["IOClass"]
                s = obj.Object(
                    self._struct_or_class("OSString"),
                    offset=addr,
                    vm=self.addr_space,
                )
                current_name = "IOCLass: %s" % str(s)

        if current_name == "":
            serv = obj.Object(
                self._struct_or_class("IOService"),
                offset=reg_addr,
                vm=self.addr_space,
            )
            buf = self.addr_space.read(serv.pwrMgt.Name, 128)
            if buf:
                idx = buf.find(b"\x00")
                if idx != -1:
                    buf = buf[:idx]

                current_name = buf

        prop_string = "".join(
            ["%s=%x, " % (k, v) for (k, v) in list(props.items())])

        # print "%-20s | %s | %s" % (current_name, keys, prop_string)

        offset = self.addr_space.profile.get_obj_offset(
            self._struct_or_class("_IOServiceInterestNotifier"), "chain")

        for (k, v) in list(props.items()):
            if k.find("nterest") != -1:
                cmd = obj.Object(
                    self._struct_or_class("IOCommand"),
                    offset=v,
                    vm=self.addr_space,
                )
                notifier_ptr = cmd.fCommandChain.next
                first_ptr = notifier_ptr

                last = 0

                while notifier_ptr.is_valid() and notifier_ptr != last:
                    notifier = obj.Object(
                        self._struct_or_class("_IOServiceInterestNotifier"),
                        offset=notifier_ptr - offset,
                        vm=self.addr_space,
                    )

                    if not notifier.handler.is_valid():
                        break

                    last = notifier_ptr
                    notifier_ptr = notifier.chain.next

                    if notifier_ptr == first_ptr:
                        break

                    handler = notifier.handler.v()

                    (module, handler_sym) = common.get_handler_name(
                        kaddr_info, handler)

                    yield k, handler, module, handler_sym

        for child in children:
            for k, handler, module, handler_sym in self.walk_child_links(
                    child):
                yield k, handler, module, handler_sym