mirror of
https://github.com/JHUAPL/CodeCut.git
synced 2026-01-08 21:07:58 -05:00
Fixed extra directories
This commit is contained in:
0
deepcut-ghidra/Module.manifest
Normal file
0
deepcut-ghidra/Module.manifest
Normal file
75
deepcut-ghidra/README.md
Normal file
75
deepcut-ghidra/README.md
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
Ghidra Deepcut Analyzer
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Implementation of the deepcut as a Ghidra one-shot analyzer.
|
||||||
|
|
||||||
|
## Building and Installation
|
||||||
|
JDK 11 (or newer) and Ghidra 9.1.0 (or newer) are required.
|
||||||
|
|
||||||
|
Ghidra's standard Gradle build system is used. Set the
|
||||||
|
`GHIDRA_INSTALL_DIR` environment variable before building, or set it as
|
||||||
|
a Gradle property (useful for building in an IDE):
|
||||||
|
|
||||||
|
### Environment variable
|
||||||
|
```bash
|
||||||
|
$ export GHIDRA_INSTALL_DIR="/path/to/ghidra"
|
||||||
|
$ ./gradlew
|
||||||
|
```
|
||||||
|
|
||||||
|
### Gradle property
|
||||||
|
```bash
|
||||||
|
echo GHIDRA_INSTALL_DIR=/path/to/ghidra > gradle.properties
|
||||||
|
```
|
||||||
|
|
||||||
|
The module ZIP will be output to `dist/`. Use **File > Install
|
||||||
|
Extensions** and select the green plus to browse to the
|
||||||
|
extension. Restart Ghidra when prompted.
|
||||||
|
|
||||||
|
For proper functionality, the plugin should be built with the same JRE
|
||||||
|
used by your Ghidra installation. If you have multiple Java runtime
|
||||||
|
environments installed, select the correct JRE by setting the
|
||||||
|
`JAVA_HOME` environment variable before building.
|
||||||
|
|
||||||
|
### Python 3
|
||||||
|
The deepcut graph based machine learning model needs Python 3 to
|
||||||
|
execute. The analyzer calls and external python process to execute the
|
||||||
|
model on a graph representation of the binary. There are no GPU
|
||||||
|
requirements since the model converge quickly even running in CPU mode.
|
||||||
|
|
||||||
|
#### Python 3 Path
|
||||||
|
By default the analyzer use the command `/usr/local/bin/python3` to
|
||||||
|
execute the deepcut python script. This setting can be changed in the
|
||||||
|
Analysis Options menu **Analysis -> Analyze All Open...** To change the
|
||||||
|
setting you need to click the checkbox next to **Deepcut (Prototype)**
|
||||||
|
first.
|
||||||
|
|
||||||
|
#### Dependencies
|
||||||
|
Deepcut has the following Python 3 dependencies:
|
||||||
|
|
||||||
|
- torch 1.7.1
|
||||||
|
- torch-geometric 1.6.3
|
||||||
|
- torch-cluster 1.5.8
|
||||||
|
- torch-sparse 0.6.8
|
||||||
|
- torch-scatter 2.0.5
|
||||||
|
- torch-spline-conv 1.2.0
|
||||||
|
|
||||||
|
To install the dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install torch==1.7.1+cpu -f https://download.pytorch.org/whl/torch_stable.html
|
||||||
|
pip install -r requirements-torch_geometric.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
The torch-cluster dependency can take a significant amount of time to
|
||||||
|
build and install.
|
||||||
|
|
||||||
|
## Running the Analyzer
|
||||||
|
The Deepcut analyzer will not run during auto-analysis. Once the binary
|
||||||
|
is loaded and the auto-analyzer is finish use the menu item **Analysis
|
||||||
|
-> One Shot -> Deepcut**
|
||||||
|
|
||||||
|
Once complete each function will include a `moduleX` value in the
|
||||||
|
Namespace field.
|
||||||
|
|
||||||
|
If there are any errors please make sure you are using the proper path
|
||||||
|
to Python 3 and the requirement dependencies installed.
|
||||||
33
deepcut-ghidra/build.gradle
Normal file
33
deepcut-ghidra/build.gradle
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// Builds a Ghidra Extension for a given Ghidra installation.
|
||||||
|
//
|
||||||
|
// An absolute path to the Ghidra installation directory must be supplied either by setting the
|
||||||
|
// GHIDRA_INSTALL_DIR environment variable or Gradle project property:
|
||||||
|
//
|
||||||
|
// > export GHIDRA_INSTALL_DIR=<Absolute path to Ghidra>
|
||||||
|
// > gradle
|
||||||
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// > gradle -PGHIDRA_INSTALL_DIR=<Absolute path to Ghidra>
|
||||||
|
//
|
||||||
|
// Gradle should be invoked from the directory of the project to build. Please see the
|
||||||
|
// application.gradle.version property in <GHIDRA_INSTALL_DIR>/Ghidra/application.properties
|
||||||
|
// for the correction version of Gradle to use for the Ghidra installation you specify.
|
||||||
|
|
||||||
|
//----------------------START "DO NOT MODIFY" SECTION------------------------------
|
||||||
|
def ghidraInstallDir
|
||||||
|
|
||||||
|
if (System.env.GHIDRA_INSTALL_DIR) {
|
||||||
|
ghidraInstallDir = System.env.GHIDRA_INSTALL_DIR
|
||||||
|
}
|
||||||
|
else if (project.hasProperty("GHIDRA_INSTALL_DIR")) {
|
||||||
|
ghidraInstallDir = project.getProperty("GHIDRA_INSTALL_DIR")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ghidraInstallDir) {
|
||||||
|
apply from: new File(ghidraInstallDir).getCanonicalPath() + "/support/buildExtension.gradle"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new GradleException("GHIDRA_INSTALL_DIR is not defined!")
|
||||||
|
}
|
||||||
|
//----------------------END "DO NOT MODIFY" SECTION-------------------------------
|
||||||
148
deepcut-ghidra/data/GNN_Net.py
Normal file
148
deepcut-ghidra/data/GNN_Net.py
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
# © 2021 The Johns Hopkins University Applied Physics Laboratory LLC
|
||||||
|
# (JHU/APL). All Rights Reserved.
|
||||||
|
#
|
||||||
|
# This material may be only be used, modified, or reproduced by or for
|
||||||
|
# the U.S. Government pursuant to the license rights granted under the
|
||||||
|
# clauses at DFARS 252.227-7013/7014 or FAR 52.227-14. For any other
|
||||||
|
# permission, please contact the Office of Technology Transfer at
|
||||||
|
# JHU/APL.
|
||||||
|
#
|
||||||
|
# NO WARRANTY, NO LIABILITY. THIS MATERIAL IS PROVIDED “AS IS.” JHU/APL
|
||||||
|
# MAKES NO REPRESENTATION OR WARRANTY WITH RESPECT TO THE PERFORMANCE OF
|
||||||
|
# THE MATERIALS, INCLUDING THEIR SAFETY, EFFECTIVENESS, OR COMMERCIAL
|
||||||
|
# VIABILITY, AND DISCLAIMS ALL WARRANTIES IN THE MATERIAL, WHETHER
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING (BUT NOT LIMITED TO) ANY AND ALL IMPLIED
|
||||||
|
# WARRANTIES OF PERFORMANCE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
# PURPOSE, AND NON-INFRINGEMENT OF INTELLECTUAL PROPERTY OR OTHER THIRD
|
||||||
|
# PARTY RIGHTS. ANY USER OF THE MATERIAL ASSUMES THE ENTIRE RISK AND
|
||||||
|
# LIABILITY FOR USING THE MATERIAL. IN NO EVENT SHALL JHU/APL BE LIABLE
|
||||||
|
# TO ANY USER OF THE MATERIAL FOR ANY ACTUAL, INDIRECT, CONSEQUENTIAL,
|
||||||
|
# SPECIAL OR OTHER DAMAGES ARISING FROM THE USE OF, OR INABILITY TO USE,
|
||||||
|
# THE MATERIAL, INCLUDING, BUT NOT LIMITED TO, ANY DAMAGES FOR LOST
|
||||||
|
# PROFITS.
|
||||||
|
#
|
||||||
|
# HAVE A NICE DAY.
|
||||||
|
|
||||||
|
# This material is based upon work supported by the Defense Advanced Research
|
||||||
|
# Projects Agency (DARPA) and Naval Information Warfare Center Pacific (NIWC Pacific)
|
||||||
|
# under Contract Number N66001-20-C-4024.
|
||||||
|
|
||||||
|
import torch
|
||||||
|
import torch.nn.functional as F
|
||||||
|
from torch.nn import Sequential, Linear, ReLU
|
||||||
|
from torch_geometric import nn
|
||||||
|
|
||||||
|
|
||||||
|
class Net(torch.nn.Module):
|
||||||
|
def __init__(self, num_features, num_edge_features, dim=32):
|
||||||
|
super(Net, self).__init__()
|
||||||
|
|
||||||
|
self.init_mlp = Sequential(Linear(num_features, num_edge_features),
|
||||||
|
ReLU(),
|
||||||
|
Linear(num_edge_features, num_edge_features))
|
||||||
|
self.init_bn = torch.nn.LayerNorm(num_edge_features)
|
||||||
|
|
||||||
|
self.init_emlp = Sequential(Linear(num_edge_features, num_edge_features),
|
||||||
|
ReLU(),
|
||||||
|
Linear(num_edge_features, num_edge_features))
|
||||||
|
self.init_ebn = torch.nn.LayerNorm(num_edge_features)
|
||||||
|
|
||||||
|
mlp1 = Sequential(Linear(num_edge_features, dim),
|
||||||
|
ReLU(),
|
||||||
|
Linear(dim, dim), ReLU(), Linear(dim, dim))
|
||||||
|
self.e_mlp1 = Sequential(Linear(num_edge_features, dim),
|
||||||
|
ReLU(),
|
||||||
|
Linear(dim, dim), ReLU(), Linear(dim, dim))
|
||||||
|
self.e_bn1 = torch.nn.LayerNorm(dim)
|
||||||
|
self.gin1 = nn.GINEConv(mlp1, train_eps=True).jittable()
|
||||||
|
self.bn1 = nn.PairNorm() # nn.LayerNorm(dim) #torch.nn.BatchNorm1d(dim)
|
||||||
|
|
||||||
|
mlp2 = Sequential(Linear(dim, dim), ReLU(), Linear(dim, dim),
|
||||||
|
ReLU(),
|
||||||
|
Linear(dim, dim))
|
||||||
|
self.gin2 = nn.GINEConv(mlp2, train_eps=True).jittable()
|
||||||
|
self.bn2 = nn.PairNorm() # nn.LayerNorm(dim) #torch.nn.BatchNorm1d(dim)
|
||||||
|
self.e_mlp2 = Sequential(Linear(3*dim, dim),
|
||||||
|
ReLU(),
|
||||||
|
Linear(dim, dim),
|
||||||
|
ReLU(),
|
||||||
|
Linear(dim, dim))
|
||||||
|
self.ebn2 = torch.nn.LayerNorm(dim)
|
||||||
|
|
||||||
|
mlp3 = Sequential(Linear(dim, dim),
|
||||||
|
ReLU(),
|
||||||
|
Linear(dim, dim),
|
||||||
|
ReLU(),
|
||||||
|
Linear(dim, dim))
|
||||||
|
self.gin3 = nn.GINEConv(mlp3, train_eps=True).jittable()
|
||||||
|
self.bn3 = nn.PairNorm() # nn.LayerNorm(dim)
|
||||||
|
self.e_mlp3 = Sequential(Linear(3*dim, dim),
|
||||||
|
ReLU(),
|
||||||
|
Linear(dim, dim),
|
||||||
|
ReLU(),
|
||||||
|
Linear(dim, dim))
|
||||||
|
self.ebn3 = torch.nn.LayerNorm(dim)
|
||||||
|
|
||||||
|
self.out1 = torch.nn.Linear(3*dim, dim)
|
||||||
|
self.out_bn = torch.nn.LayerNorm(dim)
|
||||||
|
self.out2 = torch.nn.Linear(dim, 4)
|
||||||
|
|
||||||
|
def forward(self, x, edge_attr, edge_index, batch):
|
||||||
|
# x, edge_attr, edge_index, batch = (
|
||||||
|
# data.x,
|
||||||
|
# data.edge_attr,
|
||||||
|
# data.edge_index,
|
||||||
|
# data.batch,
|
||||||
|
# )
|
||||||
|
|
||||||
|
x = F.relu(self.init_mlp(x))
|
||||||
|
x = self.init_bn(x)
|
||||||
|
edge_attr = self.init_emlp(edge_attr)
|
||||||
|
edge_attr = self.init_ebn(edge_attr)
|
||||||
|
|
||||||
|
x = F.relu(self.gin1(x, edge_index, edge_attr))
|
||||||
|
x = self.bn1(x, batch)
|
||||||
|
edge_attr = F.relu(self.e_mlp1(edge_attr))
|
||||||
|
edge_attr = self.e_bn1(edge_attr)
|
||||||
|
|
||||||
|
x = F.relu(self.gin2(x, edge_index, edge_attr))
|
||||||
|
x = self.bn2(x, batch)
|
||||||
|
edge_attr = torch.cat([x[edge_index[0]], x[edge_index[1]], edge_attr],
|
||||||
|
dim=1)
|
||||||
|
edge_attr = self.e_mlp2(edge_attr)
|
||||||
|
edge_attr = self.ebn2(edge_attr)
|
||||||
|
|
||||||
|
x = F.relu(self.gin3(x, edge_index, edge_attr))
|
||||||
|
x = self.bn3(x, batch)
|
||||||
|
edge_attr = torch.cat([x[edge_index[0]], x[edge_index[1]], edge_attr], dim=1)
|
||||||
|
edge_attr = self.e_mlp3(edge_attr)
|
||||||
|
edge_attr = self.ebn2(edge_attr) # oops typo this should be a 3
|
||||||
|
|
||||||
|
#x = x[edge_index[0]] + x[edge_index[1]] + edge_attr
|
||||||
|
#x = F.softmax(x, dim=1)
|
||||||
|
#edge_attr = F.softmax(edge_attr, dim=1)
|
||||||
|
x = torch.cat([x[edge_index[0]], x[edge_index[1]], edge_attr], dim=1)
|
||||||
|
|
||||||
|
x = F.relu(self.out1(x))
|
||||||
|
x = self.out_bn(x)
|
||||||
|
x = self.out2(x)
|
||||||
|
|
||||||
|
#ret = torch.max(x, dim=1)[0]
|
||||||
|
ret = torch.mean(x, dim=1)
|
||||||
|
|
||||||
|
#ret = torch.max(x[edge_index[0]] + x[edge_index[1]], dim=1)[0]
|
||||||
|
#ret = torch.mean(x[edge_index[0]] + x[edge_index[1]], dim=1)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def load_gnn(model_file):
|
||||||
|
model = Net(
|
||||||
|
num_features=2,
|
||||||
|
num_edge_features=4,
|
||||||
|
dim=64,
|
||||||
|
)
|
||||||
|
|
||||||
|
loaded_weights = torch.load(model_file,
|
||||||
|
map_location=torch.device('cpu'))
|
||||||
|
model.load_state_dict(loaded_weights)
|
||||||
|
|
||||||
|
return model
|
||||||
15
deepcut-ghidra/data/README.txt
Normal file
15
deepcut-ghidra/data/README.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
The "data" directory is intended to hold data files that will be used by this module and will
|
||||||
|
not end up in the .jar file, but will be present in the zip or tar file. Typically, data
|
||||||
|
files are placed here rather than in the resources directory if the user may need to edit them.
|
||||||
|
|
||||||
|
An optional data/languages directory can exist for the purpose of containing various Sleigh language
|
||||||
|
specification files and importer opinion files.
|
||||||
|
|
||||||
|
The data/buildLanguage.xml is used for building the contents of the data/languages directory.
|
||||||
|
|
||||||
|
The skel language definition has been commented-out within the skel.ldefs file so that the
|
||||||
|
skeleton language does not show-up within Ghidra.
|
||||||
|
|
||||||
|
See the Sleigh language documentation (docs/languages/index.html) for details Sleigh language
|
||||||
|
specification syntax.
|
||||||
|
|
||||||
199
deepcut-ghidra/data/deepcut.py
Normal file
199
deepcut-ghidra/data/deepcut.py
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# © 2022 The Johns Hopkins University Applied Physics Laboratory LLC
|
||||||
|
# (JHU/APL). All Rights Reserved.
|
||||||
|
#
|
||||||
|
# This material may be only be used, modified, or reproduced by or for
|
||||||
|
# the U.S. Government pursuant to the license rights granted under the
|
||||||
|
# clauses at DFARS 252.227-7013/7014 or FAR 52.227-14. For any other
|
||||||
|
# permission, please contact the Office of Technology Transfer at
|
||||||
|
# JHU/APL.
|
||||||
|
#
|
||||||
|
# NO WARRANTY, NO LIABILITY. THIS MATERIAL IS PROVIDED “AS IS.” JHU/APL
|
||||||
|
# MAKES NO REPRESENTATION OR WARRANTY WITH RESPECT TO THE PERFORMANCE OF
|
||||||
|
# THE MATERIALS, INCLUDING THEIR SAFETY, EFFECTIVENESS, OR COMMERCIAL
|
||||||
|
# VIABILITY, AND DISCLAIMS ALL WARRANTIES IN THE MATERIAL, WHETHER
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING (BUT NOT LIMITED TO) ANY AND ALL IMPLIED
|
||||||
|
# WARRANTIES OF PERFORMANCE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
# PURPOSE, AND NON-INFRINGEMENT OF INTELLECTUAL PROPERTY OR OTHER THIRD
|
||||||
|
# PARTY RIGHTS. ANY USER OF THE MATERIAL ASSUMES THE ENTIRE RISK AND
|
||||||
|
# LIABILITY FOR USING THE MATERIAL. IN NO EVENT SHALL JHU/APL BE LIABLE
|
||||||
|
# TO ANY USER OF THE MATERIAL FOR ANY ACTUAL, INDIRECT, CONSEQUENTIAL,
|
||||||
|
# SPECIAL OR OTHER DAMAGES ARISING FROM THE USE OF, OR INABILITY TO USE,
|
||||||
|
# THE MATERIAL, INCLUDING, BUT NOT LIMITED TO, ANY DAMAGES FOR LOST
|
||||||
|
# PROFITS.
|
||||||
|
#
|
||||||
|
# HAVE A NICE DAY.
|
||||||
|
|
||||||
|
# This material is based upon work supported by the Defense Advanced Research
|
||||||
|
# Projects Agency (DARPA) and Naval Information Warfare Center Pacific (NIWC Pacific)
|
||||||
|
# under Contract Number N66001-20-C-4024.
|
||||||
|
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import torch
|
||||||
|
|
||||||
|
from math import log2, copysign
|
||||||
|
from networkx import DiGraph
|
||||||
|
from scipy.linalg import toeplitz
|
||||||
|
|
||||||
|
import GNN_Net
|
||||||
|
|
||||||
|
|
||||||
|
class Deepcut:
|
||||||
|
def __init__(self, fcg_data, model_file):
|
||||||
|
self.fcg_data = fcg_data
|
||||||
|
self.model_file = model_file
|
||||||
|
|
||||||
|
self.graph = DiGraph()
|
||||||
|
self.functions = {}
|
||||||
|
self.graph_connectivity = []
|
||||||
|
self.node_features = []
|
||||||
|
self.edge_features = []
|
||||||
|
|
||||||
|
self._generate_graph()
|
||||||
|
self._generate_features()
|
||||||
|
self._predicte_labels()
|
||||||
|
|
||||||
|
def _generate_graph(self):
|
||||||
|
for f in self.fcg_data['functions']:
|
||||||
|
self.graph.add_node(f['index'],
|
||||||
|
num_inc=log2(2 + f['num_incoming_edges']),
|
||||||
|
num_out=log2(2 + f['num_outgoing_edges']))
|
||||||
|
self.functions[f['index']] = {
|
||||||
|
'address': f['addr'],
|
||||||
|
'name': f['name'],
|
||||||
|
}
|
||||||
|
|
||||||
|
for e in self.fcg_data['edges']:
|
||||||
|
index_dist_weight = copysign(log2(2 + abs(e['index_distance'])),
|
||||||
|
e['index_distance'])
|
||||||
|
address_dist_weight = copysign(log2(2 + abs(e['addr_distance'])),
|
||||||
|
e['addr_distance']) / 4
|
||||||
|
multiplicity_weight = log2(2 + abs(e['multiplicity']))
|
||||||
|
|
||||||
|
# The weight attribute is a 4-tuple. The multiplicity value
|
||||||
|
# is 0.0 for the "opposite" direction
|
||||||
|
self.graph.add_edge(e['src_index'], e['dst_index'],
|
||||||
|
weights=(index_dist_weight,
|
||||||
|
address_dist_weight,
|
||||||
|
multiplicity_weight,
|
||||||
|
0.0))
|
||||||
|
|
||||||
|
self.graph.add_edge(e['dst_index'], e['src_index'],
|
||||||
|
weights=(-index_dist_weight,
|
||||||
|
-address_dist_weight,
|
||||||
|
0.0,
|
||||||
|
multiplicity_weight))
|
||||||
|
|
||||||
|
def _generate_features(self):
|
||||||
|
for n in sorted(list(self.graph.nodes)):
|
||||||
|
self.node_features.append([self.graph.nodes[n]['num_out'],
|
||||||
|
self.graph.nodes[n]['num_inc']])
|
||||||
|
|
||||||
|
for (n1, n2, d) in self.graph.edges(data=True):
|
||||||
|
self.graph_connectivity.append([n1, n2])
|
||||||
|
self.edge_features.append(list(d["weights"]))
|
||||||
|
|
||||||
|
def _predicte_labels(self):
|
||||||
|
model = GNN_Net.load_gnn(self.model_file)
|
||||||
|
m = model(x=torch.Tensor(self.node_features),
|
||||||
|
edge_index=torch.LongTensor(self.graph_connectivity).t().contiguous(),
|
||||||
|
edge_attr=torch.Tensor(self.edge_features),
|
||||||
|
batch=torch.tensor([0] * len(self.graph)))
|
||||||
|
|
||||||
|
self.predicted_labels = torch.sigmoid(m).detach().numpy()
|
||||||
|
|
||||||
|
def _adjacency_matrix(self):
|
||||||
|
num_funcs = len(self.graph.nodes)
|
||||||
|
A = np.zeros((num_funcs, num_funcs))
|
||||||
|
|
||||||
|
for e, v in zip(self.graph_connectivity, self.predicted_labels):
|
||||||
|
e0, e1 = e
|
||||||
|
A[e0, e1] = v
|
||||||
|
|
||||||
|
A += A.T
|
||||||
|
A *= 0.5
|
||||||
|
|
||||||
|
"""
|
||||||
|
add a small connection between adjacent nodes,
|
||||||
|
essentially to break ties in favor of merging communities
|
||||||
|
"""
|
||||||
|
x = np.zeros(num_funcs)
|
||||||
|
x[1] = 0.05
|
||||||
|
A += toeplitz(x)
|
||||||
|
|
||||||
|
return A
|
||||||
|
|
||||||
|
def _modularity(self):
|
||||||
|
adj_matrix = self._adjacency_matrix()
|
||||||
|
# node degrees
|
||||||
|
k = np.sum(adj_matrix, axis=0)
|
||||||
|
|
||||||
|
k2 = np.array([k])
|
||||||
|
B = k2.T @ k2
|
||||||
|
B /= 2 * np.sum(k2)
|
||||||
|
|
||||||
|
Q = adj_matrix - B
|
||||||
|
|
||||||
|
def compute_partial_modularity(start, stop):
|
||||||
|
return np.sum(Q[start:stop, start:stop])
|
||||||
|
|
||||||
|
scores = [0.0]
|
||||||
|
scores = np.array(scores)
|
||||||
|
cuts = [[0]]
|
||||||
|
|
||||||
|
# speedup so it runs in linear time
|
||||||
|
max_cluster_size = 100
|
||||||
|
|
||||||
|
for index in range(1, len(self.graph.nodes)):
|
||||||
|
update = [compute_partial_modularity(i, index) for i in
|
||||||
|
range(max(0, index-max_cluster_size), index)]
|
||||||
|
if index > max_cluster_size:
|
||||||
|
update = [0]*(index-max_cluster_size) + update
|
||||||
|
updated_scores = scores + update
|
||||||
|
|
||||||
|
i = np.argmax(updated_scores)
|
||||||
|
|
||||||
|
if index > max_cluster_size:
|
||||||
|
i = np.argmax(updated_scores[index-max_cluster_size:])+ (index - max_cluster_size)
|
||||||
|
|
||||||
|
s = updated_scores[i]
|
||||||
|
c = cuts[i] + [index]
|
||||||
|
|
||||||
|
scores = np.append(scores, s)
|
||||||
|
cuts.append(c)
|
||||||
|
|
||||||
|
final_cut = cuts[-1]
|
||||||
|
return final_cut
|
||||||
|
|
||||||
|
def module_list(self):
|
||||||
|
cuts = self._modularity()
|
||||||
|
return [self.functions[x] for x in cuts]
|
||||||
|
|
||||||
|
|
||||||
|
def read_input():
|
||||||
|
# Yes this expects the json to have no newlines
|
||||||
|
inp = sys.stdin.readline()
|
||||||
|
ret = json.loads(inp)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
fcg = read_input()
|
||||||
|
|
||||||
|
if len(sys.argv) == 2:
|
||||||
|
model_file = sys.argv[1]
|
||||||
|
else:
|
||||||
|
model_file = "model_weights_1.p"
|
||||||
|
|
||||||
|
d = Deepcut(fcg, model_file)
|
||||||
|
|
||||||
|
print(json.dumps(d.module_list()))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
BIN
deepcut-ghidra/data/model_weights_1.p
Normal file
BIN
deepcut-ghidra/data/model_weights_1.p
Normal file
Binary file not shown.
5
deepcut-ghidra/extension.properties
Normal file
5
deepcut-ghidra/extension.properties
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
name=@extname@
|
||||||
|
description=Use the deepcut algorithm to find module boundaries.
|
||||||
|
author=JHU/APL
|
||||||
|
createdOn=
|
||||||
|
version=@extversion@
|
||||||
1
deepcut-ghidra/ghidra_scripts/README.txt
Normal file
1
deepcut-ghidra/ghidra_scripts/README.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Java source directory to hold module-specific Ghidra scripts.
|
||||||
5
deepcut-ghidra/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
deepcut-ghidra/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
185
deepcut-ghidra/gradlew
vendored
Normal file
185
deepcut-ghidra/gradlew
vendored
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2015 the original author or authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=`expr $i + 1`
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
0) set -- ;;
|
||||||
|
1) set -- "$args0" ;;
|
||||||
|
2) set -- "$args0" "$args1" ;;
|
||||||
|
3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=`save "$@"`
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
89
deepcut-ghidra/gradlew.bat
vendored
Normal file
89
deepcut-ghidra/gradlew.bat
vendored
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto execute
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
3
deepcut-ghidra/os/linux64/README.txt
Normal file
3
deepcut-ghidra/os/linux64/README.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
The "os/linux64" directory is intended to hold Linux native binaries
|
||||||
|
which this module is dependent upon. This directory may be eliminated for a specific
|
||||||
|
module if native binaries are not provided for the corresponding platform.
|
||||||
3
deepcut-ghidra/os/osx64/README.txt
Normal file
3
deepcut-ghidra/os/osx64/README.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
The "os/osx64" directory is intended to hold macOS (OS X) native binaries
|
||||||
|
which this module is dependent upon. This directory may be eliminated for a specific
|
||||||
|
module if native binaries are not provided for the corresponding platform.
|
||||||
3
deepcut-ghidra/os/win64/README.txt
Normal file
3
deepcut-ghidra/os/win64/README.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
The "os/win64" directory is intended to hold MS Windows native binaries (.exe)
|
||||||
|
which this module is dependent upon. This directory may be eliminated for a specific
|
||||||
|
module if native binaries are not provided for the corresponding platform.
|
||||||
7
deepcut-ghidra/requirements-torch_geometric.txt
Normal file
7
deepcut-ghidra/requirements-torch_geometric.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
torch-geometric==1.6.3
|
||||||
|
|
||||||
|
--find-links https://pytorch-geometric.com/whl/torch-1.7.0+cpu.html
|
||||||
|
torch-sparse==0.6.8
|
||||||
|
torch-scatter==2.0.5
|
||||||
|
torch-cluster==1.5.8
|
||||||
|
torch-spline-conv==1.2.0
|
||||||
57
deepcut-ghidra/src/main/help/help/TOC_Source.xml
Normal file
57
deepcut-ghidra/src/main/help/help/TOC_Source.xml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?xml version='1.0' encoding='ISO-8859-1' ?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
This is an XML file intended to be parsed by the Ghidra help system. It is loosely based
|
||||||
|
upon the JavaHelp table of contents document format. The Ghidra help system uses a
|
||||||
|
TOC_Source.xml file to allow a module with help to define how its contents appear in the
|
||||||
|
Ghidra help viewer's table of contents. The main document (in the Base module)
|
||||||
|
defines a basic structure for the
|
||||||
|
Ghidra table of contents system. Other TOC_Source.xml files may use this structure to insert
|
||||||
|
their files directly into this structure (and optionally define a substructure).
|
||||||
|
|
||||||
|
|
||||||
|
In this document, a tag can be either a <tocdef> or a <tocref>. The former is a definition
|
||||||
|
of an XML item that may have a link and may contain other <tocdef> and <tocref> children.
|
||||||
|
<tocdef> items may be referred to in other documents by using a <tocref> tag with the
|
||||||
|
appropriate id attribute value. Using these two tags allows any module to define a place
|
||||||
|
in the table of contents system (<tocdef>), which also provides a place for
|
||||||
|
other TOC_Source.xml files to insert content (<tocref>).
|
||||||
|
|
||||||
|
During the help build time, all TOC_Source.xml files will be parsed and validated to ensure
|
||||||
|
that all <tocref> tags point to valid <tocdef> tags. From these files will be generated
|
||||||
|
<module name>_TOC.xml files, which are table of contents files written in the format
|
||||||
|
desired by the JavaHelp system. Additionally, the genated files will be merged together
|
||||||
|
as they are loaded by the JavaHelp system. In the end, when displaying help in the Ghidra
|
||||||
|
help GUI, there will be on table of contents that has been created from the definitions in
|
||||||
|
all of the modules' TOC_Source.xml files.
|
||||||
|
|
||||||
|
|
||||||
|
Tags and Attributes
|
||||||
|
|
||||||
|
<tocdef>
|
||||||
|
-id - the name of the definition (this must be unique across all TOC_Source.xml files)
|
||||||
|
-text - the display text of the node, as seen in the help GUI
|
||||||
|
-target** - the file to display when the node is clicked in the GUI
|
||||||
|
-sortgroup - this is a string that defines where a given node should appear under a given
|
||||||
|
parent. The string values will be sorted by the JavaHelp system using
|
||||||
|
a javax.text.RulesBasedCollator. If this attribute is not specified, then
|
||||||
|
the text of attribute will be used.
|
||||||
|
|
||||||
|
<tocref>
|
||||||
|
-id - The id of the <tocdef> that this reference points to
|
||||||
|
|
||||||
|
**The URL for the target is relative and should start with 'help/topics'. This text is
|
||||||
|
used by the Ghidra help system to provide a universal starting point for all links so that
|
||||||
|
they can be resolved at runtime, across modules.
|
||||||
|
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
<tocroot>
|
||||||
|
<!-- Uncomment and adjust fields to add help topic to help system's Table of Contents
|
||||||
|
<tocref id="Ghidra Functionality">
|
||||||
|
<tocdef id="HelpAnchor" text="My Feature" target="help/topics/my_topic/help.html" />
|
||||||
|
</tocref>
|
||||||
|
-->
|
||||||
|
</tocroot>
|
||||||
64
deepcut-ghidra/src/main/help/help/shared/Frontpage.css
Normal file
64
deepcut-ghidra/src/main/help/help/shared/Frontpage.css
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
WARNING!
|
||||||
|
This file is copied to all help directories. If you change this file, you must copy it
|
||||||
|
to each src/main/help/help/shared directory.
|
||||||
|
|
||||||
|
|
||||||
|
Java Help Note: JavaHelp does not accept sizes (like in 'margin-top') in anything but
|
||||||
|
px (pixel) or with no type marking.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 10px; } /* some padding to improve readability */
|
||||||
|
li { font-family:times new roman; font-size:14pt; }
|
||||||
|
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
|
||||||
|
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
|
||||||
|
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
|
||||||
|
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
P tag code. Most of the help files nest P tags inside of blockquote tags (the was the
|
||||||
|
way it had been done in the beginning). The net effect is that the text is indented. In
|
||||||
|
modern HTML we would use CSS to do this. We need to support the Ghidra P tags, nested in
|
||||||
|
blockquote tags, as well as naked P tags. The following two lines accomplish this. Note
|
||||||
|
that the 'blockquote p' definition will inherit from the first 'p' definition.
|
||||||
|
*/
|
||||||
|
p { margin-left: 40px; font-family:times new roman; font-size:14pt; }
|
||||||
|
blockquote p { margin-left: 10px; }
|
||||||
|
|
||||||
|
p.providedbyplugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
|
||||||
|
p.ProvidedByPlugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
|
||||||
|
p.relatedtopic { color:#800080; margin-left: 10px; font-size:14pt; }
|
||||||
|
p.RelatedTopic { color:#800080; margin-left: 10px; font-size:14pt; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
We wish for a tables to have space between it and the preceding element, so that text
|
||||||
|
is not too close to the top of the table. Also, nest the table a bit so that it is clear
|
||||||
|
the table relates to the preceding text.
|
||||||
|
*/
|
||||||
|
table { margin-left: 20px; margin-top: 10px; width: 80%;}
|
||||||
|
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
|
||||||
|
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
Code-like formatting for things such as file system paths and proper names of classes,
|
||||||
|
methods, etc. To apply this to a file path, use this syntax:
|
||||||
|
<CODE CLASS="path">...</CODE>
|
||||||
|
*/
|
||||||
|
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
|
||||||
|
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
|
||||||
23
deepcut-ghidra/src/main/help/help/topics/deepcut/help.html
Normal file
23
deepcut-ghidra/src/main/help/help/topics/deepcut/help.html
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<META name="generator" content=
|
||||||
|
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
|
||||||
|
<META http-equiv="Content-Language" content="en-us">
|
||||||
|
<META http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||||
|
<META name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||||
|
<META name="ProgId" content="FrontPage.Editor.Document">
|
||||||
|
|
||||||
|
<TITLE>Skeleton Help File for a Module</TITLE>
|
||||||
|
<LINK rel="stylesheet" type="text/css" href="../../shared/Frontpage.css">
|
||||||
|
</HEAD>
|
||||||
|
|
||||||
|
<BODY>
|
||||||
|
<H1><a name="HelpAnchor"></a>Skeleton Help File for a Module</H1>
|
||||||
|
|
||||||
|
<P>This is a simple skeleton help topic. For a better description of what should and should not
|
||||||
|
go in here, see the "sample" Ghidra extension in the Extensions/Ghidra directory, or see your
|
||||||
|
favorite help topic. In general, language modules do not have their own help topics.</P>
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
||||||
43
deepcut-ghidra/src/main/java/deepcut/Cut.java
Normal file
43
deepcut-ghidra/src/main/java/deepcut/Cut.java
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/* ###
|
||||||
|
* © 2022 The Johns Hopkins University Applied Physics Laboratory LLC
|
||||||
|
* (JHU/APL).
|
||||||
|
*
|
||||||
|
* NO WARRANTY, NO LIABILITY. THIS MATERIAL IS PROVIDED “AS IS.” JHU/APL
|
||||||
|
* MAKES NO REPRESENTATION OR WARRANTY WITH RESPECT TO THE PERFORMANCE OF
|
||||||
|
* THE MATERIALS, INCLUDING THEIR SAFETY, EFFECTIVENESS, OR COMMERCIAL
|
||||||
|
* VIABILITY, AND DISCLAIMS ALL WARRANTIES IN THE MATERIAL, WHETHER
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING (BUT NOT LIMITED TO) ANY AND ALL IMPLIED
|
||||||
|
* WARRANTIES OF PERFORMANCE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE, AND NON-INFRINGEMENT OF INTELLECTUAL PROPERTY OR OTHER THIRD
|
||||||
|
* PARTY RIGHTS. ANY USER OF THE MATERIAL ASSUMES THE ENTIRE RISK AND
|
||||||
|
* LIABILITY FOR USING THE MATERIAL. IN NO EVENT SHALL JHU/APL BE LIABLE
|
||||||
|
* TO ANY USER OF THE MATERIAL FOR ANY ACTUAL, INDIRECT, CONSEQUENTIAL,
|
||||||
|
* SPECIAL OR OTHER DAMAGES ARISING FROM THE USE OF, OR INABILITY TO USE,
|
||||||
|
* THE MATERIAL, INCLUDING, BUT NOT LIMITED TO, ANY DAMAGES FOR LOST
|
||||||
|
* PROFITS.
|
||||||
|
*
|
||||||
|
* This material is based upon work supported by the Defense Advanced Research
|
||||||
|
* Projects Agency (DARPA) and Naval Information Warfare Center Pacific (NIWC Pacific)
|
||||||
|
* under Contract Number N66001-20-C-4024.
|
||||||
|
*
|
||||||
|
* HAVE A NICE DAY.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deepcut;
|
||||||
|
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
|
class Cut {
|
||||||
|
public String address;
|
||||||
|
public String name;
|
||||||
|
|
||||||
|
public Cut(Program program, String address, String name) {
|
||||||
|
this.address = address;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.address.toString() + ":" + this.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
165
deepcut-ghidra/src/main/java/deepcut/DeepCutAnalyzer.java
Normal file
165
deepcut-ghidra/src/main/java/deepcut/DeepCutAnalyzer.java
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/* ###
|
||||||
|
* © 2022 The Johns Hopkins University Applied Physics Laboratory LLC
|
||||||
|
* (JHU/APL).
|
||||||
|
*
|
||||||
|
* NO WARRANTY, NO LIABILITY. THIS MATERIAL IS PROVIDED “AS IS.” JHU/APL
|
||||||
|
* MAKES NO REPRESENTATION OR WARRANTY WITH RESPECT TO THE PERFORMANCE OF
|
||||||
|
* THE MATERIALS, INCLUDING THEIR SAFETY, EFFECTIVENESS, OR COMMERCIAL
|
||||||
|
* VIABILITY, AND DISCLAIMS ALL WARRANTIES IN THE MATERIAL, WHETHER
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING (BUT NOT LIMITED TO) ANY AND ALL IMPLIED
|
||||||
|
* WARRANTIES OF PERFORMANCE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE, AND NON-INFRINGEMENT OF INTELLECTUAL PROPERTY OR OTHER THIRD
|
||||||
|
* PARTY RIGHTS. ANY USER OF THE MATERIAL ASSUMES THE ENTIRE RISK AND
|
||||||
|
* LIABILITY FOR USING THE MATERIAL. IN NO EVENT SHALL JHU/APL BE LIABLE
|
||||||
|
* TO ANY USER OF THE MATERIAL FOR ANY ACTUAL, INDIRECT, CONSEQUENTIAL,
|
||||||
|
* SPECIAL OR OTHER DAMAGES ARISING FROM THE USE OF, OR INABILITY TO USE,
|
||||||
|
* THE MATERIAL, INCLUDING, BUT NOT LIMITED TO, ANY DAMAGES FOR LOST
|
||||||
|
* PROFITS.
|
||||||
|
*
|
||||||
|
* This material is based upon work supported by the Defense Advanced Research
|
||||||
|
* Projects Agency (DARPA) and Naval Information Warfare Center Pacific (NIWC Pacific)
|
||||||
|
* under Contract Number N66001-20-C-4024.
|
||||||
|
*
|
||||||
|
* HAVE A NICE DAY.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deepcut;
|
||||||
|
|
||||||
|
import ghidra.app.services.AbstractAnalyzer;
|
||||||
|
import ghidra.app.services.AnalysisPriority;
|
||||||
|
import ghidra.app.services.AnalyzerType;
|
||||||
|
import ghidra.app.util.importer.MessageLog;
|
||||||
|
import ghidra.app.util.opinion.ElfLoader;
|
||||||
|
import ghidra.framework.options.Options;
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.address.AddressFactory;
|
||||||
|
import ghidra.program.model.address.AddressSetView;
|
||||||
|
import ghidra.program.model.listing.CircularDependencyException;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.model.symbol.Namespace;
|
||||||
|
import ghidra.program.model.symbol.SourceType;
|
||||||
|
import ghidra.program.model.symbol.SymbolTable;
|
||||||
|
import ghidra.util.exception.CancelledException;
|
||||||
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
import ghidra.util.exception.InvalidInputException;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Provide class-level documentation that describes what this analyzer does.
|
||||||
|
*/
|
||||||
|
public class DeepCutAnalyzer extends AbstractAnalyzer {
|
||||||
|
private final static String NAME = "Deepcut";
|
||||||
|
private final static String DESCRIPTION = "Uses the deepcut algorithm to find module boundaries.";
|
||||||
|
|
||||||
|
private final static String OPTION_NAME_PYTHON_EXEC = "Python Executable";
|
||||||
|
private final static String OPTION_DESCRIPTION_PYTHON_EXEC = "";
|
||||||
|
private final static String OPTION_DEFAULT_PYTHON_EXEC = "/projects/venv/bin/python3";
|
||||||
|
private String pythonExec = OPTION_DEFAULT_PYTHON_EXEC;
|
||||||
|
|
||||||
|
public DeepCutAnalyzer() {
|
||||||
|
super(NAME, DESCRIPTION, AnalyzerType.FUNCTION_ANALYZER);
|
||||||
|
setDefaultEnablement(false);
|
||||||
|
setPriority(AnalysisPriority.REFERENCE_ANALYSIS.after());
|
||||||
|
setPrototype();
|
||||||
|
setSupportsOneTimeAnalysis();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getDefaultEnablement(Program program) {
|
||||||
|
// Only supports one-time analysis.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canAnalyze(Program program) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerOptions(Options options, Program program) {
|
||||||
|
options.registerOption(OPTION_NAME_PYTHON_EXEC, pythonExec,
|
||||||
|
null, OPTION_DESCRIPTION_PYTHON_EXEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void optionsChanged(Options options, Program program) {
|
||||||
|
pythonExec = options.getString(OPTION_NAME_PYTHON_EXEC, pythonExec);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkError(DeepCutPython deepcut, MessageLog log)
|
||||||
|
{
|
||||||
|
String error = deepcut.readProcessError();
|
||||||
|
if (!error.isEmpty()) {
|
||||||
|
log.appendMsg(error);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
||||||
|
throws CancelledException {
|
||||||
|
|
||||||
|
DeepCutPython deepcut = new DeepCutPython(pythonExec);
|
||||||
|
FunctionCallGraph fcg = new FunctionCallGraph(program, monitor);
|
||||||
|
|
||||||
|
try {
|
||||||
|
deepcut.startProcess();
|
||||||
|
|
||||||
|
if (checkError(deepcut, log)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
deepcut.writeProcess(fcg.toJson() + "\n");
|
||||||
|
deepcut.waitFor();
|
||||||
|
|
||||||
|
if (checkError(deepcut, log)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String cuts_json = deepcut.readProcessOutput();
|
||||||
|
|
||||||
|
|
||||||
|
Cut[] cuts = new GsonBuilder().create().fromJson(cuts_json, Cut[].class);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (FunctionInfo fi : fcg.getFunctionInfos()) {
|
||||||
|
AddressFactory af = program.getAddressFactory();
|
||||||
|
Address cutAddress = af.getAddress(cuts[i].address);
|
||||||
|
|
||||||
|
if (fi.getAddress().compareTo(cutAddress) == -1) {
|
||||||
|
addNamespace(program, "object" + i, fi.getFunction());
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
addNamespace(program, "object" + i, fi.getFunction());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.appendException(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void addNamespace(Program program, String name, Function function)
|
||||||
|
throws DuplicateNameException, InvalidInputException, CircularDependencyException {
|
||||||
|
SymbolTable symbolTable = program.getSymbolTable();
|
||||||
|
Namespace namespace = null;
|
||||||
|
|
||||||
|
namespace = symbolTable.getNamespace(name, null);
|
||||||
|
if(namespace == null) {
|
||||||
|
namespace = symbolTable.createNameSpace(null, name,
|
||||||
|
SourceType.USER_DEFINED);
|
||||||
|
}
|
||||||
|
|
||||||
|
function.setParentNamespace(namespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
102
deepcut-ghidra/src/main/java/deepcut/DeepCutPython.java
Normal file
102
deepcut-ghidra/src/main/java/deepcut/DeepCutPython.java
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/* ###
|
||||||
|
* © 2022 The Johns Hopkins University Applied Physics Laboratory LLC
|
||||||
|
* (JHU/APL).
|
||||||
|
*
|
||||||
|
* NO WARRANTY, NO LIABILITY. THIS MATERIAL IS PROVIDED “AS IS.” JHU/APL
|
||||||
|
* MAKES NO REPRESENTATION OR WARRANTY WITH RESPECT TO THE PERFORMANCE OF
|
||||||
|
* THE MATERIALS, INCLUDING THEIR SAFETY, EFFECTIVENESS, OR COMMERCIAL
|
||||||
|
* VIABILITY, AND DISCLAIMS ALL WARRANTIES IN THE MATERIAL, WHETHER
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING (BUT NOT LIMITED TO) ANY AND ALL IMPLIED
|
||||||
|
* WARRANTIES OF PERFORMANCE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE, AND NON-INFRINGEMENT OF INTELLECTUAL PROPERTY OR OTHER THIRD
|
||||||
|
* PARTY RIGHTS. ANY USER OF THE MATERIAL ASSUMES THE ENTIRE RISK AND
|
||||||
|
* LIABILITY FOR USING THE MATERIAL. IN NO EVENT SHALL JHU/APL BE LIABLE
|
||||||
|
* TO ANY USER OF THE MATERIAL FOR ANY ACTUAL, INDIRECT, CONSEQUENTIAL,
|
||||||
|
* SPECIAL OR OTHER DAMAGES ARISING FROM THE USE OF, OR INABILITY TO USE,
|
||||||
|
* THE MATERIAL, INCLUDING, BUT NOT LIMITED TO, ANY DAMAGES FOR LOST
|
||||||
|
* PROFITS.
|
||||||
|
*
|
||||||
|
* This material is based upon work supported by the Defense Advanced Research
|
||||||
|
* Projects Agency (DARPA) and Naval Information Warfare Center Pacific (NIWC Pacific)
|
||||||
|
* under Contract Number N66001-20-C-4024.
|
||||||
|
*
|
||||||
|
* HAVE A NICE DAY.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deepcut;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import ghidra.framework.Application;
|
||||||
|
|
||||||
|
public class DeepCutPython {
|
||||||
|
public Runtime runtime;
|
||||||
|
public String pythonExec;
|
||||||
|
|
||||||
|
public Process process;
|
||||||
|
public OutputStream stdin;
|
||||||
|
public InputStream stdout;
|
||||||
|
public InputStream stderr;
|
||||||
|
|
||||||
|
public DeepCutPython(String pythonExec) {
|
||||||
|
this.pythonExec = pythonExec;
|
||||||
|
this.runtime = Runtime.getRuntime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startProcess() throws IOException {
|
||||||
|
String pythonFile = Application.getModuleDataFile("deepcut.py").toString();
|
||||||
|
String modelFile = Application.getModuleDataFile("model_weights_1.p").toString();
|
||||||
|
|
||||||
|
//pythonFile = "/Users/desteaj1/Programs/AMP/deepcut/src/deepcut";
|
||||||
|
String[] exec = {pythonExec, pythonFile, modelFile};
|
||||||
|
|
||||||
|
process = runtime.exec(exec);
|
||||||
|
|
||||||
|
// Yes this is confusing. stdin is a Java OutputStream, stdin is an InputStream
|
||||||
|
stdin = process.getOutputStream();
|
||||||
|
stdout = process.getInputStream();
|
||||||
|
stderr = process.getErrorStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void waitFor() throws InterruptedException {
|
||||||
|
process.waitFor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeProcess(String data) throws IOException {
|
||||||
|
writeProcess(data.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeProcess(byte[] data) throws IOException {
|
||||||
|
stdin.write(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readProcessOutput() {
|
||||||
|
return readProcess(stdout);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readProcessError() {
|
||||||
|
return readProcess(stderr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readProcess(InputStream stream) {
|
||||||
|
String result = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (stream.available() > 0 ) {
|
||||||
|
result = new BufferedReader(new InputStreamReader(stream))
|
||||||
|
.lines().collect(Collectors.joining("\n"));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
91
deepcut-ghidra/src/main/java/deepcut/EdgeInfo.java
Normal file
91
deepcut-ghidra/src/main/java/deepcut/EdgeInfo.java
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/* ###
|
||||||
|
* © 2022 The Johns Hopkins University Applied Physics Laboratory LLC
|
||||||
|
* (JHU/APL).
|
||||||
|
*
|
||||||
|
* NO WARRANTY, NO LIABILITY. THIS MATERIAL IS PROVIDED “AS IS.” JHU/APL
|
||||||
|
* MAKES NO REPRESENTATION OR WARRANTY WITH RESPECT TO THE PERFORMANCE OF
|
||||||
|
* THE MATERIALS, INCLUDING THEIR SAFETY, EFFECTIVENESS, OR COMMERCIAL
|
||||||
|
* VIABILITY, AND DISCLAIMS ALL WARRANTIES IN THE MATERIAL, WHETHER
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING (BUT NOT LIMITED TO) ANY AND ALL IMPLIED
|
||||||
|
* WARRANTIES OF PERFORMANCE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE, AND NON-INFRINGEMENT OF INTELLECTUAL PROPERTY OR OTHER THIRD
|
||||||
|
* PARTY RIGHTS. ANY USER OF THE MATERIAL ASSUMES THE ENTIRE RISK AND
|
||||||
|
* LIABILITY FOR USING THE MATERIAL. IN NO EVENT SHALL JHU/APL BE LIABLE
|
||||||
|
* TO ANY USER OF THE MATERIAL FOR ANY ACTUAL, INDIRECT, CONSEQUENTIAL,
|
||||||
|
* SPECIAL OR OTHER DAMAGES ARISING FROM THE USE OF, OR INABILITY TO USE,
|
||||||
|
* THE MATERIAL, INCLUDING, BUT NOT LIMITED TO, ANY DAMAGES FOR LOST
|
||||||
|
* PROFITS.
|
||||||
|
*
|
||||||
|
* This material is based upon work supported by the Defense Advanced Research
|
||||||
|
* Projects Agency (DARPA) and Naval Information Warfare Center Pacific (NIWC Pacific)
|
||||||
|
* under Contract Number N66001-20-C-4024.
|
||||||
|
*
|
||||||
|
* HAVE A NICE DAY.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deepcut;
|
||||||
|
|
||||||
|
class EdgeInfo {
|
||||||
|
private FunctionInfo src;
|
||||||
|
private FunctionInfo dst;
|
||||||
|
|
||||||
|
private int multiplicity;
|
||||||
|
|
||||||
|
/*
|
||||||
|
distance between the two functions,
|
||||||
|
either in terms of address
|
||||||
|
or number of functions in between.
|
||||||
|
*/
|
||||||
|
private double addressDistance;
|
||||||
|
private double indexDistance;
|
||||||
|
|
||||||
|
private boolean isSelfCall;
|
||||||
|
|
||||||
|
public EdgeInfo(FunctionInfo src, FunctionInfo dst, int multiplicity) {
|
||||||
|
this.src = src;
|
||||||
|
this.dst = dst;
|
||||||
|
|
||||||
|
this.multiplicity = multiplicity;
|
||||||
|
|
||||||
|
this.addressDistance = (double) dst.getAddress().subtract(src.getAddress());
|
||||||
|
this.indexDistance = (double) dst.getAddressIndex() - src.getAddressIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FunctionInfo getSrc() {
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FunctionInfo getDst() {
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMultiplicity() {
|
||||||
|
return multiplicity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getAddressDistance() {
|
||||||
|
return addressDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getIndexDistance() {
|
||||||
|
return indexDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getisSelfCall() {
|
||||||
|
return isSelfCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSrcAddressIndex() {
|
||||||
|
return src.getAddressIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getDstAddressIndex() {
|
||||||
|
return dst.getAddressIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%-20s -> %20-s\t#%d", src.getName(),
|
||||||
|
dst.getName(), multiplicity);
|
||||||
|
}
|
||||||
|
}
|
||||||
48
deepcut-ghidra/src/main/java/deepcut/EdgeInfoSerializer.java
Normal file
48
deepcut-ghidra/src/main/java/deepcut/EdgeInfoSerializer.java
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/* ###
|
||||||
|
* © 2022 The Johns Hopkins University Applied Physics Laboratory LLC
|
||||||
|
* (JHU/APL).
|
||||||
|
*
|
||||||
|
* NO WARRANTY, NO LIABILITY. THIS MATERIAL IS PROVIDED “AS IS.” JHU/APL
|
||||||
|
* MAKES NO REPRESENTATION OR WARRANTY WITH RESPECT TO THE PERFORMANCE OF
|
||||||
|
* THE MATERIALS, INCLUDING THEIR SAFETY, EFFECTIVENESS, OR COMMERCIAL
|
||||||
|
* VIABILITY, AND DISCLAIMS ALL WARRANTIES IN THE MATERIAL, WHETHER
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING (BUT NOT LIMITED TO) ANY AND ALL IMPLIED
|
||||||
|
* WARRANTIES OF PERFORMANCE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE, AND NON-INFRINGEMENT OF INTELLECTUAL PROPERTY OR OTHER THIRD
|
||||||
|
* PARTY RIGHTS. ANY USER OF THE MATERIAL ASSUMES THE ENTIRE RISK AND
|
||||||
|
* LIABILITY FOR USING THE MATERIAL. IN NO EVENT SHALL JHU/APL BE LIABLE
|
||||||
|
* TO ANY USER OF THE MATERIAL FOR ANY ACTUAL, INDIRECT, CONSEQUENTIAL,
|
||||||
|
* SPECIAL OR OTHER DAMAGES ARISING FROM THE USE OF, OR INABILITY TO USE,
|
||||||
|
* THE MATERIAL, INCLUDING, BUT NOT LIMITED TO, ANY DAMAGES FOR LOST
|
||||||
|
* PROFITS.
|
||||||
|
*
|
||||||
|
* This material is based upon work supported by the Defense Advanced Research
|
||||||
|
* Projects Agency (DARPA) and Naval Information Warfare Center Pacific (NIWC Pacific)
|
||||||
|
* under Contract Number N66001-20-C-4024.
|
||||||
|
*
|
||||||
|
* HAVE A NICE DAY.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deepcut;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonSerializationContext;
|
||||||
|
import com.google.gson.JsonSerializer;
|
||||||
|
|
||||||
|
class EdgeInfoSerializer implements JsonSerializer<EdgeInfo> {
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(EdgeInfo src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
|
JsonObject obj = new JsonObject();
|
||||||
|
|
||||||
|
obj.addProperty("src_index", src.getSrcAddressIndex());
|
||||||
|
obj.addProperty("dst_index", src.getDstAddressIndex());
|
||||||
|
obj.addProperty("multiplicity", src.getMultiplicity());
|
||||||
|
obj.addProperty("addr_distance", src.getAddressDistance());
|
||||||
|
obj.addProperty("index_distance", src.getIndexDistance());
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
211
deepcut-ghidra/src/main/java/deepcut/FunctionCallGraph.java
Normal file
211
deepcut-ghidra/src/main/java/deepcut/FunctionCallGraph.java
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
/* ###
|
||||||
|
* © 2022 The Johns Hopkins University Applied Physics Laboratory LLC
|
||||||
|
* (JHU/APL).
|
||||||
|
*
|
||||||
|
* NO WARRANTY, NO LIABILITY. THIS MATERIAL IS PROVIDED “AS IS.” JHU/APL
|
||||||
|
* MAKES NO REPRESENTATION OR WARRANTY WITH RESPECT TO THE PERFORMANCE OF
|
||||||
|
* THE MATERIALS, INCLUDING THEIR SAFETY, EFFECTIVENESS, OR COMMERCIAL
|
||||||
|
* VIABILITY, AND DISCLAIMS ALL WARRANTIES IN THE MATERIAL, WHETHER
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING (BUT NOT LIMITED TO) ANY AND ALL IMPLIED
|
||||||
|
* WARRANTIES OF PERFORMANCE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE, AND NON-INFRINGEMENT OF INTELLECTUAL PROPERTY OR OTHER THIRD
|
||||||
|
* PARTY RIGHTS. ANY USER OF THE MATERIAL ASSUMES THE ENTIRE RISK AND
|
||||||
|
* LIABILITY FOR USING THE MATERIAL. IN NO EVENT SHALL JHU/APL BE LIABLE
|
||||||
|
* TO ANY USER OF THE MATERIAL FOR ANY ACTUAL, INDIRECT, CONSEQUENTIAL,
|
||||||
|
* SPECIAL OR OTHER DAMAGES ARISING FROM THE USE OF, OR INABILITY TO USE,
|
||||||
|
* THE MATERIAL, INCLUDING, BUT NOT LIMITED TO, ANY DAMAGES FOR LOST
|
||||||
|
* PROFITS.
|
||||||
|
*
|
||||||
|
* This material is based upon work supported by the Defense Advanced Research
|
||||||
|
* Projects Agency (DARPA) and Naval Information Warfare Center Pacific (NIWC Pacific)
|
||||||
|
* under Contract Number N66001-20-C-4024.
|
||||||
|
*
|
||||||
|
* HAVE A NICE DAY.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deepcut;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.annotations.*;
|
||||||
|
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
import ghidra.program.flatapi.FlatProgramAPI;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
import ghidra.program.model.listing.FunctionIterator;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.model.symbol.RefType;
|
||||||
|
import ghidra.program.model.symbol.Reference;
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionCallGraph {
|
||||||
|
private TaskMonitor monitor;
|
||||||
|
private Program program;
|
||||||
|
private FlatProgramAPI api;
|
||||||
|
|
||||||
|
// map from ghidra functions to my function class.
|
||||||
|
public Map<Function, FunctionInfo> functionMap;
|
||||||
|
|
||||||
|
// list of functions, sorted by address
|
||||||
|
@Expose(serialize = true)
|
||||||
|
@SerializedName(value="functions")
|
||||||
|
public List<FunctionInfo> functionList;
|
||||||
|
|
||||||
|
// Adjacency list of edges
|
||||||
|
@Expose(serialize = true)
|
||||||
|
@SerializedName(value="edges")
|
||||||
|
public List<EdgeInfo> edgeList;
|
||||||
|
|
||||||
|
|
||||||
|
public FunctionCallGraph(Program program, TaskMonitor monitor) {
|
||||||
|
this.program = program;
|
||||||
|
this.monitor = monitor;
|
||||||
|
api = new FlatProgramAPI(program);
|
||||||
|
|
||||||
|
functionList = new ArrayList<FunctionInfo>();
|
||||||
|
functionMap = new HashMap<Function, FunctionInfo>();
|
||||||
|
edgeList = new ArrayList<EdgeInfo>();
|
||||||
|
|
||||||
|
createListOfFunctions();
|
||||||
|
createListOfEdges();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createListOfFunctions() {
|
||||||
|
// Returns an iterator over all non-external functions in address (entry point) order.
|
||||||
|
FunctionIterator iter = program.getFunctionManager().getFunctions(true);
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Function function = iter.next();
|
||||||
|
|
||||||
|
FunctionInfo func_info = new FunctionInfo(function);
|
||||||
|
func_info.setAddressIndex(index++);
|
||||||
|
|
||||||
|
functionList.add(func_info);
|
||||||
|
functionMap.put(function, func_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createListOfEdges() {
|
||||||
|
for (FunctionInfo func_info : functionList) {
|
||||||
|
Function function = func_info.getFunction();
|
||||||
|
|
||||||
|
Map<Function, Integer> hm = getCountCallingFunctions(function);
|
||||||
|
|
||||||
|
for (Map.Entry<Function, Integer> val : hm.entrySet()) {
|
||||||
|
Function src = val.getKey();
|
||||||
|
int multiplicity = val.getValue();
|
||||||
|
|
||||||
|
// no idea why, but sometimes `src` is null.
|
||||||
|
if (src == null) continue;
|
||||||
|
|
||||||
|
// set the `is_recursive` flag if the function calls itself
|
||||||
|
if(function.equals(src)) {
|
||||||
|
func_info.setIsRecursive(true);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the edge and add it to each list.
|
||||||
|
FunctionInfo src_func_info = functionMap.get(src);
|
||||||
|
EdgeInfo edge_info = new EdgeInfo(src_func_info, func_info, multiplicity);
|
||||||
|
edgeList.add(edge_info);
|
||||||
|
func_info.addIncomingEdge(edge_info);
|
||||||
|
src_func_info.addOutgoingEdge(edge_info);
|
||||||
|
}
|
||||||
|
// remove the recursive call, if applicable.
|
||||||
|
// Note: does nothing if `function` not in `hm`
|
||||||
|
hm.remove(function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
return a hashmap of the number of times each function calls this function.
|
||||||
|
*/
|
||||||
|
private Map<Function, Integer> getCountCallingFunctions(Function function) {
|
||||||
|
|
||||||
|
// hashmap to store the frequency of element
|
||||||
|
Map<Function, Integer> hm = new HashMap<Function, Integer>();
|
||||||
|
|
||||||
|
/*
|
||||||
|
first populate the hashmap with all the calling functions.
|
||||||
|
this is needed b/c `getCallingFunctions` returns some functions which
|
||||||
|
`getReferencesTo` doesn't pick up on.
|
||||||
|
|
||||||
|
I think this is b/c `getCallingFunctions` just tracks any xref.
|
||||||
|
*/
|
||||||
|
Set<Function> calling_funcs = function.getCallingFunctions(monitor);
|
||||||
|
|
||||||
|
for (Function f : calling_funcs) {
|
||||||
|
hm.put(f, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// then populate the counts
|
||||||
|
Address entryPoint = function.getEntryPoint();
|
||||||
|
Reference[] references = api.getReferencesTo(entryPoint);
|
||||||
|
|
||||||
|
ArrayList<Function> func_list = new ArrayList<Function>();
|
||||||
|
|
||||||
|
for(Reference r : references) {
|
||||||
|
RefType rt = r.getReferenceType();
|
||||||
|
boolean xref_is_call = rt.isCall() || rt.isJump();
|
||||||
|
if (xref_is_call) {
|
||||||
|
Address toAddress = r.getFromAddress();
|
||||||
|
Function func = api.getFunctionContaining(toAddress);
|
||||||
|
func_list.add(func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Function f : func_list) {
|
||||||
|
Integer j = hm.get(f);
|
||||||
|
hm.put(f, (j == null) ? 1 : j + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FunctionInfo> getFunctionInfos() {
|
||||||
|
return functionList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toJson() {
|
||||||
|
Gson gson = new GsonBuilder()
|
||||||
|
.excludeFieldsWithoutExposeAnnotation()
|
||||||
|
.registerTypeAdapter(FunctionInfo.class, new FunctionInfoSerializer())
|
||||||
|
.registerTypeAdapter(EdgeInfo.class, new EdgeInfoSerializer())
|
||||||
|
.create();
|
||||||
|
|
||||||
|
return gson.toJson(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder str = new StringBuilder();
|
||||||
|
str.append("Function List:\n");
|
||||||
|
|
||||||
|
for(FunctionInfo fi : functionList) {
|
||||||
|
str.append("{\"name\": \"" + fi.getName() +
|
||||||
|
"\", \"addr\": \"0x" + fi.getAddress() +
|
||||||
|
"\", \"idx\": " + fi.getAddressIndex() +
|
||||||
|
", \"num_incoming_edges\": " + fi.getIncomingEdges().size() +
|
||||||
|
", \"num_outgoing_edges\": " + fi.getOutgoingEdges().size() + "}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
str.append("\nEdge List:\n");
|
||||||
|
for(EdgeInfo ei : edgeList) {
|
||||||
|
str.append("{\"src_idx\": " + ei.getSrc().getAddressIndex() +
|
||||||
|
", \"dst_idx\": " + ei.getDst().getAddressIndex() +
|
||||||
|
", \"multiplicity\": " + ei.getMultiplicity() +
|
||||||
|
", \"addr_dst\": " + ei.getAddressDistance() +
|
||||||
|
", \"idx_dst\": " + ei.getIndexDistance() + "}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
129
deepcut-ghidra/src/main/java/deepcut/FunctionInfo.java
Normal file
129
deepcut-ghidra/src/main/java/deepcut/FunctionInfo.java
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/* ###
|
||||||
|
* © 2022 The Johns Hopkins University Applied Physics Laboratory LLC
|
||||||
|
* (JHU/APL).
|
||||||
|
*
|
||||||
|
* NO WARRANTY, NO LIABILITY. THIS MATERIAL IS PROVIDED “AS IS.” JHU/APL
|
||||||
|
* MAKES NO REPRESENTATION OR WARRANTY WITH RESPECT TO THE PERFORMANCE OF
|
||||||
|
* THE MATERIALS, INCLUDING THEIR SAFETY, EFFECTIVENESS, OR COMMERCIAL
|
||||||
|
* VIABILITY, AND DISCLAIMS ALL WARRANTIES IN THE MATERIAL, WHETHER
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING (BUT NOT LIMITED TO) ANY AND ALL IMPLIED
|
||||||
|
* WARRANTIES OF PERFORMANCE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE, AND NON-INFRINGEMENT OF INTELLECTUAL PROPERTY OR OTHER THIRD
|
||||||
|
* PARTY RIGHTS. ANY USER OF THE MATERIAL ASSUMES THE ENTIRE RISK AND
|
||||||
|
* LIABILITY FOR USING THE MATERIAL. IN NO EVENT SHALL JHU/APL BE LIABLE
|
||||||
|
* TO ANY USER OF THE MATERIAL FOR ANY ACTUAL, INDIRECT, CONSEQUENTIAL,
|
||||||
|
* SPECIAL OR OTHER DAMAGES ARISING FROM THE USE OF, OR INABILITY TO USE,
|
||||||
|
* THE MATERIAL, INCLUDING, BUT NOT LIMITED TO, ANY DAMAGES FOR LOST
|
||||||
|
* PROFITS.
|
||||||
|
*
|
||||||
|
* This material is based upon work supported by the Defense Advanced Research
|
||||||
|
* Projects Agency (DARPA) and Naval Information Warfare Center Pacific (NIWC Pacific)
|
||||||
|
* under Contract Number N66001-20-C-4024.
|
||||||
|
*
|
||||||
|
* HAVE A NICE DAY.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deepcut;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.listing.Function;
|
||||||
|
|
||||||
|
class FunctionInfo {
|
||||||
|
private Function function;
|
||||||
|
|
||||||
|
private Address address;
|
||||||
|
private long addressIndex;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
// `true` if the function is either external or a thunk function.
|
||||||
|
private boolean isExternalThunk;
|
||||||
|
|
||||||
|
private List<EdgeInfo> incomingEdges;
|
||||||
|
private List<EdgeInfo> outgoingEdges;
|
||||||
|
|
||||||
|
// `true` if the function ever calls itself
|
||||||
|
private boolean isRecursive;
|
||||||
|
|
||||||
|
public FunctionInfo(Function function) {
|
||||||
|
this.function = function;
|
||||||
|
address = function.getEntryPoint();
|
||||||
|
name = function.getName();
|
||||||
|
|
||||||
|
// will be set in a later pass
|
||||||
|
addressIndex = -1;
|
||||||
|
isRecursive = false;
|
||||||
|
|
||||||
|
isExternalThunk = function.isThunk() || function.isExternal() ||
|
||||||
|
(!function.getParentNamespace().isGlobal());
|
||||||
|
|
||||||
|
incomingEdges = new ArrayList<EdgeInfo>();
|
||||||
|
outgoingEdges = new ArrayList<EdgeInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addIncomingEdge(EdgeInfo edge) {
|
||||||
|
incomingEdges.add(edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<EdgeInfo> getIncomingEdges() {
|
||||||
|
return incomingEdges;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIncomingEdgeSize() {
|
||||||
|
return incomingEdges.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addOutgoingEdge(EdgeInfo edge) {
|
||||||
|
outgoingEdges.add(edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<EdgeInfo> getOutgoingEdges() {
|
||||||
|
return outgoingEdges;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOutgoingEdgeSize() {
|
||||||
|
return outgoingEdges.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Function getFunction() {
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsRecursive(boolean val) {
|
||||||
|
isRecursive = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getIsRecursive() {
|
||||||
|
return isRecursive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddress(Address address) {
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddressIndex(int index) {
|
||||||
|
this.addressIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getAddressIndex() {
|
||||||
|
return addressIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getFunction().getName() + " " + address +
|
||||||
|
" (" + addressIndex + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/* ###
|
||||||
|
* © 2022 The Johns Hopkins University Applied Physics Laboratory LLC
|
||||||
|
* (JHU/APL).
|
||||||
|
*
|
||||||
|
* NO WARRANTY, NO LIABILITY. THIS MATERIAL IS PROVIDED “AS IS.” JHU/APL
|
||||||
|
* MAKES NO REPRESENTATION OR WARRANTY WITH RESPECT TO THE PERFORMANCE OF
|
||||||
|
* THE MATERIALS, INCLUDING THEIR SAFETY, EFFECTIVENESS, OR COMMERCIAL
|
||||||
|
* VIABILITY, AND DISCLAIMS ALL WARRANTIES IN THE MATERIAL, WHETHER
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING (BUT NOT LIMITED TO) ANY AND ALL IMPLIED
|
||||||
|
* WARRANTIES OF PERFORMANCE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE, AND NON-INFRINGEMENT OF INTELLECTUAL PROPERTY OR OTHER THIRD
|
||||||
|
* PARTY RIGHTS. ANY USER OF THE MATERIAL ASSUMES THE ENTIRE RISK AND
|
||||||
|
* LIABILITY FOR USING THE MATERIAL. IN NO EVENT SHALL JHU/APL BE LIABLE
|
||||||
|
* TO ANY USER OF THE MATERIAL FOR ANY ACTUAL, INDIRECT, CONSEQUENTIAL,
|
||||||
|
* SPECIAL OR OTHER DAMAGES ARISING FROM THE USE OF, OR INABILITY TO USE,
|
||||||
|
* THE MATERIAL, INCLUDING, BUT NOT LIMITED TO, ANY DAMAGES FOR LOST
|
||||||
|
* PROFITS.
|
||||||
|
*
|
||||||
|
* This material is based upon work supported by the Defense Advanced Research
|
||||||
|
* Projects Agency (DARPA) and Naval Information Warfare Center Pacific (NIWC Pacific)
|
||||||
|
* under Contract Number N66001-20-C-4024.
|
||||||
|
*
|
||||||
|
* HAVE A NICE DAY.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package deepcut;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonSerializationContext;
|
||||||
|
import com.google.gson.JsonSerializer;
|
||||||
|
|
||||||
|
class FunctionInfoSerializer implements JsonSerializer<FunctionInfo> {
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(FunctionInfo src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
|
JsonObject obj = new JsonObject();
|
||||||
|
obj.addProperty("name", src.getName());
|
||||||
|
obj.addProperty("addr", src.getAddress().toString());
|
||||||
|
obj.addProperty("index", src.getAddressIndex());
|
||||||
|
obj.addProperty("num_incoming_edges", src.getIncomingEdges().size());
|
||||||
|
obj.addProperty("num_outgoing_edges", src.getOutgoingEdges().size());
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
2
deepcut-ghidra/src/main/resources/images/README.txt
Normal file
2
deepcut-ghidra/src/main/resources/images/README.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
The "src/resources/images" directory is intended to hold all image/icon files used by
|
||||||
|
this module.
|
||||||
2
deepcut-ghidra/src/test/java/README.test.txt
Normal file
2
deepcut-ghidra/src/test/java/README.test.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
The "test" directory is intended to hold unit test cases. The package structure within
|
||||||
|
this folder should correspond to that found in the "src" folder.
|
||||||
Reference in New Issue
Block a user