コード例 #1
0
ファイル: disasm.py プロジェクト: talsaiag/winappdbg
    def decode(self, address, code):

        # Decode each instruction in the buffer.
        result = []
        offset = 0
        while offset < len(code):

            # Decode the current instruction.
            opcode = libdisassemble.Opcode(code[offset:offset + 32])
            length = opcode.getSize()
            disasm = opcode.printOpcode('INTEL')
            hexdump = HexDump.hexadecimal(code[offset:offset + length])

            # Add the decoded instruction to the list.
            result.append((
                address + offset,
                length,
                disasm,
                hexdump,
            ))

            # Move to the next instruction.
            offset += length

        # Return the list of decoded instructions.
        return result
コード例 #2
0
ファイル: disasm.py プロジェクト: MarioVilas/winappdbg
    def decode(self, address, code):

        # Decode each instruction in the buffer.
        result = []
        offset = 0
        while offset < len(code):

            # Decode the current instruction.
            opcode  = libdisassemble.Opcode( code[offset:offset+32] )
            length  = opcode.getSize()
            disasm  = opcode.printOpcode('INTEL')
            hexdump = HexDump.hexadecimal( code[offset:offset+length] )

            # Add the decoded instruction to the list.
            result.append((
                address + offset,
                length,
                disasm,
                hexdump,
            ))

            # Move to the next instruction.
            offset += length

        # Return the list of decoded instructions.
        return result
コード例 #3
0
ファイル: disasm.py プロジェクト: MarioVilas/winappdbg
    def decode(self, address, code):

        # Decode each instruction in the buffer.
        result = []
        offset = 0
        while offset < len(code):

            # Try to decode the current instruction.
            instruction = pydasm.get_instruction(code[offset:offset+32],
                                                 pydasm.MODE_32)

            # Get the memory address of the current instruction.
            current = address + offset

            # Illegal opcode or opcode longer than remaining buffer.
            if not instruction or instruction.length + offset > len(code):
                hexdump = '%.2X' % ord(code[offset])
                disasm  = 'db 0x%s' % hexdump
                ilen    = 1

            # Correctly decoded instruction.
            else:
                disasm  = pydasm.get_instruction_string(instruction,
                                                        pydasm.FORMAT_INTEL,
                                                        current)
                ilen    = instruction.length
                hexdump = HexDump.hexadecimal(code[offset:offset+ilen])

            # Add the decoded instruction to the list.
            result.append((
                current,
                ilen,
                disasm,
                hexdump,
            ))

            # Move to the next instruction.
            offset += ilen

        # Return the list of decoded instructions.
        return result
コード例 #4
0
ファイル: disasm.py プロジェクト: talsaiag/winappdbg
    def decode(self, address, code):

        # Decode each instruction in the buffer.
        result = []
        offset = 0
        while offset < len(code):

            # Try to decode the current instruction.
            instruction = pydasm.get_instruction(code[offset:offset + 32],
                                                 pydasm.MODE_32)

            # Get the memory address of the current instruction.
            current = address + offset

            # Illegal opcode or opcode longer than remaining buffer.
            if not instruction or instruction.length + offset > len(code):
                hexdump = '%.2X' % ord(code[offset])
                disasm = 'db 0x%s' % hexdump
                ilen = 1

            # Correctly decoded instruction.
            else:
                disasm = pydasm.get_instruction_string(instruction,
                                                       pydasm.FORMAT_INTEL,
                                                       current)
                ilen = instruction.length
                hexdump = HexDump.hexadecimal(code[offset:offset + ilen])

            # Add the decoded instruction to the list.
            result.append((
                current,
                ilen,
                disasm,
                hexdump,
            ))

            # Move to the next instruction.
            offset += ilen

        # Return the list of decoded instructions.
        return result
コード例 #5
0
ファイル: disasm.py プロジェクト: MarioVilas/winappdbg
    def decode(self, address, code):

        # Get the constants for the requested architecture.
        arch, mode = self.__constants[self.arch]

        # Get the decoder function outside the loop.
        md = capstone.Cs(arch, mode)
        decoder = md.disasm_lite

        # If the buggy version of the bindings are being used, we need to catch
        # all exceptions broadly. If not, we only need to catch CsError.
        if self.__bug:
            CsError = Exception
        else:
            CsError = capstone.CsError

        # Create the variables for the instruction length, mnemonic and
        # operands. That way they won't be created within the loop,
        # minimizing the chances data might be overwritten.
        # This only makes sense for the buggy vesion of the bindings, normally
        # memory accesses are safe).
        length = mnemonic = op_str = None

        # For each instruction...
        result = []
        offset = 0
        while offset < len(code):

            # Disassemble a single instruction, because disassembling multiple
            # instructions may cause excessive memory usage (Capstone allocates
            # approximately 1K of metadata per each decoded instruction).
            instr = None
            try:
                instr = list(decoder(
                    code[offset:offset+16], address+offset, 1
                ))[0]
            except IndexError:
                pass   # No instructions decoded.
            except CsError:
                pass   # Any other error.

            # On success add the decoded instruction.
            if instr is not None:

                # Get the instruction length, mnemonic and operands.
                # Copy the values quickly before someone overwrites them,
                # if using the buggy version of the bindings (otherwise it's
                # irrelevant in which order we access the properties).
                length   = instr[1]
                mnemonic = instr[2]
                op_str   = instr[3]

                # Concatenate the mnemonic and the operands.
                if op_str:
                    disasm = "%s %s" % (mnemonic, op_str)
                else:
                    disasm = mnemonic

                # Get the instruction bytes as a hexadecimal dump.
                hexdump = HexDump.hexadecimal( code[offset:offset+length] )

            # On error add a "define constant" instruction.
            # The exact instruction depends on the architecture.
            else:

                # The number of bytes to skip depends on the architecture.
                # On Intel processors we'll skip one byte, since we can't
                # really know the instruction length. On the rest of the
                # architectures we always know the instruction length.
                if self.arch in (win32.ARCH_I386, win32.ARCH_AMD64):
                    length = 1
                else:
                    length = 4

                # Get the skipped bytes as a hexadecimal dump.
                skipped = code[offset:offset+length]
                hexdump = HexDump.hexadecimal(skipped)

                # Build the "define constant" instruction.
                # On Intel processors it's "db".
                # On ARM processors it's "dcb".
                if self.arch in (win32.ARCH_I386, win32.ARCH_AMD64):
                    mnemonic = "db "
                else:
                    mnemonic = "dcb "
                bytes = []
                for b in skipped:
                    if b.isalpha():
                        bytes.append("'%s'" % b)
                    else:
                        bytes.append("0x%x" % ord(b))
                op_str = ", ".join(bytes)
                disasm = mnemonic + op_str

            # Add the decoded instruction to the list.
            result.append((
                address + offset,
                length,
                disasm,
                hexdump,
            ))

            # Update the offset.
            offset += length

        # Return the list of decoded instructions.
        return result
