python 插件
python 插件编写文档

反混淆
需要mapping.txt配合 

 #coding=utf-8

#?description=Create JEB2DeobscureClass (Android Debug Bridge) wrappers and adb utility objects

#?shortcut=

from gettext import find

from pickle import NONE

import re

import string

from unittest import result

from com.pnfsoftware.jeb.client.api import IScript

from com.pnfsoftware.jeb.core import RuntimeProjectUtil

from com.pnfsoftware.jeb.core.units.code import ICodeUnit, ICodeItem

from com.pnfsoftware.jeb.core.units.code.android import IDexUnit

from com.pnfsoftware.jeb.core.actions import Actions, ActionContext, ActionCommentData, ActionRenameData,ActionMoveToData,ActionMoveToPackageData,ActionCreatePackageData

from java.lang import Runnable

from com.pnfsoftware.jeb.client.api import IScript

from com.pnfsoftware.jeb.client.api import IScript, IGraphicalClientContext

from com.pnfsoftware.jeb.core import RuntimeProjectUtil

from com.pnfsoftware.jeb.core.actions import Actions, ActionContext, ActionXrefsData

from com.pnfsoftware.jeb.core.events import JebEvent, J

from com.pnfsoftware.jeb.core.output import AbstractUnitRepresentation, UnitRepresentationAdapter

from com.pnfsoftware.jeb.core.units.code import ICodeUnit, ICodeItem

from com.pnfsoftware.jeb.core.units.code.java import IJavaSourceUnit, IJavaStaticField, IJavaNewArray, IJavaConstant, IJavaCall, IJavaField, IJavaMethod, IJavaClass

from com.pnfsoftware.jeb.core.actions import ActionTypeHierarchyData

from com.pnfsoftware.jeb.core.actions import ActionRenameData

from com.pnfsoftware.jeb.core.util import DecompilerHelper

from com.pnfsoftware.jeb.core.output.text import ITextDocument

from com.pnfsoftware.jeb.core.units.code.android import IDexUnit

from com.pnfsoftware.jeb.core.actions import ActionOverridesData

from com.pnfsoftware.jeb.core.units import UnitUtil

from com.pnfsoftware.jeb.core.units import UnitAddress

import threading

# from Reader import Reader, Resource

import os.path, time, sys

# from Reader import Reader, Resource, allClassEntry

curPosition = 0

textLine = []

allClassEntry = {}

rlock = threading.RLock()

 

"""

Sample script for JEB Decompiler.

This script shows how to create and use Android Debug Bridge (adb) wrappers and adb utility objects.

Reference: AdbWrapperFactory, AdbWrapper, AndroidDeviceUtil

"""

class DeGurd(IScript):

 def __init__(self):

 path = os.path.dirname(os.path.realpath(__file__))

 self.readerFile(path + "/../mapping.txt")

 def readerFile(self, fileName):

 starttime = time.clock()

 #线程数

 threadNum = 4

 #文件

 res = Resource(fileName)

 threads = []

 #初始化线程

 for i in range(threadNum):

 rdr = Reader(res)

 threads.append(rdr)

 #开始线程

 for i in range(threadNum):

 threads[i].start()

 #结束线程

 # result = {};

 for i in range(threadNum):

 threads[i].join()

 # result[i] = threads[i].getResult();

 

 # file =open('D:/data.txt','w')

 # for key in allClassEntry :

 # file.write("class: " + key + ", origalClassName" + allClassEntry[key].getOrigalClassName() + "\n")

 # methods = allClassEntry.get(key).getMethodEntry();

 # members = allClassEntry.get(key).getMemberEntry();

 # if NONE == methods:

 # continue

 # for method in methods:

 # file.write(" confusionmethod: " + method + ", origalMethodName" + methods[method].getOrigalMethodName() + "\n")

 

 # if NONE == members:

 # continue

 

 # for member in members:

 # file.write(" confusionmember: " + member.getConfusionMemberName() + ", origalMemberName" + member.getOrigalMemberName() + "\n")

 

 # file.close()

 return

 

 def run(self, ctx):

 ctx.executeAsync("Running deobscure class ...", JEB2AutoRename(ctx))

 print('Done')

