def get(pe): try: for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get(resource_type.struct.Id) if name == None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: try: data = pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) except: pass lang = pefile.LANG.get(resource_lang.data.lang, '*unknown*') sublang = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang ) data = filter(lambda x: x in string.printable, data) #print name, data, lang, sublang, hex(resource_lang.data.struct.OffsetToData), resource_lang.data.struct.Size res_array.append({"name": name, "data": data, "offset": hex(resource_lang.data.struct.OffsetToData), "size": resource_lang.data.struct.Size, "language": lang, "sublanguage": sublang}) except: pass return res_array
def check_rsrc(pe): ret = {} if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'): i = 0 for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get(resource_type.struct.Id) if name == None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: data = pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) filetype = get_filetype_data(data) lang = pefile.LANG.get(resource_lang.data.lang, '*unknown*') sublang = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang ) ret[i] = (name, resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size, filetype, lang, sublang) #ret[i] = (name, resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size, lang, sublang) i += 1 if not ret: return None else: return ret else: return None
def resource(level, r): """Recursive printing of resources""" if hasattr(r, "data"): # resource offset = r.data.struct.OffsetToData size = r.data.struct.Size data = pe.get_memory_mapped_image()[offset:offset+size] m = hashlib.md5() m.update(data) print(" "*level + "-%s\t%i\t%i\t%s\t%s\t%s" % ( str(r.name), r.id, size, m.hexdigest(), pefile.LANG.get(r.data.lang, 'UNKNOWN'), pefile.get_sublang_name_for_lang(r.data.lang, r.data.sublang) ) ) else: # directory if r.name is None: print(" "*level + "-" + str(r.id)) else: print(" "*level + "-" + str(r.name)) for r2 in r.directory.entries: resource(level+1, r2)
def resource(self, pe, level, r, parents): """Recursive printing of resources""" if hasattr(r, "data"): # resource offset = r.data.struct.OffsetToData size = r.data.struct.Size data = pe.get_memory_mapped_image()[offset:offset+size] m = hashlib.md5() m.update(data) print("%-12s %-7s %-9s %-14s %-17s %-14s %-9s" % ( "-".join(parents + [str(r.id)]), str(r.name), "%i B" % size, pefile.LANG.get(r.data.lang, 'UNKNOWN'), pefile.get_sublang_name_for_lang(r.data.lang, r.data.sublang), magic.from_buffer(data), m.hexdigest() ) ) else: # directory parents = copy.copy(parents) if r.id is not None: parents.append(str(r.id)) else: parents.append(r.name.string.decode('utf-8')) for r2 in r.directory.entries: self.resource(pe, level+1, r2, parents)
def get_resources(pe): resources = [] if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'): count = 1 for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: try: resource = {} if resource_type.name is not None: name = str(resource_type.name) else: name = str(pefile.RESOURCE_TYPE.get(resource_type.struct.Id, "UNKNOWN")) if name is None: name = str(resource_type.struct.Id) if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: data = pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) entropy = get_entropy(data) filetype = get_type(data) md5 = get_md5(data) sha256 = get_sha256(data) language = pefile.LANG.get(resource_lang.data.lang, None) language_desc = LCID.get(resource_lang.id, 'unknown language') sublanguage = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang) offset = ('%-8s' % hex(resource_lang.data.struct.OffsetToData)).strip() size = ('%-8s' % hex(resource_lang.data.struct.Size)).strip() resource = [ count, name, offset, md5, sha256, size, filetype, entropy, language, sublanguage, language_desc ] # Dump resources if requested if self.dump and pe == self.pe: if self.dump: folder = self.dump else: folder = tempfile.mkdtemp() resource_path = path.join(folder, '{0}_{1}_{2}'.format( self.sha256, offset, name)) resource.append(resource_path) with open(resource_path, 'wb') as resource_handle: resource_handle.write(data) resources.append(resource) count += 1 except Exception as e: log.error(e) continue return resources
def get(pe): try: for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: #리소스 종류가 정의되있는 디렉토와 파일 비교. if resource_type.name is not None: #리소스 타입이 정의된 경우 name = "%s" % resource_type.name #리소스의 타입을 정수로 받아 이름을 저장 else: name = "%s" % pefile.RESOURCE_TYPE.get(resource_type.struct.Id) #리소스 이름을 resource_type.struct.Id 통해 받아옴 if name == None: #두 경우가 아닌경우 name = "%d" % resource_type.struct.Id #구조체의 이름을 리소스 이름으로 정의 if hasattr(resource_type, 'directory'): # resource_type 에 directory 변수가 있는지 확인. for resource_id in resource_type.directory.entries: # 모든 디렉토리 검사. if hasattr(resource_id, 'directory'): # resource_id 에 directory 변수가 있는지 검사. for resource_lang in resource_id.directory.entries: # resource_id.directory.entries try: data = pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) #리소스의 구조가 정의되있고 사이즈가 같다면 except: pass lang = pefile.LANG.get(resource_lang.data.lang, '*unknown*') #pefile.LANG.get 함수를 이용해 리소스 이름이 있다면 지정. 없다면 unknown으로 지정 sublang = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang ) #언어 형식지정을 위한 sublang 사용 (pefile에 정의되있음) """모든값은 16진수로 저장됨""" data = filter(lambda x: x in string.printable, data) #람다식을 이용해 16진수값을 출력가능한 값으로 변환 #print 이름, 데이터, hex(resource_lang.data.struct.OffsetToData),리소스 사이즈 출력 res_array.append({"name": name, "data": data, "offset": hex(resource_lang.data.struct.OffsetToData), "size": resource_lang.data.struct.Size, "language": lang, "sublanguage": sublang}) except: pass return res_array
def get_resource_info(self): if hasattr(self._pe, 'DIRECTORY_ENTRY_RESOURCE'): for resource_type in self._pe.DIRECTORY_ENTRY_RESOURCE.entries: if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get(resource_type.struct.Id) if name == None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: data = self._pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) lang = pefile.LANG.get(resource_lang.data.lang, '*unknown*') sublang = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang ) resource_md5 = "hash2be" if self._hash_mode == "md5": resource_md5=hashlib.md5(data).hexdigest() elif self._hash_mode == "sha1": resource_md5=hashlib.sha1(data).hexdigest() elif self._hash_mode == "sha256": resource_md5=hashlib.sha256(data).hexdigest() if self._ssd: resource_ssdeep = ssdeep.hash(data) if self._dump_mode == True: resource_dump=open("ripPE-RESOURCE-" + self._md5 + "-" + name + "-" + resource_md5 + ".rsrc","wb+") resource_dump.write(data) resource_dump.close() self.output_handle("%s,%s,resource_md5,RESOURCE-%s,%s" % (self._filename,self._md5,name,resource_md5)) if self._ssd: self.output_handle("%s,%s,resource_ssdeep,RESOURCE-%s,%s" % (self._filename,self._md5,name,resource_ssdeep))
def check_rsrc(self, pe): ret = {} if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'): i = 0 for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get( resource_type.struct.Id) if name == None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: data = pe.get_data( resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) filetype = get_filetype(data) lang = pefile.LANG.get(resource_lang.data.lang, '*unknown*') sublang = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang) ret[i] = ( name, resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size, filetype, lang, sublang) i += 1 return ret
def check_rsrc(self, pe): ret = {} if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'): i = 0 for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get(resource_type.struct.Id) if name is None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: data = pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) if 'magic' in sys.modules: if sys.version_info <= (2, 6): filetype = self.ms.buffer(data) else: # filetype = magic._buffer(data) filetype = "Magic Error" lang = pefile.LANG.get(resource_lang.data.lang, '*unknown*') sublang = pefile.get_sublang_name_for_lang(resource_lang.data.lang, resource_lang.data.sublang) else: filetype = None if filetype == None: filetype = '' ret[i] = (name, resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size, filetype, lang, sublang) i += 1 return ret
def check_rsrc(self): """ Function needed to determine the compilation language """ try: ret = {} if hasattr(self.pe, 'DIRECTORY_ENTRY_RESOURCE'): i = 0 for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries: if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get(resource_type.struct.Id) if name == None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: try: data = self.pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) filetype = magic.from_buffer(open(self.filename).read(1024)) lang = pefile.LANG.get(resource_lang.data.lang, 'qq_*unknown*') sublang = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang ) ret[i] = (name, resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size, filetype, lang, sublang) i += 1 except pefile.PEFormatError: pass except: ret = False pass finally: return ret
def resource(pe, level, r, parents): """Recursive printing of resources""" if hasattr(r, "data"): # resource offset = r.data.struct.OffsetToData size = r.data.struct.Size data = pe.get_memory_mapped_image()[offset:offset + size] m = hashlib.md5() m.update(data) result = ("-".join(parents + [str(r.id)]), str(r.name), "%i B" % size, pefile.LANG.get(r.data.lang, 'UNKNOWN'), pefile.get_sublang_name_for_lang(r.data.lang, r.data.sublang), m.hexdigest()) res.append(result) # print tabulate(result, headers=['Id', 'Name', 'Size', 'Lang', 'Sublang', 'MD5']) else: # directory #try: parents = copy.copy(parents) if r.id: parents.append(str(r.id)) elif r.name: parents.append(r.name.string.decode('utf-8')) for r2 in r.directory.entries: resource(pe, level + 1, r2, parents)
def resources(self): # TODO: Add Tests For Resources # TODO: Handle all cases + refactor. rv = {} # https://github.com/hiddenillusion/AnalyzePE/blob/9c76ecbc3ac417bc07439c244f2d5ed19af06578/pescanner.py#L190 if hasattr(self.pe, 'DIRECTORY_ENTRY_RESOURCE'): for index, resource_entry in enumerate( self.pe.DIRECTORY_ENTRY_RESOURCE.entries): # pylint: disable=no-member rv[index] = { "name": "", "filetype": "", "lang": "", "sublang": "" } if resource_entry.name is not None: rv[index]["name"] = resource_entry.name else: rv[index]["name"] = pefile.RESOURCE_TYPE.get( resource_entry.struct.Id, resource_entry.struct.Id) if hasattr(resource_entry, 'directory'): for resource_id in resource_entry.directory.entries: if hasattr(resource_id, 'directory'): for entry in resource_id.directory.entries: data = self.pe.get_data( entry.data.struct.OffsetToData, entry.data.struct.Size) rv[index]["filetype"] = magic.from_buffer(data) rv[index]["lang"] = pefile.LANG.get( entry.data.lang, '*unknown*') rv[index][ "sublang"] = pefile.get_sublang_name_for_lang( entry.data.lang, entry.data.sublang) return rv
def get_resources(pe): resources = [] if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'): count = 1 for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: try: resource = {} if resource_type.name is not None: name = str(resource_type.name) else: name = str(pefile.RESOURCE_TYPE.get(resource_type.struct.Id)) if name is None: name = str(resource_type.struct.Id) if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: data = pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) filetype = get_type(data) md5 = get_md5(data) language = pefile.LANG.get(resource_lang.data.lang, None) sublanguage = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang) offset = ('%-8s' % hex(resource_lang.data.struct.OffsetToData)).strip() size = ('%-8s' % hex(resource_lang.data.struct.Size)).strip() resource = [count, name, offset, md5, size, filetype, language, sublanguage] # Dump resources if requested to and if the file currently being # processed is the opened session file. # This is to avoid that during a --scan all the resources being # scanned are dumped as well. if (self.args.open or self.args.dump) and pe == self.pe: if self.args.dump: folder = self.args.dump else: folder = tempfile.mkdtemp() resource_path = os.path.join( folder, '{0}_{1}_{2}'.format(__sessions__.current.file.md5, offset, name)) resource.append(resource_path) with open(resource_path, 'wb') as resource_handle: resource_handle.write(data) resources.append(resource) count += 1 except Exception as e: self.log('error', e) continue return resources
def resources(self): resources = [] if hasattr(self.pe, "DIRECTORY_ENTRY_RESOURCE"): for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries: try: if resource_type.name is not None: name = str(resource_type.name) else: name = str(pefile.RESOURCE_TYPE.get(resource_type.struct.Id)) if name is None: name = str(resource_type.struct.Id) if hasattr(resource_type, "directory"): for resource_id in resource_type.directory.entries: if hasattr(resource_id, "directory"): for resource_lang in resource_id.directory.entries: data = self.pe.get_data( resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size ) filetype = self.__get_filetype(data) md5 = self.__md5(data) language = pefile.LANG.get(resource_lang.data.lang, None) sublanguage = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang ) offset = ("%-8s" % hex(resource_lang.data.struct.OffsetToData)).strip() size = ("%-8s" % hex(resource_lang.data.struct.Size)).strip() resource = { "name": name, "offset": offset, "md5": md5, "size": size, "filetype": filetype, "language": language.replace("LANG_", "").lower(), "sublanguage": sublanguage.replace("SUBLANG_", "").lower(), } # Dump resources if requested to and if the file currently being # processed is the opened session file. # This is to avoid that during a --scan all the resources being # scanned are dumped as well. # if dump_to and self.pe == self.pe: # resource_path = os.path.join(dump_to, # '{0}_{1}_{2}'.format(__session__.file.md5, # offset, name)) # resource.append(resource_path) # # with open(resource_path, 'wb') as resource_handle: # resource_handle.write(data) resources.append(resource) except Exception as e: print_error(e) continue return resources
def get_resources_info(self): res_array = [] printable = string.printable try: for resource_type in self.__pe.DIRECTORY_ENTRY_RESOURCE.entries: if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get( resource_type.struct.Id) if name == None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: try: data = self.__pe.get_data( resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) except: pass lang = pefile.LANG.get(resource_lang.data.lang, '*unknown*') sublang = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang) result = "" for each in data: if chr(each) in printable: result += chr(each) # print name, data, lang, sublang, hex(resource_lang.data.struct.OffsetToData), resource_lang.data.struct.Size res_array.append({ "name": name, "data": result, "offset": hex(resource_lang.data.struct.OffsetToData), "size": resource_lang.data.struct.Size, "language": lang, "sublanguage": sublang }) except: pass return res_array
def _resources_data_entry(exe): data = list() data.append(exe.DIRECTORY_ENTRY_RESOURCE.struct.dump_dict()) for resource_type in exe.DIRECTORY_ENTRY_RESOURCE.entries: resource_type_dict = dict() if resource_type.name is not None: resource_type_dict['Name'] = resource_type.name else: resource_type_dict['Id'] = ( resource_type.struct.Id, pefile.RESOURCE_TYPE.get(resource_type.struct.Id, '-')) resource_type_dict.update(resource_type.struct.dump_dict()) data.append(resource_type_dict) if hasattr(resource_type, 'directory'): directory_list = list() directory_list.append(resource_type.directory.struct.dump_dict()) data.append(directory_list) for resource_id in resource_type.directory.entries: resource_id_dict = dict() if resource_id.name is not None: resource_id_dict['Name'] = resource_id.name else: resource_id_dict['Id'] = resource_id.struct.Id resource_id_dict.update(resource_id.struct.dump_dict()) directory_list.append(resource_id_dict) if hasattr(resource_id, 'directory'): resource_id_list = list() resource_id_list.append(resource_id.directory.struct.dump_dict()) directory_list.append(resource_id_list) for resource_lang in resource_id.directory.entries: if hasattr(resource_lang, 'data'): resource_lang_dict = dict() resource_lang_dict['LANG'] = resource_lang.data.lang resource_lang_dict['SUBLANG'] = resource_lang.data.sublang resource_lang_dict['LANG_NAME'] = pefile.LANG.get(resource_lang.data.lang, '*unknown*') resource_lang_dict['SUBLANG_NAME'] = pefile.get_sublang_name_for_lang(resource_lang.data.lang, resource_lang.data.sublang) resource_lang_dict.update(resource_lang.struct.dump_dict()) resource_lang_dict.update(resource_lang.data.struct.dump_dict()) resource_id_list.append(resource_lang_dict) if hasattr(resource_id.directory, 'strings') and resource_id.directory.strings: for idx, res_string in list(resource_id.directory.strings.items()): resource_id_list.append(res_string.encode( 'unicode-escape', 'backslashreplace').decode( 'ascii')) return data
def get_resources(self, depth=0, resource=None, file_details={}, resource_path=[]): if depth == 0: if hasattr(self.pe, 'DIRECTORY_ENTRY_RESOURCE'): for resource in self.pe.DIRECTORY_ENTRY_RESOURCE.entries: file_details.update(self.get_resources(depth + 1, resource, file_details, [])) return {'resources' : file_details} else: if hasattr(resource, 'data'): resource_data = self.pe.get_data(resource.data.struct.OffsetToData, resource.data.struct.Size) md5 = hashlib.md5() md5.update(resource_data) md5_hash = md5.hexdigest() id = None name = None if resource.id: id = str(resource.id) if resource.name: name = str(resource.name) else: name = str(pefile.RESOURCE_TYPE.get(resource.struct.Id)) if id is not None: resource_path.append(id) if name is not None: resource_path.append(name) file_details[':'.join(resource_path)] = {'md5' : md5_hash, 'lang' : pefile.LANG.get(resource.data.lang, 'none'), 'sub_lang' : pefile.get_sublang_name_for_lang(resource.data.lang, resource.data.lang), 'type' : utils.get_type(buffer=resource_data).get('file_type', 'unknown'), 'size' : resource.data.struct.Size, 'offset' : resource.data.struct.OffsetToData} return file_details else: # We're at a directory and need to recurse deeper id = None name = None if resource.id: id = resource.id if resource.name: name = resource.name.string.decode('utf-8') else: name = pefile.RESOURCE_TYPE.get(resource.struct.Id) if id is not None: resource_path.append(str(id)) if name is not None: resource_path.append(str(name)) for child_resource in resource.directory.entries: file_details.update(self.get_resources(depth+1, child_resource, file_details, resource_path)) return file_details return file_details
def resource_info(pe, r, parents): """Recursive info of resources""" # resource if hasattr(r, "data"): # gather all the info offset = r.data.struct.OffsetToData size = r.data.struct.Size data = pe.get_memory_mapped_image()[offset:offset + size] parents_path = "/".join(parents) + "/" path = parents_path + str( r.id) if not r.name else parents_path + r.name m = hashlib.md5() m.update(data) md5 = m.hexdigest() magic_type = magic.from_buffer(data) lang = pefile.LANG.get(r.data.lang, 'UNKNOWN') sublang = pefile.get_sublang_name_for_lang( r.data.lang, r.data.sublang) # display it if we want cli_out( "%-19s %-9s %-14s %-17s %-14s %-9s" % (path, "%i B" % size, lang, sublang, magic_type, md5), cli_mode) # return it in a dict return [{ "path": path, "size": size, "md5": md5, "magic_type": magic_type, "lang": lang, "sublang": sublang }] # directory else: res = [] # append this name or ID to the parents list parents = copy.copy(parents) if r.id is not None: parents.append(str(r.id)) else: parents.append(r.name.string.decode('utf-8')) for r2 in r.directory.entries: res += resource_info(pe, r2, parents) return res
def resources(self): resources = [] if hasattr(self.pe, 'DIRECTORY_ENTRY_RESOURCE'): for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries: try: if resource_type.name is not None: name = str(resource_type.name) else: name = str(pefile.RESOURCE_TYPE.get(resource_type.struct.Id)) if name is None: name = str(resource_type.struct.Id) if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: data = self.pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) filetype = self.__get_filetype(data) md5 = self.__md5(data) language = pefile.LANG.get(resource_lang.data.lang, None) sublanguage = pefile.get_sublang_name_for_lang(resource_lang.data.lang, resource_lang.data.sublang) offset = ('%-8s' % hex(resource_lang.data.struct.OffsetToData)).strip() size = ('%-8s' % hex(resource_lang.data.struct.Size)).strip() resource = {'name': name, 'offset': offset, 'md5': md5, 'size': size, 'filetype': filetype, 'language': language.replace('LANG_', '').lower(), 'sublanguage': sublanguage.replace('SUBLANG_', '').lower()} # Dump resources if requested to and if the file currently being # processed is the opened session file. # This is to avoid that during a --scan all the resources being # scanned are dumped as well. # if dump_to and self.pe == self.pe: # resource_path = os.path.join(dump_to, # '{0}_{1}_{2}'.format(__session__.file.md5, # offset, name)) # resource.append(resource_path) # # with open(resource_path, 'wb') as resource_handle: # resource_handle.write(data) resources.append(resource) except Exception as e: print_error(e) continue return resources
def _get_resources(self): """Get resources. @return: resources dict or None. """ if not self.pe: return None resources = [] if hasattr(self.pe, "DIRECTORY_ENTRY_RESOURCE"): for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries: try: resource = {} if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get( resource_type.struct.Id) if name == None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, "directory"): for resource_id in resource_type.directory.entries: if hasattr(resource_id, "directory"): for resource_lang in resource_id.directory.entries: data = self.pe.get_data( resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) filetype = self._get_filetype(data) language = pefile.LANG.get( resource_lang.data.lang, None) sublanguage = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang) resource["name"] = name resource["offset"] = ("%-8s" % hex( resource_lang.data.struct.OffsetToData) ).strip() resource["size"] = ( "%-8s" % hex(resource_lang.data.struct.Size) ).strip() resource["filetype"] = filetype resource["language"] = language resource["sublanguage"] = sublanguage resources.append(resource) except: continue return resources
def get_resources(pe): resources = [] if hasattr(pe, "DIRECTORY_ENTRY_RESOURCE"): for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: try: resource = {} if resource_type.name is not None: name = str(resource_type.name) else: name = str(pefile.RESOURCE_TYPE.get(resource_type.struct.Id)) if name == None: name = str(resource_type.struct.Id) if hasattr(resource_type, "directory"): for resource_id in resource_type.directory.entries: if hasattr(resource_id, "directory"): for resource_lang in resource_id.directory.entries: data = pe.get_data( resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size ) filetype = self.__get_filetype(data) md5 = self.__get_md5(data) language = pefile.LANG.get(resource_lang.data.lang, None) sublanguage = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang ) offset = ("%-8s" % hex(resource_lang.data.struct.OffsetToData)).strip() size = ("%-8s" % hex(resource_lang.data.struct.Size)).strip() resource = [name, offset, md5, size, filetype, language, sublanguage] # Dump resources if requested to and if the file currently being # processed is the opened session file. # This is to avoid that during a --scan all the resources being # scanned are dumped as well. if arg_dump and pe == self.pe: resource_path = os.path.join( arg_dump, "{0}_{1}_{2}".format(__session__.file.md5, offset, name) ) resource.append(resource_path) with open(resource_path, "wb") as resource_handle: resource_handle.write(data) resources.append(resource) except Exception as e: print_error(e) continue return resources
def get_resources(self, pe: pefile.PE) -> List[Dict[str, str]]: """Get resources. @return: resources dict or None. """ if not pe: return None resources = [] if not hasattr(pe, "DIRECTORY_ENTRY_RESOURCE"): return resources for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: try: if resource_type.name is not None: name = str(resource_type.name) else: name = str( pefile.RESOURCE_TYPE.get(resource_type.struct.Id)) if hasattr(resource_type, "directory"): for resource_id in resource_type.directory.entries: if hasattr(resource_id, "directory"): for resource_lang in resource_id.directory.entries: data = pe.get_data( resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) resources.append({ "name": name, "offset": f"0x{resource_lang.data.struct.OffsetToData:08x}", "size": f"0x{resource_lang.data.struct.Size:08x}", "filetype": self._get_filetype(data), "language": pefile.LANG.get(resource_lang.data.lang), "sublanguage": pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang), "entropy": f"{float(self.get_entropy(data)):.02f}", }) except pefile.PEFormatError as e: log.error("get_resources error: %s", str(e)) except Exception as e: log.error(e, exc_info=True) continue return resources
def resources(self): resources = [] if hasattr(self.pe, 'DIRECTORY_ENTRY_RESOURCE'): for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries: try: resource = {} if resource_type.name is not None: name = str(resource_type.name) else: name = str(pefile.RESOURCE_TYPE.get(resource_type.struct.Id)) if name == None: name = str(resource_type.struct.Id) if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: data = self.pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) md5 = self.__get_md5(data) fs_id = "" if not self.artifact.database.fs.exists({"md5":md5}): fs_id = self.artifact.database.fs.put(data) else: grid_file = self.artifact.database.fs.get_version(md5=md5) fs_id = grid_file._id filetype = self.__get_filetype(data) language = pefile.LANG.get(resource_lang.data.lang, None) sublanguage = pefile.get_sublang_name_for_lang(resource_lang.data.lang, resource_lang.data.sublang) offset = ('%-8s' % hex(resource_lang.data.struct.OffsetToData)).strip() size = ('%-8s' % hex(resource_lang.data.struct.Size)).strip() resource = { "name": name, "filetype": filetype, "offset": offset, "size": size, "md5": md5, "language": language, "sublanguage": sublanguage, "fs_id": fs_id } resources.append(resource) except Exception as e: logging.error(e) continue self.data["sub"] = resources
def process(self): pelib = self._getLibrary(PEFileModule().getName()) if (pelib is None): return "" ret = [] if hasattr(pelib, 'DIRECTORY_ENTRY_RESOURCE'): i = 0 for resource_type in pelib.DIRECTORY_ENTRY_RESOURCE.entries: if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get( resource_type.struct.Id) if name is None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: try: data = pelib.get_data( resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) # fd=open(name,'wb') # fd.write(data) # (data) except pefile.PEFormatError: return "corrupt" filetype = MIME_TYPE(data, False) lang = pefile.LANG.get(resource_lang.data.lang, 'unknown') sublang = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang) entry = {} entry["name"] = self._normalize(name) entry["rva"] = self._normalize( hex(resource_lang.data.struct.OffsetToData) ) entry["size"] = self._normalize( hex(resource_lang.data.struct.Size)) entry["type"] = self._normalize(filetype) entry["lang"] = self._normalize(lang) entry["sublang"] = self._normalize(sublang) entry["sha1"] = SHA1(data) ret.append(entry) return ret
def analyze_dir(self, directory, prefix='', _type='', timedate=0): """ Analyze a resource directory and obtain all of its items.""" log = logging.getLogger('Mastiff.Plugins.' + self.name + '.analyze') # save the timedate stamp timedate = directory.struct.TimeDateStamp for top_item in directory.entries: if hasattr(top_item, 'data'): # at the language level that contains all of our information resource = dict() resource['Id'] = prefix resource['Type'] = _type # store the offset as the offset within the file, not the RVA! try: resource['Offset'] = self.pe.get_offset_from_rva( top_item.data.struct.OffsetToData) resource['Size'] = top_item.data.struct.Size resource['Lang'] = [ pefile.LANG.get(top_item.data.lang, '*unknown*'), \ pefile.get_sublang_name_for_lang( top_item.data.lang, top_item.data.sublang ) ] resource['TimeDate'] = timedate except pefile.PEFormatError, err: log.error('Error grabbing resource \"%s\" info: %s' % (prefix, err)) return False self.resources.append(resource) log.debug('Adding resource item %s' % resource['Id']) elif hasattr(top_item, 'directory'): if top_item.name is not None: # in a name level if len(prefix) == 0: newprefix = prefix + str(top_item.name) else: newprefix = ', '.join([prefix, str(top_item.name)]) else: # if name is blank, we are in a Type level if len(prefix) == 0: newprefix = 'ID ' + str(top_item.id) _type = pefile.RESOURCE_TYPE.get(top_item.id) else: newprefix = ', '.join( [prefix, 'ID ' + str(top_item.id)]) # we aren't at the end, recurse self.analyze_dir(top_item.directory, prefix=newprefix, _type=_type)
def get(pe): try: for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get(resource_type.struct.Id) if name == None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: try: data = pe.get_data( resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) except: pass lang = pefile.LANG.get(resource_lang.data.lang, '*unknown*') sublang = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang) data = filter(lambda x: x in string.printable, data) #print name, data, lang, sublang, hex(resource_lang.data.struct.OffsetToData), resource_lang.data.struct.Size res_array.append({ "name": name, "data": data, "offset": hex(resource_lang.data.struct.OffsetToData), "size": resource_lang.data.struct.Size, "language": lang, "sublanguage": sublang }) except: pass return res_array
def _get_resources(self): """Get resources. @return: resources dict or None. """ if not self.pe: return None resources = [] if hasattr(self.pe, "DIRECTORY_ENTRY_RESOURCE"): for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries: try: resource = {} if resource_type.name is not None: name = str(resource_type.name) else: name = str( pefile.RESOURCE_TYPE.get(resource_type.struct.Id)) if hasattr(resource_type, "directory"): for resource_id in resource_type.directory.entries: if hasattr(resource_id, "directory"): for resource_lang in resource_id.directory.entries: data = self.pe.get_data( resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) filetype = _get_filetype(data) language = pefile.LANG.get( resource_lang.data.lang, None) sublanguage = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang) resource["name"] = name resource["offset"] = "0x{0:08x}".format( resource_lang.data.struct.OffsetToData) resource["size"] = "0x{0:08x}".format( resource_lang.data.struct.Size) resource["filetype"] = filetype resource["language"] = language resource["sublanguage"] = sublanguage resource["entropy"] = "{0:.02f}".format( float(_get_entropy(data))) resources.append(resource) except: continue return resources
def set_resources_info(self): res_array = [] if hasattr(self.pe, 'DIRECTORY_ENTRY_RESOURCE'): for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries: if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get( resource_type.struct.Id) if name == None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: raw_data = self.pe.get_data( resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) ent = self.__get_entropy(raw_data) raw_data = [format(i, '02x') for i in raw_data] lang = pefile.LANG.get(resource_lang.data.lang, '*unknown*') sublang = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang) file_ratio = self.__get_file_ratio(raw_data) res_array.append({ "name": name, "data": raw_data, "offset": hex(resource_lang.data.struct.OffsetToData ), "size": resource_lang.data.struct.Size, "file_ratio": file_ratio, "entropy": ent, "language": lang, "sublanguage": sublang }) if len(res_array) != 0: self.info['PE']['Resource'] = res_array
def _get_resources(self): if not self.pe: return None resources = [] if not hasattr(self.pe, "DIRECTORY_ENTRY_RESOURCE"): return resources for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries: try: resource = {} if resource_type.name is not None: name = str(resource_type.name) else: struct_id = resource_type.struct.Id name = str(pefile.RESOURCE_TYPE.get(struct_id)) if not hasattr(resource_type, "directory"): continue for resource_id in resource_type.directory.entries: if not hasattr(resource_id, "directory"): continue for resource_lang in resource_id.directory.entries: offset = resource_lang.data.struct.OffsetToData size = resource_lang.data.struct.Size lang = resource_lang.data.lang sublang = resource_lang.data.sublang data = self.pe.get_data(offset, size) filetype = self._get_filetype(data) language = pefile.LANG.get(lang, None) sublanguage = pefile.get_sublang_name_for_lang( lang, sublang) resource["name"] = name resource["offset"] = "0x{0:08x}".format(offset) resource["size"] = "0x{0:08x}".format(size) resource["filetype"] = filetype resource["language"] = language resource["sublanguage"] = sublanguage resources.append(resource) except: continue return resources
def _get_resources(self): if not self.pe: return None resources = [] if not hasattr(self.pe, "DIRECTORY_ENTRY_RESOURCE"): return resources for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries: try: resource = {} if resource_type.name is not None: name = str(resource_type.name) else: struct_id = resource_type.struct.Id name = str(pefile.RESOURCE_TYPE.get(struct_id)) if not hasattr(resource_type, "directory"): continue for resource_id in resource_type.directory.entries: if not hasattr(resource_id, "directory"): continue for resource_lang in resource_id.directory.entries: offset = resource_lang.data.struct.OffsetToData size = resource_lang.data.struct.Size lang = resource_lang.data.lang sublang = resource_lang.data.sublang data = self.pe.get_data(offset, size) filetype = self._get_filetype(data) language = pefile.LANG.get(lang, None) sublanguage = pefile.get_sublang_name_for_lang(lang, sublang) resource["name"] = name resource["offset"] = "0x{0:08x}".format(offset) resource["size"] = "0x{0:08x}".format(size) resource["filetype"] = filetype resource["language"] = language resource["sublanguage"] = sublanguage resources.append(resource) except: continue return resources
def process(self): pelib = self._getLibrary(PEFileModule().getName()) if(pelib is None): return "" ret = [] if hasattr(pelib, 'DIRECTORY_ENTRY_RESOURCE'): i = 0 for resource_type in pelib.DIRECTORY_ENTRY_RESOURCE.entries: if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get( resource_type.struct.Id) if name is None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: try: data = pelib.get_data( resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) # fd=open(name,'wb') # fd.write(data) # (data) except pefile.PEFormatError: return "corrupt" filetype = MIME_TYPE(data, False) lang = pefile.LANG.get( resource_lang.data.lang, 'unknown') sublang = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang) entry = {} entry["name"] = self._normalize(name) entry["rva"] = self._normalize( hex(resource_lang.data.struct.OffsetToData)) entry["size"] = self._normalize( hex(resource_lang.data.struct.Size)) entry["type"] = self._normalize(filetype) entry["lang"] = self._normalize(lang) entry["sublang"] = self._normalize(sublang) entry["sha1"] = SHA1(data) ret.append(entry) return ret
def analyze_dir(self, directory, prefix='', _type='', timedate=0): """ Analyze a resource directory and obtain all of its items.""" log = logging.getLogger('Mastiff.Plugins.' + self.name + '.analyze') # save the timedate stamp timedate = directory.struct.TimeDateStamp for top_item in directory.entries: if hasattr(top_item, 'data'): # at the language level that contains all of our information resource = dict() resource['Id'] = prefix resource['Type'] = _type # store the offset as the offset within the file, not the RVA! try: resource['Offset'] = self.pe.get_offset_from_rva(top_item.data.struct.OffsetToData) resource['Size'] = top_item.data.struct.Size resource['Lang'] = [ pefile.LANG.get(top_item.data.lang, '*unknown*'), \ pefile.get_sublang_name_for_lang( top_item.data.lang, top_item.data.sublang ) ] resource['TimeDate'] = timedate except pefile.PEFormatError, err: log.error('Error grabbing resource \"%s\" info: %s' % (prefix, err)) return False self.resources.append(resource) log.debug('Adding resource item %s' % resource['Id']) elif hasattr(top_item, 'directory'): if top_item.name is not None: # in a name level if len(prefix) == 0: newprefix = prefix + str(top_item.name) else: newprefix = ', '.join([prefix, str(top_item.name)]) else: # if name is blank, we are in a Type level if len(prefix) == 0: newprefix = 'ID ' + str(top_item.id) _type = pefile.RESOURCE_TYPE.get(top_item.id) else: newprefix = ', '.join([prefix, 'ID ' + str(top_item.id)]) # we aren't at the end, recurse self.analyze_dir(top_item.directory, prefix=newprefix, _type=_type)
def _get_resources(self): """Get resources. @return: resources dict or None. """ if not self.pe: return None resources = [] if hasattr(self.pe, "DIRECTORY_ENTRY_RESOURCE"): for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries: try: resource = {} if resource_type.name is not None: name = str(resource_type.name) else: name = str(pefile.RESOURCE_TYPE.get(resource_type.struct.Id)) if hasattr(resource_type, "directory"): for resource_id in resource_type.directory.entries: if hasattr(resource_id, "directory"): for resource_lang in resource_id.directory.entries: data = self.pe.get_data( resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size ) filetype = _get_filetype(data) language = pefile.LANG.get(resource_lang.data.lang, None) sublanguage = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang ) resource["name"] = name resource["offset"] = "0x{0:08x}".format(resource_lang.data.struct.OffsetToData) resource["size"] = "0x{0:08x}".format(resource_lang.data.struct.Size) resource["filetype"] = filetype resource["language"] = language resource["sublanguage"] = sublanguage resource["entropy"] = "{0:.02f}".format(float(_get_entropy(data))) resources.append(resource) except: continue return resources
def get_resource_data(pe): resources = [] if hasattr(pe, "DIRECTORY_ENTRY_RESOURCE"): for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: resource = {} try: if resource_type.name is not None: name = str(resource_type.name) else: name = str( pefile.RESOURCE_TYPE.get(resource_type.struct.Id)) except TypeError: name = 'unknown' if hasattr(resource_type, "directory"): for resource_id in resource_type.directory.entries: if hasattr(resource_id, "directory"): for resource_lang in resource_id.directory.entries: data = pe.get_data( resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) language = pefile.LANG.get(resource_lang.data.lang, None) sub_language = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang) resource["name"] = name resource["offset"] = "0x{0:08x}".format( resource_lang.data.struct.OffsetToData) resource["size"] = "0x{0:08x}".format( resource_lang.data.struct.Size) resource["language"] = language resource["sublanguage"] = sub_language resource['filetype'] = magic.from_buffer( pe.get_memory_mapped_image() [resource_lang.data.struct.OffsetToData: resource_lang.data.struct.OffsetToData + 1024]) resources.append(resource) return resources
def _parse_resource(self, type: str, entry, pe) -> Tuple[Dict, bytes]: sublang = pefile.get_sublang_name_for_lang(entry.data.lang, entry.data.sublang) rva = entry.data.struct.OffsetToData size = entry.data.struct.Size raw_data = pe.get_data(rva, size) metadata = { 'type': type, 'resource_id': entry.id, 'resource_type': entry.data.struct.name, 'address': rva, 'offset': pe.get_offset_from_rva(rva), 'sha256': hashlib.sha256(raw_data).hexdigest(), 'sha1': hashlib.sha1(raw_data).hexdigest(), 'md5': hashlib.md5(raw_data).hexdigest(), 'language': pefile.LANG.get(entry.data.lang, 'unknown'), 'sub_language': sublang, 'size': size, 'name': f'resource_{type}_{entry.id}', } return (metadata, raw_data)
def _get_resources(self): """Get resources. @return: resources dict or None. """ if not self.pe: return None resources = [] if hasattr(self.pe, "DIRECTORY_ENTRY_RESOURCE"): for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries: try: resource = {} if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get(resource_type.struct.Id) if name == None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, "directory"): for resource_id in resource_type.directory.entries: if hasattr(resource_id, "directory"): for resource_lang in resource_id.directory.entries: data = self.pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) filetype = self._get_filetype(data) language = pefile.LANG.get(resource_lang.data.lang, None) sublanguage = pefile.get_sublang_name_for_lang(resource_lang.data.lang, resource_lang.data.sublang) resource["name"] = name resource["offset"] = ("%-8s" % hex(resource_lang.data.struct.OffsetToData)).strip() resource["size"] = ("%-8s" % hex(resource_lang.data.struct.Size)).strip() resource["filetype"] = filetype resource["language"] = language resource["sublanguage"] = sublanguage resources.append(resource) except: continue return resources
def resource(level, r): """Recursive printing of resources""" if hasattr(r, "data"): # resource offset = r.data.struct.OffsetToData size = r.data.struct.Size data = pe.get_memory_mapped_image()[offset:offset + size] m = hashlib.md5() m.update(data) print(" " * level + "-%s\t%i\t%i\t%s\t%s\t%s" % (str(r.name), r.id, size, m.hexdigest(), pefile.LANG.get(r.data.lang, 'UNKNOWN'), pefile.get_sublang_name_for_lang(r.data.lang, r.data.sublang))) else: # directory if r.name is None: print(" " * level + "-" + str(r.id)) else: print(" " * level + "-" + str(r.name)) for r2 in r.directory.entries: resource(level + 1, r2)
def _parse_resource(self, type: str, entry, pe) -> Tuple[Dict, bytes]: sublang = pefile.get_sublang_name_for_lang(entry.data.lang, entry.data.sublang) rva = entry.data.struct.OffsetToData size = entry.data.struct.Size raw_data = pe.get_data(rva, size) metadata = { "type": type, "resource_id": entry.id, "resource_type": entry.data.struct.name, "address": rva, "offset": pe.get_offset_from_rva(rva), "sha256": hashlib.sha256(raw_data).hexdigest(), "sha1": hashlib.sha1(raw_data).hexdigest(), "md5": hashlib.md5(raw_data).hexdigest(), "language": pefile.LANG.get(entry.data.lang, "unknown"), "sub_language": sublang, "size": size, "name": f"resource_{type}_{entry.id}", } return (metadata, raw_data)
def lang_bools(pe): """Scours the resource directory of a PE32 file for language information. Returns four booleans that Yonts argued might make good malware indicators. The booleans are: Language=0, Language>127, SubLanguage=0, SubLanguage=2""" ret = [0, 0, 0, 0] # Getting to the language attributes requires a lot of digging if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'): for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: lang = pefile.LANG.get(resource_lang.data.lang, \ '*unknown*') sublang = pefile.get_sublang_name_for_lang( \ resource_lang.data.lang, resource_lang.data.sublang) # Here we check if we need to set any bools to true try: if (pefile.LANG[lang] == 0): ret[0] = 1 if (pefile.LANG[lang] > 127): ret[1] = 1 except KeyError: print 'KeyError!' ret[0] = -1 ret[1] = -1 try: if (pefile.SUBLANG[sublang] == 0): ret[2] = 1 if (pefile.SUBLANG[sublang] == 2): ret[3] = 1 except KeyError: print 'KeyError!' ret[2] = -1 ret[3] = -1 return ret
def lang_bools(pe): """Scours the resource directory of a PE32 file for language information. Returns four booleans that Yonts argued might make good malware indicators. The booleans are: Language=0, Language>127, SubLanguage=0, SubLanguage=2""" ret = [0, 0, 0, 0] # Getting to the language attributes requires a lot of digging if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'): for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: lang = pefile.LANG.get(resource_lang.data.lang, \ '*unknown*') sublang = pefile.get_sublang_name_for_lang( \ resource_lang.data.lang, resource_lang.data.sublang) # Here we check if we need to set any bools to true try: if(pefile.LANG[lang] == 0): ret[0] = 1 if(pefile.LANG[lang] > 127): ret[1] = 1 except KeyError: print 'KeyError!' ret[0] = -1 ret[1] = -1 try: if(pefile.SUBLANG[sublang] == 0): ret[2] = 1 if(pefile.SUBLANG[sublang] == 2): ret[3] = 1 except KeyError: print 'KeyError!' ret[2] = -1 ret[3] = -1 return ret
def getPEResource(f): try: pe = pefile.PE(data=f) resourcesList = [] if hasattr(pe, "DIRECTORY_ENTRY_RESOURCE"): for entry in pe.DIRECTORY_ENTRY_RESOURCE.entries: type = pefile.RESOURCE_TYPE.get(entry.id, 'NA') for e in entry.directory.entries: for m in e.directory.entries: lang = pefile.LANG.get(m.data.lang, '*unknown*') sublang = pefile.get_sublang_name_for_lang( m.data.lang, m.data.sublang) rva = m.data.struct.OffsetToData size = m.data.struct.Size data = pe.get_data(rva, size) name = entry.name resources = (type, hashlib.sha256(data).hexdigest(), hashlib.md5(data).hexdigest(), lang, sublang, size) resourcesList.append(resources) return resourcesList except: return
def get_resources(pe): res_array = [] try: ''' # resource types # description RT_CURSOR = 1 # Hardware-dependent cursor resource. RT_BITMAP = 2 # Bitmap resource. RT_ICON = 3 # Hardware-dependent icon resource. RT_MENU = 4 # Menu resource. RT_DIALOG = 5 # Dialog box. RT_STRING = 6 # String-table entry. RT_FONTDIR = 7 # Font directory resource. RT_FONT = 8 # Font resource. RT_ACCELERATOR = 9 # Accelerator table. RT_RCDATA = 10 # Application-defined resource (raw data.) RT_MESSAGETABLE = 11 # Message-table entry. RT_VERSION = 16 # Version resource. RT_DLGINCLUDE = 17 # Allows a resource editing tool to associate a string with an .rc file. RT_PLUGPLAY = 19 # Plug and Play resource. RT_VXD = 20 # VXD. RT_ANICURSOR = 21 # Animated cursor. RT_ANIICON = 22 # Animated icon. RT_HTML = 23 # HTML resource. RT_MANIFEST = 24 # Side-by-Side Assembly Manifest. RT_GROUP_CURSOR = RT_CURSOR + 11 # Hardware-independent cursor resource. RT_GROUP_ICON = RT_ICON + 11 # Hardware-independent icon resource. ''' for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: if resource_type.name is not None: name = "%s" % resource_type.name else: name = "%s" % pefile.RESOURCE_TYPE.get(resource_type.struct.Id) if name == None: name = "%d" % resource_type.struct.Id if hasattr(resource_type, 'directory'): i = 0 for resource_id in resource_type.directory.entries: if len(resource_type.directory.entries) > 1: i = i+1 newname = name+'_'+str(i) else: newname = name for resource_lang in resource_id.directory.entries: data_byte = pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size)[:50] is_pe = False if magic_check(data_byte)[:8]: is_pe = True lang = pefile.LANG.get(resource_lang.data.lang, '*unknown*') sublang = pefile.get_sublang_name_for_lang(resource_lang.data.lang, resource_lang.data.sublang) res_array.append({ "name": newname, "data": str(data_byte), "executable": is_pe, "offset": resource_lang.data.struct.OffsetToData, "size": resource_lang.data.struct.Size, "language": lang, "sublanguage": sublang }) except: pass return res_array
def startAnalyses(): version() try: opts, args = getopt.getopt(sys.argv[1:], "hf:", ["help", "file="]) except getopt.GetoptError: help() sys.exit(2) for opt, arg in opts: if opt in ("-h", "--help"): help() sys.exit() elif opt in ("-f", "--file"): filePath = arg f = open(filePath) html = createFile(filePath) pe = pefile.PE(filePath) # get the filetype by calling the external program file filetype = subprocess.check_output(["file", "-b", filePath]) html.write("File Size: %s<br>\nFile Type: %s<br>\n" % (os.path.getsize(filePath), filetype)) html.write( "Compilation timestamp: %s<br>\n" % (datetime.datetime.fromtimestamp(pe.FILE_HEADER.TimeDateStamp))) insertSeperator(html) html.write("<br><b><a id='version'>File Version Info:</a></b>\n<br>\n") # from Ero Carrera's blog for fileinfo in pe.FileInfo: if fileinfo.Key == 'StringFileInfo': for st in fileinfo.StringTable: for entry in st.entries.items(): html.write("%s: %s<br>\n" % (entry[0], entry[1])) if fileinfo.Key == 'VarFileInfo': for var in fileinfo.Var: html.write("%s: %s<br>\n" % var.entry.items()[0]) insertSeperator(html) # calculate some Checksums md5, sha1, sha256, sha512 = calcChecksum(f) html.write( "<br><b><a id='checksums'>File Checksums:</a></b>\n<br>\nMD5: %s<br>\nSHA1: %s<br>\nSHA256: %s<br>\nSHA512: %s<br>\n" % ( md5, sha1, sha256, sha512)) insertSeperator(html) # create Virustotal Analysis Link vtlink = vtanalysisurl + sha256 + "/analysis" # request Results from Virustotal try: response_dict = queryVT(md5) html.write("<br><b><a id='virus'>VirusTotal Results:</a></b><br>%s / %s<br><br><a href='%s' target='_blank'>VirusTotal Analysis Link</a><br>\n" % ( response_dict.get("positives"), response_dict.get("total"), vtlink)) except: html.write("<br><b><a id='virus'>VirusTotal Results:</a></b><br>Error!<br>\n") insertSeperator(html) html.write("<br><b><a id='sections'>Sections:</a></b><br>\n") html.write("Entrypoint: %s<br>Number of Sections: %i<br><br>\n" % ( hex(pe.OPTIONAL_HEADER.AddressOfEntryPoint), len(pe.sections))) html.write("<table><tr><th>Name</th> <th>Virtual address</th> <th>Virtual size</th> <th>Raw size</th> <th>Entropy</th></tr>\n") for section in pe.sections: e = getEntropy(section.get_data()) if e < 6.0: a = "Not packed" elif e < 7.0: a = "Maybe packed" else: # 7.0 .. 8.0 a = "Packed" html.write("<tr><td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%.2f (%s)</td></tr>\n" % ( section.Name, hex(section.VirtualAddress), hex(section.Misc_VirtualSize), section.SizeOfRawData, e, a)) html.write("</table>\n") insertSeperator(html) susp_api = [] apis = getList(BASE_DIR + "/api.txt") pe.parse_data_directories() html.write("<br><b><a id='imports'>Imports:</a></b><br>\n") for entry in pe.DIRECTORY_ENTRY_IMPORT: html.write("<b>%s</b><br>\n" % entry.dll) for imp in entry.imports: html.write("%s %s<br>\n" % (hex(imp.address), imp.name)) if (imp.name != None) and (imp.name != ""): for api in apis: if imp.name.startswith(api): susp_api.append(imp) insertSeperator(html) html.write("<br><b><a id='suspicious'>Suspicious APIs:</a></b><br>\n") for imp in susp_api: html.write("%s %s<br>\n" % (hex(imp.address), imp.name)) insertSeperator(html) html.write("<br><b><a id='exports'>Exports:</a></b><br>\n") try: for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols: html.write("%s %s<br>\n" % (hex(pe.OPTIONAL_HEADER.ImageBase + exp.address), exp.name)) except: html.write("No Exports found!<br>\n") insertSeperator(html) html.write("<br><b><a id='resources'>Resources:</a></b><br>\n") html.write("<table><tr><th>Name</th> <th>Virtual address</th> <th>Virtual size</th> <th>Raw size</th> <th>Entropy</th></tr>\n") for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries: if resource_type.name is not None: name = "%s" % resource_type.name print name else: name = "%s" % pefile.RESOURCE_TYPE.get(resource_type.struct.Id) if name == None: name = "%d" % resource_type.struct.Id for resource_id in resource_type.directory.entries: if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: data = pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) lang = pefile.LANG.get(resource_lang.data.lang) sublang = pefile.get_sublang_name_for_lang(resource_lang.data.lang, resource_lang.data.sublang) html.write("<tr><td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td></tr>\n" % (name, hex(resource_lang.data.struct.OffsetToData), hex(resource_lang.data.struct.Size), lang, sublang)) html.write("</table>\n") insertSeperator(html) # get printable strings in the binary file by calling the external program strings strings = subprocess.check_output(["strings", filePath]) html.write("<br><b><a id='strings'>Strings:</a></b><br>\n") html.write("<br>\n".join(strings.split()))
def _resources_data_entry(exe): data = list() data.append(exe.DIRECTORY_ENTRY_RESOURCE.struct.dump_dict()) for resource_type in exe.DIRECTORY_ENTRY_RESOURCE.entries: resource_type_dict = dict() if resource_type.name is not None: resource_type_dict['Name'] = resource_type.name else: resource_type_dict['Id'] = (resource_type.struct.Id, pefile.RESOURCE_TYPE.get( resource_type.struct.Id, '-')) resource_type_dict.update(resource_type.struct.dump_dict()) data.append(resource_type_dict) if hasattr(resource_type, 'directory'): directory_list = list() directory_list.append(resource_type.directory.struct.dump_dict()) data.append(directory_list) for resource_id in resource_type.directory.entries: resource_id_dict = dict() if resource_id.name is not None: resource_id_dict['Name'] = resource_id.name else: resource_id_dict['Id'] = resource_id.struct.Id resource_id_dict.update(resource_id.struct.dump_dict()) directory_list.append(resource_id_dict) if hasattr(resource_id, 'directory'): resource_id_list = list() resource_id_list.append( resource_id.directory.struct.dump_dict()) directory_list.append(resource_id_list) for resource_lang in resource_id.directory.entries: if hasattr(resource_lang, 'data'): resource_lang_dict = dict() resource_lang_dict[ 'LANG'] = resource_lang.data.lang resource_lang_dict[ 'SUBLANG'] = resource_lang.data.sublang resource_lang_dict['LANG_NAME'] = pefile.LANG.get( resource_lang.data.lang, '*unknown*') resource_lang_dict[ 'SUBLANG_NAME'] = pefile.get_sublang_name_for_lang( resource_lang.data.lang, resource_lang.data.sublang) resource_lang_dict.update( resource_lang.struct.dump_dict()) resource_lang_dict.update( resource_lang.data.struct.dump_dict()) resource_id_list.append(resource_lang_dict) if hasattr(resource_id.directory, 'strings') and resource_id.directory.strings: for idx, res_string in list( resource_id.directory.strings.items()): resource_id_list.append( res_string.encode( 'unicode-escape', 'backslashreplace').decode('ascii')) return data
def resources(self): if not self.pe: return def usage(): print("usage: pe resources [-d=folder]") def help(): usage() print("") print("Options:") print("\t--help (-h)\tShow this help message") print("\t--dump (-d)\tDestination directory to store resource files in") print("") try: opts, argv = getopt.getopt(self.args[1:], 'hd:', ['help', 'dump=']) except getopt.GetoptError as e: print(e) usage() return dump_to = None for opt, value in opts: if opt in ('-h', '--help'): help() return elif opt in ('-d', '--dump'): dump_to = value resources = [] if hasattr(self.pe, 'DIRECTORY_ENTRY_RESOURCE'): for resource_type in self.pe.DIRECTORY_ENTRY_RESOURCE.entries: try: resource = {} if resource_type.name is not None: name = str(resource_type.name) else: name = str(pefile.RESOURCE_TYPE.get(resource_type.struct.Id)) if name == None: name = str(resource_type.struct.Id) if hasattr(resource_type, 'directory'): for resource_id in resource_type.directory.entries: if hasattr(resource_id, 'directory'): for resource_lang in resource_id.directory.entries: data = self.pe.get_data(resource_lang.data.struct.OffsetToData, resource_lang.data.struct.Size) filetype = self.__get_filetype(data) language = pefile.LANG.get(resource_lang.data.lang, None) sublanguage = pefile.get_sublang_name_for_lang(resource_lang.data.lang, resource_lang.data.sublang) offset = ('%-8s' % hex(resource_lang.data.struct.OffsetToData)).strip() size = ('%-8s' % hex(resource_lang.data.struct.Size)).strip() resource = [name, offset, size, filetype, language, sublanguage] if dump_to: resource_path = os.path.join(dump_to, '{0}_{1}_{2}'.format(__session__.file.md5, offset, name)) resource.append(resource_path) with open(resource_path, 'wb') as resource_handle: resource_handle.write(data) resources.append(resource) except Exception as e: print_error(e) continue headers = ['Name', 'Offset', 'Size', 'File Type', 'Language', 'Sublanguage'] if dump_to: headers.append('Dumped To') print table(headers, resources)
def _run(self, scanObject, result, depth, args): moduleResult = [] imports = {} sections = {} exports = [] try: pe = pefile.PE(data=scanObject.buffer) dump_dict = pe.dump_dict() # Parse sections for section in dump_dict.get("PE Sections", []): secName = section.get("Name", {}).get("Value", "").strip("\0") ptr = section.get("PointerToRawData", {}).get("Value") virtAddress = section.get("VirtualAddress", {}).get("Value") virtSize = section.get("Misc_VirtualSize", {}).get("Value") size = section.get("SizeOfRawData", {}).get("Value") secData = pe.get_data(ptr, size) secInfo = { "Virtual Address": "0x%08X" % virtAddress, "Virtual Size": virtSize, "Raw Size": size, "MD5": section.get("MD5", ""), "SHA1": section.get("SHA1", ""), "SHA256": section.get("SHA256", ""), "Entropy": section.get("Entropy", ""), "Section Characteristics": section.get("Flags", []), "Structure": section.get("Structure", ""), } if secInfo["MD5"] != scanObject.objectHash: moduleResult.append(ModuleObject(buffer=secData, externalVars=ExternalVars(filename=secName))) sections[secName] = secInfo sections["Total"] = pe.FILE_HEADER.NumberOfSections scanObject.addMetadata(self.module_name, "Sections", sections) # Parse imports and exports try: for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols: exports.append(exp.name) scanObject.addMetadata(self.module_name, "Exports", exports) except ScanError: raise except: logging.debug("No export entries") for imp_symbol in dump_dict.get("Imported symbols", []): for imp in imp_symbol: if imp.get("DLL"): dll = imp.get("DLL") imports.setdefault(dll, []) # Imports can be identified by ordinal or name if imp.get("Ordinal"): ordinal = imp.get("Ordinal") imports[dll].append(ordinal) if imp.get("Name"): name = imp.get("Name") imports[dll].append(name) scanObject.addMetadata(self.module_name, "Imports", imports) # Parse resources try: for resource in pe.DIRECTORY_ENTRY_RESOURCE.entries: res_type = pefile.RESOURCE_TYPE.get(resource.id, "Unknown") for entry in resource.directory.entries: for e_entry in entry.directory.entries: sublang = pefile.get_sublang_name_for_lang(e_entry.data.lang, e_entry.data.sublang) offset = e_entry.data.struct.OffsetToData size = e_entry.data.struct.Size r_data = pe.get_data(offset, size) language = pefile.LANG.get(e_entry.data.lang, "Unknown") data = { "Type": res_type, "Id": e_entry.id, "Name": e_entry.data.struct.name, "Offset": offset, "Size": size, "SHA256": hashlib.sha256(r_data).hexdigest(), "SHA1": hashlib.sha1(r_data).hexdigest(), "MD5": hashlib.md5(r_data).hexdigest(), "Language": language, "Sub Language": sublang, } scanObject.addMetadata(self.module_name, "Resources", data) except ScanError: raise except: logging.debug("No resources") # Gather miscellaneous stuff try: scanObject.addMetadata(self.module_name, "Imphash", pe.get_imphash()) except ScanError: raise except: logging.debug("Unable to identify imphash") imgChars = dump_dict.get("Flags", []) scanObject.addMetadata(self.module_name, "Image Characteristics", imgChars) # Make a pretty date format date = datetime.fromtimestamp(pe.FILE_HEADER.TimeDateStamp) isoDate = date.isoformat() scanObject.addMetadata(self.module_name, "Date", isoDate) scanObject.addMetadata(self.module_name, "Timestamp", pe.FILE_HEADER.TimeDateStamp) machine = pe.FILE_HEADER.Machine machineData = {"Id": machine, "Type": pefile.MACHINE_TYPE.get(machine)} scanObject.addMetadata(self.module_name, "Machine Type", machineData) # Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms680339%28v=vs.85%29.aspx scanObject.addMetadata( self.module_name, "Image Magic", IMAGE_MAGIC_LOOKUP.get(pe.OPTIONAL_HEADER.Magic, "Unknown") ) dllChars = dump_dict.get("DllCharacteristics", []) scanObject.addMetadata(self.module_name, "DLL Characteristics", dllChars) subsystem = pe.OPTIONAL_HEADER.Subsystem subName = pefile.SUBSYSTEM_TYPE.get(subsystem) scanObject.addMetadata(self.module_name, "Subsystem", subName) # Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms648009%28v=vs.85%29.aspx scanObject.addMetadata(self.module_name, "Stack Reserve Size", pe.OPTIONAL_HEADER.SizeOfStackReserve) scanObject.addMetadata(self.module_name, "Stack Commit Size", pe.OPTIONAL_HEADER.SizeOfStackCommit) scanObject.addMetadata(self.module_name, "Heap Reserve Size", pe.OPTIONAL_HEADER.SizeOfHeapReserve) scanObject.addMetadata(self.module_name, "Heap Commit Size", pe.OPTIONAL_HEADER.SizeOfHeapCommit) scanObject.addMetadata(self.module_name, "EntryPoint", hex(pe.OPTIONAL_HEADER.AddressOfEntryPoint)) scanObject.addMetadata(self.module_name, "ImageBase", hex(pe.OPTIONAL_HEADER.ImageBase)) # Parse RSDS & Rich scanObject.addMetadata(self.module_name, "Rich Header", self.parseRich(pe)) if hasattr(pe, "DIRECTORY_ENTRY_DEBUG"): debug = dict() for e in pe.DIRECTORY_ENTRY_DEBUG: rawData = pe.get_data(e.struct.AddressOfRawData, e.struct.SizeOfData) if rawData.find("RSDS") != -1 and len(rawData) > 24: pdb = rawData[rawData.find("RSDS") :] debug["guid"] = "%s-%s-%s-%s" % ( binascii.hexlify(pdb[4:8]), binascii.hexlify(pdb[8:10]), binascii.hexlify(pdb[10:12]), binascii.hexlify(pdb[12:20]), ) debug["age"] = struct.unpack("<L", pdb[20:24])[0] debug["pdb"] = pdb[24:].rstrip("\x00") scanObject.addMetadata(self.module_name, "RSDS", debug) elif rawData.find("NB10") != -1 and len(rawData) > 16: pdb = rawData[rawData.find("NB10") + 8 :] debug["created"] = datetime.fromtimestamp(struct.unpack("<L", pdb[0:4])[0]).isoformat() debug["age"] = struct.unpack("<L", pdb[4:8])[0] debug["pdb"] = pdb[8:].rstrip("\x00") scanObject.addMetadata(self.module_name, "NB10", debug) except pefile.PEFormatError: logging.debug("Invalid PE format") return moduleResult
def scan(self, data, file, options, expire_at): try: pe = pefile.PE(data=data) except pefile.PEFormatError: self.flags.append('pe_format_error') return cert_dict = parse_certificates(data) if cert_dict: self.event['security'] = cert_dict self.event['total'] = { 'libraries': 0, 'resources': 0, 'sections': len(pe.sections), 'symbols': 0, } self.event['summary'] = {} if hasattr(pe, 'DIRECTORY_ENTRY_DEBUG'): for d in pe.DIRECTORY_ENTRY_DEBUG: data = pe.get_data(d.struct.AddressOfRawData, d.struct.SizeOfData) if data.find(b'RSDS') != -1 and len(data) > 24: pdb = data[data.find(b'RSDS'):] self.event['debug'] = { 'type': 'rsds', 'guid': b'%s-%s-%s-%s' % ( binascii.hexlify(pdb[4:8]), binascii.hexlify(pdb[8:10]), binascii.hexlify(pdb[10:12]), binascii.hexlify(pdb[12:20]), ), 'age': struct.unpack('<L', pdb[20:24])[0], 'pdb': pdb[24:].rstrip(b'\x00') } elif data.find(b'NB10') != -1 and len(data) > 16: pdb = data[data.find(b'NB10') + 8:] self.event['debug'] = { 'type': 'nb10', 'created': struct.unpack('<L', pdb[0:4])[0], 'age': struct.unpack('<L', pdb[4:8])[0], 'pdb': pdb[8:].rstrip(b'\x00'), } self.event['file_info'] = { 'fixed': {}, 'string': [], 'var': {}, } # https://github.com/erocarrera/pefile/blob/master/pefile.py#L3553 if hasattr(pe, 'FileInfo'): fi = pe.FileInfo[0] # contains a single element for i in fi: if i.Key == b'StringFileInfo': for st in i.StringTable: for k, v in st.entries.items(): if k.decode() in COMMON_FILE_INFO_NAMES: self.event['file_info'][COMMON_FILE_INFO_NAMES[ k.decode()]] = v.decode() else: self.event['file_info']['string'].append({ 'name': k.decode(), 'value': v.decode(), }) elif i.Key == b'VarFileInfo': for v in i.Var: translation = v.entry.get(b'Translation') (lang, char) = (translation.split()) self.event['file_info']['var'] = { 'language': VAR_FILE_INFO_LANGS.get(int(lang, 16)), 'character_set': VAR_FILE_INFO_CHARS.get(int(char, 16)), } if hasattr(pe, 'VS_FIXEDFILEINFO'): vs_ffi = pe.VS_FIXEDFILEINFO[0] # contains a single element self.event['file_info']['fixed'] = { 'flags': [], 'operating_systems': [], 'type': { 'primary': FIXED_FILE_INFO_TYPE.get(vs_ffi.FileType), 'sub': FIXED_FILE_INFO_SUBTYPE.get( (vs_ffi.FileType, vs_ffi.FileSubtype), ''), } } # http://www.jasinskionline.com/windowsapi/ref/v/vs_fixedfileinfo.html ff_flags = vs_ffi.FileFlagsMask & vs_ffi.FileFlags for f in FIXED_FILE_INFO_FLAGS: if ff_flags & f: self.event['file_info']['fixed']['flags'].append( FIXED_FILE_INFO_FLAGS[f]) for o in FIXED_FILE_INFO_OS: if vs_ffi.FileOS & o: self.event['file_info']['fixed'][ 'operating_systems'].append(FIXED_FILE_INFO_OS[o]) self.event['header'] = { 'machine': { 'id': pe.FILE_HEADER.Machine, 'type': pefile.MACHINE_TYPE.get(pe.FILE_HEADER.Machine).replace( 'IMAGE_FILE_MACHINE_', ''), }, 'magic': { 'dos': MAGIC_DOS.get(pe.DOS_HEADER.e_magic, ''), 'image': MAGIC_IMAGE.get(pe.OPTIONAL_HEADER.Magic, ''), }, 'subsystem': pefile.SUBSYSTEM_TYPE.get(pe.OPTIONAL_HEADER.Subsystem).replace( 'IMAGE_SUBSYSTEM_', ''), } self.event['base_of_code'] = pe.OPTIONAL_HEADER.BaseOfCode self.event[ 'address_of_entry_point'] = pe.OPTIONAL_HEADER.AddressOfEntryPoint self.event['image_base'] = pe.OPTIONAL_HEADER.ImageBase self.event['size_of_code'] = pe.OPTIONAL_HEADER.SizeOfCode self.event[ 'size_of_initialized_data'] = pe.OPTIONAL_HEADER.SizeOfInitializedData self.event['size_of_headers'] = pe.OPTIONAL_HEADER.SizeOfHeaders self.event[ 'size_of_heap_reserve'] = pe.OPTIONAL_HEADER.SizeOfHeapReserve self.event['size_of_image'] = pe.OPTIONAL_HEADER.SizeOfImage self.event[ 'size_of_stack_commit'] = pe.OPTIONAL_HEADER.SizeOfStackCommit self.event[ 'size_of_stack_reserve'] = pe.OPTIONAL_HEADER.SizeOfStackReserve self.event['size_of_heap_commit'] = pe.OPTIONAL_HEADER.SizeOfHeapCommit self.event[ 'size_of_uninitalized_data'] = pe.OPTIONAL_HEADER.SizeOfUninitializedData self.event['file_alignment'] = pe.OPTIONAL_HEADER.FileAlignment self.event['section_alignment'] = pe.OPTIONAL_HEADER.SectionAlignment self.event['checksum'] = pe.OPTIONAL_HEADER.CheckSum self.event[ 'major_image_version'] = pe.OPTIONAL_HEADER.MajorImageVersion self.event[ 'minor_image_version'] = pe.OPTIONAL_HEADER.MinorImageVersion self.event[ 'major_linker_version'] = pe.OPTIONAL_HEADER.MajorLinkerVersion self.event[ 'minor_linker_version'] = pe.OPTIONAL_HEADER.MinorLinkerVersion self.event[ 'major_operating_system_version'] = pe.OPTIONAL_HEADER.MajorOperatingSystemVersion self.event[ 'minor_operating_system_version'] = pe.OPTIONAL_HEADER.MinorOperatingSystemVersion self.event[ 'major_subsystem_version'] = pe.OPTIONAL_HEADER.MajorSubsystemVersion self.event[ 'minor_subsystem_version'] = pe.OPTIONAL_HEADER.MinorSubsystemVersion self.event['image_version'] = float( f'{pe.OPTIONAL_HEADER.MajorImageVersion}.{pe.OPTIONAL_HEADER.MinorImageVersion}' ) self.event['linker_version'] = float( f'{pe.OPTIONAL_HEADER.MajorLinkerVersion}.{pe.OPTIONAL_HEADER.MinorLinkerVersion}' ) self.event['operating_system_version'] = float( f'{pe.OPTIONAL_HEADER.MajorOperatingSystemVersion}.{pe.OPTIONAL_HEADER.MinorOperatingSystemVersion}' ) self.event['subsystem_version'] = float( f'{pe.OPTIONAL_HEADER.MajorSubsystemVersion}.{pe.OPTIONAL_HEADER.MinorSubsystemVersion}' ) try: self.event['compile_time'] = datetime.datetime.utcfromtimestamp( pe.FILE_HEADER.TimeDateStamp).isoformat() except OverflowError: logging.info("invalid compile time caused an overflow error") if hasattr(pe.OPTIONAL_HEADER, 'BaseOfData'): self.event['base_of_data'] = pe.OPTIONAL_HEADER.BaseOfData dll_characteristics = [] for o in CHARACTERISTICS_DLL: if pe.OPTIONAL_HEADER.DllCharacteristics & o: dll_characteristics.append(CHARACTERISTICS_DLL[o]) if dll_characteristics: self.event['dll_characteristics'] = dll_characteristics image_characteristics = [] for o in CHARACTERISTICS_IMAGE: if pe.FILE_HEADER.Characteristics & o: image_characteristics.append(CHARACTERISTICS_IMAGE[o]) if image_characteristics: self.event['image_characteristics'] = image_characteristics self.event['resources'] = [] if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'): resource_md5_set = set() resource_sha1_set = set() resource_sha256_set = set() for res0 in pe.DIRECTORY_ENTRY_RESOURCE.entries: for res1 in res0.directory.entries: for res2 in res1.directory.entries: lang = res2.data.lang sub = res2.data.sublang sub = pefile.get_sublang_name_for_lang(lang, sub) data = pe.get_data(res2.data.struct.OffsetToData, res2.data.struct.Size) resource_md5 = hashlib.md5(data).hexdigest() resource_sha1 = hashlib.sha1(data).hexdigest() resource_sha256 = hashlib.sha256(data).hexdigest() resource_md5_set.add(resource_md5) resource_sha1_set.add(resource_sha1) resource_sha256_set.add(resource_sha256) resource_dict = { 'id': res1.id, 'language': { 'sub': sub.replace('SUBLANG_', '') }, 'type': pefile.RESOURCE_TYPE.get(res0.id, '').replace('RT_', ''), 'md5': resource_md5, 'sha1': resource_sha1, 'sha256': resource_sha256, } if lang in pefile.LANG: resource_dict['language']['primary'] = pefile.LANG[ lang].replace('LANG_', '') if res1.name: resource_dict['name'] = str(res1.name) self.event['resources'].append(resource_dict) self.event['summary']['resource_md5'] = list(resource_md5_set) self.event['summary']['resource_sha1'] = list(resource_sha1_set) self.event['summary']['resource_sha256'] = list( resource_sha256_set) self.event['total']['resources'] = len(self.event['resources']) self.event['sections'] = [] section_md5_set = set() section_sha1_set = set() section_sha256_set = set() for sec in pe.sections: try: name = sec.Name.rstrip(b'\x00').decode() section_md5 = sec.get_hash_md5() section_sha1 = sec.get_hash_sha1() section_sha256 = sec.get_hash_sha256() section_md5_set.add(section_md5) section_sha1_set.add(section_sha1) section_sha256_set.add(section_sha256) row = { 'address': { 'physical': sec.Misc_PhysicalAddress, 'virtual': sec.VirtualAddress, }, 'characteristics': [], 'entropy': sec.get_entropy(), 'name': name, 'size': sec.SizeOfRawData, 'md5': section_md5, 'sha1': section_sha1, 'sha256': section_sha256, } for o in CHARACTERISTICS_SECTION: if sec.Characteristics & o: row['characteristics'].append( CHARACTERISTICS_SECTION[o]) self.event['sections'].append(row) self.event['summary']['section_md5'] = list(section_md5_set) self.event['summary']['section_sha1'] = list(section_sha1_set) self.event['summary']['section_sha256'] = list( section_sha256_set) except Exception as e: logging.warning(f"exception thrown when parsing section's {e}") self.event['symbols'] = { 'exported': [], 'imported': [], 'libraries': [], 'table': [], } if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'): self.event['imphash'] = pe.get_imphash() for imp in pe.DIRECTORY_ENTRY_IMPORT: lib = imp.dll.decode() if lib not in self.event['symbols']['libraries']: self.event['symbols']['libraries'].append(lib) row = { 'library': lib, 'symbols': [], 'type': 'import', } for e in imp.imports: if not e.name: name = f'ord{e.ordinal}' else: name = e.name.decode() self.event['symbols']['imported'].append(name) row['symbols'].append(name) self.event['symbols']['table'].append(row) if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'): for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols: if not exp.name: name = f'ord{exp.ordinal}' else: name = exp.name self.event['symbols']['exported'].append(name) self.event['symbols']['table'].append({ 'address': exp.address, 'symbol': name, 'type': 'export', }) self.event['total']['libraries'] = len( self.event['symbols']['libraries']) self.event['total']['symbols'] = len(self.event['symbols']['table'])
def _run(self, scanObject, result, depth, args): moduleResult = [] imports = {} sections = {} exports = [] try: pe = pefile.PE(data=scanObject.buffer) dump_dict = pe.dump_dict() # Parse sections for section in dump_dict.get('PE Sections', []): secName = section.get('Name', {}).get('Value', '').strip('\0') ptr = section.get('PointerToRawData', {}).get('Value') virtAddress = section.get('VirtualAddress', {}).get('Value') virtSize = section.get('Misc_VirtualSize', {}).get('Value') size = section.get('SizeOfRawData', {}).get('Value') secData = pe.get_data(ptr, size) secInfo = { 'Virtual Address': '0x%08X' % virtAddress, 'Virtual Size': virtSize, 'Raw Size': size, 'MD5': section.get('MD5', ''), 'SHA1': section.get('SHA1', ''), 'SHA256': section.get('SHA256', ''), 'Entropy': section.get('Entropy', ''), 'Section Characteristics': section.get('Flags', []), 'Structure': section.get('Structure', ''), } if secInfo['MD5'] != scanObject.objectHash: moduleResult.append(ModuleObject( buffer=secData, externalVars=ExternalVars(filename=secName))) sections[secName] = secInfo sections['Total'] = pe.FILE_HEADER.NumberOfSections scanObject.addMetadata(self.module_name, 'Sections', sections) # Parse imports and exports try: for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols: exports.append(exp.name) scanObject.addMetadata(self.module_name, 'Exports', exports) except ScanError: raise except: logging.debug('No export entries') for imp_symbol in dump_dict['Imported symbols']: for imp in imp_symbol: if imp.get('DLL'): dll = imp.get('DLL') imports.setdefault(dll, []) # Imports can be identified by ordinal or name if imp.get('Ordinal'): ordinal = imp.get('Ordinal') imports[dll].append(ordinal) if imp.get('Name'): name = imp.get('Name') imports[dll].append(name) scanObject.addMetadata(self.module_name, 'Imports', imports) # Parse resources try: for resource in pe.DIRECTORY_ENTRY_RESOURCE.entries: res_type = pefile.RESOURCE_TYPE.get(resource.id, 'Unknown') for entry in resource.directory.entries: for e_entry in entry.directory.entries: sublang = pefile.get_sublang_name_for_lang( e_entry.data.lang, e_entry.data.sublang, ) offset = e_entry.data.struct.OffsetToData size = e_entry.data.struct.Size r_data = pe.get_data(offset, size) language = pefile.LANG.get( e_entry.data.lang, 'Unknown') data = { 'Type': res_type, 'Id': e_entry.id, 'Name': e_entry.data.struct.name, 'Offset': offset, 'Size': size, 'SHA256': hashlib.sha256(r_data).hexdigest(), 'SHA1': hashlib.sha1(r_data).hexdigest(), 'MD5': hashlib.md5(r_data).hexdigest(), 'Language': language, 'Sub Language': sublang, } scanObject.addMetadata( self.module_name, 'Resources', data) except ScanError: raise except: logging.debug('No resources') # Gather miscellaneous stuff try: scanObject.addMetadata(self.module_name, 'Imphash', pe.get_imphash()) except ScanError: raise except: logging.debug('Unable to identify imphash') imgChars = dump_dict.get('Flags', []) scanObject.addMetadata( self.module_name, 'Image Characteristics', imgChars) # Make a pretty date format date = datetime.fromtimestamp(pe.FILE_HEADER.TimeDateStamp) isoDate = date.isoformat() scanObject.addMetadata(self.module_name, 'Date', isoDate) scanObject.addMetadata( self.module_name, 'Timestamp', pe.FILE_HEADER.TimeDateStamp) machine = pe.FILE_HEADER.Machine machineData = { 'Id': machine, 'Type': pefile.MACHINE_TYPE.get(machine) } scanObject.addMetadata( self.module_name, 'Machine Type', machineData) # Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms680339%28v=vs.85%29.aspx scanObject.addMetadata( self.module_name, 'Image Magic', IMAGE_MAGIC_LOOKUP.get(pe.OPTIONAL_HEADER.Magic, 'Unknown')) dllChars = dump_dict.get('DllCharacteristics', []) scanObject.addMetadata( self.module_name, 'DLL Characteristics', dllChars) subsystem = pe.OPTIONAL_HEADER.Subsystem subName = pefile.SUBSYSTEM_TYPE.get(subsystem) scanObject.addMetadata(self.module_name, 'Subsystem', subName) # Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms648009%28v=vs.85%29.aspx scanObject.addMetadata( self.module_name, 'Stack Reserve Size', pe.OPTIONAL_HEADER.SizeOfStackReserve) scanObject.addMetadata( self.module_name, 'Stack Commit Size', pe.OPTIONAL_HEADER.SizeOfStackCommit) scanObject.addMetadata( self.module_name, 'Heap Reserve Size', pe.OPTIONAL_HEADER.SizeOfHeapReserve) scanObject.addMetadata( self.module_name, 'Heap Commit Size', pe.OPTIONAL_HEADER.SizeOfHeapCommit) scanObject.addMetadata( self.module_name, 'EntryPoint', hex(pe.OPTIONAL_HEADER.AddressOfEntryPoint)) scanObject.addMetadata( self.module_name, 'ImageBase', hex(pe.OPTIONAL_HEADER.ImageBase)) # Parse RSDS & Rich scanObject.addMetadata( self.module_name, 'Rich Header', self.parseRich(pe)) if hasattr(pe, 'DIRECTORY_ENTRY_DEBUG'): debug = dict() for e in pe.DIRECTORY_ENTRY_DEBUG: rawData = pe.get_data(e.struct.AddressOfRawData, e.struct.SizeOfData) if rawData.find('RSDS') != -1 and len(rawData) > 24: pdb = rawData[rawData.find('RSDS'):] debug["guid"] = "%s-%s-%s-%s" % ( binascii.hexlify(pdb[4:8]), binascii.hexlify(pdb[8:10]), binascii.hexlify(pdb[10:12]), binascii.hexlify(pdb[12:20])) debug["age"] = struct.unpack('<L', pdb[20:24])[0] debug["pdb"] = pdb[24:].rstrip('\x00') scanObject.addMetadata(self.module_name, 'RSDS', debug) elif rawData.find('NB10') != -1 and len(rawData) > 16: pdb = rawData[rawData.find('NB10')+8:] debug["created"] = datetime.fromtimestamp(struct.unpack('<L', pdb[0:4])[0]).isoformat() debug["age"] = struct.unpack('<L', pdb[4:8])[0] debug["pdb"] = pdb[8:].rstrip('\x00') scanObject.addMetadata(self.module_name, 'NB10', debug) except pefile.PEFormatError: logging.debug("Invalid PE format") return moduleResult