From a99d8b5331dad3e8aee61ecdfc15b6e8140ddfa2 Mon Sep 17 00:00:00 2001 From: zoopr <32989402+zoopr@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:08:58 +0100 Subject: [PATCH 1/4] Merge CEX changes to extended ICFG --- cex/project.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/cex/project.py b/cex/project.py index d3d8089..c355966 100644 --- a/cex/project.py +++ b/cex/project.py @@ -315,6 +315,33 @@ def get_ret_addr(cfg_src, callsite): res_g = res_g.subgraph(nx.dfs_postorder_nodes(res_g, entry)).copy() return normalize_graph(entry, res_g) + + # Extend static analysis ICFGs with the knowledge of a confirmed Producer-Consumer method pair. + # The lax method simply connects the lowest return nodes to the entry node of the producer. + # This is mildly inaccurate because the real ICFG will have unknown interactions on the Java layer between them, but it does create a known connection between the graphs. + # The fine method tries to build the extended ICFG by emulating producer execution and carrying over the memory layout to consumer emulation. + # Then, the call procedures are hooked and compared to the known ICFG for each function. Each divergence is added to the known ICFG. + # This significantly enhances reachability coverage in code paths belonging to the consumer, but reliant on the native object from the producer. + def extended_cp_merge_icfgs_lax(self, entry_producer, entry_consumer): + # Similar to multilib merging, but we have to add our own edge. + icfg_producer = self.get_icfg(entry_producer) + icfg_consumer = self.get_icfg(entry_consumer) + # Get leaf return nodes from producer, connect all of them to consumer. This is very rough, + # but the general idea of all producer bottom-level returns being connected to the same consumer entry point is sound. + ret_nodes = [x for x in icfg_producer.nodes() if icfg_producer.out_degree(x)==0 and icfg_producer.in_degree(x)==1] + union_graph = nx.union(icfg_producer,icfg_consumer,rename=("prod-","cons-")) + for rn in ret_nodes: + union_graph.add_edge(rn, entry_consumer) + return normalize_graph(entry_producer, union_graph) + + def extended_cp_merge_icfgs_fine(self, entry_producer, entry_consumer, obj_positional_num): + united_icfg=self.extended_cp_merge_icfgs_lax(entry_producer,entry_consumer) + #TODO: Load emulation-related procedures from Angr plugin. + #Steps: + #TODO: Get right plugin and internal functions. + #TODO: Emulate producer execution, retrieve return pointer and memory state + #TODO: Manipulate consumer state to add memory state and place native ptr in OBJ_POSITIONAL_NUM + #TODO: emulate consumer, enrich consumer ICFG. def get_depgraph(self): if self._lib_dep_graph is not None: From 1be641a3f55b9b0b0f47aceb0bfb7bdb4714965c Mon Sep 17 00:00:00 2001 From: zoopr <32989402+zoopr@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:36:00 +0100 Subject: [PATCH 2/4] Fix: (github desktop wonky permissions) --- bin/cex | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 bin/cex diff --git a/bin/cex b/bin/cex old mode 100755 new mode 100644 From 52ddea92344821e6d2a84159c94b29ce3ba12a59 Mon Sep 17 00:00:00 2001 From: zoopr <32989402+zoopr@users.noreply.github.com> Date: Tue, 15 Apr 2025 11:22:05 +0200 Subject: [PATCH 3/4] Ref fix for angr ver bump >9.0 --- cex/cfg_extractors/angr_plugin/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cex/cfg_extractors/angr_plugin/common.py b/cex/cfg_extractors/angr_plugin/common.py index 6ee4d49..6463c33 100644 --- a/cex/cfg_extractors/angr_plugin/common.py +++ b/cex/cfg_extractors/angr_plugin/common.py @@ -147,7 +147,7 @@ def hook_with_dummy(name): h = proj.hooked_by(s.rebased_addr) if h is None or h.cc is None: continue - fun_ty = h.cc.func_ty + fun_ty = h.prototype if fun_ty is None or not hasattr(fun_ty.returnty, "name"): continue if "double" in fun_ty.returnty.name or "float" in fun_ty.returnty.name: From dcacbd617a79ee5bca07001dd8de3b109ba54aa4 Mon Sep 17 00:00:00 2001 From: zoopr <32989402+zoopr@users.noreply.github.com> Date: Tue, 9 Sep 2025 14:13:42 +0200 Subject: [PATCH 4/4] Fix: Angr attribute reference change --- cex/cfg_extractors/angr_plugin/common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cex/cfg_extractors/angr_plugin/common.py b/cex/cfg_extractors/angr_plugin/common.py index 6463c33..457c426 100644 --- a/cex/cfg_extractors/angr_plugin/common.py +++ b/cex/cfg_extractors/angr_plugin/common.py @@ -148,9 +148,9 @@ def hook_with_dummy(name): if h is None or h.cc is None: continue fun_ty = h.prototype - if fun_ty is None or not hasattr(fun_ty.returnty, "name"): + if fun_ty is None: continue - if "double" in fun_ty.returnty.name or "float" in fun_ty.returnty.name: + if "double" in fun_ty.returnty.c_repr() or "float" in fun_ty.returnty.c_repr(): float_functions.add(h.display_name) to_hook = float_functions