Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 6 additions & 12 deletions qiling/arch/arm.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ def uc(self) -> Uc:

@cached_property
def regs(self) -> QlRegisterManager:
regs_map = arm_const.reg_map
regs_map = dict(
**arm_const.reg_map,
**arm_const.reg_vfp
)

pc_reg = 'pc'
sp_reg = 'sp'

Expand All @@ -53,17 +57,7 @@ def is_thumb(self) -> bool:

@property
def endian(self) -> QL_ENDIAN:
# FIXME: ARM is a bi-endian architecture which allows flipping core endianess
# while running. endianess is tested in runtime through CPSR[9], however unicorn
# doesn't reflect the endianess correctly through that bit.
# @see: https://github.com/unicorn-engine/unicorn/issues/1542
#
# we work around this by using the initial endianess configuration, even though
# it might have been changed since.
#
# return QL_ENDIAN.EB if self.regs.cpsr & (1 << 9) else QL_ENDIAN.EL

return self._init_endian
return QL_ENDIAN.EB if self.regs.cpsr & (1 << 9) else QL_ENDIAN.EL

@property
def effective_pc(self) -> int:
Expand Down
22 changes: 18 additions & 4 deletions qiling/arch/evm/evm.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework


import types

from qiling.arch.arch import QlArch
from qiling.arch.evm.hooks import monkeypatch_core_hooks
from qiling.arch.evm.vm.evm import QlArchEVMEmulator
from qiling.arch.evm.vm.message import Message
from qiling.const import *
from ..arch import QlArch
from .vm.evm import QlArchEVMEmulator
from .hooks import monkeypath_core_hooks

class QlArchEVM(QlArch):
type = QL_ARCH.EVM
Expand All @@ -16,7 +19,8 @@ def __init__(self, ql) -> None:
super(QlArchEVM, self).__init__(ql)
self.evm = QlArchEVMEmulator(self.ql)

monkeypath_core_hooks(self.ql)
monkeypatch_core_hooks(self.ql)
monkeypatch_core_methods(self.ql)

def run(self, msg):
return self.evm.vm.execute_message(msg)
Expand All @@ -40,3 +44,13 @@ def uc(self):
@property
def endian(self) -> QL_ENDIAN:
return QL_ENDIAN.EL


def __evm_run(self, code: Message):
return self.arch.run(code)

def monkeypatch_core_methods(ql):
"""Monkeypatch core methods for evm
"""

ql.run = types.MethodType(__evm_run, ql)
4 changes: 2 additions & 2 deletions qiling/arch/evm/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ def __evm_hook_del(ql, hret):
if not hooks_list:
del evm_hooks_info.hook_addr_dict[h.addr]

def monkeypath_core_hooks(ql):
"""Monkeypath core hooks for evm
def monkeypatch_core_hooks(ql):
"""Monkeypatch core hooks for evm
"""

ql.hook_code = types.MethodType(__evm_hook_code, ql)
Expand Down
5 changes: 4 additions & 1 deletion qiling/arch/x86.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ def regs(self) -> QlRegisterManager:
**x86_const.reg_map_64_b,
**x86_const.reg_map_64_w,
**x86_const.reg_map_64_d,
**x86_const.reg_map_seg_base
**x86_const.reg_map_seg_base,
**x86_const.reg_map_xmm,
**x86_const.reg_map_ymm,
**x86_const.reg_map_zmm
)

pc_reg = 'rip'
Expand Down
33 changes: 17 additions & 16 deletions qiling/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,18 @@ class Qiling(QlCoreHooks, QlCoreStructs):
def __init__(
self,
argv: Sequence[str] = None,
rootfs: str = None,
rootfs: str = r'.',
env: MutableMapping[AnyStr, AnyStr] = {},
code: bytes = None,
ostype: Union[str, QL_OS] = None,
archtype: Union[str, QL_ARCH] = None,
verbose: QL_VERBOSE = QL_VERBOSE.DEFAULT,
profile: str = None,
console=True,
console: bool = True,
log_file=None,
log_override=None,
log_plain=False,
multithread = False,
log_plain: bool = False,
multithread: bool = False,
filter = None,
stop: QL_STOP = QL_STOP.NONE,
*,
Expand Down Expand Up @@ -100,10 +100,7 @@ def __init__(
################
# rootfs setup #
################
if rootfs is None:
rootfs = '.'

elif not os.path.exists(rootfs):
if not os.path.exists(rootfs):
raise QlErrorFileNotFound(f'Target rootfs not found: "{rootfs}"')

self._rootfs = rootfs
Expand Down Expand Up @@ -540,17 +537,21 @@ def write_exit_trap(self):
# Qiling APIS #
###############

# Emulate the binary from begin until @end, with timeout in @timeout and
# number of emulated instructions in @count
def run(self, begin=None, end=None, timeout=0, count=0, code=None):
def run(self, begin: Optional[int] = None, end: Optional[int] = None, timeout: int = 0, count: int = 0):
"""Start binary emulation.

Args:
begin : emulation starting address
end : emulation ending address
timeout : limit emulation to a specific amount of time (microseconds); unlimited by default
count : limit emulation to a specific amount of instructions; unlimited by default
"""

# replace the original entry point, exit point, timeout and count
self.entry_point = begin
self.exit_point = end
self.timeout = timeout
self.count = count

if self.interpreter:
return self.arch.run(code)
self.count = count

# init debugger (if set)
debugger = select_debugger(self._debugger)
Expand All @@ -565,7 +566,7 @@ def run(self, begin=None, end=None, timeout=0, count=0, code=None):
if self.count <= 0:
self.count = -1

self.arch.run(count=self.count, end=self.exit_point)
self.arch.run(count=self.count, end=self.exit_point)
else:
self.write_exit_trap()
# emulate the binary
Expand Down
2 changes: 1 addition & 1 deletion qiling/os/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def __init__(self, ql: Qiling):
}

if ql.arch.bits not in bit_stuff:
raise QlErrorStructConversion("Unsupported Qiling archtecture for memory manager")
raise QlErrorStructConversion("Unsupported Qiling architecture for memory manager")

max_addr = bit_stuff[ql.arch.bits]

Expand Down
2 changes: 1 addition & 1 deletion qiling/os/posix/posix.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def __init__(self):
def __len__(self):
return len(self.__fds)

def __getitem__(self, idx: int):
def __getitem__(self, idx: Union[slice, int]):
return self.__fds[idx]

def __setitem__(self, idx: int, val: Optional[IO]):
Expand Down
10 changes: 6 additions & 4 deletions qiling/os/posix/syscall/fcntl.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ def ql_syscall_fcntl(ql: Qiling, fd: int, cmd: int, arg: int):
if arg not in range(NR_OPEN):
regreturn = -EINVAL

for idx, val in enumerate(ql.os.fd, arg):
if val is None:
for idx in range(arg, len(ql.os.fd)):
if ql.os.fd[idx] is None:
ql.os.fd[idx] = f.dup()
regreturn = idx
break
Expand Down Expand Up @@ -173,11 +173,13 @@ def ql_syscall_fcntl64(ql: Qiling, fd: int, cmd: int, arg: int):
if arg not in range(NR_OPEN):
regreturn = -1

for idx, val in enumerate(ql.os.fd, arg):
if val is None:
for idx in range(arg, len(ql.os.fd)):
if ql.os.fd[idx] is None:
ql.os.fd[idx] = f.dup()
regreturn = idx
break
else:
regreturn = -1

elif cmd == F_GETFL:
regreturn = 2
Expand Down
11 changes: 6 additions & 5 deletions qiling/os/posix/syscall/unistd.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,14 @@ def ql_syscall_brk(ql: Qiling, inp: int):
# otherwise, just return current brk_address

if inp:
new_brk_addr = ((inp + 0xfff) // 0x1000) * 0x1000
cur_brk_addr = ql.loader.brk_address
new_brk_addr = ql.mem.align_up(inp)

if inp > ql.loader.brk_address: # increase current brk_address if inp is greater
ql.mem.map(ql.loader.brk_address, new_brk_addr - ql.loader.brk_address, info="[brk]")
if inp > cur_brk_addr: # increase current brk_address if inp is greater
ql.mem.map(cur_brk_addr, new_brk_addr - cur_brk_addr, info="[brk]")

elif inp < ql.loader.brk_address: # shrink current bkr_address to inp if its smaller
ql.mem.unmap(new_brk_addr, ql.loader.brk_address - new_brk_addr)
elif inp < cur_brk_addr: # shrink current bkr_address to inp if its smaller
ql.mem.unmap(new_brk_addr, cur_brk_addr - new_brk_addr)

ql.loader.brk_address = new_brk_addr

Expand Down
6 changes: 3 additions & 3 deletions qiling/os/windows/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
#

import ntpath
from typing import Callable, TextIO
from typing import Callable, TextIO, Type

from unicorn import UcError

from qiling import Qiling
from qiling.arch.x86_const import GS_SEGMENT_ADDR, GS_SEGMENT_SIZE, FS_SEGMENT_ADDR, FS_SEGMENT_SIZE
from qiling.arch.x86_utils import GDTManager, SegmentManager86, SegmentManager64
from qiling.arch.x86_utils import GDTManager, SegmentManager, SegmentManager86, SegmentManager64
from qiling.cc import intel
from qiling.const import QL_ARCH, QL_OS, QL_INTERCEPT
from qiling.exception import QlErrorSyscallError, QlErrorSyscallNotFound, QlMemoryMappedError
Expand Down Expand Up @@ -137,7 +137,7 @@ def load(self):
def setupGDT(self):
gdtm = GDTManager(self.ql)

segm_class = {
segm_class: Type[SegmentManager] = {
32 : SegmentManager86,
64 : SegmentManager64
}[self.ql.arch.bits]
Expand Down
4 changes: 2 additions & 2 deletions qltool
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ if __name__ == '__main__':
code_parser.add_argument('--thumb', action='store_true', 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('--os', required=True, choices=os_map)
code_parser.add_argument('--rootfs', help='emulated root filesystem, that is where all libraries reside')
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')

# set "examples" subcommand
Expand Down Expand Up @@ -223,7 +223,7 @@ if __name__ == '__main__':
handle_examples(parser)

# ql file setup
if options.subcommand == 'run':
elif options.subcommand == 'run':
ql = handle_run(options)

# ql code setup
Expand Down