Commit b65e0142 by 文周繁

feat: add testghidra

parent a4087e70
### IntelliJ IDEA ###
out/
!**/src/main/**/out/
!**/src/test/**/out/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
\ No newline at end of file
import ghidra.app.script.GhidraScript;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.symbol.SymbolIterator;
import ghidra.program.model.symbol.SymbolTable;
public class FunctionRef extends GhidraScript {
public void run() throws Exception {
printf("Hello World\n"); //格式化输出
println("Hello World"); //打印字符串并换行
printerr("Hello World"); //错误消息打印控制台显示红色
SymbolTable st=currentProgram.getSymbolTable();
SymbolIterator iter=st.getSymbolIterator();
int count=0;
while(iter.hasNext()&& !monitor.isCancelled()){
Symbol sym=iter.next();
if(sym!=null){
printf("%s\n",sym.getName());
count++;
}
}
println(count+" symbols");
// get function reference
FunctionIterator funcIterator=currentProgram.getListing().getFunctions(true);
for(Function function:funcIterator){
if(function.getName().equals("write")){
printf("\t%s @ %s\n",function.getName(),function.getEntryPoint());
Reference[] references=getReferencesTo(function.getEntryPoint());
for(Reference reference: references){
Function referencefunction=getFunctionContaining(reference.getFromAddress());
if(referencefunction!=null && !referencefunction.isThunk())
{
printf("\t\t%s @ %s\n",referencefunction.getName(),
referencefunction.getEntryPoint().toString());
}
}
}
}
}
}
\ No newline at end of file
//@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 HelloIdeaGhidra 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("D:\\fftp-funcInfo.log");
FileOutputStream LogVarWriter=new FileOutputStream("D:\\fftp-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();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="GHIDRA_EXT" name="Ghidra">
<configuration>
<option name="installationPath" value="$MODULE_DIR$/../../Tools/Ghidra10.1.5/ghidra" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_11" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Ghidra" level="application" />
</component>
</module>
\ No newline at end of file
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