class JEB2AutoRename(Runnable):

 def __init__(self, ctx):

 print ("__file__=%s" % __file__)

 self.ctx = ctx

 # 逻辑开始

 self.debug = 0 #0=False, 1=True

 self.ctx = ctx

 self.errMsg1 = u'请移动鼠标，将光标输入点放到源码文件中的函数名称处~然后使用F2快捷键运行此脚本(JEB 中 F2快捷键的功能是运行最近使用的脚本)'

 self.errMsg2 = u'未输入新函数名称，脚本已退出'

 # 获取所有重载了此方法的函数清单，然后逐个重命名

 self.nTotal = 0

 self.nSucc = 0

 self.nFail = 0

 

 # for key in allClassEntry:

 # print("key: %s" % key)

 

 def run(self):

 ctx = self.ctx

 # print(allClassEntry);

 engctx = ctx.getEnginesContext()

 if not engctx:

 print('Back-end engines not initialized')

 return

 projects = engctx.getProjects()

 if not projects:

 print('There is no opened project')

 return

 prj = projects[0]

 units = RuntimeProjectUtil.findUnitsByType(prj, IDexUnit, False)

 try:

 for unit in units:

 classes = unit.getClasses()

 if not classes:

 continue

 self.parseClass(classes, unit)

 

 except Exception , e:

 print ( e) 

 # 分析类

 def parseClass(self, classes, unit):

 for clazz in classes:

 sourceIndex = clazz.getSourceStringIndex()

 clazzAddress = clazz.getAddress()

 

 # if sourceIndex == -1 or '$' in clazzAddress:# Do not rename inner class

 # # print('without have source field', clazz.getName(True))

 # continue

 sourceStr = str(unit.getString(sourceIndex))

 if '.java' in sourceStr:

 sourceStr = sourceStr[:-5]

 

 className = clazz.getName(True)

 # if className!= sourceStr:

 

 package= clazz.getAddress(True)

 # print("package: %s, className: %s" % (package, className))

 package = package[1:len(package) - 1]

 package = package.replace("/", ".")

 # print("package: %s" % package) 

 # completeClassName = package + "." + className

 # if "a.b" != package:

 # continue

 classEntry = allClassEntry.get(package)

 

 # print("package: %s" % package);

 if not classEntry :

 continue

 

 originalName = classEntry.getOrigalClassName()

 # print(" classEntry.getOrigalClassName(): %s" % classEntry.getOrigalClassName())

 # print("method: " % method)

 self.comment_class(unit, clazz, originalName) # Backup origin clazz name to comment

 self.rename_class(unit, clazz, originalName, True) # Rename to source name

 methodsEntry = classEntry.getMethodEntry(); 

 self.renameMethodName(methodsEntry, clazz, unit)

 

 memberEntry = classEntry.getMemberEntry()

 self.renameMemberName(classEntry, clazz, unit)

 self.moveToPackage(unit, clazz, classEntry)

 

 

 # 修改属性名称

 # classEntry mapping.txt 所组装的类信息

 def renameMemberName(self, classEntry, clazz, unit):

 fieldEntry = classEntry.getMemberEntry()

 if not fieldEntry:

 print ("没有属性")

 return

 

 originName = None

 pos = 0

 print("\n")

 for field in clazz.getFields():

 

 fieldName = field.getName(True)

 # print("fieldName: %s" % fieldName)

 confusionEntry = fieldEntry.get(fieldName)

 

 # print(confusionEntry)

 pos = fieldName.find("$")

 if None != confusionEntry:

 originName = confusionEntry.getOrigalMemberName();

 self.realRename(field, originName, unit)

 # elif -1 != pos:

 # 匿名内部类

 # anonymousInnerClassName = field.getAddress();

 # print("address: %s" % anonymousInnerClassName)

 # anonymousInnerClassName = anonymousInnerClassName[1:anonymousInnerClassName.find(";")]

 # anonymousInnerClassName = anonymousInnerClassName.replace("/", ".")

 # anonymousInnerEntry = classEntry.getAnonymousInnerClassEntry();

 # anonymousInnerClass = anonymousInnerEntry.get(anonymousInnerClassName);

 # newName = anonymousInnerClass.getOrigalAnonymousInnerClassName()

 

 # self.realRename(field, newName, unit)

 # print ("anonymousInnerClassName: %s" % anonymousInnerClassName)

 

 # classEntry 从 mapping.txt 中提取的信息

 # clazz 当前 字节码信息

 def renameMethodName(self, methodsEntry, clazz, unit):

 # className = classEntry.getOrigalClassName()

 if not methodsEntry:

 print ("没有方法")

 return

 

 # for key in methodsEntry:

 # print ("key: %s, original: %s" % (key, methodsEntry.get(key).getOrigalMethodName()))

 # print ("className: %s" % className)

 # 处理方法名字

 for method in clazz.getMethods():

 # print("value: " % value)

 

 # print("method: " % method)

 confusionName = method.getName()

 # print("confusionName: %s" % (confusionName))

 current = methodsEntry.get(confusionName);

 # print (current)

 if not current:

 continue

 

 originName = current.getOrigalMethodName();

 # print ("originName: %s" % originName)

 self.realRename(method, originName, unit)

 # method = clazz.getMethod(clazz.getAddress, True, True);

 def rename_class(self, unit, originClazz, sourceName, isBackup):

 actCtx = ActionContext(unit, Actions.RENAME, originClazz.getItemId(), originClazz.getAddress())

 actData = ActionRenameData()

 # dir(actData)

 # print("sourceNameFront: %s" % sourceName)

 length = len(sourceName);

 lastPos = sourceName.rfind(".", 0, length)

 posDoller = sourceName.find("$")

 if -1 != posDoller:

 sourceName = sourceName[posDoller+1: length]

 elif -1 != lastPos:

 sourceName = sourceName[lastPos + 1: length]

 

 # print("sourceNameAfter: %s" % sourceName)

 actData.setNewName(sourceName)

 # print('sourceName: %s !' % sourceName)

 if unit.prepareExecution(actCtx, actData):

 try:

 result = unit.executeAction(actCtx, actData)

 # if result:

 # print('rename to %s success!' % sourceName)

 # else:

 # print('rename to %s failed!' % sourceName)

 except Exception, e:

 print (Exception, e)

 # Actions,

 # ActionContext,

 # ActionCommentData, ActionRenameData,ActionMoveToPackageData,ActionCreatePackageData

 # 修改包名

 def moveToPackage(self, unit, originClazz, classEntry):

 actCntx = ActionContext(unit, Actions.CREATE_PACKAGE, originClazz.getItemId(), originClazz.getAddress())

 actData = ActionCreatePackageData()

 packageName = classEntry.getOrigalClassName();

 packageName = packageName.replace(" ", "");

 # print("packageName: %s\n" % packageName)

 actData.setFqname (packageName[0: packageName.rfind(".")])

 

 if(unit.prepareExecution(actCntx, actData)):

 try:

 bRlt = unit.executeAction(actCntx, actData)

 if(not bRlt):

 print('executeAction fail!')

 except Exception, e:

 print (e)

 actCntx = ActionContext(unit, Actions.MOVE_TO_PACKAGE, originClazz.getItemId(), originClazz.getAddress())

 actData = ActionMoveToPackageData ()

 confusionMemberName = classEntry.getConfusionClassName();

 confusionMemberNameTxt = confusionMemberName[0:confusionMemberName.rfind(".")]

 specifical = packageName[0: packageName.rfind(".")];

 actData.setCurrentPackageFqname("L" + confusionMemberNameTxt+"/")

 actData.setDstPackageFqname ("L" + specifical+"/")

 # print("specifical: %s, confusionMemberNameTxt: %s\n" % (specifical, confusionMemberNameTxt))

 if(unit.prepareExecution(actCntx, actData)):

 try:

 bRlt = unit.executeAction(actCntx, actData)

 except Exception, e:

 print (e)

 print('total:%d succ:%d fail:%d' %(self.nTotal, self.nSucc, self.nFail))

 print('Done.')

 

 return

 def parseMethod(self, unit, originClazz, newMethodName):

 # 弹出输入框用以输入新函数名

 # newMethodName = self.ctx.displayQuestionBox('input new function name', 'input new function name\n\n', '')

 # if newMethodName == None:

 # print(self.errMsg2)

 # return

 

 actCntx = ActionContext(unit, Actions.QUERY_OVERRIDES, originClazz.getItemId(), originClazz.getAddress())

 actData = ActionOverridesData()

 

 

 if(self.focusUnit.prepareExecution(actCntx, actData)):

 try:

 bRlt = self.focusUnit.executeAction(actCntx, actData)

 if(not bRlt):

 print('executeAction fail!')

 else:

 overrideAddrList = actData.getAddresses()

 self.nTotal = len(overrideAddrList)

 for addr in overrideAddrList:

 #print('renaming %s' % addr)

 if(self.realRename(addr, newMethodName)):

 self.nSucc += 1

 else:

 self.nFail += 1

 if(self.debug):

 break;

 except Exception, e:

 print (e)

 

 print('total:%d succ:%d fail:%d' %(self.nTotal, self.nSucc, self.nFail))

 print('Done.')

 

 

 

 

 # 对指定函数进行重命名

 def realRename(self, method, newMethodName, unit):

 # m = self.GetMethodByAddress(methodAddr)

 m = method 

 if(not m):

 print(u'失败 %s' % m)

 return False

 

 actCntx = ActionContext(unit, Actions.RENAME, m.getItemId(), m.getAddress())

 actData = ActionRenameData()

 actData.setNewName(newMethodName)

 

 if(unit.prepareExecution(actCntx, actData)):

 # 执行重命名动作

 try:

 bRlt = unit.executeAction(actCntx, actData)

 if(not bRlt):

 (u'失败 %s' % method.getName())

 else:

 print('%s => %s' %(method.getName(), newMethodName))

 return True

 except Exception,e:

 print (e)

 return False

 ## end of realRename

 

 

 

 # def GetUnitByAddress(self, addr):

 # decomp = DecompilerHelper.getDecompiler(self.focusUnit2)

 # if not decomp:

 # print('There is no decompiler available for code unit %s' % self.focusUnit2)

 # return

 

 # tmpUnit = decomp.decompile(addr)

 # self.ctx.openView(tmpUnit)

 # if(self.ctx.getFocusedView().getActiveFragment().setActiveAddress(methodAddr)):

 # print('setActiveAddress succ')

 # return tmpUnit

 ## end of GetUnitByAddress

 

 

 def GetMethodByAddress(self, addr):

 found = 0

 self.codeUnit = RuntimeProjectUtil.findUnitsByType(self.prj, ICodeUnit, False)

 if(not self.codeUnit):

 return None

 for unit in self.codeUnit:

 classes = unit.getClasses()

 if(not classes):

 continue

 for c in classes:

 cAddr = c.getAddress()

 if(not cAddr):

 continue

 if(addr.find(cAddr) == 0):

 mlist = c.getMethods()

 if(not mlist):

 continue

 for m in mlist:

 mAddr = m.getAddress()

 if(addr == mAddr):

 #print(mAddr)

 return m

 return None

 def comment_class(self, unit, originClazz, commentStr):

 actCtx = ActionContext(unit, Actions.COMMENT, originClazz.getItemId(), originClazz.getAddress())

 actData = ActionCommentData()

 actData.setNewComment(commentStr)

 if unit.prepareExecution(actCtx, actData):

 try:

 result = unit.executeAction(actCtx, actData)

 # if result:

 # print('comment to %s success!' % commentStr)

 # else:

 # print('comment to %s failed!' % commentStr)

 except Exception, e:

 print (Exception, e)

