def sections(self, args, file, opts): output = [] with open(file.file_path, 'rb') as f: try: for section in elffile.ELFFile(f).iter_sections(): s = {} # pylint: disable=invalid-name if section.name == '': s['name'] = '-' else: s['name'] = str(section.name) s['address'] = str(hex(section['sh_addr'])) s['size'] = str(hex(section['sh_size'])) s['offset'] = str(hex(section['sh_offset'])) s['type'] = str(section['sh_type'])[4:] if str(descriptions.describe_sh_flags( section['sh_flags'])) == '': s['flags'] = '-' else: s['flags'] = str( descriptions.describe_sh_flags( section['sh_flags'])) output += [s] except exceptions.ELFError as err: raise error.CommandError(str(err)) return output
def display_section_headers(self, show_heading=True): """ Display the ELF section headers """ elfheader = self.elffile.header if show_heading: self._emitline('There are %s section headers, starting at offset %s' % ( elfheader['e_shnum'], self._format_hex(elfheader['e_shoff']))) self._emitline('\nSection Header%s:' % ( 's' if elfheader['e_shnum'] > 1 else '')) # Different formatting constraints of 32-bit and 64-bit addresses # if self.elffile.elfclass == 32: self._emitline(' [Nr] Name Type Addr Off Size ES Flg Lk Inf Al') else: self._emitline(' [Nr] Name Type Address Offset') self._emitline(' Size EntSize Flags Link Info Align') # Now the entries # for nsec, section in enumerate(self.elffile.iter_sections()): self._emit(' [%2u] %-17.17s %-15.15s ' % ( nsec, bytes2str(section.name), describe_sh_type(section['sh_type']))) if self.elffile.elfclass == 32: self._emitline('%s %s %s %s %3s %2s %3s %2s' % ( self._format_hex(section['sh_addr'], fieldsize=8, lead0x=False), self._format_hex(section['sh_offset'], fieldsize=6, lead0x=False), self._format_hex(section['sh_size'], fieldsize=6, lead0x=False), self._format_hex(section['sh_entsize'], fieldsize=2, lead0x=False), describe_sh_flags(section['sh_flags']), section['sh_link'], section['sh_info'], section['sh_addralign'])) else: # 64 self._emitline(' %s %s' % ( self._format_hex(section['sh_addr'], fullhex=True, lead0x=False), self._format_hex(section['sh_offset'], fieldsize=16 if section['sh_offset'] > 0xffffffff else 8, lead0x=False))) self._emitline(' %s %s %3s %2s %3s %s' % ( self._format_hex(section['sh_size'], fullhex=True, lead0x=False), self._format_hex(section['sh_entsize'], fullhex=True, lead0x=False), describe_sh_flags(section['sh_flags']), section['sh_link'], section['sh_info'], section['sh_addralign'])) self._emitline('Key to Flags:') self._emit(' W (write), A (alloc), X (execute), M (merge), S (strings)') if self.elffile['e_machine'] in ('EM_X86_64', 'EM_L10M'): self._emitline(', l (large)') else: self._emitline() self._emitline(' I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)') self._emitline(' O (extra OS processing required) o (OS specific), p (processor specific)')
def elf_section_headers(self): section_headers = [] def add_info(dic): section_headers.append(dic) if self.elffile.num_sections() == 0: return None for nsec, section in enumerate(self.elffile.iter_sections()): section_hdr = {} section_hdr['index'] = nsec section_hdr['Name'] = section.name section_hdr['Type'] = describe_sh_type(section['sh_type']) section_hdr['Addr'] = self._format_hex(section['sh_addr'], fieldsize=8, lead0x=False) section_hdr['Offset'] = self._format_hex(section['sh_offset'], fieldsize=6, lead0x=False) section_hdr['Size'] = self._format_hex(section['sh_size'], fieldsize=6, lead0x=False) section_hdr['ES'] = self._format_hex(section['sh_entsize'], fieldsize=2, lead0x=False) section_hdr['Flag'] = describe_sh_flags(section['sh_flags']) section_hdr['Lk'] = section['sh_link'] section_hdr['Inf'] = section['sh_info'] section_hdr['Al'] = section['sh_addralign'] add_info(section_hdr) return section_headers
def sections(self): if not self.__check_session(): return rows = [] # TODO: Add get_entropy in pyelftools sections for section in self.elf.iter_sections(): rows.append([ section.name, hex(section['sh_addr']), hex(section['sh_size']), section['sh_type'], describe_sh_flags(section['sh_flags']) ]) self.log('info', "ELF Sections:") self.log('table', dict(header=['Name', 'Addr', 'Size', 'Type', 'Flags'], rows=rows))
def _collect_sections_info(elffile): sections = {} for section in elffile.iter_sections(): if section.is_null() or section.name.startswith(".debug"): continue section_type = section["sh_type"] section_flags = describe_sh_flags(section["sh_flags"]) section_size = section.data_size sections[section.name] = { "size": section_size, "start_addr": section["sh_addr"], "type": section_type, "flags": section_flags, } return sections
def sections(self): if not self.__check_session(): return rows = [] # TODO: Add get_entropy in pyelftools sections for section in self.elf.iter_sections(): rows.append( [ section.name, hex(section["sh_addr"]), hex(section["sh_size"]), section["sh_type"], describe_sh_flags(section["sh_flags"]), ] ) print_info("ELF Sections:") print(table(header=["Name", "Addr", "Size", "Type", "Flags"], rows=rows))
def display_section_headers(self, show_heading=True): """ Display the ELF section headers """ elfheader = self.elffile.header if show_heading: self._emitline( 'There are %s section headers, starting at offset %s' % (elfheader['e_shnum'], self._format_hex(elfheader['e_shoff']))) self._emitline('\nSection Header%s:' % ('s' if elfheader['e_shnum'] > 1 else '')) # Different formatting constraints of 32-bit and 64-bit addresses # if self.elffile.elfclass == 32: self._emitline( ' [Nr] Name Type Addr Off Size ES Flg Lk Inf Al' ) else: self._emitline( ' [Nr] Name Type Address Offset' ) self._emitline( ' Size EntSize Flags Link Info Align' ) # Now the entries # for nsec, section in enumerate(self.elffile.iter_sections()): self._emit( ' [%2u] %-17.17s %-15.15s ' % (nsec, bytes2str( section.name), describe_sh_type(section['sh_type']))) if self.elffile.elfclass == 32: self._emitline( '%s %s %s %s %3s %2s %3s %2s' % (self._format_hex( section['sh_addr'], fieldsize=8, lead0x=False), self._format_hex( section['sh_offset'], fieldsize=6, lead0x=False), self._format_hex( section['sh_size'], fieldsize=6, lead0x=False), self._format_hex( section['sh_entsize'], fieldsize=2, lead0x=False), describe_sh_flags( section['sh_flags']), section['sh_link'], section['sh_info'], section['sh_addralign'])) else: # 64 self._emitline( ' %s %s' % (self._format_hex( section['sh_addr'], fullhex=True, lead0x=False), self._format_hex(section['sh_offset'], fieldsize=16 if section['sh_offset'] > 0xffffffff else 8, lead0x=False))) self._emitline( ' %s %s %3s %2s %3s %s' % (self._format_hex( section['sh_size'], fullhex=True, lead0x=False), self._format_hex( section['sh_entsize'], fullhex=True, lead0x=False), describe_sh_flags( section['sh_flags']), section['sh_link'], section['sh_info'], section['sh_addralign'])) self._emitline('Key to Flags:') self._emit( ' W (write), A (alloc), X (execute), M (merge), S (strings)') if self.elffile['e_machine'] in ('EM_X86_64', 'EM_L10M'): self._emitline(', l (large)') else: self._emitline() self._emitline( ' I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)' ) self._emitline( ' O (extra OS processing required) o (OS specific), p (processor specific)' )
def get_sections(self): sections = [] for nsec, section in enumerate(self._elf.iter_sections()): result = {} result['nsec'] = nsec result['name'] = section.name result['sh_type'] = describe_sh_type(section['sh_type']) if self._elf.elfclass == 32: result['sh_addr'] = section['sh_addr'] result['shoffset'] = section['sh_offset'] result['sh_size'] = section['sh_size'] result['sh_entsize'] = section['sh_entsize'] result['sh_flags'] = describe_sh_flags(section['sh_flags']) result['sh_link'] = section['sh_link'] result['sh_info'] = section['sh_info'] result['sh_addralign'] = section['sh_addralign'] else: # 64 result['sh_addr'] = section['sh_addr'] result['sh_offset'] = section['sh_offset'] result['sh_size'] = section['sh_size'] result['sh_entsize'] = section['sh_entsize'] result['sh_flags'] = describe_sh_flags(section['sh_flags']) result['sh_link'] = section['sh_link'], section['sh_info'] result['sh_addralign'] = section['sh_addralign'] # Dynamic Section if isinstance(section, DynamicSection): result['special_type'] = 'dynamic' result['dynamic'] = [] has_dynamic_sections = True for tag in section.iter_tags(): dynamic = {} if tag.entry.d_tag == 'DT_NEEDED': parsed = 'Shared library: [%s]' % tag.needed elif tag.entry.d_tag == 'DT_RPATH': parsed = 'Library rpath: [%s]' % tag.rpath elif tag.entry.d_tag == 'DT_RUNPATH': parsed = 'Library runpath: [%s]' % tag.runpath elif tag.entry.d_tag == 'DT_SONAME': parsed = 'Library soname: [%s]' % tag.soname elif tag.entry.d_tag.endswith(('SZ', 'ENT')): parsed = '%i (bytes)' % tag['d_val'] elif tag.entry.d_tag.endswith(('NUM', 'COUNT')): parsed = '%i' % tag['d_val'] elif tag.entry.d_tag == 'DT_PLTREL': s = describe_dyn_tag(tag.entry.d_val) if s.startswith('DT_'): s = s[3:] parsed = '%s' % s else: parsed = '%#x' % tag['d_val'] dynamic['tag'] = ENUM_D_TAG.get( tag.entry.d_tag, tag.entry.d_tag) dynamic['tag_type'] = tag.entry.d_tag[3:] dynamic['tag_value'] = parsed result['dynamic'].append(dynamic) #Relocation Section if isinstance(section, RelocationSection): result['special_type'] = 'relocation' result['relocation'] = [] has_relocation_sections = True # The symbol table section pointed to in sh_link symtable = self._elf.get_section(section['sh_link']) for rel in section.iter_relocations(): relocation = {} relocation['r_offset'] = rel['r_offset'] relocation['r_info'] = rel['r_info'] relocation['r_info_type'] = describe_reloc_type( rel['r_info_type'], self._elf) if rel['r_info_sym'] == 0: continue symbol = symtable.get_symbol(rel['r_info_sym']) # Some symbols have zero 'st_name', so instead what's used is # the name of the section they point at if symbol['st_name'] == 0: symsec = self._elf.get_section(symbol['st_shndx']) relocation['symbol_name'] = symbol_name = symsec.name else: symbol_name = symbol.name relocation['st_value'] = symbol['st_value'] relocation['symbol_name'] = symbol_name if section.is_RELA(): relocation['r_addend'] = rel['r_addend'] result['relocation'].append(relocation) #Symbol Section if isinstance(section, SymbolTableSection): self._init_versioninfo() if section['sh_entsize'] == 0: continue result['special_type'] = 'symbol' result['symbol'] = [] for nsym, symbol in enumerate(section.iter_symbols()): sym_dic = {} version_info = '' # readelf doesn't display version info for Solaris versioning if (section['sh_type'] == 'SHT_DYNSYM' and self._versioninfo['type'] == 'GNU'): version = self._symbol_version(nsym) if (version['name'] != symbol.name and version['index'] not in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL')): if version['filename']: # external symbol version_info = '@%(name)s (%(index)i)' % version else: # internal symbol if version['hidden']: version_info = '@%(name)s' % version else: version_info = '@@%(name)s' % version # symbol names are truncated to 25 chars, similarly to readelf sym_dic['nsym'] = nsym sym_dic['st_value'] = symbol['st_value'] sym_dic['st_size'] = symbol['st_size'] sym_dic['st_type'] = describe_symbol_type( symbol['st_info']['type']) sym_dic['bind'] = describe_symbol_bind( symbol['st_info']['bind']) sym_dic['vis'] = describe_symbol_visibility( symbol['st_other']['visibility']) sym_dic['ndx'] = describe_symbol_shndx( symbol['st_shndx']) sym_dic['name'] = symbol.name sym_dic['version'] = version_info result['symbol'].append(sym_dic) sections.append(result) return sections
def parse_static_features(app, d, dvmx): coi_modules = { 'ImageFileExtensionMismatch', 'APKFileExtensionMismatch', 'TextScriptMatch' } #"AdvancedCodeFound", 'ELFExecutableMatch', 'DEXFileMatch', 'APKFileMatch', "EncryptedOrCompressedMatch" data = {} file_type_key = { "Text Executable": ["text", "executable"], "ELF Executable": ["ELF", "executable"], "fount": ["font"], "APK": ["Android", "application", "package", "file"], "DEX": ["Dalvik", "dex", "file"] } types = {} extensions = {} components_of_interest = [] num_componenets_of_interest = {} # -------- Strings su = 0 emulator = 0 sdk = 0 for string in d.get_strings(): if 'su' == string: su += 1 if 'emulator' in string.lower(): emulator += 1 if 'sdk' in string.lower(): emulator += 1 if su > 0: data['su'] = su if emulator > 0: data['emulator'] = emulator if sdk > 0: data['sdk'] = sdk data['package'] = app.get_package() data['main_activity'] = app.get_main_activity() try: data['num_activities'] = len(app.get_activities()) except: data['num_activities'] = 0 data['num_services'] = len(app.get_services()) data['num_receivers'] = len(app.get_receivers()) if data['num_receivers'] > 0: data['receivers'] = app.get_receivers() if data['num_services'] > 0: data['services'] = app.get_receivers() num_action_android_intent = 0 num_action_com_android_vending = 0 num_action_android_net = 0 num_action_com_android = 0 num_action_other = 0 actions = get_actions(app) for action in actions: if 'android.intent.action' in action: num_action_android_intent += 1 elif 'com.android.vending' in action: num_action_com_android_vending += 1 elif 'android.net' in action: num_action_android_net += 1 elif 'com.android' in action: num_action_com_android += 1 else: num_action_other += 1 if num_action_android_intent > 0: data['num_intent_action_android_intent'] = num_action_android_intent if num_action_com_android_vending > 0: data[ 'num_intent_action_com_android_vending'] = num_action_com_android_vending if num_action_android_net > 0: data['num_intent_action_android_net'] = num_action_android_net if num_action_com_android > 0: data['num_intent_action_com_android'] = num_action_com_android if num_action_other > 0: data['num_intent_action_other'] = num_action_other if actions > 0: data['num_intent_actions'] = len(actions) if len(actions) > 0: data['intent_actions'] = actions data['num_providers'] = len(app.get_providers()) data['num_libraries'] = len(app.get_libraries()) data['num_permissions'] = len(app.get_permissions()) data['num_third_part_permissions'] = len( app.get_requested_third_party_permissions()) # -------- Requested permissions data['permissions'] = [] requested_permissions = app.get_permissions() for x in requested_permissions: data['permissions'].append(x) # -------- Used permissions data['used_permissions'] = {} used_permissions = dvmx.get_permissions([]) for x in used_permissions: data['used_permissions'][x] = len(used_permissions[x]) data['native_code'] = count_native_code(dvmx) data['dynamic_code'] = count_dyn_code(dvmx) data['reflection'] = count_reflection_code(dvmx) data['ascii_obfuscation'] = count_ascii_obfuscation(d) try: data['version_code'] = app.get_androidversion_code() except: pass target_sdk = app.get_target_sdk_version() if target_sdk: data['target_sdk'] = app.get_target_sdk_version() data['is_valid_APK'] = app.is_valid_APK() tags = {} intent_objects = [] intent_consts = [] intent_consts_all = [] #package:method sensitive_API = { 'SmsManager:sendTextMessage': 0, 'URL:openConnection': 0, 'TelephonyManager:getDeviceId': 0, 'TelephonyManager:getLine1Number': 0, 'HttpURLConnection:connect': 0, 'URLConnection:getInputStream': 0, 'TelephonyManager:getSubscriberId': 0, 'WifiManager:getConnectionInfo': 0, 'TelephonyManager:getSimSerialNumber': 0, 'ConnectivityManager:getActiveNetworkInfo': 0, 'LocationManager:getLastKnownLocation': 0, 'LocationManager:requestLocationUpdate': 0, 'TelephonyManager:getCellLocation': 0, # ------------------------------------ 'ContentResolver:insert': 0, 'ContentResolver:delete': 0, 'ContentResolver:query': 0, 'Context:getFilesDir': 0, 'Context:openFileOuput': 0, 'Context:getApplicationInfo': 0, 'Intent:setDataAndType': 0, 'Intent:setFlags': 0, 'Intent:addFlags': 0, 'Intent:setDataAndType': 0, 'ActivityManager:getRunningServices': 0, 'ActivityManager:getMemoryInfo': 0, 'ActivityManager:restartPackage': 0, 'PackageManager:getInstalledPackages': 0, 'TelephonyManager:getNetworkOperator': 0, 'Process:myPid': 0, 'Process:killProcess': 0, 'File:mkdir': 0, 'File:delete': 0, 'File:exists': 0, 'File:ListFiles': 0, 'WifiManager:isWifiEnabled': 0, 'WifiManager:getIpAddress': 0 } for i in dvmx.get_methods(): i.create_tags() if not i.tags.empty(): for tag in i.tags.get_list(): try: count = tags[tag] + 1 except: count = 1 tags[tag] = count m = i.get_method() code = m.get_code() if code is not None: instructions = code.get_bc().get_instructions() for i in instructions: try: tkind = i.get_translated_kind() var = m.get_class_name() + " => " + m.get_name( ) + " => " + i.get_name() + " => " + tkind #print '++++++++++++++++++', var if 'object' in i.get_name() and 'intent' in tkind: intent_objects.append(var) if 'const-string' in i.get_name() and '.intent.' in tkind: intent_consts_all.append(var) intent_consts.append(tkind) for sapi in sensitive_API: sapi_split = sapi.split(':') pckg = sapi_split[0] mthd = sapi_split[1] if pckg in tkind and mthd in tkind: sensitive_API[sapi] = sensitive_API[sapi] + 1 except AttributeError: pass data['sensitive_API'] = sensitive_API if len(intent_objects) > 0: data['intent_objects'] = intent_objects if len(intent_consts) > 0: data['intent_consts'] = intent_consts num_action_android_intent = 0 num_action_com_android_vending = 0 num_action_android_net = 0 num_action_com_android = 0 num_action_other = 0 for const in intent_consts: if 'android.intent.action' in const: num_action_android_intent += 1 elif 'com.android.vending' in const: num_action_com_android_vending += 1 elif 'android.net' in const: num_action_android_net += 1 elif 'com.android' in const: num_action_com_android += 1 else: num_action_other += 1 if num_action_android_intent > 0: data['num_intent_const_android_intent'] = num_action_android_intent if num_action_com_android_vending > 0: data[ 'num_intent_const_com_android_vending'] = num_action_com_android_vending if num_action_android_net > 0: data['num_intent_const_android_net'] = num_action_android_net if num_action_com_android > 0: data['num_intent_const_com_android'] = num_action_com_android if num_action_other > 0: data['num_intent_const_other'] = num_action_other data['method_tags'] = tags data['num_files'] = len(app.get_files()) incognito_apk = [] incognito_dex = [] incognito_sh = [] incognito_elf = [] # COMPONENTS: assets and resources components files = app.get_files_types() for f in files: # ------ File extension # fileName, fileExtension = os.path.splitext(f) try: extensions[fileExtension] = extensions[fileExtension] + 1 except KeyError: extensions[fileExtension] = 1 # ------ Magic number extension try: #print files[f] file_type = None for key in file_type_key: match = 0 for token in file_type_key[key]: if token in files[f]: match = match + 1 if len(file_type_key[key]) is match: file_type = key if file_type == None: file_type = files[f].split(" ")[0] types[file_type] = types[file_type] + 1 except KeyError: types[file_type] = 1 # ------ Components of interest crc = app.get_files_crc32()[f] for sub_class_name in FileCoI.FileCoI.__subclasses__(): coi_type = sub_class_name.__name__ if coi_type in coi_modules: sub_class = sub_class_name(app, fileName, fileExtension, file_type, files[f], f, crc) if sub_class.check(): components_of_interest.append(sub_class) try: count = num_componenets_of_interest[coi_type] + 1 except KeyError: count = 1 num_componenets_of_interest[coi_type] = count if file_type == 'APK': incognito_apk.append(f) if file_type == 'DEX' and 'classes' != fileName: incognito_dex.append(f) if file_type == 'ELF': incognito_elf.append(f) if file_type == "Text Executable": incognito_sh.append(f) text_executable_commands = {} if incognito_sh: regexp = '|'.join(sh_commands) pattern = re.compile(regexp) for file_path in incognito_sh: content = app.get_file(file_path) matches = pattern.findall(content) for match in matches: try: count = text_executable_commands[match] except KeyError: count = 0 text_executable_commands[match] = count + 1 if text_executable_commands: data['text_executable_commands'] = text_executable_commands if types: data['file'] = types if num_componenets_of_interest: data['CoIs'] = num_componenets_of_interest # TODO: KNOWN SECTIONS: http://link.springer.com/article/10.1007/s10115-011-0393-5#/page-1 ''' # feature | description | example --------------------------------- ========== File Header ========== data['e_ehsize']: Size of this header: 52 (bytes) data['e_phentsize']: Size of program headers: 32 (bytes) data['e_phnum']: Number of program headers: 5 data['e_shentsize']: Size of section headers: 40 (bytes) data['e_shnum']: Number of section headers: 21 data['e_shstrndx']: Section header string table index: 18 ========== Sections ========== section['sh_flags']: Flags of a given section: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) ========== Shared Libraries ========== data['symbols_shared_libraries']: Relocation information for PLT (Position Independent Code): ioctl, fork, etc. ''' for file_path in incognito_elf: content = app.get_file(file_path) import StringIO steam_content = StringIO.StringIO() steam_content.write(content) try: readelf = ReadElf(steam_content, sys.stdout) #stream if readelf: data['e_ehsize'] = readelf.elffile.header['e_ehsize'] data['e_phentsize'] = readelf.elffile.header['e_phentsize'] data['e_phnum'] = readelf.elffile.header['e_phnum'] data['e_shentsize'] = readelf.elffile.header['e_shentsize'] data['e_shnum'] = readelf.elffile.header['e_shnum'] data['e_shstrndx'] = readelf.elffile.header['e_shstrndx'] symbols_shared_libraries = [ ] # Relocation information for PLT (Position Independent Code) sections_flags = {} for nsec, section in enumerate( readelf.elffile.iter_sections()): # ---------- Relocation information for PLT (Position Independent Code) ---------- if isinstance(section, RelocationSection): try: # The symbol table section pointed to in sh_link symtable = readelf.elffile.get_section( section['sh_link']) for rel in section.iter_relocations(): if rel['r_info_sym'] == 0: continue symbol = symtable.get_symbol(rel['r_info_sym']) # Some symbols have zero 'st_name', so instead what's used is # the name of the section they point at if symbol['st_name'] == 0: symsec = readelf.elffile.get_section( symbol['st_shndx']) symbol_name = symsec.name else: symbol_name = symbol.name if symbol_name in elf_symbols_white_list: symbols_shared_libraries.append( symbol_name) except ELFParseError, e: print 'Waring ELFParseError for', data['package'] # ---------- Flags from the section ---------- flag = describe_sh_flags(section['sh_flags']) if not flag: continue try: count = sections_flags[flag] except KeyError: count = 0 sections_flags[flag] = count + 1 if sections_flags: data['e_sh_flags'] = sections_flags if symbols_shared_libraries: data['symbols_shared_libraries'] = symbols_shared_libraries except Exception, e: print 'WARNING: cannot read elf', str( e), app.get_filename(), file_path readelf = None