Skip to content

Commit

Permalink
Double linefeed consistance in core
Browse files Browse the repository at this point in the history
  • Loading branch information
klks committed May 29, 2020
1 parent 095cdc8 commit 7b5dc8a
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 6 deletions.
9 changes: 9 additions & 0 deletions qiling/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def __init__(
# Run the loader
self.loader.run()


# 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):
Expand Down Expand Up @@ -208,41 +209,49 @@ def patch(self, addr, code, file_name=b''):
else:
self.patch_lib.append((addr, code, file_name.decode()))


# ql.output var getter
@property
def output(self):
return self._output


# ql.output - output var setter eg. QL_OUTPUT.DEFAULT and etc
@output.setter
def output(self, output):
self._output = output_convert(output)


# ql.platform - platform var = host os getter eg. LINUX and etc
@property
def platform(self):
return self._platform


# ql.platform - platform var = host os setter eg. LINUX and etc
@platform.setter
def platform(self, value):
self._platform = ostype_convert(value.lower())


def __enable_bin_patch(self):
for addr, code in self.patch_bin:
self.mem.write(self.loader.load_address + addr, code)


def enable_lib_patch(self):
for addr, code, filename in self.patch_lib:
try:
self.mem.write(self.mem.get_lib_base(filename) + addr, code)
except:
raise RuntimeError("Fail to patch filename %s at addr 0x%x" % (filename, addr))


# stop emulation
def emu_stop(self):
self.uc.emu_stop()


# start emulation
def emu_start(self, begin, end, timeout=0, count=0):
self.uc.emu_start(begin, end, timeout, count)
45 changes: 43 additions & 2 deletions qiling/core_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,47 +20,56 @@ def __init__(self, callback, user_data=None, begin=1, end=0):
self.user_data = user_data
self.begin = begin
self.end = end



def bound_check(self, pc):
if self.end < self.begin or (self.begin <= pc and self.end >= pc):
return True
return False


def check(self, *args):
return True


def call(self, ql, *args):
if self.user_data == None:
return self.callback(ql, *args)
return self.callback(ql, *args, self.user_data)


class HookAddr(Hook):
def __init__(self, callback, address, user_data=None):
super(HookAddr, self).__init__(callback, user_data, address, address)
self.addr = address


def call(self, ql, *args):
if self.user_data == None:
return self.callback(ql)
return self.callback(ql, self.user_data)


class HookIntr(Hook):
def __init__(self, callback, intno, user_data=None):
super(HookIntr, self).__init__(callback, user_data, 0, -1)
self.intno = intno


def check(self, ql, intno):
ql.dprint(D_CTNT, "[+] Received Interupt: %i Hooked Interupt: %i" % (intno, self.intno))
if intno < 0 or self.intno == intno:
return True
return False


class HookRet:
def __init__(self, ql, t, h):
self._ql = ql
self._t = t
self._h = h


def remove(self):
self._ql.hook_del(self._t, self._h)

Expand Down Expand Up @@ -102,6 +111,7 @@ def _callback_type3(self, uc, intno, pack_data):
return callback(ql, intno, user_data)
return callback(ql, intno) # callback does not require user_data


def _hook_intr_cb(self, uc, intno, pack_data):
ql, hook_type = pack_data
catched = False
Expand All @@ -116,6 +126,7 @@ def _hook_intr_cb(self, uc, intno, pack_data):
if catched == False:
raise QlErrorCoreHook("_hook_intr_cb : catched == False")


def _hook_insn_cb(self, uc, *args):
ql, hook_type = args[-1]

Expand All @@ -126,18 +137,21 @@ def _hook_insn_cb(self, uc, *args):
if isinstance(ret, int) == True and ret & QL_HOOK_BLOCK != 0:
break


def _callback_type4(self, uc, addr, size, pack_data):
ql, user_data, callback = pack_data
if user_data:
return callback(ql, addr, size, user_data)
return callback(ql, addr, size)


def _callback_type4a(self, uc, _addr, _size, pack_data):
ql, user_data, callback = pack_data
if user_data:
return callback(ql, user_data)
return callback(ql)


def _hook_trace_cb(self, uc, addr, size, pack_data):
ql, hook_type = pack_data
if hook_type in self._hook.keys():
Expand All @@ -147,12 +161,14 @@ def _hook_trace_cb(self, uc, addr, size, pack_data):
if isinstance(ret, int) == True and ret & QL_HOOK_BLOCK != 0:
break


def _callback_type6(self, uc, access, addr, size, value, pack_data):
ql, user_data, callback = pack_data
if user_data:
return callback(ql, addr, size, value, user_data)
return callback(ql, addr, size, value)


def _hook_mem_cb(self, uc, access, addr, size, value, pack_data):
ql, hook_type = pack_data
handled = False
Expand All @@ -168,12 +184,14 @@ def _hook_mem_cb(self, uc, access, addr, size, value, pack_data):
if handled == False:
raise QlErrorCoreHook("_hook_mem_cb : handled == False")


def _callback_x86_syscall(self, uc, pack_data):
ql, user_data, callback = pack_data
if user_data:
return callback(ql, user_data)
return callback(ql)



def _hook_insn_invalid_cb(self, uc, pack_data):
ql, hook_type = pack_data
catched = False
Expand All @@ -187,6 +205,7 @@ def _hook_insn_invalid_cb(self, uc, pack_data):
if catched == False:
raise QlErrorCoreHook("_hook_intr_invalid_cb : catched == False")


def _hook_addr_cb(self, uc, addr, size, pack_data):
ql, addr = pack_data
if addr in self._addr_hook.keys():
Expand All @@ -203,11 +222,13 @@ def _ql_hook_internal(self, hook_type, callback, user_data=None, *args):
# pack user_data & callback for wrapper _callback
return self.uc.hook_add(hook_type, _callback, (self, user_data), 1, 0, *args)


def _ql_hook_addr_internal(self, callback, user_data, address):
_callback = (catch_KeyboardInterrupt(self))(callback)
# pack user_data & callback for wrapper _callback
return self.uc.hook_add(UC_HOOK_CODE, _callback, (self, user_data), address, address)


def _ql_hook(self, hook_type, h, *args):
base_type = [
UC_HOOK_INTR,
Expand Down Expand Up @@ -269,35 +290,45 @@ def _ql_hook(self, hook_type, h, *args):
self._hook[t] = []
self._hook[t].append(h)


def ql_hook(self, hook_type, callback, user_data=None, begin=1, end=0, *args):
h = Hook(callback, user_data, begin, end)
self._ql_hook(hook_type, h, *args)
return HookRet(self, hook_type, h)


def hook_code(self, callback, user_data=None, begin=1, end=0):
return self.ql_hook(UC_HOOK_CODE, callback, user_data, begin, end)


def hook_intr(self, callback, user_data=None, begin=1, end=0):
return self.ql_hook(UC_HOOK_INTR, callback, user_data, begin, end)


def hook_block(self, callback, user_data=None, begin=1, end=0):
return self.ql_hook(UC_HOOK_BLOCK, callback, user_data, begin, end)


def hook_mem_unmapped(self, callback, user_data=None, begin=1, end=0):
return self.ql_hook(UC_HOOK_MEM_UNMAPPED, callback, user_data, begin, end)


def hook_mem_read_invalid(self, callback, user_data=None, begin=1, end=0):
return self.ql_hook(UC_HOOK_MEM_READ_INVALID, callback, user_data, begin, end)


def hook_mem_write_invalid(self, callback, user_data=None, begin=1, end=0):
return self.ql_hook(UC_HOOK_MEM_WRITE_INVALID, callback, user_data, begin, end)


def hook_mem_fetch_invalid(self, callback, user_data=None, begin=1, end=0):
return self.ql_hook(UC_HOOK_MEM_FETCH_INVALID, callback, user_data, begin, end)


def hook_mem_invalid(self, callback, user_data=None, begin=1, end=0):
return self.ql_hook(UC_HOOK_MEM_VALID, callback, user_data, begin, end)


# a convenient API to set callback for a single address
def hook_address(self, callback, address, user_data=None):
h = HookAddr(callback, address, user_data)
Expand All @@ -311,23 +342,29 @@ def hook_address(self, callback, address, user_data=None):
self._addr_hook[address].append(h)
return HookRet(self, None, h)


def hook_intno(self, callback, intno, user_data=None):
h = HookIntr(callback, intno, user_data)
self._ql_hook(UC_HOOK_INTR, h)
return HookRet(self, UC_HOOK_INTR, h)


def hook_mem_read(self, callback, user_data=None, begin=1, end=0):
return self.ql_hook(UC_HOOK_MEM_READ, callback, user_data, begin, end)


def hook_mem_write(self, callback, user_data=None, begin=1, end=0):
return self.ql_hook(UC_HOOK_MEM_WRITE, callback, user_data, begin, end)


def hook_mem_fetch(self, callback, user_data=None, begin=1, end=0):
return self.ql_hook(UC_HOOK_MEM_FETCH, callback, user_data, begin, end)


def hook_insn(self, callback, arg1, user_data=None, begin=1, end=0):
return self.ql_hook(UC_HOOK_INSN, callback, user_data, begin, end, arg1)


# replace linux or windows syscall/api with custom api/syscall
# if replace function name is needed, first syscall must be available
# - ql.set_syscall(0x04, my_syscall_write)
Expand Down Expand Up @@ -362,19 +399,22 @@ def set_syscall(self, syscall_cur, syscall_new, pos = QL_INTERCEPT.CALL):
syscall_name = "ql_syscall_" + str(syscall_cur)
self.os.dict_posix_onExit_syscall[syscall_name] = syscall_new


# replace default API with customed function
def set_api(self, api_name, my_func):
if self.ostype in (QL_OS.WINDOWS, QL_OS.UEFI):
self.os.user_defined_api[api_name] = my_func
else:
self.os.add_function_hook(api_name, my_func)


# ql.func_arg - get syscall for all posix series
@property
def func_arg(self):
if self.ostype in (QL_POSIX):
return self.os.get_func_arg()


def hook_del(self, *args):
if len(args) != 1 and len(args) != 2:
return
Expand Down Expand Up @@ -446,6 +486,7 @@ def clear_hooks(self):

self.clear_ql_hooks()


def clear_ql_hooks(self):
self._hook = {}
self._hook_fuc = {}
Expand Down
Loading

0 comments on commit 7b5dc8a

Please sign in to comment.