class MethodEntry:

 def __init__(self, confusionMethodName, origalMethodName):

 self.confusionMethodName = confusionMethodName

 self.origalMethodName = origalMethodName

 

 def getConfusionMethodName(self):

 return self.confusionMethodName

 

 def getOrigalMethodName(self):

 return self.origalMethodName

 def __getattribute__(self, name):

 

 return self[name]

# 内名内部类 节点

class AnonymousInnerClass:

 def __init__(self, confusionAnonymousInnerName, origalAnonymousInnerClassName):

 self.confusionAnonymousInnerName = confusionAnonymousInnerName;

 self.origalAnonymousInnerClassName = origalAnonymousInnerClassName;

 

 def getConfusionAnonymousInnerName(self):

 return self.confusionAnonymousInnerName

 def getOrigalAnonymousInnerClassName(self):

 return self.origalAnonymousInnerClassName

 def setConfusionAnonymousInnerName(self, confusionAnonymousInnerName):

 self.confusionAnonymousInnerName = confusionAnonymousInnerName;

 def getOrigalAnonymousInnerClassName(self):

 return self.origalAnonymousInnerClassName

 

 

class MemberEntry:

 def __init__(self, confusionMemberName, origalMemberName):

 self.confusionMemberName = confusionMemberName

 self.origalMemberName = origalMemberName

 

 def getConfusionMemberName(self):

 return self.confusionMemberName

 def getOrigalMemberName(self):

 return self.origalMemberName

 def __getattribute__(self, name):

 

 return self[name]

class ClassEntry:

 """

 confusionClassName 混淆后的类名

 origalClassName 原来的类名

 methodEntry:MethodEntry

 """

 def __init__(self, confusionClassName, origalClassName):

 self.confusionClassName = confusionClassName

 self.origalClassName = origalClassName

 self.methodEntry = {}

 self.memberEntry = {}

 self.anonymousInnerClass = {}

 

 def getConfusionClassName(self):

 return self.confusionClassName

 

 def setMethodEntry(self, methodEntry):

 self.methodEntry[methodEntry.getConfusionMethodName()] = (methodEntry)

 def setMemberEntry(self, memberEntry):

 self.memberEntry[memberEntry.getConfusionMemberName()] = memberEntry;

 def setAnonymousInnerClassEntry(self, anonymousInnerClass):

 self.anonymousInnerClass[anonymousInnerClass.getConfusionAnonymousInnerName()] = anonymousInnerClass

 

 def getAnonymousInnerClassEntry(self):

 return self.anonymousInnerClass 

 

 def getMemberEntry(self):

 return self.memberEntry

 

 def getMethodEntry(self):

 return self.methodEntry

 

 def getOrigalClassName(self):

 return self.origalClassName

 def __getattribute__(self, name):

 

 return self[name]

class Reader(threading.Thread):

 def __init__(self, res):

 self.res = res

 super(Reader, self).__init__()

 self.result = {}

 self.spaceReal = " "

 self.spaceCount = 4

 def getResult(self):

 return self.result;

 """

 m.i$a -> tree.Handle

 m.i$a a -> d

 m.i$a b -> c

 m.i$a c -> a

 m.i$a d -> b

 m.i$a e -> RIGHT

 m.i$a[] f -> $VALUES

 """

 # spaceCount: int 方法及属性空格数量

 # line 当前行

 # classEntry 当前要组装的类

 def parseMethodAndMember(self, spaceCount, line, classEntry):

 line = line[spaceCount: len(line)]

 pos = line.find("->");

 left = line[0: pos - 1]

 firstSpacePos = left.find(" ")

 

 bracketsPos = left.find("(");

 

 if -1 != pos:

 if -1 != bracketsPos: 

 # left = left.replace(" ", "")

 classEntry.setMethodEntry(MethodEntry(left[firstSpacePos+1: bracketsPos], line[pos+3: len(line) - 1]))

 else:

 # 寻找第一个空格的位置 方法

 # print("left : %s" % i.getConfusionMemberName())

 # firstSpacePos = left.find(" ")

 right = line[pos + 3: len(line) - 1]

 # right = right.replace("\n", "")

 classEntry.setMemberEntry(MemberEntry(

 line[firstSpacePos + 1: pos - 1], right

 ))

 # 

 def parseFileLBlock(self, pos, endPosition, fstream):

 global allClassEntry

 classEntry = None

 while pos < endPosition:

 line = fstream.readline()

 space = line[0: self.spaceCount]

 if space == self.spaceReal:

 self.parseMethodAndMember(self.spaceCount, line, classEntry)

 

 # 说明当前是包类名

 else:

 pos = line.find("->")

 if -1 == pos:

 continue

 

 # 判断是否是匿名内部类

 # posDoller = line.find("$")

 # if -1 != posDoller:

 # masterName = line[0: posDoller];

 # length = len(line) - 1

 # classEntry = allClassEntry.get(masterName)

 # anonymousInnerClass = AnonymousInnerClass(line[0: pos-1], line[pos+3: length])

 

 # if not classEntry:

 # classEntry = ClassEntry(masterName, line[pos+3: length])

 # classEntry.setAnonymousInnerClassEntry(anonymousInnerClass)

 # else:

 

 # classEntry.setAnonymousInnerClassEntry(anonymousInnerClass)

 # else:

 className = line[0:pos-1]

 classEntry = ClassEntry(className, line[pos+2: len(line) - 1])

 allClassEntry[classEntry.getConfusionClassName()] = (classEntry)

 # textLine.append(line);

 #处理line

 # print(line.strip())

 pos = fstream.tell()

 

 # 

 def run(self):

 global curPosition

 fstream = open(self.res.fileName, 'r')

 while True:

 #锁定共享资源

 rlock.acquire()

 startPosition = curPosition

 curPosition = endPosition = (startPosition + self.res.blockSize) if (startPosition + self.res.blockSize) < self.res.fileSize else self.res.fileSize

 #释放共享资源

 rlock.release()

 if startPosition == self.res.fileSize:

 break

 elif startPosition != 0:

 fstream.seek(startPosition)

 fstream.readline()

 pos = fstream.tell()

 self.parseFileLBlock(pos, endPosition, fstream)

 

 fstream.close()

 # self.result = allClassEntry;

 # print(allClassEntry[classEntry.getConfusionClassName()])

 # return allClassEntry

class Resource(object):

 def __init__(self, fileName):

 self.fileName = fileName

 #分块大小

 self.blockSize = 100000000

 self.getFileSize()

 #计算文件大小

 def getFileSize(self):

 fstream = open(self.fileName, 'r')

 fstream.seek(0, os.SEEK_END)

 self.fileSize = fstream.tell()

 fstream.close()