Beispiel #1
0
    def __init__(self,
                 filename,
                 session=None,
                 readers_public_key=None,
                 writers_private_key=None):
        self.fd = standard.WritableAddressSpace(filename=filename,
                                                session=session,
                                                mode="w+b")
        self.session = session
        self.profile = AgentProfile(session=session)
        self.cipher = CipherProperties(session=session).generate_keys()
        self.readers_public_key = readers_public_key
        self.writers_private_key = writers_private_key

        # Cipher is encrypted with the reader's public key - only the reader can
        # read it. It is also signed with the sender's private key.
        signature = Signature(session=session)
        cipher_plain_text = self.cipher.to_json()
        signature.encrypted_cipher = readers_public_key.encrypt(
            cipher_plain_text)
        signature.signature = writers_private_key.sign(cipher_plain_text)
        serialized_signature = signature.to_json()
        self.write_part(serialized_signature, "EncryptedCipher")
        self.hmac = hmac.HMAC(self.cipher.hmac_key.RawBytes(),
                              hashes.SHA256(),
                              backend=openssl.backend)
        self.hmac.update(serialized_signature)
Beispiel #2
0
    def collect(self):
        PAGE_SIZE = 0x1000

        # We write the image to the destination using the WritableAddressSpace.
        out_as = standard.WritableAddressSpace(
            filename=self.plugin_args.destination,
            session=self.session,
            mode="w+b")

        # Pad the header area with PAGE pattern:
        if self.profile.metadata("arch") == "AMD64":
            header = self.profile._DMP_HEADER64(vm=out_as)
            out_as.write(0, "PAGE" * (header.obj_size / 4))
            out_as.write(4, "DU64")
        else:
            # 32 bit systems use a smaller structure.
            header = self.profile._DMP_HEADER(vm=out_as)
            out_as.write(0, "PAGE" * (header.obj_size / 4))
            out_as.write(4, "DUMP")

            # PEA address spaces.
            if getattr(self.kernel_address_space, "pae", None):
                header.PaeEnabled = 1

        # Write the runs from our physical address space.
        number_of_pages = 0
        i = None

        for i, run in enumerate(self.physical_address_space.get_mappings()):
            # Convert to pages
            start = run.start / PAGE_SIZE
            length = run.length / PAGE_SIZE

            header.PhysicalMemoryBlockBuffer.Run[i].BasePage = start
            header.PhysicalMemoryBlockBuffer.Run[i].PageCount = length
            number_of_pages += length

        # There must be at least one run.
        if i is None:
            raise plugin.PluginError(
                "Physical address space has no available data.")

        header.PhysicalMemoryBlockBuffer.NumberOfRuns = i + 1
        header.PhysicalMemoryBlockBuffer.NumberOfPages = number_of_pages

        resolver = self.session.address_resolver

        # Set members of the crash header
        header.MajorVersion = 0xf
        header.MinorVersion = 0x1db1
        header.DirectoryTableBase = self.session.GetParameter("dtb")
        header.PfnDataBase = self._pointer_to_int(
            resolver.get_address_by_name("nt!MmPfnDatabase"))

        header.PsLoadedModuleList = self._pointer_to_int(
            resolver.get_address_by_name("nt!PsLoadedModuleList"))

        header.PsActiveProcessHead = self._pointer_to_int(
            resolver.get_address_by_name("nt!PsActiveProcessHead"))

        header.KdDebuggerDataBlock = self._pointer_to_int(
            resolver.get_address_by_name("nt!KdDebuggerDataBlock"))

        header.MachineImageType = 0x8664

        # Find the number of processors
        header.NumberProcessors = self.profile.get_constant_object(
            "KeNumberProcessors", "unsigned int")

        # Copy some stuff from _KUSER_SHARED_DATA.
        kuser_shared = self.profile.get_constant_object(
            "KI_USER_SHARED_DATA", "_KUSER_SHARED_DATA")
        header.SystemTime = kuser_shared.SystemTime.as_windows_timestamp()
        header.SystemUpTime = (
            kuser_shared.InterruptTime.LowPart +
            kuser_shared.InterruptTime.High1Time << 32) / 100000
        header.ProductType = kuser_shared.NtProductType
        header.SuiteMask = kuser_shared.SuiteMask

        # Zero out the BugCheck members
        header.BugCheckCode = 0x00000000
        header.BugCheckCodeParameter[0] = 0x00000000
        header.BugCheckCodeParameter[1] = 0x00000000
        header.BugCheckCodeParameter[2] = 0x00000000
        header.BugCheckCodeParameter[3] = 0x00000000

        # Set the sample run information
        header.RequiredDumpSpace = number_of_pages + header.obj_size / PAGE_SIZE
        header.DumpType = 1

        # Zero out the remaining non-essential fields from ContextRecordOffset
        # to ExceptionOffset.
        out_as.write(
            header.ContextRecord.obj_offset,
            "\x00" * (header.m("Exception").obj_offset -
                      header.ContextRecord.obj_offset))

        # Set the "converted" comment
        out_as.write(header.Comment.obj_offset,
                     "Created with Rekall Memory Forensics\x00")

        # Now copy the physical address space to the output file.
        output_offset = header.obj_size
        for run in self.physical_address_space.get_mappings():
            # Convert to pages
            start = run.start / PAGE_SIZE
            length = run.length / PAGE_SIZE

            yield ("\nRun [0x%08X, 0x%08X] \n" % (start, length), )
            data_length = length * PAGE_SIZE
            start_offset = start * PAGE_SIZE
            offset = 0
            while data_length > 0:
                to_read = min(data_length, self.buffer_size)

                data = self.physical_address_space.read(
                    start_offset + offset, to_read)

                out_as.write(output_offset, data)
                output_offset += len(data)
                offset += len(data)
                data_length -= len(data)
                self.session.render_progress(
                    "Wrote %sMB.", (start_offset + offset) / 1024 / 1024)

        # Rebuild the KDBG data block if needed. According to the
        # disassembly of nt!KdCopyDataBlock the data block is
        # encrypted when nt!KdpDataBlockEncoded is non zero:

        # ------ nt!KdCopyDataBlock ------
        # SUB RSP, 0x28
        # CMP BYTE [RIP+0x10fac7], 0x0   0x0 nt!KdpDataBlockEncoded
        # MOV RDX, RCX
        # JZ 0xf8000291e6a7              nt!KdCopyDataBlock + 0x57

        if self.plugin_args.rebuild or self.profile.get_constant_object(
                "KdpDataBlockEncoded", "byte") > 0:
            yield ("Rebuilding KDBG data block.\n", )
            self.RebuildKDBG(out_as)
Beispiel #3
0
            aux.vna_name = template.vna_name


def remove_symbol_versions(hdr):
    versyms = hdr.section_by_name(".gnu.version")
    sym_table = versyms.get_section()
    # Just remove all versions from all symbols.
    for i, other_ref in enumerate(sym_table):
        sym_table[i] = 0



if __name__ == "__main__":
    argument_parser = argparse.ArgumentParser()
    argument_parser.add_argument(
        'binary',
        default=None,
        help="Path to the ELF binary."
    )

    args = argument_parser.parse_args()
    print ("***Modifying file %s **" % args.binary)

    vm = standard.WritableAddressSpace(
        filename=args.binary, session=session.Session(), mode="r+b")
    profile = elf.ELFProfile(session=session)
    hdr = profile.elf64_hdr(vm=vm, offset=0)

    fix_version_needed(hdr)
    remove_symbol_versions(hdr)