JEB2发布有段时间了,相比于JEB1来说功能强大了很多,但是API也发生了巨大的变化,不仅是定义上也包括架构上,这给我们移植或者是新编写插件带来了一定不便, 目前也还没看到详细一些的API分析教程。本文以一个具体的应用分析为例,解释如何编写一个JEB2中处理混淆应用的插件,来实现自动识别和重命名。

案例

我们的样例APK是一个采用了比较剑走偏锋混淆的东西,其中绝大部分类名、函数名、field名都被替换成了包含lIi的字符串,如下截图所示:

这种给人工分析时追踪函数调用带来了不便,因为这些字符串字母长的都比较像,所以我们需要写一个JEB脚本来自动化重命名这些item。我们的逻辑如下:

对于类:递归寻找它的父类和实现的接口。如果父类和接口包含了有意义的名字:例如SDK类Activity、不能混淆的类名MainActivity,以此为基础进行重命名

对于Field:根据该Field的类型,重命名其名字

对于函数:根据该函数的参数类型,重命名其名字

JEB2的API架构

由于JEB2试图成为像IDA那样的universal disassembler,其架构多了很多包装层。对于APK分析来说,关键的部分关系如下所示:

IProjectUnit -> ICodeUnit -> IJavaSourceUnit

IProjectUnit代表了整个workspace,一般我们只会使用project[0]

>>> engctx.getProjects()

[Project:{/xxx/xxx.apk.jdb2}]

ICodeUnit则代表了一个project中所有的可解析部分,如下面我们提到的,因为JEB2为各种架构都提供了统一包装层,ICodeUnit不再仅仅是dex或者jar,而还会包括了libraries中的各种native Library。

>>> units = RuntimeProjectUtil.findUnitsByType(prj, ICodeUnit, False)

>>> map(lambda x: print(x.name), units)

[u'Bytecode', u'arm64 image', u'arm image', u'arm image', u'mips image', u'x86 image', u'x86_64 image']

其中Bytecode项是对应的dex体. 其对应的ICodeUnit代表了整个dex, 已经提供了基本的类型信息,例如Class, Type, Method, Field, Package 使用者可以通过ICodeUnit.getClass/getMethod/getField获取到对应的ICodeClass/ICodeMethod/ICodeField. 但是这个层级的unit并没有提供class hierchy信息和具体的源代码AST信息,故我们还需要IJavaSourceUnit.

IJavaSourceUnit代表的是执行过反编译之后生成的Java源代码体,提供了更加丰富和细节的Java代码信息供使用. 其对应的AST元素为IJavaClass/IJavaMethod等等. 通过decompiler.decompile(icodeclass.getAddress())获取IJavaSourceUnit, 通过IJavaSourceUnit.getClassElement获取IJavaClass.

需要强调的是, ICodeUnit对应的是整个dex, 而IJavaSourceUnit对应的是单个反编译出的类.

自订操作

在JEB2中,用户操作(自定义操作)被统一包装在ActionContext类之下,类似于transaction的形势.API使用者提交各种ActionContext,并检查返回值是否成功.一个典型的重命名操作如下:

>>> actCntx = ActionContext(self.targetUnit, Actions.RENAME, clz.getItemId(), clz.getAddress())

actData = ActionRenameData()

actData.setNewName(newName)

if codeUnit.prepareExecution(actCntx, actData):

codeUnit.executeAction(actCntx, actData)

值的注意的是,这里的clz对象均为ICodeUnit调用getClass所查询出的ICodeClass类,而不是IJavaSourceUnit对应的IJavaClass. ActionContext作用的对象也是代表整个dex的ICodeUnit.

