Commit 7681ccd6 by 文周繁

feat:rename

parent cc4fbcdd
//@author Kolmogorov
//@category test
//@keybinding
//@menupath
//@toolbar
import ghidra.app.script.GhidraScript;
import ghidra.graph.GDirectedGraph;
import ghidra.graph.GraphFactory;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.block.*;
import ghidra.program.model.block.graph.CodeBlockEdge;
import ghidra.program.model.block.graph.CodeBlockVertex;
import ghidra.program.model.data.DataType;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.pcode.Varnode;
import ghidra.program.model.symbol.RefType;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.ReferenceManager;
import ghidra.program.model.symbol.Symbol;
import ghidra.util.exception.CancelledException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
public class GhidraCustomScript extends GhidraScript {
/*
* Creates a new control flow graph for a function
* Vertex: a Basic Block as CodeBlockVertex
* Edge: connection between basic blocks as CodeBlockEdge
* */
public class FunctionControlFlowGraph {
protected GDirectedGraph<CodeBlockVertex, CodeBlockEdge> cfg;
protected Function function;
protected GDirectedGraph<CodeBlockVertex, CodeBlockEdge> createGraph() {
return GraphFactory.createDirectedGraph();
}
// Dummy constructor
public FunctionControlFlowGraph() {
this.cfg = this.createGraph();
}
// Creates a control flow graph for the input function
public FunctionControlFlowGraph(Function function) {
this.cfg = this.createGraph();
this.function = function;
BasicBlockModel basicBlockModel = new BasicBlockModel(currentProgram);
AddressSetView addrSet = function.getBody();
try {
CodeBlockIterator codeBlockIter = basicBlockModel.getCodeBlocksContaining(addrSet, getMonitor());
// go through each block and add the outgoing edges to the graph
while (codeBlockIter.hasNext()) {
CodeBlock block = codeBlockIter.next();
CodeBlockReferenceIterator dstBlocks = block.getDestinations(getMonitor());
// using the CodeBlockReference to add each edge
while (dstBlocks.hasNext()) {
this.addEdge(dstBlocks.next());
}
}
} catch (CancelledException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/*
* Helper function to print a Vertex and its successors
*/
public void printVertex(CodeBlockVertex codeBlockVertex) {
CodeBlock blockInfo = codeBlockVertex.getCodeBlock();
printf("[+] Code Block Start Address: 0x%x\n", blockInfo.getFirstStartAddress().getOffset());
Collection<CodeBlockVertex> successors = cfg.getSuccessors(codeBlockVertex);
for (CodeBlockVertex cbv : successors) {
blockInfo = cbv.getCodeBlock();
printf("[-] ------> Successor Block at: 0x%x\n", blockInfo.getFirstStartAddress().getOffset());
}
}
/*
* Prints the edges of the CFG
*/
public void printEdges() {
printf("[+] Printing Edges of the CFG:\n");
Collection<CodeBlockEdge> edges = cfg.getEdges();
CodeBlock blockFrom, blockTo;
for (CodeBlockEdge edge : edges) {
blockFrom = edge.getStart().getCodeBlock();
blockTo = edge.getEnd().getCodeBlock();
printf("[-] 0x%x --> 0x%x\n", blockFrom.getFirstStartAddress().getOffset(), blockTo.getFirstStartAddress().getOffset());
}
}
/*
* Simple dumping of the CFG just for validation
*/
public void printFCFG() {
Address entryPoint = this.function.getEntryPoint();
BasicBlockModel basicBlockModel = new BasicBlockModel(currentProgram);
printf("[+] Printing CFG for function at:0x%x\n", this.function.getEntryPoint().getOffset());
try {
CodeBlock entryBlock = basicBlockModel.getCodeBlockAt(entryPoint, getMonitor());
CodeBlockVertex entryVertex = new CodeBlockVertex(entryBlock);
List<CodeBlockVertex> vertexBuffer = new ArrayList<CodeBlockVertex>();
vertexBuffer.add(entryVertex);
int i = 0;
while (i < vertexBuffer.size()) {
this.printVertex(vertexBuffer.get(i));
for (CodeBlockVertex successor : cfg.getSuccessors(vertexBuffer.get(i))) {
if (!vertexBuffer.contains(successor)) {
vertexBuffer.add(successor);
}
}
i++;
}
} catch (CancelledException e) {
throw new RuntimeException(e);
}
}
public void addEdge(CodeBlockReference codeBlockRef) {
CodeBlockEdge edge = new CodeBlockEdge(new CodeBlockVertex(codeBlockRef.getSourceBlock()), new CodeBlockVertex(codeBlockRef.getDestinationBlock()));
this.cfg.addEdge(edge);
}
public void addEdge(CodeBlock srcBlock, CodeBlock dstBlock) {
CodeBlockEdge edge = new CodeBlockEdge(new CodeBlockVertex(srcBlock), new CodeBlockVertex(dstBlock));
this.cfg.addEdge(edge);
}
}
protected void run() throws Exception {
// hello
printf("hello idea\n");
printf("hello ghidra\n");
String name = currentProgram.getName();
Address BaseAddr = currentProgram.getImageBase();
MemoryBlock[] sections = currentProgram.getMemory().getBlocks();
// getSection Information
LinkedList<MemoryBlock> pltsection = new LinkedList<MemoryBlock>();
for (MemoryBlock section : sections) {
if (section.getName().matches(".plt.*")) {
printf("Name:%s,addr:0x%x-0x%x,size:0x%x", section.getName(), section.getStart().getOffset(), section.getEnd().getOffset(), section.getSize());
pltsection.add(section);
}
}
long BaseOff = BaseAddr.getOffset();
printf("[*] name:%s\n", name);
printf("[*] Base addr:0x%x\n", BaseOff);
// getFunctions
Listing listing = currentProgram.getListing();
long funcOff;
long funcRetOff = 0;
LinkedList<String> funcNameList = new LinkedList<String>();
String funcName;
Address Instraddr;
String Instroper;
int variable_len;
int stack_offset = 0;
int prev_stack_offset = 0;
int FirstUseOffset;
Symbol variableSymbol;
Reference[] varReferences;
FileOutputStream LogfileWriter = new FileOutputStream("/home/hunter/Desktop/jhead-funcInfo.log");
FileOutputStream LogVarWriter = new FileOutputStream("/home/hunter/Desktop/jhead-VarInfo.log");
FunctionIterator functions = listing.getFunctions(true);
//
int RBPOpNum = 0;
int RSPOpNum = 0;
int BBNum;
BasicBlockModel basicBlockModel = new BasicBlockModel(currentProgram);
List<CodeBlock> CodeBlockBuffer = new ArrayList<CodeBlock>();
List<CodeBlock> FunCodeBlockBuffer = new ArrayList<CodeBlock>();
int StateNum = 0, LenNum = 0, OtherNum = 0;
for (Function function : functions) {
StateNum = 0;
LenNum = 0;
OtherNum = 0;
BBNum = 0;
funcOff = function.getEntryPoint().getOffset() - BaseOff;
funcName = function.getName();
AddressSetView addrSet = function.getBody();
printf("\n--------------------------%s @ 0x%x~0x%x--------------------\n", funcName, addrSet.getMinAddress().getOffset(), addrSet.getMaxAddress().getOffset());
int j = 0;
boolean skipflag = false;
while (j < pltsection.size()) {
if (pltsection.get(j).getStart().getOffset() <= function.getEntryPoint().getOffset() && function.getEntryPoint().getOffset() <= pltsection.get(j).getStart().getOffset() + pltsection.get(j).getSize()) {
printf("function %s is in section:%s,we skip it\n", funcName, pltsection.get(j).getName());
skipflag = true;
break;
}
j++;
}
if (skipflag) {
continue;
}
if (!funcNameList.contains(funcName)) {
funcNameList.add(funcName);
String record = "0x" + Integer.toHexString((int) funcOff) + ":" + funcName + "\n";
LogfileWriter.write(record.getBytes());
}
// Control Flow Graph Recovery
// FunctionControlFlowGraph fcfg=new FunctionControlFlowGraph(function);
// fcfg.printFCFG();
// fcfg.printEdges();
// getBasicBlock Information
// get Basic Block information
// try
// {
// CodeBlockIterator codeBlockIter =basicBlockModel.getCodeBlocksContaining(addrSet,getMonitor());
// // go through each block and add the outgoing edges to the graph
// while(codeBlockIter.hasNext()){
// CodeBlock block=codeBlockIter.next();
// CodeBlockReferenceIterator dstBlocks=block.getDestinations(getMonitor());
// CodeBlockBuffer.add(block);
// FunCodeBlockBuffer.add(block); // local store
// BBNum++;
// }
// printf("[*] Basic Block is:%d",BBNum);
// }
// catch (CancelledException e)
// {
// e.printStackTrace();
// throw new RuntimeException(e);
// }
//
// int i=0;
// Address StartAddr,EndAddr;
// while(i<FunCodeBlockBuffer.size())
// {
// StartAddr=FunCodeBlockBuffer.get(i).getFirstStartAddress();
// InstructionIterator instructions = listing.getInstructions(StartAddr, true);
//
// if(i+1<FunCodeBlockBuffer.size())
// {
// EndAddr=FunCodeBlockBuffer.get(i+1).getFirstStartAddress();
// printf("[*] ------------------------------------------------------\n");
// for(Instruction instr:instructions)
// {
// Instraddr = instr.getAddress();
// if(instr.getAddress().getOffset() < EndAddr.getOffset()) // locate RET instruction
// {
// printf("[*] 0x%x:%s\n", Instraddr.getOffset(), instr);
// }
// else
// break;
// }
// }
// else {
// printf("[*] ------------------------------------------------------\n");
// for(Instruction instr:instructions)
// {
// Instraddr = instr.getAddress();
// if(addrSet.contains(instr.getAddress())) // locate RET instruction
// {
// printf("[*] 0x%x:%s\n", Instraddr.getOffset(), instr);
// }
// else
// break;
// }
// }
//
// i++;
// }
// FunCodeBlockBuffer.clear();
// variable analysis
Variable[] variables = function.getLocalVariables();
if (variables.length == 0) {
printf("[*] function have zero variable\n");
printf("[*] ------------------------------------------------------\n");
// print instr information
continue;
} else {
printf("[*] function have %d variable(s)\n", variables.length);
// Analysis instr to find Instrument Point
printf("[*] ------------------------------------------------------\n");
// instruction analysis
InstructionIterator instructions = listing.getInstructions(function.getEntryPoint(), true);
for (Instruction instr : instructions) {
Instraddr = instr.getAddress();
Instroper = instr.getMnemonicString();
printf("[*] 0x%x:%s\n", Instraddr.getOffset(), instr);
Address[] flows = instr.getFlows();
// for(Address flow:flows)
// {
// printf("[-] instr flows to:0x%x\n",flow.getOffset());
// }
if (flows.length >= 1) {
//printf("[*] 0x%x:%s\n",Instraddr.getOffset(),instr);
printf("[*] ------------------------------------------------------\n");
}
if (instr.toString().equals("PUSH RBP") && instr.getNext().toString().equals("MOV RBP,RSP")) {
// printf("[*] 0x%x:%s\n",Instraddr.getOffset(),instr);
// funcOff=instr.getNext().getAddress().getOffset()-BaseOff;
printf("[-] A standard way to Generate Stack Frame\n");
// printf("[-] update instrument point address from start addr 0x%x to 0x%x\n",function.getEntryPoint().getOffset()-BaseOff,funcOff);
}
if (instr.toString().contains("SUB RSP")) {
// printf("[*] 0x%x:%s\n",Instraddr.getOffset(),instr);
printf("[-] Adjust Stack Frame\n");
}
if (!addrSet.contains(Instraddr)) // locate RET instruction
{
// printf("[*] 0x%x:%s\n",Instraddr.getOffset(),instr);
// funcRetOff=Instraddr.getOffset()-BaseOff;
funcRetOff = instr.getPrevious().getAddress().getOffset() - BaseOff;
//printf("[*] %s:[RET]\n",addr);
break; // function end
}
}
}
StackFrame funcStackFrame = function.getStackFrame();
int ReturnAddr = funcStackFrame.getReturnAddressOffset();
int idex = 0;
int varlen = 0;
int inferLen = 0;
int RefWNum = 0, RefRNum = 0, RefDNum = 0;
for (Variable variable : variables) {
RefWNum = 0;
RefRNum = 0;
RefDNum = 0;
variable_len = variable.getLength();
FirstUseOffset = variable.getFirstUseOffset();
variableSymbol = variable.getSymbol();
printf("[*]-------------------------var[%d]:%s-----------------------\n", idex, variable.getName());
printf("[*] varName: %s @ varlen is:%d\n", variable.getName(), variable_len);
printf("[*] first use offset is:0x%x\n", FirstUseOffset);
if (variable.isStackVariable()) {
// get name and stack offset
stack_offset = variable.getStackOffset();
printf("[*] stack offset:%d\n", stack_offset);
// DataType Info
DataType varType = variable.getDataType();
varlen = varType.getLength();
printf("[*] [type info]:%s @ [type len]:%d \n", varType.getName(), varlen); // byte
if (idex != 0) // skip the first
{
inferLen = prev_stack_offset - stack_offset;
if (inferLen != variable_len) {
printf("[*] inferred len is:%d bytes", inferLen);
}
}
prev_stack_offset = stack_offset;
VariableStorage varStore = variable.getVariableStorage();
int stackOff = varStore.getStackOffset();
Varnode firstVarnode = variable.getFirstStorageVarnode();
int size = firstVarnode.getSize();
long off = firstVarnode.getOffset();
// get xref info
ReferenceManager referenceManager = function.getProgram().getReferenceManager();
varReferences = referenceManager.getReferencesTo(variable);
for (Reference varReference : varReferences) {
RefType varefType = varReference.getReferenceType();
Address varFromAddr = varReference.getFromAddress();
Address varToAddr = varReference.getToAddress();
printf("[*] [ref addr]:0x%x @ [ref type]:%s\n", varFromAddr.getOffset() - BaseOff, varefType.getName());
// analysis xref info
if (varefType.getName().equals("WRITE")) {
RefWNum++;
}
if (varefType.getName().equals("READ")) {
RefRNum++;
}
if (varefType.getName().equals("DATA")) {
RefDNum++;
}
}
printf("[*] Refer Info: [W]:%d,[R]:%d,[D]:%d\n", RefWNum, RefRNum, RefDNum);
// judge if it should be record
if (inferLen >= 16) {
LenNum++;
if ((RefWNum >= 1 && RefDNum >= 1) || (RefRNum >= 1 && RefDNum >= 1) || (RefWNum >= 1 && RefRNum >= 1) || (RefDNum >= 2)) {
printf("[*] This var relate to state");
// write to varlog file funcName@funcOffset:VarStackOffset@VarSize
String Varecord = "0x" + Integer.toHexString((int) funcOff) + ":" + funcName + "@" + "RET" + ":" + "0x" + Integer.toHexString((int) funcRetOff) + "@" + Integer.toString(stack_offset) + ":" + Integer.toString(inferLen) + "\n";
StateNum++;
LogVarWriter.write(Varecord.getBytes()); // Record
} else {
printf("[*] Ref type is not various\n");
}
} else {
OtherNum++;
printf("[*] not enough length\n");
}
}
idex++;
} // end variable
// analysis variable reference type
printf("LenVar/Total:[%d/%d], StateVar/Total[%d/%d]:, StateVar/LenVar:[%d/%d]\n", LenNum, idex, StateNum, idex, StateNum, LenNum);
if (StateNum >= 1) {
printf("[*]******************[*]\n");
}
} //end function
//printf("[*] Basic Block is:%d",CodeBlockBuffer.size());
LogfileWriter.close();
LogVarWriter.close();
}
}
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