mirror of
https://github.com/qilingframework/qiling.git
synced 2026-10-12 02:21:40 +00:00
Correctly handle subcommands args
This commit is contained in:
+2
-1
@@ -91,10 +91,11 @@ def __casefold_enum(e: Type[T]) -> Mapping[str, T]:
|
||||
return dict((k.casefold(), v) for k, v in e.__members__.items())
|
||||
|
||||
|
||||
debugger_map = __casefold_enum(QL_DEBUGGER)
|
||||
endian_map = __casefold_enum(QL_ENDIAN)
|
||||
arch_map = __casefold_enum(QL_ARCH)
|
||||
os_map = __casefold_enum(QL_OS)
|
||||
verbose_map = __casefold_enum(QL_VERBOSE)
|
||||
debugger_map = __casefold_enum(QL_DEBUGGER)
|
||||
|
||||
arch_os_map = {
|
||||
QL_ARCH.EVM : QL_OS.EVM,
|
||||
|
||||
@@ -10,7 +10,7 @@ import ast
|
||||
import pickle
|
||||
|
||||
from pprint import pprint
|
||||
from typing import TYPE_CHECKING, Mapping, Type
|
||||
from typing import TYPE_CHECKING, Any, AnyStr, Dict, Literal, Mapping, Type, overload
|
||||
|
||||
from unicorn import __version__ as uc_ver
|
||||
from qiling import __version__ as ql_ver
|
||||
@@ -18,7 +18,7 @@ from qiling import __version__ as ql_ver
|
||||
from qiling import Qiling
|
||||
from qiling.arch import utils as arch_utils
|
||||
from qiling.debugger.qdb import QlQdb
|
||||
from qiling.const import QL_VERBOSE, QL_ENDIAN, os_map, arch_map, verbose_map
|
||||
from qiling.const import QL_ENDIAN, QL_VERBOSE, endian_map, os_map, arch_map, verbose_map
|
||||
from qiling.extensions.coverage import utils as cov_utils
|
||||
from qiling.extensions import report
|
||||
|
||||
@@ -27,9 +27,19 @@ if TYPE_CHECKING:
|
||||
from enum import Enum
|
||||
|
||||
|
||||
# read code from file
|
||||
def read_file(fname: str):
|
||||
with open(fname, "rb") as f:
|
||||
@overload
|
||||
def read_file(fname: AnyStr) -> str: ...
|
||||
|
||||
|
||||
@overload
|
||||
def read_file(fname: AnyStr, mode: Literal['b']) -> bytes: ...
|
||||
|
||||
|
||||
def read_file(fname: AnyStr, mode: Literal['b', ''] = ''):
|
||||
"""Read file contents.
|
||||
"""
|
||||
|
||||
with open(fname, f'r{mode}') as f:
|
||||
content = f.read()
|
||||
|
||||
return content
|
||||
@@ -59,66 +69,64 @@ def __make_enum_arg(enum_rmap: Mapping[str, 'Enum'], aliases: Mapping[str, str]
|
||||
return __enum_arg
|
||||
|
||||
|
||||
__arg_endian = __make_enum_arg(endian_map)
|
||||
__arg_archtype = __make_enum_arg(arch_map, {'x86_64': 'x8664', 'riscv32': 'riscv'})
|
||||
__arg_ostype = __make_enum_arg(os_map, {'darwin': 'macos'})
|
||||
__arg_verbose = __make_enum_arg(verbose_map)
|
||||
|
||||
|
||||
def handle_code(options: argparse.Namespace):
|
||||
archendian = {
|
||||
'little': QL_ENDIAN.EL,
|
||||
'big' : QL_ENDIAN.EB
|
||||
}[options.endian]
|
||||
|
||||
def handle_code(options: argparse.Namespace) -> Dict[str, Any]:
|
||||
if options.format == 'hex':
|
||||
if options.input is not None:
|
||||
print("Load HEX from ARGV")
|
||||
code = str(options.input).strip("\\\\x").split("x")
|
||||
code = "".join(code).strip()
|
||||
code = bytes.fromhex(code)
|
||||
print("Loading HEX from ARGV")
|
||||
payload = str(options.input)
|
||||
|
||||
elif options.filename is not None:
|
||||
print("Load HEX from FILE")
|
||||
code = str(read_file(options.filename)).strip('b\'').strip('\\n')
|
||||
code = code.strip('x').split("\\\\x")
|
||||
code = "".join(code).strip()
|
||||
code = bytes.fromhex(code)
|
||||
print("Loading HEX from FILE")
|
||||
payload = read_file(options.filename)
|
||||
|
||||
else:
|
||||
print("ERROR: File not found")
|
||||
print("Error: please specify an input source for hex")
|
||||
exit(1)
|
||||
|
||||
elif options.format == 'asm':
|
||||
print("Load ASM from FILE")
|
||||
assembly = read_file(options.filename)
|
||||
code = bytes.fromhex(payload.replace(r'\x', ''))
|
||||
|
||||
assembler = arch_utils.assembler(options.arch, archendian, options.thumb)
|
||||
code, _ = assembler.asm(assembly)
|
||||
elif options.format == 'asm':
|
||||
print("Loading ASM from FILE")
|
||||
|
||||
if options.filename is None:
|
||||
print("Error: please specify an input source for asm")
|
||||
exit(1)
|
||||
|
||||
payload = read_file(options.filename)
|
||||
|
||||
# assemble the payload and turn it into opcodes bytes
|
||||
assembler = arch_utils.assembler(options.arch, options.endian, options.thumb)
|
||||
code, _ = assembler.asm(payload)
|
||||
code = bytes(code)
|
||||
|
||||
elif options.format == 'bin':
|
||||
print("Load BIN from FILE")
|
||||
if options.filename is not None:
|
||||
code = read_file(options.filename)
|
||||
else:
|
||||
print("ERROR: File not found")
|
||||
print("Loading BIN from FILE")
|
||||
|
||||
if options.filename is None:
|
||||
print("Error: please specify an input source for bin")
|
||||
exit(1)
|
||||
|
||||
ql = Qiling(
|
||||
rootfs=options.rootfs,
|
||||
env=options.env,
|
||||
code=code,
|
||||
ostype=options.os,
|
||||
archtype=options.arch,
|
||||
verbose=options.verbose,
|
||||
profile=options.profile,
|
||||
filter=options.filter,
|
||||
endian=archendian,
|
||||
thumb=options.thumb,
|
||||
)
|
||||
code = read_file(options.filename, 'b')
|
||||
|
||||
return ql
|
||||
ql_args = {
|
||||
'rootfs': options.rootfs,
|
||||
'code': code,
|
||||
'ostype': options.os,
|
||||
'archtype': options.arch,
|
||||
'endian': options.endian,
|
||||
'thumb': options.thumb
|
||||
}
|
||||
|
||||
return ql_args
|
||||
|
||||
|
||||
def handle_run(options: argparse.Namespace):
|
||||
def handle_run(options: argparse.Namespace) -> Dict[str, Any]:
|
||||
effective_argv = []
|
||||
|
||||
# with argv
|
||||
@@ -132,26 +140,12 @@ def handle_run(options: argparse.Namespace):
|
||||
else:
|
||||
print("ERROR: Command error!")
|
||||
|
||||
ql = Qiling(
|
||||
argv=effective_argv,
|
||||
rootfs=options.rootfs,
|
||||
env=options.env,
|
||||
verbose=options.verbose,
|
||||
profile=options.profile,
|
||||
console=options.console,
|
||||
log_file=options.log_file,
|
||||
log_plain=options.log_plain,
|
||||
multithread=options.multithread,
|
||||
filter=options.filter,
|
||||
libcache=options.libcache
|
||||
)
|
||||
ql_args = {
|
||||
'argv': effective_argv,
|
||||
'rootfs': options.rootfs
|
||||
}
|
||||
|
||||
# attach Qdb at entry point
|
||||
if options.qdb is True:
|
||||
QlQdb(ql, rr=options.rr).run()
|
||||
exit()
|
||||
|
||||
return ql
|
||||
return ql_args
|
||||
|
||||
|
||||
def handle_examples(parser: argparse.ArgumentParser):
|
||||
@@ -211,7 +205,7 @@ if __name__ == '__main__':
|
||||
code_parser.add_argument('-i', '--input', metavar="INPUT", dest="input", help='input hex value')
|
||||
code_parser.add_argument('--arch', required=True, choices=arch_map, action=__arg_archtype)
|
||||
code_parser.add_argument('--thumb', action='store_true', default=False, help='specify thumb mode for ARM')
|
||||
code_parser.add_argument('--endian', choices=('little', 'big'), default='little', help='specify endianess for bi-endian archs')
|
||||
code_parser.add_argument('--endian', choices=endian_map, default=QL_ENDIAN.EL, action=__arg_endian, help='specify endianess for bi-endian archs')
|
||||
code_parser.add_argument('--os', required=True, choices=os_map, action=__arg_ostype)
|
||||
code_parser.add_argument('--rootfs', default='.', help='emulated root filesystem, that is where all libraries reside')
|
||||
code_parser.add_argument('--format', choices=('asm', 'hex', 'bin'), default='bin', help='input file format')
|
||||
@@ -222,7 +216,6 @@ if __name__ == '__main__':
|
||||
# set "qltui" subcommand
|
||||
qltui_parser = commands.add_parser('qltui', help='show qiling Terminal User Interface', add_help=False)
|
||||
|
||||
qltui_enabled = False
|
||||
comm_parser = run_parser
|
||||
|
||||
if len(sys.argv) > 1 and sys.argv[1] == 'code':
|
||||
@@ -249,21 +242,44 @@ if __name__ == '__main__':
|
||||
comm_parser.add_argument('--libcache', action='store_true', help='enable dll caching for windows')
|
||||
options = parser.parse_args()
|
||||
|
||||
if options.subcommand == 'examples':
|
||||
handle_examples(parser)
|
||||
qltui_enabled = False
|
||||
ql_args = {}
|
||||
|
||||
if options.subcommand == 'qltui':
|
||||
import qltui
|
||||
options = qltui.get_data()
|
||||
qltui_enabled = True
|
||||
|
||||
if options.subcommand == 'examples':
|
||||
handle_examples(parser)
|
||||
|
||||
# ql file setup
|
||||
if options.subcommand == 'run':
|
||||
ql = handle_run(options)
|
||||
elif options.subcommand == 'run':
|
||||
ql_args = handle_run(options)
|
||||
|
||||
# ql code setup
|
||||
if options.subcommand == 'code':
|
||||
ql = handle_code(options)
|
||||
elif options.subcommand == 'code':
|
||||
ql_args = handle_code(options)
|
||||
|
||||
ql_args.update({
|
||||
'env': options.env,
|
||||
'verbose': options.verbose,
|
||||
'profile': options.profile,
|
||||
'console': options.console,
|
||||
'filter': options.filter,
|
||||
'log_file': options.log_file,
|
||||
'log_plain': options.log_plain,
|
||||
'multithread': options.multithread,
|
||||
'libcache': options.libcache
|
||||
})
|
||||
|
||||
ql = Qiling(**ql_args)
|
||||
|
||||
# attach Qdb at entry point
|
||||
if options.qdb:
|
||||
QlQdb(ql, rr=bool(options.rr)).run()
|
||||
|
||||
parser.exit(0)
|
||||
|
||||
# ql execute additional options
|
||||
if options.gdb:
|
||||
@@ -281,20 +297,25 @@ if __name__ == '__main__':
|
||||
ql.debug_stop = True
|
||||
|
||||
if options.root:
|
||||
ql.root = True
|
||||
ql.os.root = True
|
||||
|
||||
if qltui_enabled:
|
||||
hook_dictionary = qltui.hook(ql)
|
||||
|
||||
# ql run
|
||||
with cov_utils.collect_coverage(ql, options.coverage_format, options.coverage_file):
|
||||
if qltui_enabled:
|
||||
hook_dictionary = qltui.hook(ql)
|
||||
if options.coverage_file:
|
||||
with cov_utils.collect_coverage(ql, options.coverage_format, options.coverage_file):
|
||||
ql.run(timeout=options.timeout)
|
||||
else:
|
||||
ql.run(timeout=options.timeout)
|
||||
|
||||
if options.json:
|
||||
report = report.generate_report(ql)
|
||||
rep = report.generate_report(ql)
|
||||
|
||||
if qltui_enabled:
|
||||
report["syscalls"] = qltui.transform_syscalls(ql.os.stats.syscalls)
|
||||
qltui.show_report(ql, report, hook_dictionary)
|
||||
rep["syscalls"] = qltui.transform_syscalls(ql.os.stats.syscalls)
|
||||
qltui.show_report(ql, rep, hook_dictionary)
|
||||
else:
|
||||
pprint(report)
|
||||
pprint(rep)
|
||||
|
||||
exit(ql.os.exit_code)
|
||||
|
||||
Reference in New Issue
Block a user