除了重命名操作之外, ActionContext还包括了COMMENT, CONVERT, CREATE_PACKAGE, DELETE, MOVE_TO_PACKAGE, QUERY_OVERRIDES, QUERY_TYPE_HIER, QUERY_XREFS, RENAME等操作, 其实就是我们在UI中右键所能执行的操作. 读者可能要问, 像QUEYR_TYPE_HIER这种操作, 通过IJavaSource解析AST不是也可以做? 我认为确实是这样, 这里可能还是为了给不同语言提供一个统一的抽象接口. 当然QUERY_XREFS顾名思义是获取到对应的引用, 这方便我们做一些callgraph的查询.

案例解析

如文章开头所示, 我们的目的是根据被混淆item的基类信息和类型信息/参数信息对其重命名. 主要逻辑如下:

for clz in codeunit.getClasses():

if isObfuscated(clz):

name = determineNameFromHierchy(clz) --->1

rename(clz, name)

for field in codeUnit.getFields():

if isObfuscated(field):

name = determineNameByFieldType(field)

rename(field, name)

for mtd in codeUnit.getMethods():

if isObfuscated(mtd):

name = determineNameByArgsType(field)

rename(field, name)

例如, class IiIiIiIi是继承于class iIiIiIiI, 而iIiIiIiI又继承于Activity/实现了onClickListener, 那么我们就可以使用Activity/onClickListener作为基准重命名两个被混淆的类. 这里的关键在于一个递归获取基类的函数, 如下所示:

'''

clzElement is ICodeClass retrieved from ICodeUnit.getClass()

'''

def tryDetermineGodeName(self, clzElement):

javaunit = self.decomp.decompile(clzElement.getAddress())

clzElement = javaunit.getClassElement()

#now clzElement is a IJavaClass

if not isFuckingName(clzElement.getName()):

#this is a non-obfuscated name, just return it

return clzElement.getName()

ssupers = clzElement.getImplementedInterfaces()

supers = []

supers.extend(ssupers)

# do not directly append on returned list!

superSig = clzElement.getSupertype().getSignature()

supers.append(clzElement.getSupertype())

for superItem in supers:

sig = superItem.getSignature()

if sig == "Ljava/lang/Object;":

#extend from java/lang/Object gives us zero info

#so try next

continue

if not isFuckingName(sig):

#return first non-obfuscated name

return sig

resolvedType = self.targetUnit.getClass(sig)

if resolvedType:

#this is a concret class

guessedName = self.tryDetermineGoodName(resolvedType)

if guessedName:

return guessedName

else:

#this is a SDK class

return sig

#cannot determine name from its supers, return None

return None

相对来讲, method和field的重命名就简单了很多, 如附代码所示, 在此不再赘述.

这里还有一个小细节, 因为需要操作的类比较多, 我们将插件定义为后台运行, 这样可以不阻塞UI, 同时获得更好的log效果.

重命名后的效果如下:

可以看到我们恢复出了较多可读信息. 完整代码: https://gist.github.com/flankerhqd/ca92b42f1f796763e5d1f8cd73247a30

总结

JEB2的API相对于JEB1组织层次更多, 也就没那么直观. 但有了初步了解之后, 也可以很快掌握使用方法. 测试版本: JEB2 2.3.4

Ref:

http://blog.csdn.net/weixin_37556843/article/details/66476295

https://www.pnfsoftware.com/jeb2/apidoc/reference/packages.html

https://groups.google.com/forum/#!topic/jeb-decompiler

