Exemple #1
0
def lsmod(addr_space, profile):
    """ A Generator for modules (uses _KPCR symbols) """
    ## Locate the kpcr struct - this is hard coded right now
    kpcr = NewObject("_KPCR", kpcr_addr, addr_space, profile=profile)

    ## Try to dereference the KdVersionBlock as a 64 bit struct
    DebuggerDataList = kpcr.KdVersionBlock.dereference_as(
        "_DBGKD_GET_VERSION64").DebuggerDataList

    if DebuggerDataList.is_valid():
        offset = DebuggerDataList.dereference().v()
        ## This is a pointer to a _KDDEBUGGER_DATA64 struct. We only
        ## care about the PsActiveProcessHead entry:
        tmp = NewObject("_KDDEBUGGER_DATA64",
                        offset,
                        addr_space,
                        profile=profile).PsLoadedModuleList

        if not tmp.is_valid():
            ## Ok maybe its a 32 bit struct
            tmp = NewObject("_KDDEBUGGER_DATA32",
                            offset,
                            addr_space,
                            profile=profile).PsLoadedModuleList

        ## Try to iterate over the process list in PsActiveProcessHead
        ## (its really a pointer to a _LIST_ENTRY)
        for l in tmp.dereference_as("_LIST_ENTRY").list_of_type(
                "_LDR_MODULE", "InLoadOrderModuleList"):
            yield l
Exemple #2
0
def get_root(address_space, profile, stable=True):
    if stable:
        return NewObject("_CM_KEY_NODE",
                         ROOT_INDEX,
                         address_space,
                         profile=profile)
    else:
        return NewObject("_CM_KEY_NODE",
                         ROOT_INDEX | 0x80000000,
                         address_space,
                         profile=profile)
Exemple #3
0
    def list_of_type(self, type, member, forward=True):
        if not self.is_valid(): return

        ## Get the first element
        if forward:
            lst = self.Flink.dereference()
        else:
            lst = self.Blink.dereference()

        offset = self.profile.get_obj_offset(type, member)

        seen = set()
        seen.add(lst.offset)

        while 1:
            ## Instantiate the object
            obj = NewObject(type,
                            offset=lst.offset - offset,
                            vm=self.vm,
                            parent=self.parent,
                            profile=self.profile,
                            name=type)

            if forward:
                lst = obj.m(member).Flink.dereference()
            else:
                lst = obj.m(member).Blink.dereference()

            if not lst.is_valid() or lst.offset in seen: return
            seen.add(lst.offset)

            yield obj
Exemple #4
0
    def next_xpress(self, XpressHeader, XpressBlockSize):
        XpressHeaderOffset = XpressBlockSize + XpressHeader.offset + \
                             XpressHeader.size()

        ## We only search this far
        BLOCKSIZE = 1024
        original_offset = XpressHeaderOffset
        while 1:
            data = self.base.read(XpressHeaderOffset, BLOCKSIZE)
            Magic_offset = data.find("\x81\x81xpress")
            if Magic_offset >= 0:
                XpressHeaderOffset += Magic_offset
                break
            else:
                XpressHeaderOffset += len(data)

            ## Only search this far in advance
            if XpressHeaderOffset - original_offset > 10240:
                return None, None

        XpressHeader = NewObject("_IMAGE_XPRESS_HEADER",
                                 XpressHeaderOffset,
                                 self.base,
                                 profile=self.profile)
        XpressBlockSize = self.get_xpress_block_size(XpressHeader)

        return XpressHeader, XpressBlockSize
Exemple #5
0
def pslist(addr_space, profile):
    """ A Generator for _EPROCESS objects (uses _KPCR symbols) """

    ## Locate the kpcr struct - this is hard coded right now
    kpcr = NewObject("_KPCR", kpcr_addr, addr_space, profile=profile)

    ## Try to dereference the KdVersionBlock as a 64 bit struct
    DebuggerDataList = kpcr.KdVersionBlock.dereference_as(
        "_DBGKD_GET_VERSION64").DebuggerDataList
    PsActiveProcessHead = DebuggerDataList.dereference_as("_KDDEBUGGER_DATA64"
                                                          ).PsActiveProcessHead \
                     or DebuggerDataList.dereference_as("_KDDEBUGGER_DATA32"
                                                        ).PsActiveProcessHead \
                     or kpcr.KdVersionBlock.dereference_as("_KDDEBUGGER_DATA32"
                                                           ).PsActiveProcessHead

    if PsActiveProcessHead:
        print type(PsActiveProcessHead)
        ## Try to iterate over the process list in PsActiveProcessHead
        ## (its really a pointer to a _LIST_ENTRY)
        for l in PsActiveProcessHead.dereference_as(
                "_LIST_ENTRY").list_of_type("_EPROCESS", "ActiveProcessLinks"):
            yield l
    else:
        raise RuntimeError(
            "Unable to find PsActiveProcessHead - is this image supported?")
Exemple #6
0
    def __init__(self, baseAddressSpace, opts):
        assert (baseAddressSpace)
        self.runs = []
        self.base = baseAddressSpace
        self.PageDict = {}
        self.HighestPage = 0
        self.PageIndex = 0
        self.AddressList = []
        self.LookupCache = {}
        self.PageCache = Store(50)
        self.MemRangeCnt = 0
        self.offset = 0
        # Extract header information
        self.profile = Profile()
        self.header = NewObject('_IMAGE_HIBER_HEADER',
                                0,
                                baseAddressSpace,
                                profile=self.profile)

        ## Is the signature right?
        assert (self.header.Signature.v() == 'hibr')

        # Extract processor state
        self.ProcState = NewObject("_KPROCESSOR_STATE",
                                   2 * 4096,
                                   baseAddressSpace,
                                   profile=self.profile)

        ## This is a pointer to the page table - any ASs above us dont
        ## need to search for it.
        self.dtb = self.ProcState.SpecialRegisters.Cr3.v()

        try:
            fd = open("/tmp/cache.bin", 'rb')
            data = pickle.load(fd)
            self.PageDict, self.LookupCache = data
            fd.close()
        except (IOError, EOFError):
            self.build_page_cache()
            fd = open("/tmp/cache.bin", 'wb')
            pickle.dump((self.PageDict, self.LookupCache), fd, -1)
            fd.close()
Exemple #7
0
def subkeys(key):
    if not key.is_valid(): return
    if key.SubKeyCounts[0] > 0:
        sk_off = key.SubKeyLists[0]
        sk = NewObject("_CM_KEY_INDEX", sk_off, key.vm, profile=key.profile)
        if not sk or not sk.is_valid():
            pass
        else:
            for i in read_sklist(sk):
                if i.Signature.v() == NK_SIG:
                    yield i

    if key.SubKeyCounts[1] > 0:
        sk_off = key.SubKeyLists[1]
        sk = NewObject("_CM_KEY_INDEX", sk_off, key.vm, profile=key.profile)
        if not sk or not sk.is_valid():
            pass
        else:
            for i in read_sklist(sk):
                if i and i.Signature.v() == NK_SIG:
                    yield i
Exemple #8
0
    def _make_handle_array(self, offset, level):
        """ Returns an array of _HANDLE_TABLE_ENTRY rooted at offset,
        and iterates over them.

        """
        table = NewObject("Array",
                          offset,
                          self.vm,
                          count=0x200,
                          parent=self,
                          profile=self.profile,
                          target=Curry(NewObject, "_HANDLE_TABLE_ENTRY"))
        for t in table:
            offset = t.dereference_as('unsigned int')
            if not offset.is_valid(): break

            if level > 0:
                ## We need to go deeper:
                for h in self._make_handle_array(offset, level - 1):
                    yield h
            else:
                ## OK We got to the bottom table, we just resolve
                ## objects here:
                offset = int(offset) & ~0x00000007
                obj = NewObject("_OBJECT_HEADER",
                                offset,
                                self.vm,
                                parent=self,
                                profile=self.profile)
                try:
                    if obj.Type.Name.__str__() == 'File':
                        file = NewObject("_FILE_OBJECT",
                                         obj.Body.offset,
                                         self.vm,
                                         parent=self,
                                         profile=self.profile)
                        yield file

                except Exception, e:
                    pass
