|
|
@@ -0,0 +1,1201 @@ |
|
|
import jeb.api.IScript; |
|
|
import jeb.api.JebInstance; |
|
|
import jeb.api.ast.*; |
|
|
import jeb.api.ast.Class; |
|
|
import jeb.api.dex.*; |
|
|
import jeb.api.ui.JavaView; |
|
|
import jeb.api.ui.View; |
|
|
|
|
|
import java.util.Arrays; |
|
|
import java.util.HashMap; |
|
|
import java.util.List; |
|
|
import java.util.regex.Pattern; |
|
|
|
|
|
/** |
|
|
* Created by AKosterin on 31/01/16. |
|
|
*/ |
|
|
public class DexGuardDecoder implements IScript { |
|
|
private static JebInstance mJebInstance; |
|
|
|
|
|
private static HashMap<String,byte[]> staticByteArrays; |
|
|
private static HashMap<String,Integer> staticIntegers; |
|
|
|
|
|
private static String decoderMethodSignature; |
|
|
|
|
|
private static boolean debug = false; |
|
|
|
|
|
@Override |
|
|
public void run(JebInstance jebInstance) { |
|
|
mJebInstance = jebInstance; |
|
|
mJebInstance.print("DexGuardDecoder_Start"); |
|
|
|
|
|
if (!mJebInstance.isFileLoaded()) { |
|
|
mJebInstance.print("Please load a dex file"); |
|
|
return; |
|
|
} |
|
|
|
|
|
Dex mDex = mJebInstance.getDex(); |
|
|
|
|
|
JavaView view = (JavaView) jebInstance.getUI().getView(View.Type.JAVA); |
|
|
|
|
|
String signature = view.getCodePosition().getSignature(); |
|
|
if (debug) mJebInstance.print(getClassFromSignature(signature)); |
|
|
|
|
|
Class mClass = mJebInstance.getDecompiledClassTree(getClassFromSignature(signature)); |
|
|
defineDecoderMethodSignature(mClass); |
|
|
|
|
|
if(!decoderMethodSignature.isEmpty()){ |
|
|
normalizeDecoderMethod(); |
|
|
initDecoderValues(mClass); |
|
|
|
|
|
for (Method mMethod : (List<Method>) mClass.getMethods()) { |
|
|
decodeMethod(mMethod); |
|
|
} |
|
|
} |
|
|
|
|
|
jebInstance.getUI().getView(View.Type.JAVA).refresh(); |
|
|
|
|
|
jebInstance.print("DexGuardStringDecoder_End"); |
|
|
// printAllOperators(); |
|
|
} |
|
|
|
|
|
private static void defineDecoderMethodSignature(Class mClass){ |
|
|
for (Method mMethod : (List<Method>) mClass.getMethods()) { |
|
|
String mMethodSignature = mMethod.getSignature(); |
|
|
|
|
|
if(mMethod.isStatic() && Pattern.matches("^.*[(][IBS]{3}[)]Ljava[/]lang[/]String[;]$",mMethodSignature.split(">")[1])){ |
|
|
decoderMethodSignature = mMethodSignature; |
|
|
if (debug) mJebInstance.print("decoderMethodSignature = " + decoderMethodSignature); |
|
|
return; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
private static void normalizeDecoderMethod(){ |
|
|
Method mMethod = mJebInstance.getDecompiledMethodTree(decoderMethodSignature); |
|
|
Block mMethodBodyBlock = mMethod.getBody(); |
|
|
|
|
|
int ifStmLine = 0; |
|
|
|
|
|
while(!(mMethodBodyBlock.get(ifStmLine) instanceof IfStm)){ |
|
|
ifStmLine++; |
|
|
if(ifStmLine == mMethodBodyBlock.size()){ |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
Block mElseBlock = ((IfStm)mMethodBodyBlock.get(ifStmLine)).getDefaultBlock(); |
|
|
Block mWhileBlock = Block.build(); |
|
|
|
|
|
int labelLine = 0; |
|
|
|
|
|
while(!(mElseBlock.get(0) instanceof Label)){ |
|
|
mMethodBodyBlock.insert(ifStmLine + labelLine, mElseBlock.get(0)); |
|
|
mElseBlock.remove(0); |
|
|
labelLine++; |
|
|
} |
|
|
|
|
|
|
|
|
for (int i = 0; i < mElseBlock.size() - 1; i++) { |
|
|
if(mElseBlock.get(i+1) instanceof IfStm){ |
|
|
IfStm mIfStm = (IfStm) mElseBlock.get(i+1); |
|
|
Predicate mIfPredicate = mIfStm.getBranchPredicate(0); |
|
|
Block mIfIfBlock = mIfStm.getBranchBody(0); |
|
|
Block mIfElseBlock = mIfStm.getDefaultBlock(); |
|
|
|
|
|
mWhileBlock.insert(mWhileBlock.size(), IfStm.build(mIfPredicate,mIfIfBlock)); |
|
|
for (int k = 0; k < mIfElseBlock.size(); k++) { |
|
|
mWhileBlock.insert(mWhileBlock.size(), mIfElseBlock.get(k)); |
|
|
} |
|
|
} else { |
|
|
mWhileBlock.insert(mWhileBlock.size(), mElseBlock.get(i + 1)); |
|
|
} |
|
|
} |
|
|
|
|
|
int size = mMethodBodyBlock.size() - ifStmLine - labelLine - 2; |
|
|
|
|
|
for (int i = 0; i < size; i++) { |
|
|
mWhileBlock.insert(mWhileBlock.size(), mMethodBodyBlock.get(ifStmLine + labelLine + 1)); |
|
|
mMethodBodyBlock.remove(ifStmLine+labelLine + 1); |
|
|
} |
|
|
|
|
|
mMethodBodyBlock.remove(ifStmLine + labelLine + 1); |
|
|
|
|
|
IExpression mIExpression = new Constant.Builder(mJebInstance).buildInt(1); |
|
|
|
|
|
Predicate mTruePredicate = Predicate.build(mIExpression, Operator.EQ, mIExpression); |
|
|
|
|
|
WhileStm mWhileStm = WhileStm.build(mTruePredicate,mWhileBlock); |
|
|
mMethodBodyBlock.replaceSubElement(mMethodBodyBlock.get(ifStmLine+labelLine), mWhileStm); |
|
|
} |
|
|
|
|
|
private static void initDecoderValues(Class mClass) { |
|
|
staticByteArrays = new HashMap<String,byte[]>(); |
|
|
staticIntegers = new HashMap<String, Integer>(); |
|
|
|
|
|
for (Method mMethod : (List<Method>) mClass.getMethods()) { |
|
|
if (mMethod.getName().equals("<clinit>")) { |
|
|
Block clinitMethodBlock = mMethod.getBody(); |
|
|
for (int i = 0; i < clinitMethodBlock.size(); i++) { |
|
|
if(clinitMethodBlock.get(i) instanceof Assignment){ |
|
|
Assignment mAssignment = (Assignment) clinitMethodBlock.get(i); |
|
|
|
|
|
IExpression mLeftExpression = mAssignment.getLeft(); |
|
|
IExpression mRightExpression = mAssignment.getRight(); |
|
|
|
|
|
if(mLeftExpression instanceof StaticField) { |
|
|
StaticField mStaticField = (StaticField) mLeftExpression; |
|
|
|
|
|
if (mStaticField.getField().getType().equals("[B")) { |
|
|
byte[] b = getByteArrayValue(mRightExpression, staticIntegers, staticByteArrays); |
|
|
|
|
|
if (b == null){ |
|
|
mJebInstance.print("Incorrect static byte[] " + mStaticField.getField().getName() + " define - initDecoderValues"); |
|
|
return; |
|
|
} |
|
|
|
|
|
staticByteArrays.put(mStaticField.getField().getName(), b); |
|
|
|
|
|
if (debug) mJebInstance.print("static byte[] " + mStaticField.getField().getName()); |
|
|
} else if (mStaticField.getField().getType().equals("I") || mStaticField.getField().getType().equals("S") || mStaticField.getField().getType().equals("B")) { |
|
|
int a = getIntValueOfExpression(mRightExpression, staticIntegers, staticByteArrays); |
|
|
|
|
|
if(a == Integer.MIN_VALUE) { |
|
|
mJebInstance.print("Incorrect int " + mStaticField.getField().getName()); |
|
|
return; |
|
|
} |
|
|
|
|
|
staticIntegers.put(mStaticField.getField().getName(), a); |
|
|
|
|
|
if (debug) mJebInstance.print("static int " + mStaticField.getField().getName() + " = " + a); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
private static void decodeMethod(Method mMethod){ |
|
|
if (debug) mJebInstance.print("Start decode " + mMethod.getSignature()); |
|
|
|
|
|
HashMap<String, Integer> intValues = new HashMap<String,Integer>(); |
|
|
intValues.putAll(staticIntegers); |
|
|
HashMap<String, byte[]> byteArrayValues = new HashMap<String, byte[]>(); |
|
|
byteArrayValues.putAll(staticByteArrays); |
|
|
|
|
|
for (int i = 0; i < mMethod.getBody().size(); i++){ |
|
|
if(!mMethod.getSignature().equals(decoderMethodSignature)) decodeIElement(mMethod.getBody().get(i), mMethod.getBody(), intValues, byteArrayValues, 1); |
|
|
} |
|
|
} |
|
|
|
|
|
public static String repeat(String str, int times){ |
|
|
return new String(new char[times]).replace("\0", str); |
|
|
} |
|
|
|
|
|
private static void decodeIElement(IElement mIElement, IElement mParentIElement, HashMap<String, Integer> intValues, HashMap<String, byte[]> byteArrayValues, int level){ |
|
|
if (debug) mJebInstance.print(repeat("\t", level) + "decodeIElement(" + mIElement.getClass().getName() + ", " + mParentIElement.getClass().getName() + ", ... )"); |
|
|
|
|
|
if (mIElement instanceof Assignment){ |
|
|
Assignment mAssignment = (Assignment) mIElement; |
|
|
|
|
|
IExpression mLeftExpression = mAssignment.getLeft(); |
|
|
IExpression mRightExpression = mAssignment.getRight(); |
|
|
|
|
|
if (mAssignment.isSimpleAssignment()) { |
|
|
if (mLeftExpression instanceof Definition) { |
|
|
Definition mDefinition = (Definition) mLeftExpression; |
|
|
|
|
|
String type = mDefinition.getType(); |
|
|
|
|
|
if (type.equals("I") || type.equals("B") || type.equals("S")) { |
|
|
int val = getIntValueOfExpression(mRightExpression, intValues, byteArrayValues); |
|
|
|
|
|
if (val == Integer.MIN_VALUE) { |
|
|
mJebInstance.print("Incorrect mRightExpression int " + mDefinition.getIdentifier().getName() + " == " + val + " for SimpleAssignment - decodeIElement"); |
|
|
return; |
|
|
} |
|
|
|
|
|
intValues.put(mDefinition.getIdentifier().getName(), val); |
|
|
|
|
|
if (debug) |
|
|
mJebInstance.print("\t\tint " + mDefinition.getIdentifier().getName() + " = " + val); |
|
|
} /*else if (type.equals("[B")) { |
|
|
byte[] val = getByteArrayValue(mRightExpression, intValues, byteArrayValues); |
|
|
|
|
|
if (val == null) { |
|
|
mJebInstance.print("Incorrect mRightExpression byte[] " + mDefinition.getIdentifier().getName() + " == " + val + " for SimpleAssignment - decodeIElement"); |
|
|
return; |
|
|
} |
|
|
|
|
|
byteArrayValues.put(mDefinition.getIdentifier().getName(), val); |
|
|
|
|
|
if (debug) |
|
|
mJebInstance.print("\t\tbyte[] " + mDefinition.getIdentifier().getName() + " = " + Arrays.toString(val)); |
|
|
}*/ |
|
|
} else if (mLeftExpression instanceof Identifier) { |
|
|
Identifier mIdentifier = (Identifier) mLeftExpression; |
|
|
|
|
|
if (intValues.containsKey(mIdentifier.getName())) { |
|
|
int val = getIntValueOfExpression(mRightExpression, intValues, byteArrayValues); |
|
|
|
|
|
if (val == Integer.MIN_VALUE) { |
|
|
mJebInstance.print("Incorrect mRightExpression " + mIdentifier.getName() + " == " + val + " for SimpleAssignment - decodeIElement"); |
|
|
return; |
|
|
} |
|
|
|
|
|
intValues.put(mIdentifier.getName(), val); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + " = " + val); |
|
|
} /*else if (byteArrayValues.containsKey(mIdentifier.getName())) { |
|
|
byte[] val = getByteArrayValue(mRightExpression, intValues, byteArrayValues); |
|
|
|
|
|
if (val == null) { |
|
|
mJebInstance.print("Incorrect mRightExpression " + mIdentifier.getName() + " == " + val + " for SimpleAssignment - decodeIElement"); |
|
|
return; |
|
|
} |
|
|
|
|
|
byteArrayValues.put(mIdentifier.getName(), val); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + " = " + val); |
|
|
}*/ |
|
|
} /*else if (mLeftExpression instanceof ArrayElt) { |
|
|
ArrayElt mArrayElt = (ArrayElt) mLeftExpression; |
|
|
|
|
|
if (mArrayElt.getArray() instanceof Identifier) { |
|
|
String arrayName = ((Identifier) mArrayElt.getArray()).getName(); |
|
|
|
|
|
if (!byteArrayValues.containsKey(arrayName)) { |
|
|
mJebInstance.print("Unavailable byte[] " + arrayName + " for SimpleAssignment - decodeIElement"); |
|
|
return; |
|
|
} |
|
|
|
|
|
int position = getIntValueOfExpression(mArrayElt.getIndex(), intValues, byteArrayValues); |
|
|
|
|
|
if (position < 0 || position >= byteArrayValues.get(arrayName).length) { |
|
|
mJebInstance.print("Incorrect position " + position + " for SimpleAssignment - decodeIElement"); |
|
|
return; |
|
|
} |
|
|
|
|
|
byte[] result = byteArrayValues.get(arrayName); |
|
|
|
|
|
int val = getIntValueOfExpression(mRightExpression, intValues, byteArrayValues); |
|
|
|
|
|
if (val == Integer.MIN_VALUE) { |
|
|
mJebInstance.print("Incorrect mRightExpression " + arrayName + "[" + position + "] == " + val + " for SimpleAssignment - decodeIElement"); |
|
|
return; |
|
|
} |
|
|
|
|
|
result[position] = (byte) val; |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + arrayName + "[" + position + "] = " + val); |
|
|
byteArrayValues.put(arrayName, result); |
|
|
} |
|
|
}*/ |
|
|
} else if (mAssignment.isCombinedOperatorAssignment()) { |
|
|
if (!(mLeftExpression instanceof Identifier)) { |
|
|
mJebInstance.print("Incorrect left IExpression type " + mLeftExpression.getClass().getName() + " for CombinedOperatorAssignment - decodeIElement"); |
|
|
return; |
|
|
} |
|
|
|
|
|
if (mRightExpression == null) { |
|
|
mJebInstance.print("Incorrect right IExpression " + mRightExpression.getClass().getName() + " == null for CombinedOperatorAssignment - decodeIElement"); |
|
|
return; |
|
|
} |
|
|
|
|
|
Identifier mIdentifier = (Identifier) mLeftExpression; |
|
|
|
|
|
if (intValues.containsKey(mIdentifier.getName())) { |
|
|
int val = getIntValueOfExpression(mRightExpression, intValues, byteArrayValues); |
|
|
|
|
|
if (val == Integer.MIN_VALUE) { |
|
|
mJebInstance.print("Incorrect mRightExpression int value " + val + " for CombinedOperatorAssignment - decodeIElement"); |
|
|
return; |
|
|
} |
|
|
|
|
|
Operator mOperator = mAssignment.getCombinedOperator(); |
|
|
|
|
|
if(mOperator.equals(Operator.ADD)){ |
|
|
int val2 = intValues.get(mIdentifier.getName()); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + " += " + val2); |
|
|
|
|
|
intValues.put(mIdentifier.getName(), val2 + val); |
|
|
} else if (mOperator.equals(Operator.SUB)){ |
|
|
int val2 = intValues.get(mIdentifier.getName()); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + " -= " + val2); |
|
|
|
|
|
intValues.put(mIdentifier.getName(), val - val2); |
|
|
} else if (mOperator.equals(Operator.MUL)){ |
|
|
int val2 = intValues.get(mIdentifier.getName()); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + " *= " + val2); |
|
|
|
|
|
intValues.put(mIdentifier.getName(), val * val2); |
|
|
} |
|
|
} |
|
|
|
|
|
} else if (mAssignment.isUnaryOperatorAssignment()) { |
|
|
if (!(mLeftExpression instanceof Identifier)) { |
|
|
mJebInstance.print("Incorrect left IExpretion type " + mLeftExpression.getClass().getName() + " for UnaryOperatorAssignment - decodeIElement"); |
|
|
return; |
|
|
} |
|
|
|
|
|
if (mRightExpression != null) { |
|
|
mJebInstance.print("Incorrect right IExpretion " + mRightExpression.getClass().getName() + " != null for UnaryOperatorAssignment - decodeIElement"); |
|
|
return; |
|
|
} |
|
|
|
|
|
Identifier mIdentifier = (Identifier) mLeftExpression; |
|
|
|
|
|
if (intValues.containsKey(mIdentifier.getName())) { |
|
|
boolean[] unaryFlags = new boolean[2]; |
|
|
|
|
|
mAssignment.getUnaryOperator(unaryFlags); |
|
|
|
|
|
if (unaryFlags[0]) { |
|
|
intValues.put(mIdentifier.getName(), intValues.get(mIdentifier.getName()) + 1); |
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + "++"); |
|
|
} else { |
|
|
intValues.put(mIdentifier.getName(), intValues.get(mIdentifier.getName()) - 1); |
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + "--"); |
|
|
} |
|
|
} |
|
|
} |
|
|
} else if (mIElement instanceof Call) { |
|
|
Call mCall = (Call) mIElement; |
|
|
String methodSignature = mCall.getMethod().getSignature(); |
|
|
|
|
|
if(methodSignature.equals(decoderMethodSignature) && !(mParentIElement instanceof Block)){ |
|
|
List<IExpression> params = mCall.getArguments(); |
|
|
|
|
|
int param1 = getIntValueOfExpression(params.get(0),intValues,byteArrayValues); |
|
|
int param2 = getIntValueOfExpression(params.get(1),intValues,byteArrayValues); |
|
|
int param3 = getIntValueOfExpression(params.get(2),intValues,byteArrayValues); |
|
|
|
|
|
String result = decodeDexGuardString(param1,param2,param3); |
|
|
|
|
|
mJebInstance.print("decodeDexGuardString(" + param1 + ", " + param2 + ", " + param3 + ") = " + result); |
|
|
|
|
|
if(result != null) mParentIElement.replaceSubElement(mIElement, (new Constant.Builder(mJebInstance)).buildString(result)); |
|
|
} else { |
|
|
for(int i = 0; i < mIElement.getSubElements().size(); i++){ |
|
|
decodeIElement((IElement)mIElement.getSubElements().get(i), mIElement, intValues, byteArrayValues, level+1); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
for (IElement element : (List<IElement>) mIElement.getSubElements()) { |
|
|
if (!((element instanceof Class) || (element instanceof Field) || (element instanceof Method))) { |
|
|
decodeIElement(element, mIElement, intValues, byteArrayValues, level + 1); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
private static String decodeDexGuardString(int param1, int param2, int param3) { |
|
|
if (debug) mJebInstance.print("decodeDexGuardString(" + param1 + ", " + param2 + ", " + param3 + ")"); |
|
|
|
|
|
Method mMethod = mJebInstance.getDecompiledMethodTree(decoderMethodSignature); |
|
|
List<Definition> params = mMethod.getParameters(); |
|
|
|
|
|
Block mMethodBlock = mMethod.getBody(); |
|
|
|
|
|
HashMap<String, Integer> intValuesMap = new HashMap<String, Integer>(); |
|
|
intValuesMap.put(params.get(0).getIdentifier().getName(), param1); |
|
|
intValuesMap.put(params.get(1).getIdentifier().getName(), param2); |
|
|
intValuesMap.put(params.get(2).getIdentifier().getName(), param3); |
|
|
intValuesMap.putAll(staticIntegers); |
|
|
|
|
|
HashMap<String, byte[]> byteArrayValuesMap = new HashMap<String, byte[]>(); |
|
|
byteArrayValuesMap.putAll(staticByteArrays); |
|
|
|
|
|
for (int i = 0; i < mMethodBlock.size(); i++) { |
|
|
if (debug) mJebInstance.print(mMethodBlock.get(i).getClass().getName()); |
|
|
|
|
|
if(mMethodBlock.get(i) instanceof Definition){ |
|
|
Definition mDefinition = (Definition) mMethodBlock.get(i); |
|
|
|
|
|
String type = mDefinition.getType(); |
|
|
|
|
|
if (type.equals("I") || type.equals("B") || type.equals("S")){ |
|
|
intValuesMap.put(mDefinition.getIdentifier().getName(), Integer.MIN_VALUE); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\tint " + mDefinition.getIdentifier().getName()); |
|
|
} else if (type.equals("[B")){ |
|
|
byteArrayValuesMap.put(mDefinition.getIdentifier().getName(), null); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\tbyte[] " + mDefinition.getIdentifier().getName()); |
|
|
} else { |
|
|
mJebInstance.print("Unsupported Definition variable " + mDefinition.getIdentifier().getName() + " type \"" + type + "\" - decodeDexGuardString / Definition"); |
|
|
return null; |
|
|
} |
|
|
} else if (mMethodBlock.get(i) instanceof Assignment){ |
|
|
Assignment mAssignment = (Assignment) mMethodBlock.get(i); |
|
|
|
|
|
IExpression mLeftExpression = mAssignment.getLeft(); |
|
|
IExpression mRightExpression = mAssignment.getRight(); |
|
|
|
|
|
if (mAssignment.isSimpleAssignment()) { |
|
|
if (mLeftExpression instanceof Definition) { |
|
|
Definition mDefinition = (Definition) mLeftExpression; |
|
|
|
|
|
String type = mDefinition.getType(); |
|
|
|
|
|
if (type.equals("I") || type.equals("B") || type.equals("S")) { |
|
|
int val = getIntValueOfExpression(mRightExpression, intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if (val == Integer.MIN_VALUE) { |
|
|
mJebInstance.print("Incorrect mRightExpression int " + mDefinition.getIdentifier().getName() + " == " + val + " for SimpleAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
intValuesMap.put(mDefinition.getIdentifier().getName(), val); |
|
|
|
|
|
if (debug) |
|
|
mJebInstance.print("\t\tint " + mDefinition.getIdentifier().getName() + " = " + val); |
|
|
} else if (type.equals("[B")) { |
|
|
byte[] val = getByteArrayValue(mRightExpression, intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if (val == null) { |
|
|
mJebInstance.print("Incorrect mRightExpression byte[] " + mDefinition.getIdentifier().getName() + " == " + val + " for SimpleAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
byteArrayValuesMap.put(mDefinition.getIdentifier().getName(), val); |
|
|
|
|
|
if (debug) |
|
|
mJebInstance.print("\t\tbyte[] " + mDefinition.getIdentifier().getName() + " = " + Arrays.toString(val)); |
|
|
} else { |
|
|
mJebInstance.print("Unsupported Definition variable " + mDefinition.getIdentifier().getName() + " type \"" + type + "\" - decodeDexGuardString / Definition"); |
|
|
return null; |
|
|
} |
|
|
} else if (mLeftExpression instanceof Identifier) { |
|
|
Identifier mIdentifier = (Identifier) mLeftExpression; |
|
|
|
|
|
if (intValuesMap.containsKey(mIdentifier.getName())) { |
|
|
int val = getIntValueOfExpression(mRightExpression, intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if (val == Integer.MIN_VALUE) { |
|
|
mJebInstance.print("Incorrect mRightExpression " + mIdentifier.getName() + " == " + val + " for SimpleAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
intValuesMap.put(mIdentifier.getName(), val); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + " = " + val); |
|
|
} else if (byteArrayValuesMap.containsKey(mIdentifier.getName())) { |
|
|
byte[] val = getByteArrayValue(mRightExpression, intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if (val == null) { |
|
|
mJebInstance.print("Incorrect mRightExpression " + mIdentifier.getName() + " == " + val + " for SimpleAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
byteArrayValuesMap.put(mIdentifier.getName(), val); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + " = " + val); |
|
|
} else { |
|
|
mJebInstance.print("Unknown variable " + mIdentifier.getName() + " type - decodeDexGuardString / Definition"); |
|
|
return null; |
|
|
} |
|
|
} else if (mLeftExpression instanceof ArrayElt) { |
|
|
ArrayElt mArrayElt = (ArrayElt) mLeftExpression; |
|
|
|
|
|
if(mArrayElt.getArray() instanceof Identifier) { |
|
|
String arrayName = ((Identifier)mArrayElt.getArray()).getName(); |
|
|
|
|
|
if(!byteArrayValuesMap.containsKey(arrayName)){ |
|
|
mJebInstance.print("Unavailable byte[] " + arrayName + " for SimpleAssignment - decodeDexGuardString / Assignment / ArrayElt"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
int position = getIntValueOfExpression(mArrayElt.getIndex(), intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if(position < 0 || position >= byteArrayValuesMap.get(arrayName).length){ |
|
|
mJebInstance.print("Incorrect position " + position + " for SimpleAssignment - decodeDexGuardString / Assignment / ArrayElt"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
byte[] result = byteArrayValuesMap.get(arrayName); |
|
|
|
|
|
int val = getIntValueOfExpression(mRightExpression, intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if (val == Integer.MIN_VALUE) { |
|
|
mJebInstance.print("Incorrect mRightExpression " + arrayName + "[" + position + "] == " + val + " for SimpleAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
result[position] = (byte) val; |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + arrayName + "[" + position + "] = " + val); |
|
|
byteArrayValuesMap.put(arrayName, result); |
|
|
} else { |
|
|
mJebInstance.print("Incorrect Array IExpression type " + mArrayElt.getArray().getClass().getName() + " for SimpleAssignment - decodeDexGuardString / Assignment / ArrayElt"); |
|
|
return null; |
|
|
} |
|
|
} else { |
|
|
mJebInstance.print("Incorrect left IExpression type " + mLeftExpression.getClass().getName() + " for SimpleAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
} else if (mAssignment.isCombinedOperatorAssignment()){ |
|
|
if(!(mLeftExpression instanceof Identifier)){ |
|
|
mJebInstance.print("Incorrect left IExpression type " + mLeftExpression.getClass().getName() + " for CombinedOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
if(mRightExpression == null){ |
|
|
mJebInstance.print("Incorrect right IExpression " + mRightExpression.getClass().getName() + " == null for CombinedOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
Identifier mIdentifier = (Identifier) mLeftExpression; |
|
|
|
|
|
if(!intValuesMap.containsKey(mIdentifier.getName())){ |
|
|
mJebInstance.print("Unavailable int " + mIdentifier.getName() + " for CombinedOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
int val = getIntValueOfExpression(mRightExpression, intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if(val == Integer.MIN_VALUE){ |
|
|
mJebInstance.print("Incorrect mRightExpression int value " + val + " for CombinedOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
Operator mOperator = mAssignment.getCombinedOperator(); |
|
|
|
|
|
if(mOperator.equals(Operator.ADD)){ |
|
|
int val2 = intValuesMap.get(mIdentifier.getName()); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + " += " + val2); |
|
|
|
|
|
intValuesMap.put(mIdentifier.getName(), val2 + val); |
|
|
} else if (mOperator.equals(Operator.SUB)){ |
|
|
int val2 = intValuesMap.get(mIdentifier.getName()); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + " -= " + val2); |
|
|
|
|
|
intValuesMap.put(mIdentifier.getName(), val - val2); |
|
|
} else if (mOperator.equals(Operator.MUL)){ |
|
|
int val2 = intValuesMap.get(mIdentifier.getName()); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + " *= " + val2); |
|
|
|
|
|
intValuesMap.put(mIdentifier.getName(), val * val2); |
|
|
} else { |
|
|
mJebInstance.print("Unsopported combinedOperator type \"" + mOperator.toString() + "=\" for CombinedOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
} else if (mAssignment.isUnaryOperatorAssignment()){ |
|
|
if(!(mLeftExpression instanceof Identifier)){ |
|
|
mJebInstance.print("Incorrect left IExpretion type " + mLeftExpression.getClass().getName() + " for UnaryOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
if(mRightExpression != null){ |
|
|
mJebInstance.print("Incorrect right IExpretion " + mRightExpression.getClass().getName() + " != null for UnaryOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
Identifier mIdentifier = (Identifier) mLeftExpression; |
|
|
|
|
|
if(!intValuesMap.containsKey(mIdentifier.getName())){ |
|
|
mJebInstance.print("Unavailable int " + mIdentifier.getName() + " - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
boolean[] unaryFlags = new boolean[2]; |
|
|
|
|
|
mAssignment.getUnaryOperator(unaryFlags); |
|
|
|
|
|
if(unaryFlags[0]){ |
|
|
intValuesMap.put(mIdentifier.getName(), intValuesMap.get(mIdentifier.getName()) + 1); |
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + "++"); |
|
|
} else { |
|
|
intValuesMap.put(mIdentifier.getName(), intValuesMap.get(mIdentifier.getName()) - 1); |
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + "--"); |
|
|
} |
|
|
} else { |
|
|
mJebInstance.print("Incorrect type Assignment - decodeDexGuardString"); |
|
|
} |
|
|
} else if (mMethodBlock.get(i) instanceof WhileStm){ |
|
|
WhileStm mWhileStm = (WhileStm)mMethodBlock.get(i); |
|
|
|
|
|
Block mWhileBlock = mWhileStm.getBody(); |
|
|
|
|
|
int controller = 0; |
|
|
|
|
|
while (controller < 70) { |
|
|
controller++; |
|
|
|
|
|
for (int j = 0; j < mWhileBlock.size(); j++) { |
|
|
if (debug) mJebInstance.print("\t\t\t\t"+ mWhileBlock.get(j).getClass().getName()); |
|
|
|
|
|
if(mWhileBlock.get(j) instanceof Definition){ |
|
|
Definition mDefinition = (Definition) mWhileBlock.get(j); |
|
|
|
|
|
String type = mDefinition.getType(); |
|
|
|
|
|
if (type.equals("I") || type.equals("B") || type.equals("S")){ |
|
|
intValuesMap.put(mDefinition.getIdentifier().getName(), Integer.MIN_VALUE); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t\t\t\t\tint " + mDefinition.getIdentifier().getName()); |
|
|
} else if (type.equals("[B")){ |
|
|
byteArrayValuesMap.put(mDefinition.getIdentifier().getName(), null); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t\t\t\t\tbyte[] " + mDefinition.getIdentifier().getName()); |
|
|
} else { |
|
|
mJebInstance.print("Unsupported Definition variable " + mDefinition.getIdentifier().getName() + " type \"" + type + "\" - decodeDexGuardString / Definition"); |
|
|
return null; |
|
|
} |
|
|
} else if (mWhileBlock.get(j) instanceof Assignment){ |
|
|
Assignment mAssignment = (Assignment) mWhileBlock.get(j); |
|
|
|
|
|
IExpression mLeftExpression = mAssignment.getLeft(); |
|
|
IExpression mRightExpression = mAssignment.getRight(); |
|
|
|
|
|
if (mAssignment.isSimpleAssignment()){ |
|
|
if(mLeftExpression instanceof Definition){ |
|
|
Definition mDefinition = (Definition) mLeftExpression; |
|
|
|
|
|
String type = mDefinition.getType(); |
|
|
|
|
|
if (type.equals("I") || type.equals("B") || type.equals("S")){ |
|
|
int val = getIntValueOfExpression(mRightExpression, intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if (val == Integer.MIN_VALUE) { |
|
|
mJebInstance.print("Incorrect mRightExpression int " + mDefinition.getIdentifier().getName() + " == " + val + " for SimpleAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
intValuesMap.put(mDefinition.getIdentifier().getName(), val); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t\t\t\t\tint " + mDefinition.getIdentifier().getName() + " = " + val); |
|
|
} else if (type.equals("[B")){ |
|
|
byte[] val = getByteArrayValue(mRightExpression, intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if (val == null) { |
|
|
mJebInstance.print("Incorrect mRightExpression byte[] " + mDefinition.getIdentifier().getName() + " == " + val + " for SimpleAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
byteArrayValuesMap.put(mDefinition.getIdentifier().getName(), val); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t\t\t\t\tbyte[] " + mDefinition.getIdentifier().getName() + " = " + Arrays.toString(val)); |
|
|
} else { |
|
|
mJebInstance.print("Unsupported Definition variable " + mDefinition.getIdentifier().getName() + " type \"" + type + "\" - decodeDexGuardString / Definition"); |
|
|
return null; |
|
|
} |
|
|
} else if (mLeftExpression instanceof Identifier) { |
|
|
Identifier mIdentifier = (Identifier) mLeftExpression; |
|
|
|
|
|
if (intValuesMap.containsKey(mIdentifier.getName())){ |
|
|
int val = getIntValueOfExpression(mRightExpression, intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if (val == Integer.MIN_VALUE) { |
|
|
mJebInstance.print("Incorrect mRightExpression " + mIdentifier.getName() + " == " + val + " for SimpleAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
intValuesMap.put(mIdentifier.getName(), val); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t\t\t\t\t" + mIdentifier.getName() + " = " + val); |
|
|
} else if (byteArrayValuesMap.containsKey(mIdentifier.getName())){ |
|
|
byte[] val = getByteArrayValue(mRightExpression, intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if (val == null) { |
|
|
mJebInstance.print("Incorrect mRightExpression " + mIdentifier.getName() + " == " + val + " for SimpleAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
byteArrayValuesMap.put(mIdentifier.getName(), val); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t\t\t\t\t" + mIdentifier.getName() + " = " + val); |
|
|
} else { |
|
|
mJebInstance.print("Unknown variable " + mIdentifier.getName() + " type - decodeDexGuardString / Definition"); |
|
|
return null; |
|
|
} |
|
|
} else if (mLeftExpression instanceof ArrayElt) { |
|
|
ArrayElt mArrayElt = (ArrayElt) mLeftExpression; |
|
|
|
|
|
if(mArrayElt.getArray() instanceof Identifier) { |
|
|
String arrayName = ((Identifier)mArrayElt.getArray()).getName(); |
|
|
|
|
|
if(!byteArrayValuesMap.containsKey(arrayName)){ |
|
|
mJebInstance.print("Unavailable byte[] " + arrayName + " for SimpleAssignment - decodeDexGuardString / Assignment / ArrayElt"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
int position = getIntValueOfExpression(mArrayElt.getIndex(), intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if(position < 0 || position >= byteArrayValuesMap.get(arrayName).length){ |
|
|
mJebInstance.print("Incorrect position " + position + " for SimpleAssignment - decodeDexGuardString / Assignment / ArrayElt"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
byte[] result = byteArrayValuesMap.get(arrayName); |
|
|
|
|
|
int val = getIntValueOfExpression(mRightExpression, intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if (val == Integer.MIN_VALUE) { |
|
|
mJebInstance.print("Incorrect mRightExpression " + arrayName + "[" + position + "] == " + val + " for SimpleAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
result[position] = (byte) val; |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + arrayName + "[" + position + "] = " + val); |
|
|
byteArrayValuesMap.put(arrayName, result); |
|
|
} else { |
|
|
mJebInstance.print("Incorrect Array IExpression type " + mArrayElt.getArray().getClass().getName() + " for SimpleAssignment - decodeDexGuardString / Assignment / ArrayElt"); |
|
|
return null; |
|
|
} |
|
|
} else { |
|
|
mJebInstance.print("Incorrect left IExpression type " + mLeftExpression.getClass().getName() + " for SimpleAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
} else if (mAssignment.isCombinedOperatorAssignment()){ |
|
|
if(!(mLeftExpression instanceof Identifier)){ |
|
|
mJebInstance.print("Incorrect left IExpression type " + mLeftExpression.getClass().getName() + " for CombinedOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
if(mRightExpression == null){ |
|
|
mJebInstance.print("Incorrect right IExpression " + mRightExpression.getClass().getName() + " == null for CombinedOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
Identifier mIdentifier = (Identifier) mLeftExpression; |
|
|
|
|
|
if(!intValuesMap.containsKey(mIdentifier.getName())){ |
|
|
mJebInstance.print("Unavailable int " + mIdentifier.getName() + " for CombinedOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
int val = getIntValueOfExpression(mRightExpression, intValuesMap, byteArrayValuesMap); |
|
|
|
|
|
if(val == Integer.MIN_VALUE){ |
|
|
mJebInstance.print("Incorrect mRightExpression int value " + val + " for CombinedOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
Operator mOperator = mAssignment.getCombinedOperator(); |
|
|
|
|
|
if(mOperator.equals(Operator.ADD)){ |
|
|
int val2 = intValuesMap.get(mIdentifier.getName()); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + " += " + val2); |
|
|
|
|
|
intValuesMap.put(mIdentifier.getName(), val2 + val); |
|
|
} else if (mOperator.equals(Operator.SUB)){ |
|
|
int val2 = intValuesMap.get(mIdentifier.getName()); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + " -= " + val2); |
|
|
|
|
|
intValuesMap.put(mIdentifier.getName(), val - val2); |
|
|
} else if (mOperator.equals(Operator.MUL)){ |
|
|
int val2 = intValuesMap.get(mIdentifier.getName()); |
|
|
|
|
|
if (debug) mJebInstance.print("\t\t" + mIdentifier.getName() + " *= " + val2); |
|
|
|
|
|
intValuesMap.put(mIdentifier.getName(), val * val2); |
|
|
} else { |
|
|
mJebInstance.print("Unsopported combinedOperator type \"" + mOperator.toString() + "=\" for CombinedOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
} else if (mAssignment.isUnaryOperatorAssignment()){ |
|
|
if(!(mLeftExpression instanceof Identifier)){ |
|
|
mJebInstance.print("Incorrect left IExpretion type " + mLeftExpression.getClass().getName() + " for UnaryOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
if(mRightExpression != null){ |
|
|
mJebInstance.print("Incorrect right IExpretion " + mRightExpression.getClass().getName() + " != null for UnaryOperatorAssignment - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
Identifier mIdentifier = (Identifier) mLeftExpression; |
|
|
|
|
|
if(!intValuesMap.containsKey(mIdentifier.getName())){ |
|
|
mJebInstance.print("Unavailable int " + mIdentifier.getName() + " - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
boolean[] unaryFlags = new boolean[2]; |
|
|
|
|
|
mAssignment.getUnaryOperator(unaryFlags); |
|
|
|
|
|
if(unaryFlags[0]){ |
|
|
intValuesMap.put(mIdentifier.getName(), intValuesMap.get(mIdentifier.getName()) + 1); |
|
|
if (debug) mJebInstance.print("\t\t\t\t\t\t" + mIdentifier.getName() + "++"); |
|
|
} else { |
|
|
intValuesMap.put(mIdentifier.getName(), intValuesMap.get(mIdentifier.getName()) - 1); |
|
|
if (debug) mJebInstance.print("\t\t\t\t\t\t" + mIdentifier.getName() + "--"); |
|
|
} |
|
|
} else { |
|
|
mJebInstance.print("Incorrect type Assignment - decodeDexGuardString"); |
|
|
} |
|
|
} else if (mWhileBlock.get(j) instanceof IfStm){ |
|
|
IfStm mIfStm = (IfStm) mWhileBlock.get(j); |
|
|
|
|
|
Predicate mPredicate = mIfStm.getBranchPredicate(0); |
|
|
String lVarName = ((Identifier) mPredicate.getLeft()).getName(); |
|
|
String rVarName = ((Identifier) mPredicate.getRight()).getName(); |
|
|
|
|
|
Block ifBlock = mIfStm.getBranchBody(0); |
|
|
|
|
|
if(intValuesMap.get(lVarName).equals(intValuesMap.get(rVarName))){ |
|
|
String resultByteArray = ""; |
|
|
|
|
|
for (int k = 0; k < ifBlock.size(); k++) { |
|
|
if(ifBlock.get(k) instanceof Return){ |
|
|
Return mReturn = (Return) ifBlock.get(k); |
|
|
|
|
|
if(mReturn.getExpression() instanceof New){ |
|
|
New mNew = (New) mReturn.getExpression(); |
|
|
|
|
|
List args = mNew.getArguments(); |
|
|
|
|
|
if (args.size() > 0 && args.get(0) instanceof Identifier) { |
|
|
Identifier mIdentifier = (Identifier) args.get(0); |
|
|
|
|
|
resultByteArray = mIdentifier.getName(); |
|
|
} else { |
|
|
mJebInstance.print("String init params incorrect"); |
|
|
|
|
|
return null; |
|
|
} |
|
|
} else if (mReturn.getExpression() instanceof Call) { |
|
|
Call mCall = (Call) mReturn.getExpression(); |
|
|
|
|
|
List<IExpression> par = mCall.getArguments(); |
|
|
|
|
|
if(par.size() <= 0) { |
|
|
mJebInstance.print("Unavailable String Creater"); |
|
|
|
|
|
return null; |
|
|
} |
|
|
|
|
|
if (par.get(0) instanceof New) { |
|
|
New mNew = (New) par.get(0); |
|
|
|
|
|
List args = mNew.getArguments(); |
|
|
|
|
|
if (args.size() > 0 && args.get(0) instanceof Identifier) { |
|
|
Identifier mIdentifier = (Identifier) args.get(0); |
|
|
|
|
|
resultByteArray = mIdentifier.getName(); |
|
|
} else { |
|
|
mJebInstance.print("String init params incorrect"); |
|
|
|
|
|
return null; |
|
|
} |
|
|
} else { |
|
|
mJebInstance.print("Unavailable String Creater in Call"); |
|
|
|
|
|
return null; |
|
|
} |
|
|
|
|
|
} else { |
|
|
mJebInstance.print("Incorrect Return Expression " + mReturn.getExpression().getClass().getName()); |
|
|
|
|
|
return null; |
|
|
} |
|
|
} else { |
|
|
mJebInstance.print("Statement is not Return (" + ifBlock.get(k).getClass().getName() + ")"); |
|
|
|
|
|
return null; |
|
|
} |
|
|
} |
|
|
|
|
|
//mJebInstance.print("t4 - " + resultByteArray + " = " + Arrays.toString(byteArrayValuesMap.get(resultByteArray)) + " " + new String(byteArrayValuesMap.get(resultByteArray))); |
|
|
|
|
|
return new String(byteArrayValuesMap.get(resultByteArray)); |
|
|
} |
|
|
} else { |
|
|
mJebInstance.print("Unsupported Statement type " + mWhileBlock.get(j).getClass().getName() + " - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} else { |
|
|
mJebInstance.print("Unsupported Statement type " + mMethodBlock.get(i).getClass().getName() + " - decodeDexGuardString / Assignment"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return ""; |
|
|
} |
|
|
|
|
|
private static byte[] getByteArrayValue(IExpression mIExpression, HashMap<String,Integer> intValues, HashMap<String, byte[]> byteArrayValues){ |
|
|
if (debug) mJebInstance.print("\t\t\t\t\t\t\t\tgetByteArrayValue for " + mIExpression.getClass().getName()); |
|
|
|
|
|
if (mIExpression instanceof Call) { |
|
|
//TODO |
|
|
mJebInstance.print("Unsupported IExpression parametr type - getByteArrayValue of Call"); |
|
|
return null; |
|
|
} else if (mIExpression instanceof Identifier) { |
|
|
Identifier mIdentifier = (Identifier) mIExpression; |
|
|
|
|
|
if(!byteArrayValues.containsKey(mIdentifier.getName())) { |
|
|
mJebInstance.print("Unavailable byte[] " + mIdentifier.getName() + " - getByteArrayValue of Identifier"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
return byteArrayValues.get(mIdentifier.getName()); |
|
|
} else if (mIExpression instanceof InstanceField) { |
|
|
//TODO |
|
|
mJebInstance.print("Unsupported IExpression parametr type - getByteArrayValue of InstanceField"); |
|
|
return null; |
|
|
} else if (mIExpression instanceof NewArray) { |
|
|
NewArray mNewArray = (NewArray) mIExpression; |
|
|
|
|
|
if(!mNewArray.getType().equals("[B")){ |
|
|
mJebInstance.print("Unsupported NewArray type " + mNewArray.getType() + " - getByteArrayValue of NewArray"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
if(mNewArray.getInitialValues() != null){ |
|
|
List<Constant> initialValues = mNewArray.getInitialValues(); |
|
|
|
|
|
if(initialValues.isEmpty()){ |
|
|
return null; |
|
|
} |
|
|
|
|
|
byte[] rezult = new byte[initialValues.size()]; |
|
|
|
|
|
for (int i = 0; i < initialValues.size(); i++) { |
|
|
rezult[i] = initialValues.get(i).getByte(); |
|
|
} |
|
|
|
|
|
return rezult; |
|
|
} else if (mNewArray.getSizes() != null) { |
|
|
|
|
|
if (mNewArray.getSizes().size() > 1) { |
|
|
mJebInstance.print("Unsupported NewArray multiSizes array " + mNewArray.getSizes().size() + " - getByteArrayValue of NewArray"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
IExpression mSizeIExpression = (IExpression) mNewArray.getSizes().get(0); |
|
|
int sizeArray = getIntValueOfExpression(mSizeIExpression, intValues, byteArrayValues); |
|
|
|
|
|
if (sizeArray < 0) { |
|
|
mJebInstance.print("Incorrect array size " + sizeArray + " - getByteArrayValue of NewArray"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
return new byte[sizeArray]; |
|
|
} else { |
|
|
mJebInstance.print("Error - getByteArrayValue of NewArray"); |
|
|
return null; |
|
|
} |
|
|
} else if (mIExpression instanceof StaticField) { |
|
|
StaticField mStaticField = (StaticField) mIExpression; |
|
|
|
|
|
String fType = mStaticField.getField().getType(); |
|
|
|
|
|
if(!fType.equals("[B")){ |
|
|
mJebInstance.print("Incorrect StaticField type " + fType + " - getByteArrayValue of StaticField"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
if(!byteArrayValues.containsKey(mStaticField.getField().getName())){ |
|
|
mJebInstance.print("Unavailable byte[] " + mStaticField.getField().getName() + " - getByteArrayValue of StaticField"); |
|
|
return null; |
|
|
} |
|
|
|
|
|
return byteArrayValues.get(mStaticField.getField().getName()); |
|
|
} else { |
|
|
mJebInstance.print("Unsupported IExpression parametr type - getByteArrayValue of " + mIExpression.getClass().getName()); |
|
|
return null; |
|
|
} |
|
|
} |
|
|
|
|
|
private static int getIntValueOfExpression(IExpression mIExpression, HashMap<String, Integer> intValues, HashMap<String,byte[]> byteArrayValues) { |
|
|
if (debug) mJebInstance.print("\t\t\t\t\t\t\t\tgetIntValueOfExpression for " + mIExpression.getClass().getName()); |
|
|
|
|
|
if(mIExpression instanceof ArrayElt){ |
|
|
ArrayElt mArrayElt = (ArrayElt) mIExpression; |
|
|
|
|
|
if(!(mArrayElt.getArray() instanceof Identifier || mArrayElt.getArray() instanceof StaticField)){ |
|
|
mJebInstance.print("Unsupported type of Array " + mArrayElt.getArray().getClass().getName() + " - getIntValueOfExpression of ArrayElt"); |
|
|
return Integer.MIN_VALUE; |
|
|
} |
|
|
|
|
|
String byteArrayName = (mArrayElt.getArray() instanceof Identifier) ? ((Identifier)mArrayElt.getArray()).getName() : ((StaticField)mArrayElt.getArray()).getField().getName(); |
|
|
|
|
|
if(!byteArrayValues.containsKey(byteArrayName)){ |
|
|
mJebInstance.print("Unavailable byteArray " + byteArrayName + " - getIntValueOfExpression of ArrayElt"); |
|
|
return Integer.MIN_VALUE; |
|
|
} |
|
|
|
|
|
byte[] mBytes = byteArrayValues.get(byteArrayName); |
|
|
|
|
|
int position = getIntValueOfExpression(mArrayElt.getIndex(), intValues, byteArrayValues); |
|
|
|
|
|
if(mBytes.length <= position){ |
|
|
mJebInstance.print("Incorrect position (byte[].length " + mBytes.length + " <= position " + position + ") - getIntValueOfExpression of ArrayElt"); |
|
|
return Integer.MIN_VALUE; |
|
|
} else if (position < 0){ |
|
|
mJebInstance.print("Incorrect position (position " + position + " < 0) - getIntValueOfExpression of ArrayElt"); |
|
|
return Integer.MIN_VALUE; |
|
|
} |
|
|
|
|
|
return mBytes[position]; |
|
|
} else if (mIExpression instanceof Call) { |
|
|
//TODO |
|
|
mJebInstance.print("Unsupported IExpression parametr type - getIntValueOfExpression of Call"); |
|
|
return Integer.MIN_VALUE; |
|
|
} else if (mIExpression instanceof Constant) { |
|
|
Constant mConstant = (Constant) mIExpression; |
|
|
|
|
|
if(mConstant.isFalse() || mConstant.isNull() || mConstant.isTrue() || mConstant.isString()){ |
|
|
mJebInstance.print("Unsupported type of Constant - getIntValueOfExpression of Constant"); |
|
|
return Integer.MIN_VALUE; |
|
|
} |
|
|
|
|
|
String type = ((Constant) mIExpression).getType(); |
|
|
|
|
|
if(type.equals("B")){ |
|
|
return (int) ((Constant) mIExpression).getByte(); |
|
|
} else if (type.equals("S")){ |
|
|
return (int) ((Constant) mIExpression).getShort(); |
|
|
} else { |
|
|
return ((Constant) mIExpression).getInt(); |
|
|
} |
|
|
} else if (mIExpression instanceof Expression) { |
|
|
Expression mExpression = (Expression) mIExpression; |
|
|
|
|
|
int lValue = Integer.MIN_VALUE; |
|
|
|
|
|
if(mExpression.getLeft() != null) { |
|
|
lValue = getIntValueOfExpression(mExpression.getLeft(), intValues, byteArrayValues); |
|
|
if (lValue == Integer.MIN_VALUE) { |
|
|
mJebInstance.print("Incorrect lValue " + lValue + " - getIntValueOfExpression of Expression"); |
|
|
return Integer.MIN_VALUE; |
|
|
} |
|
|
} |
|
|
|
|
|
int rValue = getIntValueOfExpression(mExpression.getRight(), intValues, byteArrayValues); |
|
|
if (rValue == Integer.MIN_VALUE) { |
|
|
mJebInstance.print("Incorrect rValue " + rValue + " - getIntValueOfExpression of Expression"); |
|
|
return Integer.MIN_VALUE; |
|
|
} |
|
|
|
|
|
Operator mOperator = mExpression.getOperator(); |
|
|
|
|
|
if(mOperator.equals(Operator.ADD)){ |
|
|
return lValue + rValue; |
|
|
} else if (mOperator.equals(Operator.SUB)){ |
|
|
return lValue - rValue; |
|
|
} else if (mOperator.equals(Operator.MUL)){ |
|
|
return lValue * rValue; |
|
|
} else if (mOperator.equals(Operator.DIV)){ |
|
|
return lValue / rValue; |
|
|
} else if (mOperator.equals(Operator.REM)){ |
|
|
return lValue % rValue; |
|
|
} else if (mOperator.equals(Operator.OR)){ |
|
|
return lValue | rValue; |
|
|
} else if (mOperator.equals(Operator.AND)){ |
|
|
return lValue & rValue; |
|
|
} else if (mOperator.equals(Operator.XOR)){ |
|
|
return lValue ^ rValue; |
|
|
} else if (mOperator.equals(Operator.SHL)){ |
|
|
return lValue << rValue; |
|
|
} else if (mOperator.equals(Operator.SHR)){ |
|
|
return lValue >> rValue; |
|
|
} else if (mOperator.equals(Operator.USHR)){ |
|
|
return lValue >>> rValue; |
|
|
} else if (mOperator.equals(Operator.NEG)) { |
|
|
return -rValue; |
|
|
} else if (mOperator.equals(Operator.CAST_TO_BYTE)) { |
|
|
return rValue; |
|
|
} else if (mOperator.equals(Operator.CAST_TO_SHORT)) { |
|
|
return rValue; |
|
|
} else if (mOperator.equals(Operator.CAST_TO_INT)) { |
|
|
return rValue; |
|
|
} else { |
|
|
mJebInstance.print("Unsupported operation type \"" + mOperator.toString() + "\" - getIntValueOfExpression of Expression"); |
|
|
return Integer.MIN_VALUE; |
|
|
} |
|
|
} else if (mIExpression instanceof Identifier) { |
|
|
Identifier mIdentifier = (Identifier) mIExpression; |
|
|
|
|
|
if(!intValues.containsKey(mIdentifier.getName())){ |
|
|
mJebInstance.print("intValues.keys = " + Arrays.toString(intValues.keySet().toArray())); |
|
|
|
|
|
mJebInstance.print("Unavailable int " + mIdentifier.getName() + " - getIntValueOfExpression of Identifier"); |
|
|
return Integer.MIN_VALUE; |
|
|
} |
|
|
|
|
|
return intValues.get(mIdentifier.getName()); |
|
|
} else if (mIExpression instanceof InstanceField) { |
|
|
//TODO |
|
|
mJebInstance.print("Unsupported IExpression parametr type - getIntValueOfExpression of InstanceField"); |
|
|
return Integer.MIN_VALUE; |
|
|
} else if (mIExpression instanceof StaticField) { |
|
|
StaticField mStaticField = (StaticField) mIExpression; |
|
|
|
|
|
String fType = mStaticField.getField().getType(); |
|
|
|
|
|
if(!(fType.equals("I") || fType.equals("B") || fType.equals("S") )){ |
|
|
mJebInstance.print("Incorrect StaticField type " + fType + " - getIntValueOfExpression of StaticField"); |
|
|
return Integer.MIN_VALUE; |
|
|
} |
|
|
|
|
|
if(!intValues.containsKey(mStaticField.getField().getName())){ |
|
|
mJebInstance.print("Unavailable int " + mStaticField.getField().getName() + " - getIntValueOfExpression of StaticField"); |
|
|
return Integer.MIN_VALUE; |
|
|
} |
|
|
|
|
|
return intValues.get(mStaticField.getField().getName()); |
|
|
} else { |
|
|
mJebInstance.print("Unsupported IExpression parametr type - getIntValueOfExpression of " + mIExpression.getClass().getName()); |
|
|
return Integer.MIN_VALUE; |
|
|
} |
|
|
} |
|
|
|
|
|
private static void printAllOperators(){ |
|
|
mJebInstance.print("ADD " + Operator.ADD.toString()); |
|
|
mJebInstance.print("SUB " + Operator.SUB.toString()); |
|
|
mJebInstance.print("MUL " + Operator.MUL.toString()); |
|
|
mJebInstance.print("DIV " + Operator.DIV.toString()); |
|
|
mJebInstance.print("REM " + Operator.REM.toString()); |
|
|
mJebInstance.print("AND " + Operator.AND.toString()); |
|
|
mJebInstance.print("OR " + Operator.OR.toString()); |
|
|
mJebInstance.print("XOR " + Operator.XOR.toString()); |
|
|
mJebInstance.print("SHL " + Operator.SHL.toString()); |
|
|
mJebInstance.print("SHR " + Operator.SHR.toString()); |
|
|
mJebInstance.print("USHR " + Operator.USHR.toString()); |
|
|
mJebInstance.print("NEG " + Operator.NEG.toString()); |
|
|
mJebInstance.print("NOT " + Operator.NOT.toString()); |
|
|
mJebInstance.print("LOG_IDENT " + Operator.LOG_IDENT.toString()); |
|
|
mJebInstance.print("LOG_NOT " + Operator.LOG_NOT.toString()); |
|
|
mJebInstance.print("LOG_OR " + Operator.LOG_OR.toString()); |
|
|
mJebInstance.print("LOG_AND " + Operator.LOG_AND.toString()); |
|
|
mJebInstance.print("INSTANCEOF " + Operator.INSTANCEOF.toString()); |
|
|
mJebInstance.print("EQ " + Operator.EQ.toString()); |
|
|
mJebInstance.print("NE " + Operator.NE.toString()); |
|
|
mJebInstance.print("LT " + Operator.LT.toString()); |
|
|
mJebInstance.print("GE " + Operator.GE.toString()); |
|
|
mJebInstance.print("GT " + Operator.GT.toString()); |
|
|
mJebInstance.print("LE " + Operator.LE.toString()); |
|
|
mJebInstance.print("CAST_TO_BYTE " + Operator.CAST_TO_BYTE.toString()); |
|
|
mJebInstance.print("CAST_TO_CHAR " + Operator.CAST_TO_CHAR.toString()); |
|
|
mJebInstance.print("CAST_TO_SHORT " + Operator.CAST_TO_SHORT.toString()); |
|
|
mJebInstance.print("CAST_TO_INT " + Operator.CAST_TO_INT.toString()); |
|
|
mJebInstance.print("CAST_TO_LONG " + Operator.CAST_TO_LONG.toString()); |
|
|
mJebInstance.print("CAST_TO_FLOAT " + Operator.CAST_TO_FLOAT.toString()); |
|
|
mJebInstance.print("CAST_TO_DOUBLE " + Operator.CAST_TO_DOUBLE.toString()); |
|
|
mJebInstance.print("CAST_TO_BOOLEAN " + Operator.CAST_TO_BOOLEAN.toString()); |
|
|
mJebInstance.print("CONCAT " + Operator.CONCAT.toString()); |
|
|
} |
|
|
|
|
|
private static String getClassFromSignature(String signature){ |
|
|
String pattern = "^(L[a-zA-Z/$]*[;])(.*)$"; |
|
|
return signature.replaceAll(pattern, "$1"); |
|
|
} |
|
|
} |