jeb安装教程_JEB2插件教程之一相关推荐

  1. Visual Studio Code安装(软件及插件)教程

    官网下载地址https://code.visualstudio.com/Download 百度网盘下载链接分享 链接:https://pan.baidu.com/s/1fTb4aG91N_Z-3VGk ...

  2. Pycharm2020.1安装中文语言插件教程,不需要汉化

    方法一(在专业版和社区版都搜索不到插件): 1.安装好Pycharm并打开Pycharm 2.打开File,找到Settings并打开 3.打开Settings中的Pulgins,选择Marketpl ...

  3. thinkcmf搭建教程_ThinkCMF插件教程之写个HelloWorld插件

    前言 趁着有时间,学习一波插件,插件是个好东西,希望人人都会写. 环境 语言:php5.6 框架:ThinkCMF 教程开始 1. 编写插件 创建插件配置文件:创建插件主类文件:在根目录的plugin ...

  4. Activiti6.0教程 Eclipse安装Activiti Diagram插件(一)

    最近这段时间打算出一个Activiti6.0的详细教程,Activiti作为一个流行的开源工作流引擎,正在不断发展,其6.0版本以API形式提供服务,而之前版本基本都是要求我们的应用以JDK方式与其交 ...

  5. notepad++安装NPPJSONViewer插件教程

    首先,下载notepad++并安装. notepad++官网我们一般是进不去的,无法从官网下载: 但是github上有release版本可以免费下载:Notepad++ release下载 很多安装j ...

  6. IDEA 2022 常用 插件 安装 与 全局配置 教程 大全

    IDEA 2022 常用 插件 安装 与 全局配置 教程 大全 文章目录 IDEA 2022 常用 插件 安装 与 全局配置 教程 大全 一. 安装必备插件 1. Codota 代码智能提示插件 2. ...

  7. Chrome安装油猴插件详细教程

    Chrome安装油猴插件详细教程 一.油猴安装方法 方法一:Google官方商店安装(推荐,需要科学上网) 方法二:本地安装(无需科学上网,不会科学上网的适用) 二.安装油猴插件 方法一:Google ...

  8. IDEA安装教程及插件推荐

    目录 使用Jetbrains Toolbox安装(推荐) Windows版手动安装教程 Ubuntu版手动安装教程 推荐插件 中文语言包 CodeGlance Pro Rainbow Brackets ...

  9. vsCode安装使用教程和插件安装

    vsCode安装使用教程 vsCode是什么 vsCode安装 vsCode汉化 vsCode常用命令说明 vsCode左边图标说明 vsCode基本使用 前端常用插件 在vosCode中显示html ...

  10. 【Ubuntu 16.04中为Chromium、Chrome、Firefox安装Flash播放器插件教程】

    Ubuntu 16.04中为Chromium.Chrome.Firefox安装Flash播放器插件教程: Ubuntu 16.04中安装Chromium浏览器  http://www.linuxidc ...

最新文章

  1. IP BASE对OSPF的支持版本
  2. 神经网络的反向传导到底是在干什么?
  3. html5赛车小游戏,html5公路赛车小游戏
  4. Web API 实现JSONP或者安装配置Cors跨域
  5. 如何比较 Java 的字符串
  6. 真的没办法一心一意麽? php 文件操作
  7. python根据字典绘制条形图_使用 Bokeh 为你的 Python 绘图添加交互性 | Linux 中国
  8. 想换行做 5G 的开发者到底该咋办?
  9. v8:: fatalProcessOutOfMemory
  10. 【生信进阶练习1000days】day11day12-GEO data mining
  11. Ubuntu源码安装gcc-10
  12. 台式计算机时间跳动,电脑时间总是自动跳
  13. 云计算发展趋势-华为HCIA云计算学习笔记六
  14. 【coq】函数语言设计 笔记 07 - indProp
  15. smith 图中Q值和阻抗匹配
  16. PlatformIO使用Arduino[Ticker]库(ESP8266)
  17. 周志华 《机器学习初步》 绪论
  18. Substance Painter里 AO贴图 烘焙黑图 原因
  19. 域名批量查询 到期未续费域名查询
  20. c语言int x=3,C语言 设有 int x=11,则表示式((x++)*1/3)的值是几,为啥子

热门文章

  1. openssl--生成RSA公钥和私钥
  2. 读取 system serial number
  3. 软件测试方法可以分为几种?
  4. MapGuide Maestro 3.0发布
  5. 数据挖掘技术基本任务
  6. oracle10g在win10上的安装
  7. LordPE关闭重定位 alsr
  8. 模拟退火算法求解最优化问题
  9. 第八章--注册码是怎样炼成的
  10. Springboot整合junit单元测试