(self)
Initialize the binary.

        :return: None
Initialize the binary.
Initialize the binary .
def _initialize(self):
        """
        Initialize the binary.

        :return: None
        """

        # figure out section alignments
        for section in self.project.loader.main_object.sections:
            in_segment = False
            for segment in self.project.loader.main_object.segments:
                segment_addr = segment.vaddr
                if segment_addr <= section.vaddr < segment_addr + segment.memsize:
                    in_segment = True
                    break
            if not in_segment:
                continue

            # calculate alignments
            if section.vaddr % 0x20 == 0:
                alignment = 0x20
            elif section.vaddr % 0x10 == 0:
                alignment = 0x10
            elif section.vaddr % 0x8 == 0:
                alignment = 0x8
            elif section.vaddr % 0x4 == 0:
                alignment = 0x4
            else:
                alignment = 2

            self._section_alignments[section.name] = alignment

        l.debug('Generating CFG...')
        cfg = self.project.analyses.CFG(normalize=True, resolve_indirect_jumps=True, data_references=True,
                                        extra_memory_regions=[(0x4347c000, 0x4347c000 + 0x1000)],
                                        data_type_guessing_handlers=[
                                            self._sequence_handler,
                                            self._cgc_extended_application_handler,
                                            self._unknown_data_size_handler,
                                        ],
                                        )

        self.cfg = cfg

        old_capstone_syntax = self.project.arch.capstone_x86_syntax
        if old_capstone_syntax is None:
            old_capstone_syntax = 'intel'

        if self.syntax == 'at&t':
            # switch capstone to AT&T style
            self.project.arch.capstone_x86_syntax = "at&t"
            # clear the block cache in lifter!
            self.project.factory.default_engine.clear_cache()

        # initialize symbol manager
        self.symbol_manager = SymbolManager(self, cfg)

        # collect address of all instructions
        l.debug('Collecting instruction addresses...')
        for cfg_node in self.cfg.nodes():
            self.all_insn_addrs |= set(cfg_node.instruction_addrs)

        # Functions

        l.debug('Creating functions...')
        for f in cfg.kb.functions.values():
            # Skip all SimProcedures
            if self.project.is_hooked(f.addr):
                continue
            elif self.project.simos.is_syscall_addr(f.addr):
                continue

            # Check which section the start address belongs to
            section = next(iter(sec.name for sec in self.project.loader.main_object.sections
                                if f.addr >= sec.vaddr and f.addr < sec.vaddr + sec.memsize
                                ),
                           ".text"
                           )

            if section in ('.got', '.plt', 'init', 'fini'):
                continue

            procedure = Procedure(self, f, section=section)
            self.procedures.append(procedure)

        self.procedures = sorted(self.procedures, key=lambda x: x.addr)

        # Data

        has_sections = len(self.project.loader.main_object.sections) > 0

        l.debug('Creating data entries...')
        for addr, memory_data in cfg._memory_data.items():

            if memory_data.sort in ('code reference', ):
                continue

            if memory_data.sort == 'string':
                # it might be the CGC package list
                new_sort, new_size = self._cgc_package_list_identifier(memory_data.address, memory_data.size)
                if new_sort is not None:
                    # oh we got it!
                    memory_data = memory_data.copy()
                    memory_data.sort = new_sort

            if has_sections:
                # Check which section the start address belongs to
                section = next(iter(sec for sec in self.project.loader.main_object.sections
                                    if sec.vaddr <= addr < sec.vaddr + sec.memsize
                                    ),
                               None
                               )

                if section is not None and section.name not in ('.note.gnu.build-id', ):  # ignore certain section names
                    data = Data(self, memory_data, section=section)
                    self.data.append(data)
                elif memory_data.sort == 'segment-boundary':
                    # it just points to the end of the segment or a section
                    section = next(iter(sec for sec in self.project.loader.main_object.sections
                                        if addr == sec.vaddr + sec.memsize),
                                   None
                                   )
                    if section is not None:
                        data = Data(self, memory_data, section=section)
                        self.data.append(data)

                else:
                    # data = Data(self, memory_data, section_name='.data')
                    # the data is not really within any existing section. weird. ignored it.
                    pass
            else:
                # the binary does not have any section
                # we use segment information instead
                # TODO: this logic needs reviewing
                segment = next(iter(seg for seg in self.project.loader.main_object.segments
                                    if seg.vaddr <= addr <= seg.vaddr + seg.memsize
                                    ),
                               None
                               )

                if segment is not None:
                    data = Data(self, memory_data, section_name='.data')
                    self.data.append(data)

        # remove all data that belong to GCC-specific sections
        section_names_to_ignore = {'.init', '.fini', '.fini_array', '.jcr', '.dynamic', '.got', '.got.plt',
                                   '.eh_frame_hdr', '.eh_frame', '.rel.dyn', '.rel.plt', '.rela.dyn', '.rela.plt',
                                   '.dynstr', '.dynsym', '.interp', '.note.ABI-tag', '.note.gnu.build-id', '.gnu.hash',
                                   '.gnu.version', '.gnu.version_r'
                                   }

        # make sure there are always memory data entries pointing at the end of sections
        all_data_addrs = set(d.addr for d in self.data)
        all_procedure_addrs = set(f.addr for f in self.procedures)
        all_addrs = all_data_addrs | all_procedure_addrs

        if has_sections:
            for section in self.project.loader.main_object.sections:

                if section.name in section_names_to_ignore:
                    # skip all sections that are CGC specific
                    continue

                # make sure this section is inside a segment
                for segment in self.project.loader.main_object.segments:
                    segment_start = segment.vaddr
                    segment_end = segment_start + segment.memsize
                    if segment_start <= section.vaddr < segment_end:
                        break
                else:
                    # this section is not mapped into memory
                    continue

                section_boundary_addr = section.vaddr + section.memsize
                if section_boundary_addr not in all_addrs:
                    data = Data(self, addr=section_boundary_addr, size=0, sort='segment-boundary',
                                section_name=section.name
                                )
                    self.data.append(data)
                    # add the address to all_data_addrs so we don't end up adding another boundary in
                    all_data_addrs.add(section_boundary_addr)

        self.data = sorted(self.data, key=lambda x: x.addr)

        data_indices_to_remove = set()

        # Go through data entry list and refine them
        for i, data in enumerate(self.data):

            if i in data_indices_to_remove:
                continue

            # process the overlapping ones
            if i < len(self.data) - 1:
                if data.addr + data.size > self.data[i + 1].addr:
                    # they are overlapping :-(

                    # TODO: make sure new_size makes sense
                    new_size = self.data[i + 1].addr - data.addr

                    # there are cases that legit data is misclassified as pointers
                    # we are able to detect some of them here
                    if data.sort == 'pointer-array':
                        pointer_size = self.project.arch.bytes
                        if new_size % pointer_size != 0:
                            # the self.data[i+1] cannot be pointed to by a pointer
                            # remove that guy later
                            data_indices_to_remove.add(i + 1)
                            # mark the source as a non-pointer
                            # apparently the original Reassembleable Disassembler paper cannot get this case
                            source_addr = self.data[i + 1].memory_data.pointer_addr
                            if source_addr is not None:
                                # find the original data
                                original_data = next((d for d in self.data if d.addr <= source_addr < d.addr + d.size),
                                                     None
                                                     )
                                if original_data is not None:
                                    original_data.desymbolize()

                            continue

                    data.shrink(new_size)

            # process those ones whose type is unknown
            if data.sort == 'unknown' and data.size == 0:
                # increase its size until reaching the next item

                if i + 1 == len(self.data):
                    if data.section is None:
                        continue
                    data.size = data.section.vaddr + data.section.memsize - data.addr
                else:
                    data.size = self.data[i + 1].addr - data.addr

        for i in sorted(data_indices_to_remove, reverse=True):
            self.data = self.data[ : i] + self.data[i + 1 : ]

        # CGC-specific data filtering
        self.data = [ d for d in self.data if d.section_name not in section_names_to_ignore ]

        # restore capstone X86 syntax at the end
        if self.project.arch.capstone_x86_syntax != old_capstone_syntax:
            self.project.arch.capstone_x86_syntax = old_capstone_syntax
            self.project.factory.default_engine.clear_cache()

        l.debug('Initialized.')
