dex字符串解密_De-obfuscation反混淆_解密字符串_ jeb script

小技巧

(1) 如果混淆的类名中出现过于复杂的Aeabffdccdac这种类型的类名,明显是经过手动更改的,所以有可能就是恶意的软件,因为大部分正规开发这只用商用的混淆器,混淆成 (a, b, c, etc.) 这种,不会过于复杂

https://rednaga.io/images/hacking-with-dex-oracle-for-android-malware-deobfuscation/class_list.png

导出Jar包流程,简单的jeb脚本

import jeb.api.IScript;

import jeb.api.JebInstance;

public class jeb_javaScript implements IScript{

@Override

public void run(JebInstance instance) {

// TODO Auto-generated method stub

instance.print("sample java script of jeb");

}

}

导出jar包时,如果使用默认的elipse配置的MANIFEST.MF,会报错

导入Jar插件出错,manifest中没有JEB插件-类属性 产生错误,不能导入程序

解决:入口类设置成类似这样:JebPlugin-entryclass: jeb_javaScript,不要使用Main-Class: jeb_javaScript

2018-09-27_185634.png

2018-09-27_185716.png

最后要保证清单文件中,至少包含这两个属性

2018-09-27_190338.png

DecryptStrings

java的解密字符串脚本 -> 传送门

这里根据JEB官网脚本传送门,来学习和编写

ast:抽象语法树,每一个节点代表源代码中的一种语法结构(while,if-else,return...)

source code

Jeb_PythonScript.py

# coding: utf8

# 这个第三方库在jeb工具doc目录下的apidoczip包里,所以脚本需要存放在plugins目录里

from jeb.api import IScript

from jeb.api.dex import Dex

from jeb.api import EngineOption

from jeb.api.ui import View

from jeb.api.ast import Class, Field, Method, Call, Constant, StaticField, NewArray

# jeb根据文件名,实例化类,执行run函数来实现整个流程

class Jeb_PythonScript(IScript):

# jeb脚本的运行函数

def run(self, jeb):

# 获取当前运行的jeb对象

self.jeb = jeb

# 当前被jeb处理的dex文件对象

self.dex = jeb.getDex()

# 获取一个AST的实例对象(包含各种语法结构,if-else,return...)

self.constant = Constant.Builder(jeb)

# 指定需要扫描的类

self.scanClassname = 'Lfree/vpn/proxy/unblock/android/easy/app/c/c;'

# 可以使用dex.getClassSignatures获取所有被签名的类名,找到指定的类名

# 反编译指定类成java代码,来判断是否找到了该类

r = jeb.decompileClass(self.scanClassname)

# 解密方法的索引

self.decryptmethodindex = None

# 调用解密方法的方法列表

self.callDecryptmthodlist = None

# 根据加密函数中用到的字符列表的类型标识来填写

wanted_flags = Dex.ACC_STATIC|Dex.ACC_FINAL|Dex.ACC_PROTECTED

if not r:

print "could not find class %s" %self.scanClassname

# 获取这个类的抽象语法树对象

classASTobj = jeb.getDecompiledClassTree(self.scanClassname)

# 获取语法树对象的字段

for rootfield in classASTobj.getFields():

# 字段的签名(也就是声明的变量)

fieldsignlist = rootfield.getSignature().split('\n')

# 过滤出解密函数中用到的char类型列表

for siglefieldsign in fieldsignlist:

if siglefieldsign.endswith(':[C'):

fielddata = self.dex.getFieldData(siglefieldsign)

# 该字段的访问标识(i.e.protected static final char[] d;中的protected static final)

if fielddata.getAccessFlags() == wanted_flags:

print "find parameter character list : %s" %siglefieldsign

"""

根据解密需要的参数列表的引用情况,找到引用他的解密函数

遍历出所有调用这个解密方法的地方

然后执行解密函数,并用解密的结果替换调用地方的内容

"""

# 获取解密函数签名(完整路径),因为只取名字会有重复

listindex = fielddata.getFieldIndex()

# 根据提供的字段索引,检索出所有引用他的方法列表(列表中是方法的索引)

for siglemthodindex in self.dex.getFieldReferences(listindex):

# 获取这个索引所代表的原版方法

self.decryptmethodindex = siglemthodindex

methodname = self.dex.getMethod(siglemthodindex).getSignature(False)

if '' not in methodname and methodname != "":

self.decryptmethodname = methodname

print "*********************************************************************"

print "[+] found decrypt method: %s" %self.dex.getMethod(siglemthodindex).getSignature(False)

break

"""

获取所有函数对象,找到调用解密方法的地方

"""

# 根据解密方法的索引,获取调用这个解密方法的方法对象(int型的索引)列表

# callDecryptmthodlist:(DexMethod型)方法对象列表

referenceMethodList = self.dex.getMethodReferences(self.decryptmethodindex)

for sigleindex in referenceMethodList:

if self.callDecryptmthodlist == None:

self.callDecryptmthodlist = [self.dex.getMethod(sigleindex)]

else:

self.callDecryptmthodlist.append(self.dex.getMethod(sigleindex))

print "*********************************************************************"

for mobj in self.callDecryptmthodlist:

print "[+] find method which call decrypt method: %s" %mobj.getSignature(False)

print "*********************************************************************"

# 在这个调用解密方法的方法中,找到解密方法的具体位置

# 获取这个方法对象的抽象树上的所有元素节点

decryptElements = self.jeb.getDecompiledMethodTree(mobj.getSignature(True)).getSubElements()

#

# self.findPositionCallDecryptMthod(decryptElements)

self.findPositionCallDecryptMthod(decryptElements)

# 检查方法元素的各个节点,找到调用解密函数的具体位置

def findPositionCallDecryptMthod(self, dts):

# 解密方法的抽象语法树

call = None

# 遍历全部元素节点找到解密函数的调用地方

for i in dts:

# 如果当前元素节点不是一个方法调用对象,就遍历该元素节点内的所有节点

if not isinstance(i, Call):

subElements = i.getSubElements()

self.findPositionCallDecryptMthod(subElements)

continue

# 当前元素是函数调用对象的前提下,判断是否为解密函数

# 只能使用签名来判断,不能使用对象值来判断,因为对象字段如"jeb.api.dex.DexMethod@161b6ca"不一样,一个是调用函数对象,一个是声明函数对象)

if i.getMethod().getSignature() != self.decryptmethodname:

subElements = i.getSubElements()

self.findPositionCallDecryptMthod(subElements)

# print subElements

continue

call = i

# 获取其参数

if call != None:

for i in call.getArguments():

print i.getLeft().getLeft()

# 这里是解密方法,相当于将源码中的解密方法,赋值过来,和我最开始想的是,直接传入参数,调用反编译后的解密方法

def decrypt():

...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值