Exemple #9
0
    def get_tcb_connections(self, base_addr, TCBTableOff, SizeOff):
        """ Follow the list of TCB Tables specified.

        The TCBTable is a hash table of lists to existing
        connections. The TCBTableOff and SizeOff are offsets relative
        to the BaseAddress of the tcpip.sys module (i.e. they are
        static module variables) to the hash table in memory.
        """
        ## We first find the size of the hash table:
        hash_table_size = NewObject('unsigned long',
                                    base_addr + SizeOff,
                                    self.addr_space,
                                    profile=self.profile).v()

        ## This is how we define a new type on the fly - We dont
        ## actually store it in the profile we only use it here.
        TCB_Table = self.profile.list_to_type(
            ## Thats the name of the type
            "TCB_Table",
            ## This is the new type:
            ## It is a pointer to an array of size hash_table_size of pointers to _TCPT_OBJECTs
            [
                'pointer',
                ['array', hash_table_size, ['pointer', ['_TCPT_OBJECT']]]
            ])

        ## To actually use it we need to instantiate it directly (we
        ## never stored it in the profile so we cant use NewObject).
        ## When we instantiate it we need to provide it with the
        ## missing parameters, namely the offset and address_space.
        TCB_Table = TCB_Table(
            offset=base_addr + TCBTableOff,
            profile=self.profile,
            vm=self.addr_space,
        ).dereference()

        ## If the pointer fails to dereference (i.e. it points
        ## somewhere invalid), we skip it:
        if not TCB_Table: return

        ## Now we just iterate over all _TCPT_OBJECT in the table and
        ## see if they follow to linked lists. We then traverse the
        ## lists:
        for i in TCB_Table:
            while i.is_valid():
                yield i.Pid.v(
                ), i.RemoteIpAddress, i.RemotePort, i.LocalIpAddress, i.LocalPort
                i = i.Next
Exemple #10
0
    def _Peb(self, attr):
        """ Returns a _PEB object which is using the process address space.

        The PEB structure is referencing back into the process address
        space so we need to switch address spaces when we look at
        it. This method ensure this happens automatically.
        """
        process_ad = self.get_process_address_space()
        if process_ad:
            offset = self.m("Peb").v()
            peb = NewObject("_PEB",
                            offset,
                            vm=process_ad,
                            profile=self.profile,
                            name="Peb",
                            parent=self)

            if peb.is_valid():
                return peb
Exemple #11
0
def read_sklist(sk):
    if (sk.Signature.v() == LH_SIG or sk.Signature.v() == LF_SIG):
        for i in sk.List:
            yield i

    elif sk.Signature.v() == RI_SIG:
        for i in range(sk.Count):
            # Read and dereference the pointer
            ptr_off = sk.get_member_offset('List') + (i * 4)
            if not self.vm.is_valid_address(ptr_off): continue
            ssk_off = read_value(self.vm, "unsigned int", ptr_off)
            if not self.vm.is_valid_address(ssk_off): continue

            ssk = NewObject("_CM_KEY_INDEX",
                            ssk_off,
                            sk.vm,
                            profile=sk.profile)
            for i in read_sklist(ssk):
                yield i
Exemple #12
0
    def __init__(self, fname, mode='rb', fast=False):
        FileAddressSpace.__init__(self, fname, mode=mode, fast=fast)
        
        ## Parse the headers:
        address_space = FileAddressSpace(fname)
        profile = Profile(abstract_types=elf_types)
        header = NewObject('Elf32_Ehdr', 0, address_space, profile=profile)

        ## Create a sorted list of virtual offsets
        self.offsets = []
        for i in header.sections:
            if i.p_filesz.v() > 0:
                self.offsets.append((i.p_vaddr.v(), ## Vaddr start
                                     i.p_vaddr.v() + i.p_filesz.v(), ## Vaddr end
                                     i.p_offset.v()))

        def comp(x,y):
            if x[0]<y[0]: return -1
            return 1

        self.offsets.sort(comp)
        print self.offsets
Exemple #13
0
    def __init__(self, baseAddressSpace, opts):
        ## We must have an AS below us
        assert (baseAddressSpace)

        ## Must start with the magic PAGEDUMP
        assert (baseAddressSpace.read(0, 8) == 'PAGEDUMP')

        self.runs = []
        self.offset = opts.get('offset', 0)
        self.base = baseAddressSpace
        self.fname = ''
        self.profile = Profile()

        self.header = NewObject("_DMP_HEADER",
                                self.offset,
                                baseAddressSpace,
                                profile=self.profile)

        self.runs = [ (x.BasePage.v(), x.PageCount.v()) \
                      for x in self.header.PhysicalMemoryBlockBuffer.Run ]

        self.dtb = self.header.DirectoryTableBase.v()
Exemple #14
0
    def _find_dtb(self):
        offset = 0
        while 1:
            data = self.base.read(offset, BLOCKSIZE)
            found = 0
            if not data:
                break

            while 1:
                found = data.find("\x03\x00\x1b\x00", found + 1)
                if found >= 0:
                    (type, size) = unpack('=HH', data[found:found + 4])
                    proc = NewObject("_EPROCESS",
                                     offset + found,
                                     self.base,
                                     profile=self.profile)
                    if 'Idle' in proc.ImageFileName.v():
                        return proc.Pcb.DirectoryTableBase[0]
                else:
                    break

            offset += len(data)

        return None
Exemple #15
0
    def build_page_cache(self):
        XpressIndex = 0
        XpressHeader = NewObject("_IMAGE_XPRESS_HEADER",
                                 (self.header.FirstTablePage + 1) * 4096, \
                                 self.base, profile=self.profile)

        XpressBlockSize = self.get_xpress_block_size(XpressHeader)

        MemoryArrayOffset = self.header.FirstTablePage * 4096

        while MemoryArrayOffset:
            MemoryArray = NewObject('_MEMORY_RANGE_ARRAY',
                                    MemoryArrayOffset,
                                    self.base,
                                    profile=self.profile)

            EntryCount = MemoryArray.MemArrayLink.EntryCount.v()
            for i in MemoryArray.RangeTable:
                start = i.StartPage.v()
                end = i.EndPage.v()
                LocalPageCnt = end - start

                if end > self.HighestPage:
                    self.HighestPage = end

                tmp = [start * 0x1000, \
                       LocalPageCnt * 0x1000]
                self.AddressList.append(tmp)

                for j in range(0, LocalPageCnt):
                    if (XpressIndex and ((XpressIndex % 0x10) == 0)):
                        XpressHeader, XpressBlockSize = \
                                      self.next_xpress(XpressHeader, XpressBlockSize)

                    PageNumber = start + j
                    XpressPage = XpressIndex % 0x10
                    #print [(PageNumber,XpressBlockSize,XpressPage)]
                    if XpressHeader.offset not in self.PageDict:
                        self.PageDict[XpressHeader.offset] = \
                            [(PageNumber,XpressBlockSize,XpressPage)]
                    else:
                        self.PageDict[XpressHeader.offset].append(
                            (PageNumber, \
                             XpressBlockSize, XpressPage))

                    ## Update the lookup cache
                    self.LookupCache[PageNumber] = (XpressHeader.offset,
                                                    XpressBlockSize,
                                                    XpressPage)

                    self.PageIndex += 1
                    XpressIndex += 1

            NextTable = MemoryArray.MemArrayLink.NextTable.v()

            if (NextTable and (EntryCount == 0xFF)):
                MemoryArrayOffset = NextTable * 0x1000
                self.MemRangeCnt += 1
                XpressHeader,XpressBlockSize = \
                                             self.next_xpress(XpressHeader, XpressBlockSize)

                XpressIndex = 0
            else:
                MemoryArrayOffset = 0