Ejemplo n.º 1
0
    def visit(self, program, is_definition, add_refs_as_defs):
        if not is_definition:
            return

        # type could be None if type class not handled
        if self._type is None:
            return

        if isinstance(self._type, VoidType):
            return

        bv = program.bv
        br = bn.BinaryReader(bv)
        mem = program.memory()
        begin = self._address
        end = begin + self._type.size(self._arch)

        for ea in range(begin, end):
            br.seek(ea)
            seg = bv.get_segment_at(ea)
            # _elf_header is getting recovered as variable
            # get_segment_at(...) returns None for elf_header
            if seg is None:
                continue

            mem.map_byte(ea, br.read8(), seg.writable, seg.executable)
Ejemplo n.º 2
0
 def __init__(self, bv, options):
     BackgroundTaskThread.__init__(self, 'Beginning scan for crypto constructs...', True)
     self.bv = bv
     self.options = options
     self.br = bn.BinaryReader(self.bv, bn.Endianness.LittleEndian)
     self.log_info('Initialising Plugin')
     self.scanconfigs = []
     self.load_configs()
     self.log_info('Loaded {count} configurations'.format(count = len(self.scanconfigs)))
Ejemplo n.º 3
0
 def get_ascii_str_at(self, addr):
     br = binaryninja.BinaryReader(self.bv)
     br.seek(addr)
     c = br.read8()
     s = ''
     while (c != 0) and (c < 0x80) and c is not None:
         s += chr(c)
         c = br.read8()
     return s
Ejemplo n.º 4
0
 def _fill_bytes(self, program, memory, start, end, ref_eas):
     br = bn.BinaryReader(program.bv)
     for bb in self._bn_func.basic_blocks:
         for ea in range(bb.start, bb.end):
             seg = program.bv.get_segment_at(ea)
             br.seek(ea)
             memory.map_byte(ea, br.read8(), seg.writable, seg.executable)
             inst = self._bn_func.get_low_level_il_at(ea)
             if inst and not is_unimplemented(program.bv, inst):
                 _collect_xrefs_from_inst(program.bv, inst, ref_eas)
Ejemplo n.º 5
0
 def _fill_bytes(self, bv, memory, start, end, ref_eas):
     br = bn.BinaryReader(bv)
     for bb in self._bn_func.basic_blocks:
         for ea in range(bb.start, bb.end):
             seg = bv.get_segment_at(ea)
             br.seek(ea)
             memory.map_byte(ea, br.read8(), seg.writable, seg.executable)
             insn = self._bn_func.get_lifted_il_at(ea)
             if insn:
                 _collect_code_xrefs_from_insn(bv, insn, ref_eas)
Ejemplo n.º 6
0
 def symbol_usage(self, tgt_syms=[]):
     br = binaryninja.BinaryReader(self.bv)
     for sym in self.bv.get_symbols():
         br.seek(sym.address)
         c = br.read32()
         self.sym_const[c] = sym
     for s in self.bv.symbols:
         ts = s.split("@IAT")[0].upper()
         if ts in self.syms:
             self.get_symbol_xrefs(s)
         if ts[:-1] in self.syms:
             self.get_symbol_xrefs(s)
def main():
    address_pointer = OBFUSCATED_CODE_ADDRESS
    bv = binaryninja.BinaryViewType["PE"].open("greek_to_me.exe")
    bv.update_analysis_and_wait()
    bw = binaryninja.BinaryWriter(bv)
    br = binaryninja.BinaryReader(bv)

    while address_pointer != (OBFUSCATED_CODE_ADDRESS + 0x79):
        br.seek(address_pointer)
        bw.seek(address_pointer)
        bw.write8((br.read8() ^ XOR_KEY) + CONST_FACTOR)
        address_pointer = address_pointer + 1

    #Save updated file
    bv.save("greek_to_me_mod.exe")
Ejemplo n.º 8
0
    def __init__(self, binary, *args, **kwargs):
        super().__init__(binary, *args, **kwargs)
        if not bn:
            raise CLEError(BINJA_NOT_INSTALLED_STR)
        # get_view_of_file can take a bndb or binary - wait for autoanalysis to complete
        self.bv = bn.BinaryViewType.get_view_of_file(binary, False)
        l.info("Analyzing %s, this may take some time...", binary)
        self.bv.update_analysis_and_wait()
        l.info("Analysis complete")
        # Note may want to add option to kick off linear sweep

        try:
            self.set_arch(self.BINJA_ARCH_MAP[self.bv.arch.name])
        except KeyError:
            l.error("Architecture %s is not supported.", self.bv.arch.name)

        for seg in self.bv.segments:
            l.info("Adding memory for segment at %x.", seg.start)
            br = bn.BinaryReader(self.bv)
            br.seek(seg.start)
            data = br.read(len(seg))
            self.memory.add_backer(seg.start, data)

        self._find_got()
        self._symbol_cache = {}
        self._init_symbol_cache()
        # Note: this represents the plt stub. ImportAddressSymbol refers to .got entries
        # Since we're not trying to import and load dependencies directly, but want to run SimProcedures,
        # We should use the binaryninja.SymbolType.ImportedFunctionSymbol
        # Also this should be generalized to get data imports, too
        self.raw_imports = {
            i.name: i.address
            for i in self.bv.get_symbols_of_type(
                bn.SymbolType.ImportedFunctionSymbol)
        }
        self._process_imports()
        self.exports = {}
        self.linking = "static" if len(self.raw_imports) == 0 else "dynamic"
        # We'll look for this attribute to see if we need to do SimProcedures for any imports in this binary
        # This is an ugly hack, but will have to use this for now until Binary Ninja exposes dependencies
        self.guess_simprocs = True
        self.guess_simprocs_hint = "nix" if self.bv.get_section_by_name(
            ".plt") else "win"
        l.warning("This backend is based on idabin.py.\n\
                   You may encounter unexpected behavior if:\n\
                   \tyour target depends on library data symbol imports, or\n\
                   \tlibrary imports that don't have a guess-able SimProcedure\n\
                   Good luck!")
Ejemplo n.º 9
0
def main():
    print "Solution for MalwareTech shellcode challenge 1!"
    bv=binaryninja.BinaryViewType["PE"].open("shellcode1.exe_")
    bv.update_analysis_and_wait()
    br=binaryninja.BinaryReader(bv)
    br.seek(ADDRESS_FLAG)
    flag=""

    #Read encoded characters and decode them with rol 5
    while True:
        enc_char=br.read8()
        if enc_char == 0:
            break
        flag+=chr(rol(enc_char,5,max_bits))

    print "The flag is: %s " % flag
Ejemplo n.º 10
0
def define_strings_vars_range(bv, addr_start, addr_len):
    br = bn.BinaryReader(bv)
    #print('Starting string search at {:x}'.format(addr_start))
    bv.begin_undo_actions()
    for possible_str in bv.get_strings(addr_start, addr_len):
        br.seek(possible_str.start + possible_str.length)
        end_char = chr(br.read8())
        #print('char @ {:x} == {}'.format(possible_str.start + possible_str.length, end_char))

        # Only automatically make strings that are at least 2 chars long and
        # that end in NULL
        if possible_str.length > 1 and end_char == '\x00':
            #print('found string @ {0.start:x} len {0.length:x}'.format(possible_str))
            str_type, _ = bv.parse_type_string('char [{}]'.format(
                possible_str.length))
            bv.define_user_data_var(possible_str.start, str_type)
    bv.commit_undo_actions()
Ejemplo n.º 11
0
    def visit(self, program, is_definition, add_refs_as_defs):
        if not is_definition:
            return

        if isinstance(self._type, VoidType):
            return

        bv = program._bv
        br = bn.BinaryReader(bv)
        mem = program.memory()
        begin = self._address
        end = begin + self._type.size(self._arch)

        for ea in range(begin, end):
            br.seek(ea)
            seg = bv.get_segment_at(ea)
            mem.map_byte(ea, br.read8(), seg.writable, seg.executable)
