前言
經(jīng)常做逆向的同學應(yīng)該不陌生這個軟件,頭幾天想分析一下太極的實現(xiàn)原理贰锁,看了一下,發(fā)現(xiàn)他對常用對字符串進行加密操作茂腥。
預(yù)覽
算法
經(jīng)過研究發(fā)現(xiàn)是使用了一個叫:StringFog 的插件捐名,并且算法使用的是xor也沒有做對應(yīng)的修改装悲。
知道了算法嘁傀,那么解碼起來就比較簡單了载荔,先使用IDEA寫個解密腳本和敬。
public class gs {
public static byte[] decode(byte[] arg7, String arg8) {
int v3 = 0;
for(int i = 0; v3 < arg7.length; ++i) {
if(i >= arg8.length()) {
i = 0;
}
arg7[v3] = ((byte)(arg7[v3] ^ arg8.charAt(i)));
++v3;
}
return arg7;
}
}
我當時是自己擼的凹炸,后面發(fā)現(xiàn)StringFog才知道源碼 ??
Github算法可能會隨著時間進行更新 此解碼非永久有效
文章編寫時間:2020-06-02
腳本
如何編寫一個JEB腳本,其實很簡單昼弟,但是要閱讀大量的英文文檔啤它,并且沒有找到對應(yīng)的中文文檔,只能硬著頭皮讀私杜,對于為這樣英語基礎(chǔ)為零的菜鳥蚕键,真的是痛苦無比。
好在網(wǎng)上有前人寫的demo衰粹,這里稍做修改就可以正常解碼了锣光。
#coding=utf-8
from com.pnfsoftware.jeb.client.api import IScript, IconType, ButtonGroupType
from com.pnfsoftware.jeb.core import RuntimeProjectUtil
from com.pnfsoftware.jeb.core.units.code.java import IJavaSourceUnit
from com.pnfsoftware.jeb.core.units.code import ICodeUnit, ICodeItem
from com.pnfsoftware.jeb.core.output.text import ITextDocument
from com.pnfsoftware.jeb.core.units.code.java import IJavaSourceUnit, IJavaStaticField, IJavaNewArray, IJavaConstant, IJavaCall, IJavaField, IJavaMethod, IJavaClass
from com.pnfsoftware.jeb.core.events import JebEvent, J
from com.pnfsoftware.jeb.core.util import DecompilerHelper
import base64
# 密碼,轉(zhuǎn)換成char類型數(shù)組
password = [88, 105, 97, 111, 109, 97, 111]
# 解碼的方法報名 以及方法名
methodName = ['Landroid/a/rc;','a']
class ReString(IScript):
def run(self, ctx):
print('start deal with strings')
self.ctx = ctx
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
units = RuntimeProjectUtil.findUnitsByType(projects[0], IJavaSourceUnit, False)
for unit in units:
javaClass = unit.getClassElement()
print('[+] decrypt:'+javaClass.getName())
self.cstbuilder = unit.getFactories().getConstantFactory()
self.processClass(javaClass)
unit.notifyListeners(JebEvent(J.UnitChange))
print('Done.')
def processClass(self ,javaClass):
if javaClass.getName() == methodName[0]:
return
for method in javaClass.getMethods():
block=method.getBody()
i = 0 ;
while i < block.size():
stm = block.get(i)
self.checkElement(block ,stm)
i += 1
def checkElement(self,parent,e):
try:
if isinstance(e,IJavaCall):
mmethod = e.getMethod()
mname = mmethod.getName()
msig = mmethod.getSignature()
if mname == methodName[1] and methodName[0] in msig :
v=[]
for arg in e.getArguments():
if isinstance(arg , IJavaConstant):
v.append(arg.getString())
if len(v) == 1 :
decstr = self.decryptstring(v[0])
parent.replaceSubElement(e, self.cstbuilder.createString(decstr))
for subelt in e.getSubElements():
if isinstance(subelt, IJavaClass) or isinstance(subelt, IJavaField) or isinstance(subelt, IJavaMethod):
continue
self.checkElement(e,subelt)
except:
print ('error')
def decryptstring(self,string):
src = []
keylen = len(password)
data = base64.decodestring(string)
for index , char in enumerate(data):
src.append( chr(ord(char) ^ password[index % keylen ]))
return ''.join(src).decode('unicode_escape')
效果
建議
- 解碼函數(shù)直接丟到native層铝耻,包括xor算法
- 使用美團的方案對jeb抵抗誊爹,僅jadx處理壓力比較大
- 一些核心的方法調(diào)用盡量考慮用線程回調(diào),如rxjava瓢捉,eventbus等
- bean文件要混淆啊
備注
參考文章: