Ejemplo n.º 1
0
    def test_load_hints(self):
        """
        Test the load_hints() function
        """
  
        from flashre.hints import load_hints
        from flashre.binaries_helpers import ReverseFlashairBinary

        # Build a fake ReverseFlashairBinary object
        # Note: get_r2pipe() could be mocked too!
        rfb = ReverseFlashairBinary("", 0)
        rfb.strings = mock.MagicMock(return_value=list())

        # Some bad inputs
        bad_inputs = list()
        bad_inputs.append("x\n")
        bad_inputs.append("x:\n")
        bad_inputs.append("  2dc6e0:       d0 01           mov $1,$tp\n")
        bad_inputs.append("     100:       00 70           di\n")

        # Mock the open() builtin
        m_open = mock.mock_open()
        m_open.return_value = bad_inputs
        with mock.patch("flashre.hints.open", m_open):
            assert load_hints(rfb, "") is None
Ejemplo n.º 2
0
def naming_command(args):
    """
    Auto-name functions using well-known patterns.
    """

    # Initialize objects
    rfb = ReverseFlashairBinary(args.binary_filename, args.offset)
    strategy = NAMING_STRATEGIES[args.strategy]()

    # Start auto-naming
    candidates = dict()
    for offset, string in rfb.strings():
        # Discard non valid strings
        if strategy.drop_string(string):
            continue

        # Look for an instruction that manipulates this string
        instr_offsets = strategy.lookup(rfb, offset)
        if not instr_offsets:
            continue

        # Gather candidates
        fname, addresses = strategy.check(rfb, string, instr_offsets)
        if not fname:
            continue
        candidates[fname] = candidates.get(fname, set())
        candidates[fname].update(addresses)

    # Display the the results as r2 commands
    print_r2_definitions(candidates)
Ejemplo n.º 3
0
def strings_command(args):
    """
    Extract strings
    """

    # Initialize object
    rfb = ReverseFlashairBinary(args.binary_filename)

    # Display strings
    strings_count = json.loads(rfb.r2p.cmd("b 128; p=zj"))
    for entropy in strings_count["entropy"]:
        if entropy["value"] >= args.value:
            print rfb.r2p.cmd("s %s; b 128; psb" % entropy["addr"])
Ejemplo n.º 4
0
def xref_command(args):
    """
    Graph exploration.
    """

    # Initialize object
    rfb = ReverseFlashairBinary(args.binary_filename, args.offset)

    # Print xrefs
    if args.reverse:
        print '\n'.join([hex(f) for f in reverse_callgraph(rfb, args.address)])
    else:
        dump_functions(rfb, args.address)
Ejemplo n.º 5
0
def hints_command(args):
    """
    Display strings used in functions
    """

    # Initialize object
    rfb = ReverseFlashairBinary(args.binary_filename, args.offset)

    # Display strings used in functions
    if args.reverse:
        for address in open(args.keyword):
            reverse_hints(rfb, address.strip())
            print "===="
        return

    # Load hints and prologues
    hints = load_hints(rfb, args.offset, args.keyword)
    prologues = sorted(rfb.prologues())

    # Display hints
    hints_addresses = sorted(hints.keys())
    current_hint = hints_addresses.pop(0)
    faddr = prologues[0]

    for i in xrange(1, len(prologues) - 1):
        print_line = False
        faddr_next = prologues[i + 1]
        while faddr < current_hint < faddr_next:
            print hex(faddr), hex(current_hint), hints[current_hint]
            if len(hints_addresses):
                current_hint = hints_addresses.pop(0)
            else:
                current_hint = -1  # exit the while loop
            print_line = True
        if print_line:
            print "===="
        faddr = faddr_next
Ejemplo n.º 6
0
def demo_command(args):
    """
    Build the demo payload
    """

    # Initialize the RFB object
    base_address = 0xc0ffe0
    rfb = ReverseFlashairBinary(args.update_filename, base_address)

    # Search the user task string in the binary
    addresses = list()
    for offset, _str in rfb.strings():
        if _str.startswith("+user_task"):
            addr = offset + base_address
            addresses.append(addr)

    # Assemble MOV instruction with the addresses
    candidates = list()
    for addr in addresses:
        candidate = rfb.assemble("MOVU R1, 0x%x" % addr)
        candidates.extend(candidate)

    # Search these instructions in the binary
    printf_addresses = set()
    for candidate in candidates:
        for offset in r2_search_memory(rfb.r2p, candidate.encode("hex")):
            # Disassemble two instructions
            result = rfb.r2p.cmdj("pdj 2 @ %s" % offset)
            try:
                instruction = result[1]["disasm"]
            except (IndexError, KeyError):
                print("Error: incorrect format: %s" % result, file=sys.stderr)
                continue

            # Check if it is a function call
            if not instruction.startswith("BSR"):
                print("Error: instruction is not BSR! - %s" % instruction,
                      file=sys.stderr)
                continue

            # Return the function address
            try:
                address = instruction.split(" ")[1]
                printf_addresses.add(address)
            except IndexError:
                print("Error: instruction is not BSR! - %s" % instruction,
                      file=sys.stderr)
                continue

    # Only a single address is valid
    if len(printf_addresses) != 1:
        print("Error: several addresses for printf() - %s" % printf_addresses,
              file=sys.stderr)
        sys.exit()

    # Assemble the MOVU instruction
    #printf_addresses = set([0xD0DEE0])  # v4.00.00 - used in userpg()
    mov_list = rfb.assemble("MOVU R0, %s" % printf_addresses.pop())
    # Filter the 24bits MOVU variant
    movu = [instr for instr in mov_list if instr[1] == "\xd0"]
    if len(movu) != 1:
        print("Error: several MOVU remains - %s" % movu, file=sys.stderr)
        sys.exit()

    movu_r0 = movu[0]
    movu_r1 = "0ad1001e".decode("hex")  # MOVU R1, 0x1E000A
    calc = """+-------------+
|        77345|
+-------------+

+-+ +-+ +-+ +-+
|7| |8| |9| |/|
+-+ +-+ +-+ +-+

+-+ +-+ +-+ +-+
|4| |5| |6| |*|
+-+ +-+ +-+ +-+

+-+ +-+ +-+ +-+
|1| |2| |3| |-|
+-+ +-+ +-+ +-+

    +-+     +-+
    |0|     |+|
    +-+     +-+
"""

    # Add a RET and a NULL byte
    sys.stdout.write(movu_r0 + movu_r1 + "\x02\x70" + calc + "\x00")