Ejemplo n.º 12
0
    def _fill_bytes(self, memory, start, end, ref_eas):
        br = bn.BinaryReader(self._bv)
        for bb in self._bn_func.basic_blocks:
            ea = bb.start
            while ea < bb.end:
                seg = self._bv.get_segment_at(ea)
                can_read = seg.readable
                can_exec = seg.executable
                can_write = seg.writable

                br.seek(ea)
                byte = br.read8()
                memory.map_byte(ea, byte, can_write, can_exec)
                insn = self._bn_func.get_lifted_il_at(ea)
                if insn:
                    _collect_code_xrefs_from_insn(self._bv, insn, ref_eas)
                ea += 1
Ejemplo n.º 13
0
def stringify(bv, addr):
    buf = ''
    br = bn.BinaryReader(bv, bn.Endianness.BigEndian)
    br.seek(addr)  # goto addr

    # read data and find null byte
    while True:
        if br.eof:  # eof?
            print("Error converting to string: EOF.")
            return

        byte = br.read8()  # read byte
        if byte == 0:
            break
        buf += chr(byte)  # append to buffer

    # finished, now lets setup a type for it
    type, _ = bv.parse_type_string("char const [%d]" %
                                   (len(buf) + 1))  # count the NULL byte
    bv.define_data_var(addr, type)
Ejemplo n.º 14
0
def main():
    print colored(banner(), "red")
    global XOR_KEY
    decode_ptr = STARTING_ADDRESS_DECODE_LOOP
    flag = []

    # Creating a binary view with binja API
    bv = binaryninja.BinaryViewType["PE"].open("IgniteMe.exe")
    bv.update_analysis_and_wait()
    br = binaryninja.BinaryReader(bv)

    print "Starting decoding the flag!"
    while decode_ptr >= ADDRESS_OBFUSCATED_FLAG:
        br.seek(decode_ptr)
        XOR_KEY = (br.read8() ^ XOR_KEY)
        flag.append(chr(XOR_KEY))
        decode_ptr = decode_ptr - 1

    flag = flag[::-1]
    print "The flag is:", colored("".join(flag), "green")
Ejemplo n.º 15
0
    def _fill_bytes(self, program, memory, start, end, ref_eas):
        br = bn.BinaryReader(program.bv)
        for bb in self._bn_func.basic_blocks:
            for ea in range(bb.start, bb.end):
                seg = program.bv.get_segment_at(ea)
                br.seek(ea)

                # NOTE(artem): This is a workaround for binary ninja's fake
                # .externs section, which is (correctly) mapped as
                # not readable, not writable, and not executable.
                # because it is a fictional creation of the disassembler.
                # When something is marked as not accessible at all,
                # assume it is readable and executable
                is_executable = seg.executable
                if seg.writable == seg.readable == False:
                    is_executable = True

                memory.map_byte(ea, br.read8(), seg.writable, is_executable)
                inst = self._bn_func.get_low_level_il_at(ea)
                if inst and not is_unimplemented(program.bv, inst):
                    _collect_xrefs_from_inst(program.bv, program, inst,
                                             ref_eas)
Ejemplo n.º 16
0
  def __init__(self, program, screen, bv):
    self.program = program
    self.screen = screen
    self.bv = bv

    # Make Pads
    self.alertsScreen = curses.newpad(1, curses.COLS)
    self.pythonConsoleScreen = curses.newpad(1, curses.COLS)
    self.logScreen = curses.newpad(1, curses.COLS)

    # Disassembly Window Stuff
    self.disassemblySettings = binja.DisassemblySettings()
    
    self.pos = self.bv.start     # Current position in the binary
    self.posOffset = 0           # Displacement in lines between the top of the screen and the rendered location of self.pos
    self.cursorOffset = 0        # Offset (in lines) from the top of the screen to the current visual cursor in linear view
    self.disassemblyLines = []   # TODO...make sure this is deleted in the view's cleanup

    self.hexOffset = 0           # Offset (in lines) from the top of the screen to the current visual cursor in hex view
    self.br = binja.BinaryReader(bv)
    self.hexLines = []           # TODO...make sure this is deleted in the view's cleanup

    # Function List Pane Stuff
    self.funcListPos = 0
    self.funcListCur = 0
    self.updateFunctionList = True

    # Global Stuff
    self.focus = 0
    self.view = 0
    # 0 - Linear
    # 1 - Hex
    # 2 - CFG

    # Set up first view
    self.linearDisassemblyScreen = curses.newpad(curses.LINES-1, curses.COLS - self.program.settings["functionListScreenWidth"])
    self.functionListScreen = curses.newpad(curses.LINES-1-self.program.settings["xrefsScreenHeight"], self.program.settings["functionListScreenWidth"])
    self.xrefsScreen = curses.newpad(self.program.settings["xrefsScreenHeight"], self.program.settings["functionListScreenWidth"])
    self.loadLinearDisassembly()