コード例 #6
0
ファイル: disasm.py プロジェクト: talsaiag/winappdbg
    def decode(self, address, code):

        # Get the constants for the requested architecture.
        arch, mode = self.__constants[self.arch]

        # Get the decoder function outside the loop.
        decoder = capstone.cs_disasm_quick

        # If the buggy version of the bindings are being used, we need to catch
        # all exceptions broadly. If not, we only need to catch CsError.
        if self.__bug:
            CsError = Exception
        else:
            CsError = capstone.CsError

        # Create the variables for the instruction length, mnemonic and
        # operands. That way they won't be created within the loop,
        # minimizing the chances data might be overwritten.
        # This only makes sense for the buggy vesion of the bindings, normally
        # memory accesses are safe).
        length = mnemonic = op_str = None

        # For each instruction...
        result = []
        offset = 0
        while offset < len(code):

            # Disassemble a single instruction, because disassembling multiple
            # instructions may cause excessive memory usage (Capstone allocates
            # approximately 1K of metadata per each decoded instruction).
            instr = None
            try:
                instr = list(
                    decoder(arch, mode, code[offset:offset + 16],
                            address + offset, 1))[0]
            except IndexError:
                pass  # No instructions decoded.
            except CsError:
                pass  # Any other error.

            # On success add the decoded instruction.
            if instr is not None:

                # Get the instruction length, mnemonic and operands.
                # Copy the values quickly before someone overwrites them,
                # if using the buggy version of the bindings (otherwise it's
                # irrelevant in which order we access the properties).
                length = instr.size
                mnemonic = instr.mnemonic
                op_str = instr.op_str

                # Concatenate the mnemonic and the operands.
                if op_str:
                    disasm = "%s %s" % (mnemonic, op_str)
                else:
                    disasm = mnemonic

                # Get the instruction bytes as a hexadecimal dump.
                hexdump = HexDump.hexadecimal(code[offset:offset + length])

            # On error add a "define constant" instruction.
            # The exact instruction depends on the architecture.
            else:

                # The number of bytes to skip depends on the architecture.
                # On Intel processors we'll skip one byte, since we can't
                # really know the instruction length. On the rest of the
                # architectures we always know the instruction length.
                if self.arch in (win32.ARCH_I386, win32.ARCH_AMD64):
                    length = 1
                else:
                    length = 4

                # Get the skipped bytes as a hexadecimal dump.
                skipped = code[offset:offset + length]
                hexdump = HexDump.hexadecimal(skipped)

                # Build the "define constant" instruction.
                # On Intel processors it's "db".
                # On ARM processors it's "dcb".
                if self.arch in (win32.ARCH_I386, win32.ARCH_AMD64):
                    mnemonic = "db "
                else:
                    mnemonic = "dcb "
                bytes = []
                for b in skipped:
                    if b.isalpha():
                        bytes.append("'%s'" % b)
                    else:
                        bytes.append("0x%x" % ord(b))
                op_str = ", ".join(bytes)
                disasm = mnemonic + op_str

            # Add the decoded instruction to the list.
            result.append((
                address + offset,
                length,
                disasm,
                hexdump,
            ))

            # Update the offset.
            offset += length

        # Return the list of decoded instructions.
        return result
