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: ...@@ -8,8 +8,8 @@ on:
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
GHIDRA_RELEASE_TAG: Ghidra_10.1.5_build GHIDRA_RELEASE_TAG: Ghidra_10.2.2_build
GHIDRA_VERSION: ghidra_10.1.5_PUBLIC_20220726 GHIDRA_VERSION: ghidra_10.2.2_PUBLIC_20221115
jobs: jobs:
...@@ -25,7 +25,7 @@ jobs: ...@@ -25,7 +25,7 @@ jobs:
docker run --rm -v $(pwd)/build:/home/cwe/artificial_samples/build cross_compiling sudo python3 -m SCons docker run --rm -v $(pwd)/build:/home/cwe/artificial_samples/build cross_compiling sudo python3 -m SCons
- uses: actions/setup-java@v1 - uses: actions/setup-java@v1
with: with:
java-version: "11.0.x" java-version: "17.0.x"
java-package: jdk java-package: jdk
architecture: x64 architecture: x64
- name: Install Ghidra - name: Install Ghidra
......
...@@ -5,7 +5,7 @@ WORKDIR /cwe_checker ...@@ -5,7 +5,7 @@ WORKDIR /cwe_checker
COPY . . COPY . .
RUN cargo build --release 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 \ RUN apt-get -y update \
&& apt-get -y install sudo \ && apt-get -y install sudo \
......
...@@ -53,7 +53,7 @@ The prebuilt Docker images on dockerhub are currently only x86-based. ...@@ -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: The following dependencies must be installed in order to build and install the *cwe_checker* locally:
- [Rust](https://www.rust-lang.org) >= 1.63 - [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. 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. 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( ...@@ -538,7 +538,7 @@ fn compute_intersection_residue_class(
// ``` // ```
let (gcd, left_inverse, right_inverse) = extended_gcd(stride_left, stride_right); 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. // The residue classes do not intersect, thus the intersection is empty.
Ok(None) Ok(None)
} else { } else {
......
...@@ -255,16 +255,9 @@ impl<T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>> State<T> ...@@ -255,16 +255,9 @@ impl<T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>> State<T>
/// Returns a vector of all currently tracked pointers. /// Returns a vector of all currently tracked pointers.
pub fn collect_all_tracked_pointers(&self) -> Vec<DataDomain<IntervalDomain>> { pub fn collect_all_tracked_pointers(&self) -> Vec<DataDomain<IntervalDomain>> {
let mut pointers: Vec<DataDomain<IntervalDomain>> = self let mut pointers: Vec<DataDomain<IntervalDomain>> =
.stack_offset_to_pointer_map self.stack_offset_to_pointer_map.values().cloned().collect();
.iter() let mut var_pointers = self.variable_to_pointer_map.values().cloned().collect();
.map(|(_, pointer)| pointer.clone())
.collect();
let mut var_pointers = self
.variable_to_pointer_map
.iter()
.map(|(_, pointer)| pointer.clone())
.collect();
let mut unassigned_pointers: Vec<DataDomain<IntervalDomain>> = let mut unassigned_pointers: Vec<DataDomain<IntervalDomain>> =
self.unassigned_return_pointer.iter().cloned().collect_vec(); self.unassigned_return_pointer.iter().cloned().collect_vec();
pointers.append(&mut var_pointers); pointers.append(&mut var_pointers);
......
...@@ -121,7 +121,7 @@ pub fn check_cwe( ...@@ -121,7 +121,7 @@ pub fn check_cwe(
_ => panic!(), _ => panic!(),
}; };
} }
let cwe_warnings = cwe_warnings.into_iter().map(|(_, cwe)| cwe).collect(); let cwe_warnings = cwe_warnings.into_values().collect();
(Vec::new(), cwe_warnings) (Vec::new(), cwe_warnings)
} }
...@@ -138,7 +138,7 @@ pub fn check_cwe( ...@@ -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(); let log_messages = log_receiver.try_iter().collect();
(log_messages, cwe_warnings) (log_messages, cwe_warnings)
......
...@@ -294,7 +294,7 @@ impl Blk { ...@@ -294,7 +294,7 @@ impl Blk {
}; };
if input.address.is_some() { if input.address.is_some() {
let temp_register_name = format!("$load_temp{}", index); 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(); *input = load_def.lhs.clone().unwrap();
refactored_defs.push(Term { refactored_defs.push(Term {
tid: jmp.tid.clone().with_id_suffix("_load"), tid: jmp.tid.clone().with_id_suffix("_load"),
......
...@@ -377,10 +377,7 @@ impl LogThread { ...@@ -377,10 +377,7 @@ impl LogThread {
.cloned() .cloned()
.chain(general_logs.into_iter()) .chain(general_logs.into_iter())
.collect(); .collect();
let cwes = collected_cwes let cwes = collected_cwes.into_values().collect();
.into_iter()
.map(|(_key, value)| value)
.collect();
(logs, cwes) (logs, cwes)
} }
} }
...@@ -261,7 +261,7 @@ public final class HelperFunctions { ...@@ -261,7 +261,7 @@ public final class HelperFunctions {
regProps.add( regProps.add(
new RegisterProperties(reg.getName(), new RegisterProperties(reg.getName(),
reg.getBaseRegister().getName(), reg.getBaseRegister().getName(),
(int)(reg.getLeastSignificatBitInBaseRegister() / 8), (int)(reg.getLeastSignificantBitInBaseRegister() / 8),
context.getRegisterVarnode(reg).getSize()) context.getRegisterVarnode(reg).getSize())
); );
} }
......
...@@ -313,6 +313,33 @@ public class ParseCspecContent { ...@@ -313,6 +313,33 @@ public class ParseCspecContent {
/** /**
* *
* @param parser: parser for .cspec file * @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 * @param convention: convention object for later serialization
* *
* Parses the parameter registers for an external symbol. * Parses the parameter registers for an external symbol.
...@@ -323,21 +350,15 @@ public class ParseCspecContent { ...@@ -323,21 +350,15 @@ public class ParseCspecContent {
ArrayList<String> floatRegisters = new ArrayList<String>(); ArrayList<String> floatRegisters = new ArrayList<String>();
parser.start("input"); parser.start("input");
while(parser.peek().isStart()) { while(parser.peek().isStart()) {
XmlElement pentry = parser.peek(); if(parser.softStart("group") != null) {
parser.start("pentry"); // The x86-64-win.cspec file has some registers that are additionally nested in "group" items
XmlElement entry = parser.peek(); while(parser.peek().isStart()) {
if(entry.getName().equals("register")) { parseSingleRegister(parser, integerRegisters, floatRegisters);
parser.start("register");
if(isFloatRegister(pentry)) {
floatRegisters.add(entry.getAttribute("name"));
} else {
integerRegisters.add(entry.getAttribute("name"));
} }
parser.end(); parser.end();
} else { } else {
discardSubTree(parser); parseSingleRegister(parser, integerRegisters, floatRegisters);
} }
parser.end();
} }
parser.end(); parser.end();
......
...@@ -34,7 +34,7 @@ struct GhidraConfig { ...@@ -34,7 +34,7 @@ struct GhidraConfig {
fn copy_config_json(location: &Path) -> Result<()> { fn copy_config_json(location: &Path) -> Result<()> {
let repo_dir = env::current_dir().unwrap(); let repo_dir = env::current_dir().unwrap();
std::fs::copy( std::fs::copy(
&repo_dir.join("src/config.json"), repo_dir.join("src/config.json"),
location.join("config.json"), location.join("config.json"),
)?; )?;
Ok(()) Ok(())
...@@ -82,7 +82,7 @@ fn get_search_locations() -> Vec<PathBuf> { ...@@ -82,7 +82,7 @@ fn get_search_locations() -> Vec<PathBuf> {
fn find_ghidra() -> Result<PathBuf> { fn find_ghidra() -> Result<PathBuf> {
let mut ghidra_locations: Vec<PathBuf> = get_search_locations() let mut ghidra_locations: Vec<PathBuf> = get_search_locations()
.into_iter() .into_iter()
.filter_map(|x| search_for_ghidrarun(&x)) .flat_map(|x| search_for_ghidrarun(&x))
.collect(); .collect();
ghidra_locations.sort(); ghidra_locations.sort();
...@@ -95,20 +95,31 @@ fn find_ghidra() -> Result<PathBuf> { ...@@ -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. /// 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) for entry in WalkDir::new(entry_path)
.max_depth(8)
.into_iter() .into_iter()
.filter_entry(|e| !is_hidden(e))
.filter_map(|e| e.ok()) .filter_map(|e| e.ok())
.filter(|e| e.metadata().unwrap().is_file()) .filter(|e| e.metadata().unwrap().is_file())
{ {
if entry.file_name().to_str().unwrap() == "ghidraRun" { if entry.file_name().to_str().unwrap() == "ghidraRun" {
let mut hit = entry.into_path(); let mut hit = entry.into_path();
hit.pop(); hit.pop();
return Some(hit); hits.push(hit);
} }
} }
None hits
} }
/// Determines if a path is a ghidra installation /// 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