77This module is intended for general purpose functions that can be used
88thoughout the qiling framework
99"""
10- import importlib , os , copy , re , pefile , configparser , logging , sys
10+ import importlib , os , copy , re , pefile , logging , sys
11+ from configparser import ConfigParser
1112from logging import LogRecord
12- from typing import Any , Container , Optional , Mapping , Sequence , Tuple , Type
13+ from typing import Any , Container , Optional , Sequence , Tuple , Type
1314from enum import Enum
1415
1516from unicorn import UC_ERR_READ_UNMAPPED , UC_ERR_FETCH_UNMAPPED
@@ -187,9 +188,7 @@ def ql_is_valid_arch(arch: QL_ARCH) -> bool:
187188 return arch in enum_values (QL_ARCH )
188189
189190def loadertype_convert_str (ostype : QL_OS ) -> Optional [str ]:
190- adapter = {}
191- adapter .update (loader_map )
192- return adapter .get (ostype )
191+ return loader_map .get (ostype )
193192
194193def __value_to_key (e : Type [Enum ], val : Any ) -> Optional [str ]:
195194 key = e ._value2member_map_ [val ]
@@ -210,14 +209,9 @@ def arch_convert_str(arch: QL_ARCH) -> Optional[str]:
210209
211210def arch_convert (arch : str ) -> Optional [QL_ARCH ]:
212211 return arch_map .get (arch )
213-
214- def arch_os_convert (arch ):
215- adapter = {}
216- adapter .update (arch_os_map )
217- if arch in adapter :
218- return adapter [arch ]
219- # invalid
220- return None
212+
213+ def arch_os_convert (arch : QL_ARCH ) -> Optional [QL_OS ]:
214+ return arch_os_map .get (arch )
221215
222216def debugger_convert (debugger : str ) -> Optional [QL_DEBUGGER ]:
223217 return debugger_map .get (debugger )
@@ -244,19 +238,13 @@ def ql_get_module_function(module_name: str, function_name: str):
244238 return module_function
245239
246240def ql_elf_parse_emu_env (path : str ) -> Tuple [Optional [QL_ARCH ], Optional [QL_OS ], Optional [QL_ENDIAN ]]:
247- def getident ():
248- return elfdata
249-
250241 with open (path , "rb" ) as f :
251242 size = os .fstat (f .fileno ()).st_size
252- if size >= 512 :
253- elfdata = f .read (512 )
254- else :
255- elfdata = f .read (20 )
256243
257- ident = getident ( )
258- ostype = None
244+ ident = f . read ( 512 if size >= 512 else 20 )
245+
259246 arch = None
247+ ostype = None
260248 archendian = None
261249
262250 if ident [:4 ] == b'\x7f ELF' :
@@ -276,65 +264,60 @@ def getident():
276264 if e_machine == b"\x03 \x00 " :
277265 archendian = QL_ENDIAN .EL
278266 arch = QL_ARCH .X86
267+
279268 elif e_machine == b"\x08 \x00 " and endian == 1 and elfbit == 1 :
280269 archendian = QL_ENDIAN .EL
281270 arch = QL_ARCH .MIPS
271+
282272 elif e_machine == b"\x00 \x08 " and endian == 2 and elfbit == 1 :
283273 archendian = QL_ENDIAN .EB
284274 arch = QL_ARCH .MIPS
275+
285276 elif e_machine == b"\x28 \x00 " and endian == 1 and elfbit == 1 :
286277 archendian = QL_ENDIAN .EL
287278 arch = QL_ARCH .ARM
279+
288280 elif e_machine == b"\x00 \x28 " and endian == 2 and elfbit == 1 :
289281 archendian = QL_ENDIAN .EB
290282 arch = QL_ARCH .ARM
283+
291284 elif e_machine == b"\xB7 \x00 " :
292285 archendian = QL_ENDIAN .EL
293286 arch = QL_ARCH .ARM64
287+
294288 elif e_machine == b"\x3E \x00 " :
295289 archendian = QL_ENDIAN .EL
296290 arch = QL_ARCH .X8664
297- else :
298- arch = None
299291
300292 return arch , ostype , archendian
301293
302294def ql_macho_parse_emu_env (path : str ) -> Tuple [Optional [QL_ARCH ], Optional [QL_OS ], Optional [QL_ENDIAN ]]:
303-
304- def getident ():
305- return machodata
306-
307- with open (path , "rb" ) as f :
308- machodata = f .read (32 )
309-
310- ident = getident ()
311-
312295 macho_macos_sig64 = b'\xcf \xfa \xed \xfe '
313296 macho_macos_sig32 = b'\xce \xfa \xed \xfe '
314297 macho_macos_fat = b'\xca \xfe \xba \xbe ' # should be header for FAT
315298
316- ostype = None
317299 arch = None
318- archendian = None
300+ ostype = None
301+ endian = None
319302
320- if ident [: 4 ] in (macho_macos_sig32 , macho_macos_sig64 , macho_macos_fat ):
303+ with open (path , 'rb' ) as f :
304+ ident = f .read (32 )
305+
306+ if ident [:4 ] in (macho_macos_sig32 , macho_macos_sig64 , macho_macos_fat ):
321307 ostype = QL_OS .MACOS
322- else :
323- ostype = None
324308
325- if ostype :
326- # if ident[0x7] == 0: # 32 bit
309+ # if ident[7] == 0: # 32 bit
327310 # arch = QL_ARCH.X86
328- if ident [0x4 ] == 7 and ident [0x7 ] == 1 : # X86 64 bit
329- archendian = QL_ENDIAN .EL
311+
312+ if ident [4 ] == 0x07 and ident [7 ] == 0x01 : # X86 64 bit
313+ endian = QL_ENDIAN .EL
330314 arch = QL_ARCH .X8664
331- elif ident [0x4 ] == 12 and ident [0x7 ] == 1 : # ARM64 ident[0x4] = 0x0C
332- archendian = QL_ENDIAN .EL
315+
316+ elif ident [4 ] == 0x0c and ident [7 ] == 0x01 : # ARM64
317+ endian = QL_ENDIAN .EL
333318 arch = QL_ARCH .ARM64
334- else :
335- arch = None
336319
337- return arch , ostype , archendian
320+ return arch , ostype , endian
338321
339322
340323def ql_pe_parse_emu_env (path : str ) -> Tuple [Optional [QL_ARCH ], Optional [QL_OS ], Optional [QL_ENDIAN ]]:
@@ -343,64 +326,67 @@ def ql_pe_parse_emu_env(path: str) -> Tuple[Optional[QL_ARCH], Optional[QL_OS],
343326 except :
344327 return None , None , None
345328
346- ostype = None
347329 arch = None
330+ ostype = None
348331 archendian = None
349332
350333 machine_map = {
351- pefile .MACHINE_TYPE ['IMAGE_FILE_MACHINE_I386' ]: QL_ARCH .X86 ,
352- pefile .MACHINE_TYPE ['IMAGE_FILE_MACHINE_AMD64' ]: QL_ARCH .X8664 ,
353- pefile .MACHINE_TYPE ['IMAGE_FILE_MACHINE_ARM' ]: QL_ARCH .ARM ,
354- pefile .MACHINE_TYPE ['IMAGE_FILE_MACHINE_THUMB' ]: QL_ARCH .ARM ,
355- # pefile.MACHINE_TYPE['IMAGE_FILE_MACHINE_ARM64'] : QL_ARCH.ARM64 #pefile does not have the definition
334+ pefile .MACHINE_TYPE ['IMAGE_FILE_MACHINE_I386' ] : QL_ARCH .X86 ,
335+ pefile .MACHINE_TYPE ['IMAGE_FILE_MACHINE_AMD64' ] : QL_ARCH .X8664 ,
336+ pefile .MACHINE_TYPE ['IMAGE_FILE_MACHINE_ARM' ] : QL_ARCH .ARM ,
337+ pefile .MACHINE_TYPE ['IMAGE_FILE_MACHINE_THUMB' ] : QL_ARCH .ARM ,
338+ # pefile.MACHINE_TYPE['IMAGE_FILE_MACHINE_ARM64'] : QL_ARCH.ARM64 #pefile does not have the definition
356339 # for IMAGE_FILE_MACHINE_ARM64
357340 0xAA64 : QL_ARCH .ARM64 # Temporary workaround for Issues #21 till pefile gets updated
358341 }
342+
359343 # get arch
360- archendian = QL_ENDIAN .EL
361344 arch = machine_map .get (pe .FILE_HEADER .Machine )
362345
363346 if arch :
364- if pe .OPTIONAL_HEADER .Subsystem >= pefile .SUBSYSTEM_TYPE ['IMAGE_SUBSYSTEM_EFI_APPLICATION' ] and \
365- pe .OPTIONAL_HEADER .Subsystem <= pefile .SUBSYSTEM_TYPE ['IMAGE_SUBSYSTEM_EFI_ROM' ] :
347+ subsystem_uefi = (
348+ pefile .SUBSYSTEM_TYPE ['IMAGE_SUBSYSTEM_EFI_APPLICATION' ],
349+ pefile .SUBSYSTEM_TYPE ['IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER' ],
350+ pefile .SUBSYSTEM_TYPE ['IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER' ],
351+ pefile .SUBSYSTEM_TYPE ['IMAGE_SUBSYSTEM_EFI_ROM' ]
352+ )
353+
354+ if pe .OPTIONAL_HEADER .Subsystem in subsystem_uefi :
366355 ostype = QL_OS .UEFI
367356 else :
368357 ostype = QL_OS .WINDOWS
369- else :
370- ostype = None
358+
359+ archendian = QL_ENDIAN . EL
371360
372361 return arch , ostype , archendian
373362
374363
375364def ql_guess_emu_env (path : str ) -> Tuple [Optional [QL_ARCH ], Optional [QL_OS ], Optional [QL_ENDIAN ]]:
376365 arch = None
377366 ostype = None
378- archendian = None
367+ endian = None
379368
380- if os .path .isdir (path ) and ( str ( path )) .endswith (" .kext" ):
369+ if os .path .isdir (path ) and path .endswith (' .kext' ):
381370 return QL_ARCH .X8664 , QL_OS .MACOS , QL_ENDIAN .EL
382371
383- if os .path .isfile (path ) and ( str ( path )) .endswith (" .DOS_COM" ):
372+ if os .path .isfile (path ) and path .endswith (' .DOS_COM' ):
384373 return QL_ARCH .A8086 , QL_OS .DOS , QL_ENDIAN .EL
385374
386- if os .path .isfile (path ) and ( str ( path )) .endswith (" .DOS_MBR" ):
375+ if os .path .isfile (path ) and path .endswith (' .DOS_MBR' ):
387376 return QL_ARCH .A8086 , QL_OS .DOS , QL_ENDIAN .EL
388377
389- if os .path .isfile (path ) and ( str ( path )) .endswith (" .DOS_EXE" ):
378+ if os .path .isfile (path ) and path .endswith (' .DOS_EXE' ):
390379 return QL_ARCH .A8086 , QL_OS .DOS , QL_ENDIAN .EL
391380
392- arch , ostype , archendian = ql_elf_parse_emu_env (path )
381+ arch , ostype , endian = ql_elf_parse_emu_env (path )
393382
394- if arch == None or ostype == None or archendian == None :
395- arch , ostype , archendian = ql_macho_parse_emu_env (path )
383+ if arch is None or ostype is None or endian is None :
384+ arch , ostype , endian = ql_macho_parse_emu_env (path )
396385
397- if arch == None or ostype == None or archendian == None :
398- arch , ostype , archendian = ql_pe_parse_emu_env (path )
399-
400- if ostype not in (QL_OS ):
401- raise QlErrorOsType ("File does not belong to either 'linux', 'windows', 'freebsd', 'macos', 'ios', 'dos', 'qnx'" )
386+ if arch is None or ostype is None or endian is None :
387+ arch , ostype , endian = ql_pe_parse_emu_env (path )
402388
403- return arch , ostype , archendian
389+ return arch , ostype , endian
404390
405391
406392def loader_setup (ostype : QL_OS , ql ):
@@ -475,7 +461,7 @@ def profile_setup(ql):
475461 return ql_hw_profile_setup (ql )
476462
477463 _profile = "Default"
478-
464+
479465 if ql .profile != None :
480466 _profile = ql .profile
481467 debugmsg = "Profile: %s" % _profile
@@ -487,24 +473,23 @@ def profile_setup(ql):
487473 else :
488474 profiles = [os_profile ]
489475
490- config = configparser . ConfigParser ()
476+ config = ConfigParser ()
491477 config .read (profiles )
492-
478+
493479 return config , debugmsg
494480
495481def ql_hw_profile_setup (ql ):
496- config = configparser .ConfigParser ()
497- debugmsg = "Profile: %s" % ql .profile
482+ config = ConfigParser ()
498483
499- profile_name = '%s.ql' % ql .profile
484+ profile_name = f' { ql .profile } .ql'
500485 profile_dir = os .path .join (os .path .dirname (os .path .abspath (__file__ )), "profiles" )
501486
502487 for path , _ , files in os .walk (profile_dir ):
503- if profile_name in files :
488+ if profile_name in files :
504489 config .read (os .path .join (profile_dir , path , profile_name ))
505490 break
506491
507- return config , debugmsg
492+ return config , f'Profile: { ql . profile } '
508493
509494def ql_resolve_logger_level (verbose : QL_VERBOSE ) -> int :
510495 return {
@@ -585,7 +570,7 @@ def verify_ret(ql, err):
585570 pass
586571 else :
587572 raise
588-
573+
589574 if ql .archtype == QL_ARCH .X8664 : # Win64
590575 if ql .os .init_sp == ql .reg .arch_sp or ql .os .init_sp + 8 == ql .reg .arch_sp or ql .os .init_sp + 0x10 == ql .reg .arch_sp : # FIXME
591576 # 0x11626 c3 ret
@@ -600,4 +585,4 @@ def verify_ret(ql, err):
600585 else :
601586 raise
602587 else :
603- raise
588+ raise
0 commit comments