From 491a6c89c6c6fe50753f8bc84d1bbd66272cb05e Mon Sep 17 00:00:00 2001
From: Paul2803k
Date: Fri, 11 Oct 2024 21:53:00 +0200
Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20feature:=20add=20new=20HookSwit?=
=?UTF-8?q?ch=20hook=20type.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
qiling/core_hooks.py | 29 ++++++++++++++++++++++++++++-
qiling/core_hooks_types.py | 13 +++++++++++++
2 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/qiling/core_hooks.py b/qiling/core_hooks.py
index 0b4b18a27..c5cbf4f08 100644
--- a/qiling/core_hooks.py
+++ b/qiling/core_hooks.py
@@ -43,7 +43,7 @@
UC_HOOK_INSN_INVALID
)
-from .core_hooks_types import Hook, HookAddr, HookIntr, HookRet
+from .core_hooks_types import Hook, HookAddr, HookIntr, HookRet, HookSwitch
from .const import QL_HOOK_BLOCK
from .exception import QlErrorCoreHook
@@ -397,6 +397,12 @@ def ql_hook(self, hook_type: int, callback: Callable, user_data: Any = None, beg
return HookRet(self, hook_type, hook)
+ def ql_switch_hook(self, callback: Callable, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
+ hook = HookSwitch(callback, user_data, begin, end)
+ self._ql_hook(UC_HOOK_CODE, hook)
+
+ return HookRet(self, UC_HOOK_CODE, hook)
+
def hook_code(self, callback: TraceHookCalback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept assembly instructions before they get executed.
@@ -419,6 +425,27 @@ def hook_code(self, callback: TraceHookCalback, user_data: Any = None, begin: in
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_switch(self, callback: TraceHookCalback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
+ """Intercept assembly instructions before they get executed.
+
+ Args:
+ callback : a method to call upon interception
+ user_data : an additional context to pass to callback (default: `None`)
+ begin : the memory address from when to start watching
+ end : the memory address from when to stop watching
+
+ Notes:
+ If `begin` and `end` are not specified, the hook will never execute, use
+ `hook_code` instead.
+ If 'begin' and 'end' are the same address, the hook will never execute, use
+ `hook_address` instead.
+
+ Returns:
+ Hook handle
+ """
+
+ return self.ql_switch_hook(callback, user_data, begin, end)
+
def hook_block(self, callback: TraceHookCalback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept landings in new basic blocks in a specified range.
diff --git a/qiling/core_hooks_types.py b/qiling/core_hooks_types.py
index 896d70a0e..03b7512e4 100644
--- a/qiling/core_hooks_types.py
+++ b/qiling/core_hooks_types.py
@@ -54,3 +54,16 @@ def __init__(self, ql, hook_type: int, hook_obj: Hook):
def remove(self) -> None:
self.__remove(self)
+
+
+class HookSwitch(Hook):
+ def __init__(self, callback, user_data=None, begin: int = 1, end: int = 0):
+ super().__init__(callback, user_data, begin, end)
+ self.switch = False
+
+ def bound_check(self, pc: int, size: int = 1) -> bool:
+ if self.begin == pc and not self.switch:
+ self.switch = True
+ if self.end == pc and self.switch:
+ self.switch = False
+ return self.switch
\ No newline at end of file
From a88f2c929aa8f5325923cc8761a48d39b1319ec8 Mon Sep 17 00:00:00 2001
From: Paul2803k
Date: Wed, 27 Nov 2024 10:10:21 +0100
Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=8E=A8=20refactor:=20move=20'hook=5Fs?=
=?UTF-8?q?witch'=20to=20'experimental'=20folder?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
qiling/core_hooks.py | 28 +--------
qiling/core_hooks_types.py | 14 +----
qiling/extensions/hookswitch/hook_switch.py | 64 +++++++++++++++++++++
3 files changed, 66 insertions(+), 40 deletions(-)
create mode 100644 qiling/extensions/hookswitch/hook_switch.py
diff --git a/qiling/core_hooks.py b/qiling/core_hooks.py
index c5cbf4f08..e8a9bdca4 100644
--- a/qiling/core_hooks.py
+++ b/qiling/core_hooks.py
@@ -43,7 +43,7 @@
UC_HOOK_INSN_INVALID
)
-from .core_hooks_types import Hook, HookAddr, HookIntr, HookRet, HookSwitch
+from .core_hooks_types import Hook, HookAddr, HookIntr, HookRet
from .const import QL_HOOK_BLOCK
from .exception import QlErrorCoreHook
@@ -397,12 +397,6 @@ def ql_hook(self, hook_type: int, callback: Callable, user_data: Any = None, beg
return HookRet(self, hook_type, hook)
- def ql_switch_hook(self, callback: Callable, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
- hook = HookSwitch(callback, user_data, begin, end)
- self._ql_hook(UC_HOOK_CODE, hook)
-
- return HookRet(self, UC_HOOK_CODE, hook)
-
def hook_code(self, callback: TraceHookCalback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept assembly instructions before they get executed.
@@ -425,26 +419,6 @@ def hook_code(self, callback: TraceHookCalback, user_data: Any = None, begin: in
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_switch(self, callback: TraceHookCalback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
- """Intercept assembly instructions before they get executed.
-
- Args:
- callback : a method to call upon interception
- user_data : an additional context to pass to callback (default: `None`)
- begin : the memory address from when to start watching
- end : the memory address from when to stop watching
-
- Notes:
- If `begin` and `end` are not specified, the hook will never execute, use
- `hook_code` instead.
- If 'begin' and 'end' are the same address, the hook will never execute, use
- `hook_address` instead.
-
- Returns:
- Hook handle
- """
-
- return self.ql_switch_hook(callback, user_data, begin, end)
def hook_block(self, callback: TraceHookCalback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept landings in new basic blocks in a specified range.
diff --git a/qiling/core_hooks_types.py b/qiling/core_hooks_types.py
index 03b7512e4..157446f01 100644
--- a/qiling/core_hooks_types.py
+++ b/qiling/core_hooks_types.py
@@ -5,6 +5,7 @@
from typing import Any, Callable
+
class Hook:
def __init__(self, callback: Callable, user_data: Any = None, begin: int = 1, end: int = 0):
self.callback = callback
@@ -54,16 +55,3 @@ def __init__(self, ql, hook_type: int, hook_obj: Hook):
def remove(self) -> None:
self.__remove(self)
-
-
-class HookSwitch(Hook):
- def __init__(self, callback, user_data=None, begin: int = 1, end: int = 0):
- super().__init__(callback, user_data, begin, end)
- self.switch = False
-
- def bound_check(self, pc: int, size: int = 1) -> bool:
- if self.begin == pc and not self.switch:
- self.switch = True
- if self.end == pc and self.switch:
- self.switch = False
- return self.switch
\ No newline at end of file
diff --git a/qiling/extensions/hookswitch/hook_switch.py b/qiling/extensions/hookswitch/hook_switch.py
new file mode 100644
index 000000000..d66d7aaf2
--- /dev/null
+++ b/qiling/extensions/hookswitch/hook_switch.py
@@ -0,0 +1,64 @@
+from __future__ import annotations
+
+from typing import Any, Callable
+
+from unicorn.unicorn_const import (
+ UC_HOOK_CODE,
+)
+
+from qiling import Qiling
+from qiling.core_hooks import TraceHookCalback
+from qiling.core_hooks_types import Hook, HookRet
+
+
+class HookSwitch(Hook):
+ def __init__(self, callback, user_data=None, begin: int = 1, end: int = 0) -> None:
+ super().__init__(callback=callback, user_data=user_data, begin=begin, end=end)
+ self.switch = False
+
+ def bound_check(self, pc: int, size: int = 1) -> bool:
+ if self.begin == pc and not self.switch:
+ self.switch = True
+ if self.end == pc and self.switch:
+ self.switch = False
+ return self.switch
+
+
+def ql_hook_switch(
+ ql: Qiling, callback: Callable, user_data: Any = None, begin: int = 1, end: int = 0
+) -> HookRet:
+ hook = HookSwitch(callback=callback, user_data=user_data, begin=begin, end=end)
+ ql._ql_hook(UC_HOOK_CODE, hook)
+
+ return HookRet(ql=ql, hook_type=UC_HOOK_CODE, hook_obj=hook)
+
+
+def hook_switch(
+ ql: Qiling,
+ callback: TraceHookCalback,
+ user_data: Any = None,
+ begin: int = 1,
+ end: int = 0,
+) -> HookRet:
+ """Intercept assembly instructions before they get executed.
+
+ Args:
+ ql : an instance of the Qiling class
+ callback : a method to call upon interception
+ user_data : an additional context to pass to callback (default: `None`)
+ begin : the memory address from when to start watching
+ end : the memory address from when to stop watching
+
+ Notes:
+ If `begin` and `end` are not specified, the hook will never execute, use
+ `hook_code` instead.
+ If 'begin' and 'end' are the same address, the hook will never execute, use
+ `hook_address` instead.
+
+ Returns:
+ Hook handle
+ """
+
+ return ql_hook_switch(
+ ql=ql, callback=callback, user_data=user_data, begin=begin, end=end
+ )
From d1ab4088ea6d6c40e4337e4c2564a6cb46527327 Mon Sep 17 00:00:00 2001
From: Paul2803k
Date: Wed, 27 Nov 2024 10:12:55 +0100
Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=8E=A8=20ref:=20remove=20extra=20whit?=
=?UTF-8?q?espaces?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
qiling/core_hooks.py | 1 -
qiling/core_hooks_types.py | 1 -
2 files changed, 2 deletions(-)
diff --git a/qiling/core_hooks.py b/qiling/core_hooks.py
index e8a9bdca4..0b4b18a27 100644
--- a/qiling/core_hooks.py
+++ b/qiling/core_hooks.py
@@ -419,7 +419,6 @@ def hook_code(self, callback: TraceHookCalback, user_data: Any = None, begin: in
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: TraceHookCalback, user_data: Any = None, begin: int = 1, end: int = 0) -> HookRet:
"""Intercept landings in new basic blocks in a specified range.
diff --git a/qiling/core_hooks_types.py b/qiling/core_hooks_types.py
index 157446f01..896d70a0e 100644
--- a/qiling/core_hooks_types.py
+++ b/qiling/core_hooks_types.py
@@ -5,7 +5,6 @@
from typing import Any, Callable
-
class Hook:
def __init__(self, callback: Callable, user_data: Any = None, begin: int = 1, end: int = 0):
self.callback = callback