コード例 #7
0
    def search_process(cls,
                       process,
                       patterns,
                       minAddr=None,
                       maxAddr=None,
                       bufferPages=None,
                       overlapping=True):
        """
        Search for the given string or pattern within the process memory.

        @type  process: L{Process}
        @param process: Process to search.

        @type  patterns: L{list of Pattern}
        @param patterns: List of strings or wildcard patterns to search for.
            It must be an instance of a subclass of L{Pattern}.

            The following L{Pattern} subclasses are provided by WinAppDbg:
             - L{StringPattern} (case sensitive string search)
             - L{IStringPattern} (case insensitive string search)
             - L{HexPattern} (hexadecimal pattern with wildcards)

            You can also write your own subclass of L{Pattern}
            for customized searches.

        @type  minAddr: int
        @param minAddr: (Optional) Start the search at this memory address.

        @type  maxAddr: int
        @param maxAddr: (Optional) Stop the search at this memory address.

        @type  bufferPages: int
        @param bufferPages: (Optional) Number of memory pages to buffer when
            performing the search. Valid values are:
             - C{0} or C{None}: Automatically determine the required buffer size.
               This is the default.
             - C{> 0}: Set the buffer size in memory pages.
             - C{< 0}: Disable buffering entirely. This may give you a little
               speed gain at the cost of an increased memory usage. If the
               target process has very large contiguous memory regions it may
               actually be slower or even fail.

        @type  overlapping: bool
        @param overlapping: C{True} to allow overlapping results, C{False}
            otherwise.

            Overlapping results yield the maximum possible number of results.

            For example, if searching for "AAAA" within "AAAAAAAA" at address
            C{0x10000}, when overlapping is turned off the following matches
            are yielded::
                (0x10000, 4, "AAAA")
                (0x10004, 4, "AAAA")

            If overlapping is turned on, the following matches are yielded::
                (0x10000, 4, "AAAA")
                (0x10001, 4, "AAAA")
                (0x10002, 4, "AAAA")
                (0x10003, 4, "AAAA")
                (0x10004, 4, "AAAA")

            As you can see, the middle results are overlapping the last two.

        @rtype:  iterator of tuple( int, int, str )
        @return: An iterator of tuples. Each tuple contains the following:
             - The memory address where the pattern was found.
             - The size of the data that matches the pattern.
             - The data that matches the pattern.

        @raise WindowsError: An error occurred when querying or reading the
            process memory.
        """

        # Quit early if we have no list of patterns.
        if not patterns:
            return

        # Reset all patterns.
        for searcher in patterns:
            searcher.reset()

        # Get a list of allocated memory regions.
        memory = list()
        for mbi in process.get_memory_map(minAddr, maxAddr):
            if mbi.State == win32.MEM_COMMIT and \
                                        not mbi.Protect & win32.PAGE_GUARD:
                memory.append((mbi.BaseAddress, mbi.RegionSize))

        # If default buffer allocation is requested, calculate it.
        # We want one more page than the minimum required to allocate the
        # target string to find. Typically this will be 2 pages, since
        # most searches will not be looking for strings over 4k.
        # (We can't do it with 1 page - the target may be between pages!)
        if bufferPages is None or bufferPages == 0:
            bufferPages = MemoryAddresses.get_buffer_size_in_pages(
                0,
                sorted(map(len, patterns))[-1] + 1)

        # If no allocation limit is set,
        # read entire regions and search on them.
        if bufferPages <= 0:
            for (address, size) in memory:
                try:
                    data = process.read(address, size)
                except WindowsError, e:
                    begin = HexDump.address(address)
                    end = HexDump.address(address + size)
                    msg = "Error reading %s-%s: %s"
                    msg = msg % (begin, end, str(e))
                    warnings.warn(msg, MemoryAccessWarning)
                    continue
                for result in cls._search_block(process, patterns, data,
                                                address, 0, overlapping):
                    yield result
コード例 #8
0
                    end = address + total_size
                    shift = 0
                    buffer = process.read(address, min(size, total_size))
                    while 1:
                        for result in cls._search_block(
                                process, patterns, buffer, address, shift,
                                overlapping):
                            yield result
                        shift = step
                        address = address + step
                        if address >= end:
                            break
                        buffer = buffer[step:]
                        buffer = buffer + process.read(address, step)
                except WindowsError, e:
                    begin = HexDump.address(address)
                    end = HexDump.address(address + total_size)
                    msg = "Error reading %s-%s: %s"
                    msg = msg % (begin, end, str(e))
                    warnings.warn(msg, MemoryAccessWarning)

    @staticmethod
    def _search_block(process, patterns, data, address, shift, overlapping):
        for searcher in patterns:
            if shift == 0:
                searcher.reset()
            else:
                searcher.shift(shift)
            while 1:
                searcher.search(address, data, overlapping)
                if searcher.result is None:
