java用的软件G,Ghidra脚本学习(Java版本)

更多全球网络安全资讯尽在邑安全

一、Hello World 脚本public class HelloWorld extends GhidraScript { public void run() throws Exception { printf("Hello World\n"); //格式化输出 println("Hello World"); //打印字符串并换行 printerr("Hello World"); //错误消息打印控制台显示红色 } }

成功运行控制台打印出Hello World。

caf2f8813a3927b29395ab011ab87dec.png

二、获取所有的符号public class HelloWorld extends GhidraScript { @Override public void run() throws Exception { //TODO Add User Code Here SymbolTable st = currentProgram.getSymbolTable(); SymbolIterator iter = st.getSymbolIterator(true); int count = 0; while (iter.hasNext() && !monitor.isCancelled()) { Symbol sym = iter.next(); if (sym != null) { printf("\t%s\n",sym.getName()); count++; } } println(count+" symbols"); }}

控制台输出如下:

d06fed9e1220cb3401a34d513038bc6b.png

脚本中使用currentProgram来获取符号表,这里currentProgram为抽象类GhidraScript提供的变量。软件中的参数和信息都是通过这些变量来获取的,常用的变量有如下几个:currentProgram 当前项目的程序

currentAddress Ghidra工具中闪烁光标位置的地址对象

currentLocation 工具中当前光标位置的程序位置;如果不存在程序位置,则为null

currentSelection 当前的选中对象;如果不存在选择,则为null

currentHighlight 工具中的当前突出显示;如果不存在突出显示,则为null

脚本开发中使用最多的是currentProgram了。

三、获取所有的Function对象public class HelloWorld extends GhidraScript { @Override public void run() throws Exception { FunctionIterator iterator2 =currentProgram.getListing().getFunctions(true); for (Function function : iterator2) { printf("\t%s\n",function.getName()); } }}

Function对象可以操作已经识别的函数,比如引用、函数内逻辑的分析、以及函数内的修改。

98e9fb89ffba53e12b6dfb70a9eb0fa5.png

四、函数交叉引用public class HelloWorld extends GhidraScript { @Override public void run() throws Exception { FunctionIterator iterator2 =currentProgram.getListing().getFunctions(true); for (Function function : iterator2) { 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()); } } } }}

控制台输出信息如下:

81c4ef8e00286d3d850c5ef78892f7bd.png

讲解下使用的api说明:function.getEntryPoint() 是返回函数地址Address对象,二进制里指的是函数所在起始地址用,但在Java中是Address对象对它进行描述。

function.getName() 是函数名,如果是有符号描述则为符号描述中但字符串,反之就是反汇编引擎随机分配的FUN_xxxx 类似名称。

getReferencesTo() 是返回Address参数的所有引用,并返回Reference对象的数组。

getFunctionContaining() 是根据传入的地址返回Function对象,如果是函数起始地址则返回Function对象,如果不是则返回null,所以使用这个API需要加上判断,以免脚本运行错误抛出异常。

五、函数转为P-CODE中间码public class HelloWorld extends GhidraScript { private DecompInterface decompInterface=null; @Override public void run() throws Exception { decompInterface = getDecompInterface(); FunctionIterator iterator2 =currentProgram.getListing().getFunctions(true); for (Function function : iterator2) { if (function.getName().equals("FUN_000aeabc")){ printf("\t%s @ %s\n",function.getName(),function.getEntryPoint()); DecompileResults results = decompInterface.decompileFunction(function,0,monitor); Iterator iterator = results.getHighFunction().getPcodeOps(); while (iterator.hasNext()){ PcodeOpAST op = iterator.next(); printf("%s\n",op.toString()); } } } } private DecompInterface getDecompInterface() throws DecompileException { DecompileOptions options = new DecompileOptions(); DecompInterface ifc = new DecompInterface(); ifc.setOptions(options); ifc.setSimplificationStyle("decompile"); if (!ifc.openProgram(this.getCurrentProgram())) { throw new DecompileException("Decompiler", "Unable to initialize: "+ifc.getLastMessage()); } return ifc; }}

控制台信息如下:

91fc4675a3c2d5cc521ee3d4022b8648.png

我们拿到Function对象需要借助DecompInterface对象来做更多事情,上面getDecompInterface()可以定式写成这样,因我们只需要拿到DecompInterface对象其他的不用考虑。decompInterface.decompileFunction(function,0,monitor); 参数解析:反编译function,设置等待时间,monitor为常量。通过这个api可以拿到DecompileResults对象,这个对象中存在HighFunction对象变量,HighFunction对象中getPcodeOps()函数可以返回值pcode迭代器,循环迭代就能获取函数里对应的pcode了。

六、函数转伪C代码public class HelloWorld extends GhidraScript { private DecompInterface decompInterface=null; @Override public void run() throws Exception { decompInterface = getDecompInterface(); FunctionIterator iterator2 =currentProgram.getListing().getFunctions(true); for (Function function : iterator2) { if (function.getName().equals("FUN_000aeabc")){ printf("\t%s @ %s\n",function.getName(),function.getEntryPoint()); DecompileResults results = decompInterface.decompileFunction(function,0,monitor); printf("%s\n",results.getDecompiledFunction().getC()); } } } private DecompInterface getDecompInterface() throws DecompileException { DecompileOptions options = new DecompileOptions(); DecompInterface ifc = new DecompInterface(); ifc.setOptions(options); ifc.setSimplificationStyle("decompile"); if (!ifc.openProgram(this.getCurrentProgram())) { throw new DecompileException("Decompiler", "Unable to initialize: "+ifc.getLastMessage()); } return ifc; }}

打印输出了伪C字符

4da05ae7f34ab89bc150b6dc79599b2d.png

DecompileResults 调用getDecompiledFunction()函数返回DecompiledFunction对象,这个对象中的getC()方法可以返回编译好伪C。当然这里输出伪C并不是唯一方法,另外还有两种方法也可以输出伪C。因为有些需求场景使用伪C字符串并不方便,所以需要另外更适合编程的方法,这个留在下一部分。

转自先知社区欢迎收藏并分享朋友圈,让五邑人网络更安全

推荐文章

1

新永恒之蓝?微软SMBv3高危漏洞(CVE-2020-0796)分析复现

2

重大漏洞预警:ubuntu最新版本存在本地提权漏洞(已有EXP)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值