Ejemplo n.º 17
0
    def visit(self, program, is_definition, add_refs_as_defs):
        if not is_definition:
            return

        # type could be None if type class not handled
        if self._type is None:
            return

        if isinstance(self._type, VoidType):
            return

        bv = program.bv
        br = bn.BinaryReader(bv)
        mem = program.memory
        begin = self._address
        end = begin + self._type.size(self._arch)

        for ea in range(begin, end):
            br.seek(ea)
            seg = bv.get_segment_at(ea)
            # _elf_header is getting recovered as variable
            # get_segment_at(...) returns None for elf_header
            if seg is None:
                continue

            #NOTE(artem): This is a workaround for binary ninja's fake
            # .externs section, which is (correctly) mapped as
            # not readable, not writable, and not executable.
            # because it is a fictional creation of the disassembler.
            #
            # However, when we do control flow tragetting to thunks,
            # we will sanity check that the target goes to an executable
            # location. If we are lying about the target being readable,
            # then we may as well lie about it being executable.
            is_executable = seg.executable
            if seg.writable == seg.readable == False:
                is_executable = True

            mem.map_byte(ea, br.read8(), seg.writable, is_executable)
Ejemplo n.º 18
0
    def _init_func_thunk_ctrl_flow(self):
        """Initializes the control flow redirections and targets
        using function thunks"""

        # We only support the ELF format for now
        if self._bv.view_type != "ELF":
            return

        # List the function thunks first
        input_file_path = self._bv.file.filename
        image_parser = create_elf_image_parser(input_file_path)
        function_thunk_list = image_parser.get_function_thunk_list()

        # Go through each function thunk and add the redirection and targets
        is_32_bit = image_parser.get_image_bitness() == 32

        reader = bn.BinaryReader(self._bv, bn.Endianness.LittleEndian)

        redirected_thunk_list = []
        for function_thunk in function_thunk_list:
            # Read the call destination
            reader.seek(function_thunk.start)
            redirection_dest = reader.read32() if is_32_bit else reader.read64(
            )

            # Get the variable defined at the dest address
            func_location = self._bv.get_data_var_at(function_thunk.start)
            if not func_location:
                DEBUG(
                    f"anvill: No variable defined for {hex(function_thunk.start)}/{function_thunk.name}"
                )
                continue

            # We should only have one caller
            for caller in func_location.code_refs:
                # Get the function containing this address; we need it to determine
                # its start address
                for caller_function in self._bv.get_functions_containing(
                        caller.address):

                    # check if the caller function name is same as the function thunk name and add
                    # redirection if it matches.
                    # TODO: It is possible that the caller function name does not exactly matches the
                    # thunk name. find such cases and add them here
                    #
                    # It is not preferred to have a loose check here. That will lead to adding redirection
                    # for the wrong functions.
                    #
                    if (function_thunk.name == caller_function.name or
                            function_thunk.name == caller_function.name[1:]):
                        DEBUG(
                            "anvill: Redirecting the user {:x} of thunk {} at {:x} to {:x}"
                            .format(
                                caller_function.start,
                                function_thunk.name,
                                function_thunk.start,
                                redirection_dest,
                            ))

                        self.add_control_flow_redirection(
                            caller_function.start, redirection_dest)

                        redirected_thunk_list.append(function_thunk.name)

                    # The imported address symbol can be references from both the thunks
                    # and other functions if it does not uses PLT. Check if the caller
                    # address is one of the call or jump instruction
                    #    e.g:    call [atoi@GOT]
                    #            jmp  [atoi@GOT]
                    #

                    # if the caller address is a call site, set a control flow
                    # target for the address
                    if self._is_call_site(caller_function, caller.address):
                        self.set_control_flow_targets(caller.address,
                                                      [redirection_dest], True)

                        DEBUG(
                            "anvill: Adding target list {:x} -> [{:x}, complete=True] for {}"
                            .format(caller.address, redirection_dest,
                                    function_thunk.name))

                        continue

                    jump_table = get_jump_targets(self._bv, caller.address,
                                                  function_thunk.start)
                    for jump_addr, targets in jump_table.items():
                        if function_thunk.start in targets:
                            self.set_control_flow_targets(
                                jump_addr, [redirection_dest], True)

                            DEBUG(
                                "anvill: Adding target list {:x} -> [{:x}, complete=True] for {}"
                                .format(jump_addr, redirection_dest,
                                        function_thunk.name))

        # Now check whether we successfully redirected all thunks
        for function_thunk in function_thunk_list:
            if function_thunk.name not in redirected_thunk_list:
                if function_thunk.name == "__libc_start_main":
                    continue

                WARN(
                    f"anvill: Thunk {hex(function_thunk.start)} ({function_thunk.name}) could not be redirected"
                )