コード例 #9
0
ファイル: search.py プロジェクト: MarioVilas/winappdbg
    def search_process(cls, process, patterns, minAddr = None,
                                               maxAddr = None,
                                               bufferPages = None,
                                               overlapping = True):
        """
        Search for the given string or pattern within the process memory.

        @type  process: L{Process}
        @param process: Process to search.

        @type  patterns: L{list of Pattern}
        @param patterns: List of strings or wildcard patterns to search for.
            It must be an instance of a subclass of L{Pattern}.

            The following L{Pattern} subclasses are provided by WinAppDbg:
             - L{StringPattern} (case sensitive string search)
             - L{IStringPattern} (case insensitive string search)
             - L{HexPattern} (hexadecimal pattern with wildcards)

            You can also write your own subclass of L{Pattern}
            for customized searches.

        @type  minAddr: int
        @param minAddr: (Optional) Start the search at this memory address.

        @type  maxAddr: int
        @param maxAddr: (Optional) Stop the search at this memory address.

        @type  bufferPages: int
        @param bufferPages: (Optional) Number of memory pages to buffer when
            performing the search. Valid values are:
             - C{0} or C{None}: Automatically determine the required buffer size.
               This is the default.
             - C{> 0}: Set the buffer size in memory pages.
             - C{< 0}: Disable buffering entirely. This may give you a little
               speed gain at the cost of an increased memory usage. If the
               target process has very large contiguous memory regions it may
               actually be slower or even fail.

        @type  overlapping: bool
        @param overlapping: C{True} to allow overlapping results, C{False}
            otherwise.

            Overlapping results yield the maximum possible number of results.

            For example, if searching for "AAAA" within "AAAAAAAA" at address
            C{0x10000}, when overlapping is turned off the following matches
            are yielded::
                (0x10000, 4, "AAAA")
                (0x10004, 4, "AAAA")

            If overlapping is turned on, the following matches are yielded::
                (0x10000, 4, "AAAA")
                (0x10001, 4, "AAAA")
                (0x10002, 4, "AAAA")
                (0x10003, 4, "AAAA")
                (0x10004, 4, "AAAA")

            As you can see, the middle results are overlapping the last two.

        @rtype:  iterator of tuple( int, int, str )
        @return: An iterator of tuples. Each tuple contains the following:
             - The memory address where the pattern was found.
             - The size of the data that matches the pattern.
             - The data that matches the pattern.

        @raise WindowsError: An error occurred when querying or reading the
            process memory.
        """

        # Quit early if we have no list of patterns.
        if not patterns:
            return

        # Reset all patterns.
        for searcher in patterns:
            searcher.reset()

        # Get a list of allocated memory regions.
        memory = list()
        for mbi in process.get_memory_map(minAddr, maxAddr):
            if mbi.State == win32.MEM_COMMIT and \
                                        not mbi.Protect & win32.PAGE_GUARD:
                memory.append( (mbi.BaseAddress, mbi.RegionSize) )

        # If default buffer allocation is requested, calculate it.
        # We want one more page than the minimum required to allocate the
        # target string to find. Typically this will be 2 pages, since
        # most searches will not be looking for strings over 4k.
        # (We can't do it with 1 page - the target may be between pages!)
        if bufferPages is None or bufferPages == 0:
            bufferPages = MemoryAddresses.get_buffer_size_in_pages(
                0, sorted(map(len, patterns))[-1] + 1)

        # If no allocation limit is set,
        # read entire regions and search on them.
        if bufferPages <= 0:
            for (address, size) in memory:
                try:
                    data = process.read(address, size)
                except WindowsError, e:
                    begin = HexDump.address(address)
                    end   = HexDump.address(address + size)
                    msg   = "Error reading %s-%s: %s"
                    msg   = msg % (begin, end, str(e))
                    warnings.warn(msg, MemoryAccessWarning)
                    continue
                for result in cls._search_block(
                            process, patterns, data, address, 0, overlapping):
                    yield result
コード例 #10
0
ファイル: search.py プロジェクト: MarioVilas/winappdbg
                    end    = address + total_size
                    shift  = 0
                    buffer = process.read(address, min(size, total_size))
                    while 1:
                        for result in cls._search_block(
                                    process, patterns, buffer,
                                    address, shift, overlapping):
                            yield result
                        shift   = step
                        address = address + step
                        if address >= end:
                            break
                        buffer  = buffer[step:]
                        buffer  = buffer + process.read(address, step)
                except WindowsError, e:
                    begin = HexDump.address(address)
                    end   = HexDump.address(address + total_size)
                    msg   = "Error reading %s-%s: %s"
                    msg   = msg % (begin, end, str(e))
                    warnings.warn(msg, MemoryAccessWarning)

    @staticmethod
    def _search_block(process, patterns, data, address, shift, overlapping):
        for searcher in patterns:
            if shift == 0:
                searcher.reset()
            else:
                searcher.shift(shift)
            while 1:
                searcher.search(address, data, overlapping)
                if searcher.result is None: