(bv, addr)
| 26 | |
| 27 | |
| 28 | def find_jump_table(bv, addr): |
| 29 | for block in bv.get_basic_blocks_at(addr): |
| 30 | func = block.function |
| 31 | arch = func.arch |
| 32 | addrsize = arch.address_size |
| 33 | |
| 34 | # Grab the instruction tokens so that we can look for the table's starting address |
| 35 | tokens, length = arch.get_instruction_text(bv.read(addr, 16), addr) |
| 36 | |
| 37 | # Look for the next jump instruction, which may be the current instruction. Some jump tables will |
| 38 | # compute the address first then jump to the computed address as a separate instruction. |
| 39 | jump_addr = addr |
| 40 | while jump_addr < block.end: |
| 41 | info = arch.get_instruction_info(bv.read(jump_addr, 16), jump_addr) |
| 42 | if len(info.branches) != 0: |
| 43 | break |
| 44 | jump_addr += info.length |
| 45 | if jump_addr >= block.end: |
| 46 | print("Unable to find jump after instruction 0x%x" % addr) |
| 47 | continue |
| 48 | print("Jump at 0x%x" % jump_addr) |
| 49 | |
| 50 | # Collect the branch targets for any tables referenced by the clicked instruction |
| 51 | branches = [] |
| 52 | for token in tokens: |
| 53 | if InstructionTextTokenType( |
| 54 | token.type |
| 55 | ) == InstructionTextTokenType.PossibleAddressToken: # Table addresses will be a "possible address" token |
| 56 | tbl = token.value |
| 57 | print("Found possible table at 0x%x" % tbl) |
| 58 | i = 0 |
| 59 | while True: |
| 60 | # Read the next pointer from the table |
| 61 | data = bv.read(tbl + (i*addrsize), addrsize) |
| 62 | if len(data) == addrsize: |
| 63 | if addrsize == 4: |
| 64 | ptr = struct.unpack("<I", data)[0] |
| 65 | else: |
| 66 | ptr = struct.unpack("<Q", data)[0] |
| 67 | |
| 68 | # If the pointer is within the binary, add it as a destination and continue |
| 69 | # to the next entry |
| 70 | if (ptr >= bv.start) and (ptr < bv.end): |
| 71 | print("Found destination 0x%x" % ptr) |
| 72 | branches.append((arch, ptr)) |
| 73 | else: |
| 74 | # Once a value that is not a pointer is encountered, the jump table is ended |
| 75 | break |
| 76 | else: |
| 77 | # Reading invalid memory |
| 78 | break |
| 79 | |
| 80 | i += 1 |
| 81 | |
| 82 | # Set the indirect branch targets on the jump instruction to be the list of targets discovered |
| 83 | func.set_user_indirect_branches(jump_addr, branches) |
| 84 | |
| 85 |
nothing calls this directly
no test coverage detected