Unverified Commit a1c1026d by Enkelmann Committed by GitHub

switch to Ghidra 10.2 (#368)

Note that this is a breaking change in the sense that Ghidra >= 10.2 is now required, older versions of Ghidra will not work anymore.
parent 1ebd9bcb
......@@ -8,8 +8,8 @@ on:
env:
CARGO_TERM_COLOR: always
GHIDRA_RELEASE_TAG: Ghidra_10.1.5_build
GHIDRA_VERSION: ghidra_10.1.5_PUBLIC_20220726
GHIDRA_RELEASE_TAG: Ghidra_10.2.2_build
GHIDRA_VERSION: ghidra_10.2.2_PUBLIC_20221115
jobs:
......@@ -25,7 +25,7 @@ jobs:
docker run --rm -v $(pwd)/build:/home/cwe/artificial_samples/build cross_compiling sudo python3 -m SCons
- uses: actions/setup-java@v1
with:
java-version: "11.0.x"
java-version: "17.0.x"
java-package: jdk
architecture: x64
- name: Install Ghidra
......
......@@ -5,7 +5,7 @@ WORKDIR /cwe_checker
COPY . .
RUN cargo build --release
FROM fkiecad/ghidra_headless_base:10.1.2 as runtime
FROM fkiecad/ghidra_headless_base:10.2.2 as runtime
RUN apt-get -y update \
&& apt-get -y install sudo \
......
......@@ -53,7 +53,7 @@ The prebuilt Docker images on dockerhub are currently only x86-based.
The following dependencies must be installed in order to build and install the *cwe_checker* locally:
- [Rust](https://www.rust-lang.org) >= 1.63
- [Ghidra](https://ghidra-sre.org/) >= 10.1.2
- [Ghidra](https://ghidra-sre.org/) >= 10.2 (**Warning:** This applies to the master branch, the v0.6 stable release needs Ghidra 10.1.5)
Run `make all GHIDRA_PATH=/path/to/ghidra_folder` (with the correct path to the local Ghidra installation inserted) to compile and install the cwe_checker.
If you omit the `GHIDRA_PATH` argument the installer will search your file system for a local installation of Ghidra.
......
......@@ -538,7 +538,7 @@ fn compute_intersection_residue_class(
// ```
let (gcd, left_inverse, right_inverse) = extended_gcd(stride_left, stride_right);
if base_left as i128 % gcd != base_right as i128 % gcd {
if base_left % gcd != base_right % gcd {
// The residue classes do not intersect, thus the intersection is empty.
Ok(None)
} else {
......
......@@ -255,16 +255,9 @@ impl<T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>> State<T>
/// Returns a vector of all currently tracked pointers.
pub fn collect_all_tracked_pointers(&self) -> Vec<DataDomain<IntervalDomain>> {
let mut pointers: Vec<DataDomain<IntervalDomain>> = self
.stack_offset_to_pointer_map
.iter()
.map(|(_, pointer)| pointer.clone())
.collect();
let mut var_pointers = self
.variable_to_pointer_map
.iter()
.map(|(_, pointer)| pointer.clone())
.collect();
let mut pointers: Vec<DataDomain<IntervalDomain>> =
self.stack_offset_to_pointer_map.values().cloned().collect();
let mut var_pointers = self.variable_to_pointer_map.values().cloned().collect();
let mut unassigned_pointers: Vec<DataDomain<IntervalDomain>> =
self.unassigned_return_pointer.iter().cloned().collect_vec();
pointers.append(&mut var_pointers);
......
......@@ -121,7 +121,7 @@ pub fn check_cwe(
_ => panic!(),
};
}
let cwe_warnings = cwe_warnings.into_iter().map(|(_, cwe)| cwe).collect();
let cwe_warnings = cwe_warnings.into_values().collect();
(Vec::new(), cwe_warnings)
}
......@@ -138,7 +138,7 @@ pub fn check_cwe(
};
}
let cwe_warnings = cwe_warnings.into_iter().map(|(_, cwe)| cwe).collect();
let cwe_warnings = cwe_warnings.into_values().collect();
let log_messages = log_receiver.try_iter().collect();
(log_messages, cwe_warnings)
......
......@@ -294,7 +294,7 @@ impl Blk {
};
if input.address.is_some() {
let temp_register_name = format!("$load_temp{}", index);
let load_def = input.to_load_def(&temp_register_name, generic_pointer_size);
let load_def = input.to_load_def(temp_register_name, generic_pointer_size);
*input = load_def.lhs.clone().unwrap();
refactored_defs.push(Term {
tid: jmp.tid.clone().with_id_suffix("_load"),
......
......@@ -377,10 +377,7 @@ impl LogThread {
.cloned()
.chain(general_logs.into_iter())
.collect();
let cwes = collected_cwes
.into_iter()
.map(|(_key, value)| value)
.collect();
let cwes = collected_cwes.into_values().collect();
(logs, cwes)
}
}
......@@ -261,7 +261,7 @@ public final class HelperFunctions {
regProps.add(
new RegisterProperties(reg.getName(),
reg.getBaseRegister().getName(),
(int)(reg.getLeastSignificatBitInBaseRegister() / 8),
(int)(reg.getLeastSignificantBitInBaseRegister() / 8),
context.getRegisterVarnode(reg).getSize())
);
}
......
......@@ -313,6 +313,33 @@ public class ParseCspecContent {
/**
*
* @param parser: parser for .cspec file
* @param integerRegisters: the list of known integer registers
* @param floatRegisters: the list of known float registers
*
* Parses a single parameter from the given parser and adds it either to the list of integer registers
* or to the list of float registers
*/
public static void parseSingleRegister(XmlPullParser parser, ArrayList<String> integerRegisters, ArrayList<String> floatRegisters) {
XmlElement pentry = parser.peek();
parser.start("pentry");
XmlElement entry = parser.peek();
if(entry.getName().equals("register")) {
parser.start("register");
if(isFloatRegister(pentry)) {
floatRegisters.add(entry.getAttribute("name"));
} else {
integerRegisters.add(entry.getAttribute("name"));
}
parser.end();
} else {
discardSubTree(parser);
}
parser.end();
}
/**
*
* @param parser: parser for .cspec file
* @param convention: convention object for later serialization
*
* Parses the parameter registers for an external symbol.
......@@ -323,21 +350,15 @@ public class ParseCspecContent {
ArrayList<String> floatRegisters = new ArrayList<String>();
parser.start("input");
while(parser.peek().isStart()) {
XmlElement pentry = parser.peek();
parser.start("pentry");
XmlElement entry = parser.peek();
if(entry.getName().equals("register")) {
parser.start("register");
if(isFloatRegister(pentry)) {
floatRegisters.add(entry.getAttribute("name"));
} else {
integerRegisters.add(entry.getAttribute("name"));
if(parser.softStart("group") != null) {
// The x86-64-win.cspec file has some registers that are additionally nested in "group" items
while(parser.peek().isStart()) {
parseSingleRegister(parser, integerRegisters, floatRegisters);
}
parser.end();
} else {
discardSubTree(parser);
parseSingleRegister(parser, integerRegisters, floatRegisters);
}
parser.end();
}
parser.end();
......
......@@ -34,7 +34,7 @@ struct GhidraConfig {
fn copy_config_json(location: &Path) -> Result<()> {
let repo_dir = env::current_dir().unwrap();
std::fs::copy(
&repo_dir.join("src/config.json"),
repo_dir.join("src/config.json"),
location.join("config.json"),
)?;
Ok(())
......@@ -82,7 +82,7 @@ fn get_search_locations() -> Vec<PathBuf> {
fn find_ghidra() -> Result<PathBuf> {
let mut ghidra_locations: Vec<PathBuf> = get_search_locations()
.into_iter()
.filter_map(|x| search_for_ghidrarun(&x))
.flat_map(|x| search_for_ghidrarun(&x))
.collect();
ghidra_locations.sort();
......@@ -95,20 +95,31 @@ fn find_ghidra() -> Result<PathBuf> {
}
}
/// check whether a path starts with ".", indicating a hidden file or folder on Linux.
fn is_hidden(path: &walkdir::DirEntry) -> bool {
path.file_name()
.to_str()
.map(|s| s.starts_with('.'))
.unwrap_or(false)
}
/// Searches for a file containing "ghidraRun" at provided path recursively.
fn search_for_ghidrarun(entry_path: &Path) -> Option<PathBuf> {
fn search_for_ghidrarun(entry_path: &Path) -> Vec<PathBuf> {
let mut hits = Vec::new();
for entry in WalkDir::new(entry_path)
.max_depth(8)
.into_iter()
.filter_entry(|e| !is_hidden(e))
.filter_map(|e| e.ok())
.filter(|e| e.metadata().unwrap().is_file())
{
if entry.file_name().to_str().unwrap() == "ghidraRun" {
let mut hit = entry.into_path();
hit.pop();
return Some(hit);
hits.push(hit);
}
}
None
hits
}
/// Determines if a path is a ghidra installation
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment