Skip to content
Open
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
Empty file modified bin/cex
100755 → 100644
Empty file.
6 changes: 3 additions & 3 deletions cex/cfg_extractors/angr_plugin/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,10 @@ 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
if fun_ty is None or not hasattr(fun_ty.returnty, "name"):
fun_ty = h.prototype
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
Expand Down
27 changes: 27 additions & 0 deletions cex/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down