ghidra/Ghidra/Features/BytePatterns/ghidra_scripts/DumpFunctionPatternInfoScri...

125 lines
4.6 KiB
Java

/* ###
* 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.
*/
//This script dumps information about byte and instructions in neighborhoods around function starts
//and returns to an XML file
//@category FunctionStartPatterns
import java.io.*;
import java.util.List;
import ghidra.app.script.GhidraScript;
import ghidra.bitpatterns.info.*;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionIterator;
import ghidra.util.Msg;
/**
* Example of command to run this script headlessly:
* ./analyzeHeadless /local/ghidraProjects/nonShared/ arm -recursive -process -noanalysis -postScript DumpFunctionPatternInfo.java
*/
public class DumpFunctionPatternInfoScript extends GhidraScript {
private static int totalFuncs = 0;
private static int programsAnalyzed = 0;
@Override
protected void run() throws Exception {
if (!isRunningHeadless()) {
totalFuncs = 0;
programsAnalyzed = 0;
}
int numFirstBytes = askInt("Number of first bytes", "bytes");
int numFirstInstructions = askInt("Number of first instructions", "instructions");
int numPreBytes = askInt("Number of pre bytes", "bytes");
int numPreInstructions = askInt("Number of pre instructions", "instructions");
int numReturnBytes = askInt("Number of return bytes", "bytes");
int numReturnInstructions = askInt("Number of return instructions", "instructions");
String saveDirName = askString("Directory to save results", "directory");
String contextRegsCSV = askString("Context register csv", "csv");
File saveDir = new File(saveDirName);
if (!saveDir.isDirectory()) {
Msg.info(this, "Invalid save directory: " + saveDirName);
return;
}
List<String> contextRegisters = DataGatheringParams.getContextRegisterList(contextRegsCSV);
programsAnalyzed++;
if (currentProgram == null) {
Msg.info(this, "null current program: try again with the -process option");
return;
}
if (currentProgram.getFunctionManager().getFunctionCount() == 0) {
Msg.info(this, "No functions found in " + currentProgram.getName() + ", skipping.");
return;
}
FunctionIterator fIter = currentProgram.getFunctionManager().getFunctions(true);
DataGatheringParams params = new DataGatheringParams();
params.setNumPreBytes(numPreBytes);
params.setNumFirstBytes(numFirstBytes);
params.setNumReturnBytes(numReturnBytes);
params.setNumPreInstructions(numPreInstructions);
params.setNumFirstInstructions(numFirstInstructions);
params.setNumReturnInstructions(numReturnInstructions);
params.setContextRegisters(contextRegisters);
FileBitPatternInfo funcPatternList = new FileBitPatternInfo();
funcPatternList.setLanguageID(currentProgram.getLanguageID().getIdAsString());
funcPatternList.setGhidraURL("TODO: url");
funcPatternList.setNumPreBytes(numPreBytes);
funcPatternList.setNumPreInstructions(numPreInstructions);
funcPatternList.setNumFirstBytes(numFirstBytes);
funcPatternList.setNumFirstInstructions(numFirstInstructions);
funcPatternList.setNumReturnBytes(numReturnBytes);
funcPatternList.setNumReturnInstructions(numReturnInstructions);
AddressSetView initialized = currentProgram.getMemory().getLoadedAndInitializedAddressSet();
while (fIter.hasNext()) {
monitor.checkCanceled();
Function func = fIter.next();
if (func.isThunk()) {
continue;
}
if (func.isExternal()) {
continue;
}
if (!initialized.contains(func.getEntryPoint())) {
continue;
}
if (currentProgram.getListing().getInstructionAt(func.getEntryPoint()) == null) {
continue;
}
FunctionBitPatternInfo fStart =
new FunctionBitPatternInfo(currentProgram, func, params);
if (fStart.getFirstBytes() != null) {
funcPatternList.getFuncBitPatternInfo().add(fStart);
totalFuncs++;
}
}
File savedFile = new File(saveDir.getAbsolutePath() + File.separator +
currentProgram.getDomainFile().getPathname().replaceAll("/", "_") + "_" +
currentProgram.getExecutableMD5() + "_funcInfo.xml");
funcPatternList.toXmlFile(savedFile);
Msg.info(this,
"Programs analyzed: " + programsAnalyzed + "; total functions: " + totalFuncs);
}
}