def _initialize ( self ) : # figure out section alignments for section in self . project . loader . main_object . sections : in_segment = False for segment in self . project . loader . main_object . segments : segment_addr = segment . vaddr if segment_addr <= section . vaddr < segment_addr + segment . memsize : in_segment = True break if not in_segment : continue # calculate alignments if section . vaddr % 0x20 == 0 : alignment = 0x20 elif section . vaddr % 0x10 == 0 : alignment = 0x10 elif section . vaddr % 0x8 == 0 : alignment = 0x8 elif section . vaddr % 0x4 == 0 : alignment = 0x4 else : alignment = 2 self . _section_alignments [ section . name ] = alignment l . debug ( 'Generating CFG...' ) cfg = self . project . analyses . CFG ( normalize = True , resolve_indirect_jumps = True , data_references = True , extra_memory_regions = [ ( 0x4347c000 , 0x4347c000 + 0x1000 ) ] , data_type_guessing_handlers = [ self . _sequence_handler , self . _cgc_extended_application_handler , self . _unknown_data_size_handler , ] , ) self . cfg = cfg old_capstone_syntax = self . project . arch . capstone_x86_syntax if old_capstone_syntax is None : old_capstone_syntax = 'intel' if self . syntax == 'at&t' : # switch capstone to AT&T style self . project . arch . capstone_x86_syntax = "at&t" # clear the block cache in lifter! self . project . factory . default_engine . clear_cache ( ) # initialize symbol manager self . symbol_manager = SymbolManager ( self , cfg ) # collect address of all instructions l . debug ( 'Collecting instruction addresses...' ) for cfg_node in self . cfg . nodes ( ) : self . all_insn_addrs |= set ( cfg_node . instruction_addrs ) # Functions l . debug ( 'Creating functions...' ) for f in cfg . kb . functions . values ( ) : # Skip all SimProcedures if self . project . is_hooked ( f . addr ) : continue elif self . project . simos . is_syscall_addr ( f . addr ) : continue # Check which section the start address belongs to section = next ( iter ( sec . name for sec in self . project . loader . main_object . sections if f . addr >= sec . vaddr and f . addr < sec . vaddr + sec . memsize ) , ".text" ) if section in ( '.got' , '.plt' , 'init' , 'fini' ) : continue procedure = Procedure ( self , f , section = section ) self . procedures . append ( procedure ) self . procedures = sorted ( self . procedures , key = lambda x : x . addr ) # Data has_sections = len ( self . project . loader . main_object . sections ) > 0 l . debug ( 'Creating data entries...' ) for addr , memory_data in cfg . _memory_data . items ( ) : if memory_data . sort in ( 'code reference' , ) : continue if memory_data . sort == 'string' : # it might be the CGC package list new_sort , new_size = self . _cgc_package_list_identifier ( memory_data . address , memory_data . size ) if new_sort is not None : # oh we got it! memory_data = memory_data . copy ( ) memory_data . sort = new_sort if has_sections : # Check which section the start address belongs to section = next ( iter ( sec for sec in self . project . loader . main_object . sections if sec . vaddr <= addr < sec . vaddr + sec . memsize ) , None ) if section is not None and section . name not in ( '.note.gnu.build-id' , ) : # ignore certain section names data = Data ( self , memory_data , section = section ) self . data . append ( data ) elif memory_data . sort == 'segment-boundary' : # it just points to the end of the segment or a section section = next ( iter ( sec for sec in self . project . loader . main_object . sections if addr == sec . vaddr + sec . memsize ) , None ) if section is not None : data = Data ( self , memory_data , section = section ) self . data . append ( data ) else : # data = Data(self, memory_data, section_name='.data') # the data is not really within any existing section. weird. ignored it. pass else : # the binary does not have any section # we use segment information instead # TODO: this logic needs reviewing segment = next ( iter ( seg for seg in self . project . loader . main_object . segments if seg . vaddr <= addr <= seg . vaddr + seg . memsize ) , None ) if segment is not None : data = Data ( self , memory_data , section_name = '.data' ) self . data . append ( data ) # remove all data that belong to GCC-specific sections section_names_to_ignore = { '.init' , '.fini' , '.fini_array' , '.jcr' , '.dynamic' , '.got' , '.got.plt' , '.eh_frame_hdr' , '.eh_frame' , '.rel.dyn' , '.rel.plt' , '.rela.dyn' , '.rela.plt' , '.dynstr' , '.dynsym' , '.interp' , '.note.ABI-tag' , '.note.gnu.build-id' , '.gnu.hash' , '.gnu.version' , '.gnu.version_r' } # make sure there are always memory data entries pointing at the end of sections all_data_addrs = set ( d . addr for d in self . data ) all_procedure_addrs = set ( f . addr for f in self . procedures ) all_addrs = all_data_addrs | all_procedure_addrs if has_sections : for section in self . project . loader . main_object . sections : if section . name in section_names_to_ignore : # skip all sections that are CGC specific continue # make sure this section is inside a segment for segment in self . project . loader . main_object . segments : segment_start = segment . vaddr segment_end = segment_start + segment . memsize if segment_start <= section . vaddr < segment_end : break else : # this section is not mapped into memory continue section_boundary_addr = section . vaddr + section . memsize if section_boundary_addr not in all_addrs : data = Data ( self , addr = section_boundary_addr , size = 0 , sort = 'segment-boundary' , section_name = section . name ) self . data . append ( data ) # add the address to all_data_addrs so we don't end up adding another boundary in all_data_addrs . add ( section_boundary_addr ) self . data = sorted ( self . data , key = lambda x : x . addr ) data_indices_to_remove = set ( ) # Go through data entry list and refine them for i , data in enumerate ( self . data ) : if i in data_indices_to_remove : continue # process the overlapping ones if i < len ( self . data ) - 1 : if data . addr + data . size > self . data [ i + 1 ] . addr : # they are overlapping :-( # TODO: make sure new_size makes sense new_size = self . data [ i + 1 ] . addr - data . addr # there are cases that legit data is misclassified as pointers # we are able to detect some of them here if data . sort == 'pointer-array' : pointer_size = self . project . arch . bytes if new_size % pointer_size != 0 : # the self.data[i+1] cannot be pointed to by a pointer # remove that guy later data_indices_to_remove . add ( i + 1 ) # mark the source as a non-pointer # apparently the original Reassembleable Disassembler paper cannot get this case source_addr = self . data [ i + 1 ] . memory_data . pointer_addr if source_addr is not None : # find the original data original_data = next ( ( d for d in self . data if d . addr <= source_addr < d . addr + d . size ) , None ) if original_data is not None : original_data . desymbolize ( ) continue data . shrink ( new_size ) # process those ones whose type is unknown if data . sort == 'unknown' and data . size == 0 : # increase its size until reaching the next item if i + 1 == len ( self . data ) : if data . section is None : continue data . size = data . section . vaddr + data . section . memsize - data . addr else : data . size = self . data [ i + 1 ] . addr - data . addr for i in sorted ( data_indices_to_remove , reverse = True ) : self . data = self . data [ : i ] + self . data [ i + 1 : ] # CGC-specific data filtering self . data = [ d for d in self . data if d . section_name not in section_names_to_ignore ] # restore capstone X86 syntax at the end if self . project . arch . capstone_x86_syntax != old_capstone_syntax : self . project . arch . capstone_x86_syntax = old_capstone_syntax self . project . factory . default_engine . clear_cache ( ) l . debug ( 'Initialized.' )