From 51ce7c2301a2b1e7b568aa0cc5530b5dd9101f49 Mon Sep 17 00:00:00 2001 From: Alexander Druffel Date: Wed, 29 Mar 2023 21:34:27 +0200 Subject: [PATCH 1/2] Fix bugs in stream loading, Android lifecycle extraction and Java method overloading --- cle/backends/backend.py | 2 +- cle/backends/java/apk.py | 11 ++++++----- cle/backends/java/soot.py | 10 ++++++++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/cle/backends/backend.py b/cle/backends/backend.py index 7cd51d94..11a762b3 100644 --- a/cle/backends/backend.py +++ b/cle/backends/backend.py @@ -148,7 +148,7 @@ def __init__( self._binary_stream: BufferedReader = binary_stream if self.binary is not None: self.binary_basename = os.path.basename(self.binary) - elif hasattr(self._binary_stream, "name"): + elif hasattr(self._binary_stream, "name") and type(self._binary_stream.name) is str: self.binary_basename = os.path.basename(self._binary_stream.name) else: self.binary_basename = str(self._binary_stream) diff --git a/cle/backends/java/apk.py b/cle/backends/java/apk.py index fa30f89b..f1910de8 100644 --- a/cle/backends/java/apk.py +++ b/cle/backends/java/apk.py @@ -33,6 +33,7 @@ class Apk(Soot): """ Backend for lifting Apk's to Soot. + Note that Soot doesn't support loading APK files from streams. """ is_default = True # let CLE automatically use this backend @@ -134,7 +135,7 @@ def _set_lifecycle(self, apk_parser): class_names = getter() self.components[key], self.callbacks[key] = self._extract_lifecycle(class_names, key) - def _extract_lifecycle(self, cls_name: List[str], component_kind: str) -> Tuple[List[SootClass], List[SootMethod]]: + def _extract_lifecycle(self, class_names: List[str], component_kind: str) -> Tuple[List[SootClass], List[SootMethod]]: """ Extract components with callbacks from class names and component kind. Use general callback name for each component by component kind @@ -147,10 +148,10 @@ def _extract_lifecycle(self, cls_name: List[str], component_kind: str) -> Tuple[ components = [] callbacks = [] - - for cls in cls_name: - components.append(self.classes[cls]) - callbacks.extend(self.get_callbacks(cls, callback[component_kind])) + for cls in class_names: + if cls in self.classes.keys(): + components.append(self.classes[cls]) + callbacks.extend(self.get_callbacks(cls, callback[component_kind])) return components, callbacks diff --git a/cle/backends/java/soot.py b/cle/backends/java/soot.py index a41d5805..ba97d68e 100644 --- a/cle/backends/java/soot.py +++ b/cle/backends/java/soot.py @@ -116,12 +116,14 @@ def get_soot_class(self, cls_name, none_if_missing=False): else: raise CLEError('Class "%s" does not exist.' % cls_name) - def get_soot_method(self, thing, class_name=None, params=(), none_if_missing=False): + def get_soot_method(self, thing, class_name=None, params=(), return_type=None, none_if_missing=False): """ Get Soot method object. :param thing: Descriptor or the method, or name of the method. :param str class_name: Name of the class. If not specified, class name can be parsed from method_name. + :param params: The method parameters + :param return_type: The methods return type :return: Soot method that satisfy the criteria. """ @@ -131,6 +133,7 @@ def get_soot_method(self, thing, class_name=None, params=(), none_if_missing=Fal "class_name": thing.class_name, "name": thing.name, "params": thing.params, + "return_type": thing.ret } elif isinstance(thing, (str, bytes)): @@ -149,6 +152,7 @@ def get_soot_method(self, thing, class_name=None, params=(), none_if_missing=Fal "class_name": class_name, "name": method_name, "params": params, + "return_type": return_type } else: @@ -190,13 +194,15 @@ def get_soot_method(self, thing, class_name=None, params=(), none_if_missing=Fal return methods[0] @staticmethod - def _description_matches_soot_method(soot_method, name=None, class_name=None, params=()): + def _description_matches_soot_method(soot_method, name=None, class_name=None, params=(), return_type=None): if name and soot_method.name != name: return False if class_name and soot_method.class_name != class_name: return False if soot_method.params != params: return False + if soot_method.ret != return_type: + return False return True @property From ef1bf157e45cd334f223e81186f8265cc86c2831 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 29 Mar 2023 19:38:42 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- cle/backends/java/apk.py | 4 +++- cle/backends/java/soot.py | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cle/backends/java/apk.py b/cle/backends/java/apk.py index f1910de8..d0f5b16f 100644 --- a/cle/backends/java/apk.py +++ b/cle/backends/java/apk.py @@ -135,7 +135,9 @@ def _set_lifecycle(self, apk_parser): class_names = getter() self.components[key], self.callbacks[key] = self._extract_lifecycle(class_names, key) - def _extract_lifecycle(self, class_names: List[str], component_kind: str) -> Tuple[List[SootClass], List[SootMethod]]: + def _extract_lifecycle( + self, class_names: List[str], component_kind: str + ) -> Tuple[List[SootClass], List[SootMethod]]: """ Extract components with callbacks from class names and component kind. Use general callback name for each component by component kind diff --git a/cle/backends/java/soot.py b/cle/backends/java/soot.py index ba97d68e..abf7097c 100644 --- a/cle/backends/java/soot.py +++ b/cle/backends/java/soot.py @@ -133,7 +133,7 @@ def get_soot_method(self, thing, class_name=None, params=(), return_type=None, n "class_name": thing.class_name, "name": thing.name, "params": thing.params, - "return_type": thing.ret + "return_type": thing.ret, } elif isinstance(thing, (str, bytes)): @@ -152,7 +152,7 @@ def get_soot_method(self, thing, class_name=None, params=(), return_type=None, n "class_name": class_name, "name": method_name, "params": params, - "return_type": return_type + "return_type": return_type, } else: