### Shell: Run BinAbsInspector Checker via Command Line Source: https://github.com/keensecuritylab/binabsinspector/blob/main/doc/developer_guide.md This command-line example shows how to execute the BinAbsInspector script with a specific checker (e.g., CWE134) using `intellj-ghidra`. It requires specifying the project path, project name, binary to import, script path, and the checker to run. ```Shell -import -scriptPath -postScript BinAbsInspector.java "@@-check CWE134" ``` -------------------------------- ### Build BinAbsInspector Ghidra Extension with Gradle Source: https://github.com/keensecuritylab/binabsinspector/blob/main/README.md This command demonstrates how to build the BinAbsInspector extension from source using Gradle. It requires Ghidra and Z3 to be installed, along with Gradle 7.x. The compiled extension will be generated as a zip file in the 'dist' directory. ```Shell gradle buildExtension ``` -------------------------------- ### Example C Program Demonstrating CWE-134 Format String Vulnerability Source: https://github.com/keensecuritylab/binabsinspector/blob/main/doc/developer_guide.md This C code snippet illustrates a potential CWE-134 (Use of Externally-Controlled Format String) vulnerability. The `foo` function calls `printf` with a user-controlled input `ptr`, which can lead to an exploitable format string vulnerability if `ptr` contains malicious format specifiers. The `main` function demonstrates both safe (constant string) and unsafe (user input) calls to `foo`. ```C #include #include void foo(char * ptr) { printf(ptr); } int main() { char * ptr = (char *) malloc(0x10); scanf("%16s", ptr); foo("test"); foo(ptr); free(ptr); } ``` -------------------------------- ### Ghidra API: GlobalState.flatAPI Source: https://github.com/keensecuritylab/binabsinspector/blob/main/doc/developer_guide.md An immutable interface to Ghidra's program analysis functionalities, providing a simplified and version-stable way to interact with the program. It is recommended for general use due to its immutability across Ghidra versions. ```APIDOC ghidra.program.flatapi.FlatProgramAPI GlobalState.flatAPI: FlatProgramAPI Description: An immutable interface for program analysis, recommended for stability. ``` -------------------------------- ### Ghidra API: GlobalState.currentProgram Source: https://github.com/keensecuritylab/binabsinspector/blob/main/doc/developer_guide.md Reference to the currently active Ghidra `Program` object, providing access to program-wide information and functionality. It is used to obtain the `SymbolTable` and other program components. ```APIDOC ghidra.program.model.listing.Program GlobalState.currentProgram: Program Description: The currently active Ghidra program instance. ``` -------------------------------- ### Iterate Abstract Environments for Ghidra Call Site Analysis Source: https://github.com/keensecuritylab/binabsinspector/blob/main/doc/developer_guide.md This Java code iterates through the abstract environments (`AbsEnv`) associated with a caller function's context at a specific call site address. It retrieves the `AbsEnv` for the `fromAddress` and then passes it along with other relevant information to a helper function, `checkFunctionParameters`, for further analysis. ```java for (Context context : Context.getContext(caller)) { AbsEnv absEnv = context.getAbsEnvIn().get(fromAddress); if (absEnv == null) { continue; } hasWarning |= checkFunctionParameters(context, absEnv, callee, fromAddress); } ``` -------------------------------- ### Java: Register a New Checker in CheckerManager Source: https://github.com/keensecuritylab/binabsinspector/blob/main/doc/developer_guide.md This snippet demonstrates how to register a newly created checker by adding a new entry to the `CHECKER_MAP` within the `CheckerManager` class. This makes the checker available for execution. ```Java public static final Map CHECKER_MAP = Map.ofEntries( Map.entry("CWE134", new CWE134()), ... ); ``` -------------------------------- ### Define Ghidra Checker Class for CWE-134 Source: https://github.com/keensecuritylab/binabsinspector/blob/main/doc/developer_guide.md This Java code defines the basic structure for a new Ghidra checker, `CWE134`, by extending `CheckerBase`. It initializes the checker with a name and version, and provides a placeholder for the core vulnerability detection logic within the `check()` method. ```java public class CWE134 extends CheckerBase { public CWE134() { super("CWE134", "0.1"); description = "Use of Externally-Controlled Format String: The software uses a function that " + "accepts a format string as an argument, but the format string originates from an external source."; } @Override public boolean check() { //implement checker logic here. } } ``` -------------------------------- ### Analyze Function Parameters for Externally Controlled Format String Source: https://github.com/keensecuritylab/binabsinspector/blob/main/doc/developer_guide.md This Java method analyzes a function's parameters using abstract interpretation to detect potential externally controlled format string vulnerabilities. It retrieves the `KSet` for a specific argument, checks if its abstract values are 'writable', and if so, generates a `CWEReport` indicating a potential issue. ```java private boolean checkFunctionParameters(Context context, AbsEnv absEnv, Function callee, Address address) { String name = callee.getName(); int paramIndex = 0; Logging.debug("Processing argument " + paramIndex + " at " + name + "()"); boolean result = false; KSet argKSet = getParamKSet(callee, paramIndex, absEnv); if (!argKSet.isNormal()) { return false; } Logging.debug("KSet for argument: " + argKSet); for (AbsVal argAbsVal : argKSet) { if (!isAbsValWritable(argAbsVal)) { Logging.debug("Argument is not writeable: " + argAbsVal); continue; } Logging.debug("Argument is writeable: " + argAbsVal); // We might have found a use of the writeable region as the format string CWEReport report = getNewReport("Potentially externally controlled format string \"" + name + "()\" call").setAddress(address); Logging.report(report); result = true; } return result; } ``` -------------------------------- ### Query Ghidra Symbol Table for printf Call Sites Source: https://github.com/keensecuritylab/binabsinspector/blob/main/doc/developer_guide.md This Java code snippet demonstrates how to use Ghidra's API to locate all call sites to the `printf` function within a program. It iterates through the symbol table, finds the `printf` symbol, and then processes its references to identify caller and callee functions, skipping thunk calls. ```java public boolean check() { boolean hasWarning = false; try { SymbolTable symbolTable = GlobalState.currentProgram.getSymbolTable(); if (symbolTable == null) { Logging.error("Empty symbols table"); return false; } SymbolIterator iterator = symbolTable.getSymbolIterator(); while (iterator.hasNext()) { Symbol currentSymbol = iterator.next(); if (!currentSymbol.getName().equals("printf")) { continue; } Logging.debug("Processing symbol \"" + currentSymbol.getName() + "()\""); for (Reference ref : currentSymbol.getReferences()) { if (ref.getReferenceType() == RefType.THUNK) { break; // skip THUNK function. } Address toAddress = ref.getToAddress(); Address fromAddress = ref.getFromAddress(); Function callee = GlobalState.flatAPI.getFunctionAt(toAddress); Function caller = GlobalState.flatAPI.getFunctionContaining(fromAddress); if (callee == null || caller == null) { continue; } Logging.debug(fromAddress + " -> " + toAddress + " " + callee.getName()); } } } catch (Exception exception) { exception.printStackTrace(); } return hasWarning; } ``` -------------------------------- ### Java: Determine if an Absolute Value Points to Writable Memory Source: https://github.com/keensecuritylab/binabsinspector/blob/main/doc/developer_guide.md The `isAbsValWritable` function checks if a given `AbsVal` (pointer) refers to a writable memory region. It considers heap and local (stack) regions as always writable. For global regions, it uses the Ghidra API to query the memory block's write permission. ```Java private static boolean isAbsValWritable(AbsVal ptr) { RegionBase region = ptr.getRegion(); if (region.isLocal() || region.isHeap()) { return true; } if (region.isGlobal() && !ptr.isBigVal()) { Address address = GlobalState.flatAPI.toAddr(ptr.getValue()); MemoryBlock memoryBlock = GlobalState.flatAPI.getMemoryBlock(address); if (memoryBlock == null) { return false; } return memoryBlock.isWrite(); } return false; } ``` -------------------------------- ### Run BinAbsInspector with Docker Source: https://github.com/keensecuritylab/binabsinspector/blob/main/README.md This snippet provides commands to clone the repository, build a Docker image for BinAbsInspector, and then run the analyzer within a container. This method offers a portable and isolated environment for executing BinAbsInspector, simplifying dependency management. ```Shell git clone git@github.com:KeenSecurityLab/BinAbsInspector.git cd BinAbsInspector docker build . -t bai docker run -v $(pwd):/data/workspace bai "@@