Ejemplo n.º 19
0
def read_bytes(addr, size):
	br = binaryninja.BinaryReader(binja.view)
	br.seek(addr)
	return bytearray(br.read(size))
Ejemplo n.º 20
0
    def _init_ctrl_flow_redirections(self):
        """Initializes the control flow redirections using function thunks"""

        # We only support the ELF format for now
        if self._bv.view_type != "ELF":
            return

        # List the function thunks first
        input_file_path = self._bv.file.filename
        image_parser = create_elf_image_parser(input_file_path)
        function_thunk_list = image_parser.get_function_thunk_list()

        # Go through each function thunk and add the redirection. Note that
        # the __libc_start_main thunk does not need redirection since it's
        # called directly without any wrapper function from the module entry
        # point
        is_32_bit = image_parser.get_image_bitness() == 32

        reader = bn.BinaryReader(self._bv, bn.Endianness.LittleEndian)

        image_base_address = self._bv.start

        redirected_thunk_list = []
        for function_thunk in function_thunk_list:
            # Read the call destination
            thunk_va = image_base_address + function_thunk.start

            reader.seek(thunk_va)
            redirection_dest = reader.read32() if is_32_bit else reader.read64(
            )

            # Get the variable defined at the dest address
            func_location = self._bv.get_data_var_at(function_thunk.start)
            if not func_location:
                print("anvill: No variable defined for {:x}".format(
                    function_thunk.start))
                continue

            # We should only have one caller
            for caller in func_location.code_refs:
                # Get the function containing this address; we need it to determine
                # its start address
                for caller_function in self._bv.get_functions_containing(
                        caller.address):
                    if (function_thunk.name == "__libc_start_main" or
                            function_thunk.name not in caller_function.name):
                        continue

                    redirection_source = caller_function.start

                    print(
                        "anvill: Redirecting the user {:x} of thunk {} at rva {:x} to {:x}"
                        .format(
                            redirection_source,
                            function_thunk.name,
                            function_thunk.start,
                            redirection_dest,
                        ))

                    self.add_control_flow_redirection(redirection_source,
                                                      redirection_dest)
                    redirected_thunk_list.append(function_thunk.name)

        # Now check whether we successfully redirected all thunks
        for function_thunk in function_thunk_list:
            if function_thunk.name not in redirected_thunk_list:
                if function_thunk.name == "__libc_start_main":
                    continue

                print("anvill: Thunk {:x} ({}) could not be redirected".format(
                    function_thunk.start, function_thunk.name))