ali CTF分析笔记

        拿到样本通过dex2jar工具将dex转为jar包,然后将java代码复制出来进行修复,修复过程如下,代码量太大,但是最开始不清楚逻辑所以只能用这种笨办法了。

public static /* synthetic */ String getClassName(String str) {
   
char[] toCharArray = str.toCharArray();
    for
(int i = 0; i < toCharArray.length; i++) {
        toCharArray[i] = (
char) (toCharArray[i] ^ 116);
   
}
   
return new String(toCharArray);
}

测试3组数据的运行结果:

1.(DDE(DDEA(DDDF(DDEA.(DDEL(DDEA(DDE(DDEG.S(DDDD(DDDB(DDE(DDE(DDEGB(DDDE(DDE(DDEL(DDED(DDEE(DDDB

2.(DDE(DDEA(DDDF(DDEA.(DDEL(DDEA(DDE(DDEG.O(DDEB(DDE(DDEE(DDEC(DDDD

3.(DDE(DDEA(DDDF(DDEA.(DDEL(DDEA(DDE(DDEG.C(DDEL(DDEA(DDDC(DDDC

 

 

 

 

 

 

 

private static /* synthetic */ String access$_T15566(String str) {

    int i = 0;

    byte[] bArr = new byte[17];

    bArr[0] = (byte) 33;

    bArr[1] = (byte) -95;

    bArr[2] = (byte) 116;

    bArr[3] = (byte) -2;

    bArr[4] = (byte) 94;

    bArr[5] = (byte) -127;

    bArr[6] = (byte) -34;

    bArr[7] = (byte) 114;

    bArr[8] = Byte.MIN_VALUE;

    bArr[9] = (byte) 62;

    bArr[10] = (byte) 122;

    bArr[11] = (byte) 20;

    bArr[12] = (byte) 99;

    bArr[13] = (byte) -64;

    bArr[14] = (byte) -14;

    bArr[15] = Byte.MIN_VALUE;

    bArr[16] = (byte) 48;

    bArr[1] = (byte) (bArr[1] - bArr[12]);

    byte[] bArr2 = new byte[12];

    bArr2[0] = (byte) 16;

    bArr2[1] = (byte) 95;

    bArr2[2] = (byte) -91;

    bArr2[3] = (byte) 122;

    bArr2[4] = (byte) -83;

    bArr2[5] = (byte) -76;

    bArr2[6] = (byte) 21;

    bArr2[7] = (byte) 52;

    bArr2[8] = (byte) 24;

    bArr2[9] = (byte) 21;

    bArr2[10] = (byte) -75;

    bArr2[11] = (byte) 4;

    bArr2[6] = (byte) (bArr2[6] - bArr2[11]);

    AccessibleObject method = null;

    try {

  

        String classNameStr = new String(new BigInteger(bArr).divide(BigInteger.valueOf((long) (bArr[11] + 60))).toByteArray(), "UTF-8");

        String methodStr = new String(new BigInteger(bArr2).divide(BigInteger.valueOf((long) (bArr2[3] ^ 94))).toByteArray(), "UTF-8");

        method = Class.forName(classNameStr).getMethod(methodStr, null);

    } catch (NoSuchMethodException e) {

        e.printStackTrace();

    } catch (ClassNotFoundException e) {

        e.printStackTrace();

    } catch (UnsupportedEncodingException e) {

        e.printStackTrace();

    }

    method.setAccessible(true);

    //char[] cArr = (char[]) method.invoke(str, new Object[0]);

    //while (i < cArr.length) {

    //  cArr[i] = (char) (cArr[i] ^ 103);

    //  i++;

    //}

    AccessibleObject constructor = null;

    try {

        constructor = Class.forName(new StringBuilder("gnirtS.gnal.avaj").reverse().toString()).getConstructor(new Class[]{Class.forName(new StringBuilder("C[").reverse().toString())});

    } catch (NoSuchMethodException e) {

        e.printStackTrace();

    } catch (ClassNotFoundException e) {

        e.printStackTrace();

    }

    constructor.setAccessible(true);

    return (String) constructor.toString();//.newInstance(new Object[]{cArr});

  }
调试结果:
 

从调试结果中知道该函数在计算类名和方法名字符串

public static void calcCheckMethodInvoke1() throws UnsupportedEncodingException {

    AccessibleObject method;

    byte[] bArr = new byte[24];

    bArr[0] = (byte) 11;

    bArr[1] = (byte) -94;

    bArr[2] = (byte) -88;

    bArr[3] = (byte) -14;

    bArr[4] = (byte) -95;

    bArr[5] = (byte) -19;

    bArr[6] = (byte) -38;

    bArr[7] = (byte) -88;

    bArr[8] = (byte) 19;

    bArr[9] = (byte) 73;

    bArr[10] = (byte) 17;

    bArr[11] = (byte) 32;

    bArr[12] = (byte) -68;

    bArr[13] = (byte) -125;

    bArr[14] = (byte) -120;

    bArr[15] = (byte) 19;

    bArr[16] = (byte) 75;

    bArr[17] = (byte) 68;

    bArr[18] = (byte) -41;

    bArr[19] = (byte) -121;

    bArr[20] = (byte) -38;

    bArr[21] = (byte) -5;

    bArr[22] = (byte) 24;

    bArr[23] = (byte) 120;

    bArr[5] = (byte) (bArr[5] - bArr[6]);

    //AccessibleObject constructor = Class.forName().getConstructor(new Class[]{Class.forName(Check.access$_T11306(System.out, "\u001e\u0015\u0002\u0015Z\u0018\u0015\u001a\u0013Z'\u0000\u0006\u001d\u001a\u0013"))});

    String classNameStr = new String(new BigInteger(bArr).divide(BigInteger.valueOf((long) (bArr[9] ^ 85))).toByteArray(), "UTF-8");

    String constructorMethodStr = getClassName("\\u001e\\u0015\\u0002\\u0015Z\\u0018\\u0015\\u001a\\u0013Z'\\u0000\\u0006\\u001d\\u001a\\u0013");

  

    System.out.println(classNameStr);

    System.out.println(constructorMethodStr);

  

    System.out.println();

    //return classNameStr;

  }

测试结果:

通过检查发现,在拷贝字符串的时候 IDE 自动添加了一个 \ 符号对字符串进行转义导致解码错误;

计算一个类名和方法名代码如下:

public static /* synthetic */ String getClassName(String str) {

    char[] toCharArray = str.toCharArray();

    for (int i = 0; i < toCharArray.length; i++) {

        toCharArray[i] = (char) (toCharArray[i] ^ 116);

    }

    return new String(toCharArray);

  }
public static void calcCheckMethodInvoke1() throws UnsupportedEncodingException {

  

    AccessibleObject method;

    byte[] bArr = new byte[24];

    bArr[0] = (byte) 11;

    bArr[1] = (byte) -94;

    bArr[2] = (byte) -88;

    bArr[3] = (byte) -14;

    bArr[4] = (byte) -95;

    bArr[5] = (byte) -19;

    bArr[6] = (byte) -38;

    bArr[7] = (byte) -88;

    bArr[8] = (byte) 19;

    bArr[9] = (byte) 73;

    bArr[10] = (byte) 17;

    bArr[11] = (byte) 32;

    bArr[12] = (byte) -68;

    bArr[13] = (byte) -125;

    bArr[14] = (byte) -120;

    bArr[15] = (byte) 19;

    bArr[16] = (byte) 75;

    bArr[17] = (byte) 68;

    bArr[18] = (byte) -41;

    bArr[19] = (byte) -121;

    bArr[20] = (byte) -38;

    bArr[21] = (byte) -5;

    bArr[22] = (byte) 24;

    bArr[23] = (byte) 120;

    bArr[5] = (byte) (bArr[5] - bArr[6]);

    //AccessibleObject constructor = Class.forName().getConstructor(new Class[]{Class.forName(Check.access$_T11306(System.out, "\u001e\u0015\u0002\u0015Z\u0018\u0015\u001a\u0013Z'\u0000\u0006\u001d\u001a\u0013"))});

    String classNameStr = new String(new BigInteger(bArr).divide(BigInteger.valueOf((long) (bArr[9] ^ 85))).toByteArray(), "UTF-8");

    String constructorMethodStr = getClassName("\u001e\u0015\u0002\u0015Z\u0018\u0015\u001a\u0013Z'\u0000\u0006\u001d\u001a\u0013");

  

    System.out.println(classNameStr);

    System.out.println(constructorMethodStr);

  

    System.out.println();

    //return classNameStr;

  }
public static void main(String[] args) {

 // write your code here

     try {

        //calc in the check method of code

        calcCheckMethodInvoke1();

    } catch (UnsupportedEncodingException e) {

        e.printStackTrace();

    }

}

 

运行结果如下:

接下来问题是,整个代码量有6000行,好像也没有特定的规律,好像只能手工转换

对样本的代码进行精简/还原,以下为手动精简后的代码:

public static boolean check(String str) {

       

        Field field = (Field) MathContext.DECIMAL64//一个 MathContext 对象,其精度设置与 IEEE 754R Decimal64 格式

        java.lang.reflect.Field.get(Object);

        MathContext mathContext = (MathContext) get(MathContext.DECIMAL64);

        long intValue = (long) ((Integer)intValue((Integer)Integer.parseInt(str))).intValue();//str is user input

        BigDecimal bigDecimal = (BigDecimal) valueOf(null, Long.valueOf(0),Integer.valueOf(0));

        BigDecimal bigDecimal2 = (BigDecimal) valueOf(Long.valueOf(4),Integer.valueOf(0));

        Field field2 = (Field) String("java.lang.System.out");

        if (((PrintStream)reflect.Field.get(field2, new Object[]{null})) == null) {

            return ((Boolean)booleanValue((Boolean)equals("9527" ,str)).booleanValue();

        }

        String str3 = null;

        Object obj4 = bigDecimal;//0

        Object obj5 = str;

        long j = intValue;  //input num

        int i = 1;

        while (true) {

            String str4 = str3;//null

            if (i < 1001) {

                Object obj6;

                if (i % 1 == 0) {

                         obj6 = obj5;

                    str3 = (String)k2015.a1.Check.access$_T15566(obj5).toString;

                }

                obj = str4;//null

                str3 = str4;//null

                long j2 = (long) i;

                //add()

                BigDecimal obj42 = (BigDecimal) obj4.add(bigDecimal2.divide((BigDecimal)valueof(Long.valueOf((long) i), Integer.valueOf(0))),MathContext), MathContext).add(bigDecimal2.divide(BigDecimal.ValueOf(Long.valueOf((long) (-(i + 2))), Integer.valueOf(0)), MathContext), MathContext);

                j += j2;

                i += 4;

                obj5 = obj6;//str      

            }

            else

            {

                break;

            }

        }

        if ((((Integer) Integer.intValue(String.hashCode(obj5).intValue() & 15) >= 0) {

                long longValue = ((Long) longValue((Long)longValue(scaleByPowerOfTen(obj42, valueOf(Integer.valueOf((int) (7 + ((((1 + j) * j) * (2 + j)) % 6)))}),r21.get(null)),new Object[0])).longValue();

                ((Boolean) booleanValue(void)((Boolean)(String.equals("4680", new Object[]{str4};), new Object[0])).booleanValue();

                return (longValue % 1000000) + 124750 == j;//124873 - 124750 = 123

        }

        if (intValue <= 8) {

                String str5 = str4;

        }

        return ((Boolean) booleanValue((Boolean) String.equals("1290", new Object[]{obj5};), new Object[0])).booleanValue();

    }

 编写测试代码如下:

public static void check2(String str) {
   
long intValue = (long) ((Integer) (Integer) Integer.parseInt(str)).intValue();

   
BigDecimal bigDecimal = (BigDecimal) valueOf(Long.valueOf(0), Integer.valueOf(0));
   
BigDecimal bigDecimal2 = (BigDecimal) valueOf(Long.valueOf(4), Integer.valueOf(0));
   
String str3 = null;
   
BigDecimal obj4 = bigDecimal;//0
   
String obj5 = str;
    long
j = intValue//input num
   
int i = 1;
   
BigDecimal obj42 = null;
    while
(true) {
        String str4 = str3
;//null
       
if (i < 1001) {
            String obj6 =
null;
            if
(i % 1 == 0) {
                obj6 = obj5
;
               
//str3 = (String) access$_T15566_update(obj5).toString();
           
}
            String obj = str4
;//null
           
str3 = str4;//null
           
long j2 = (long) i;
            
//calc  手动修改值测试
           
BigDecimal bigDecimal_i = BigDecimal.valueOf(Long.valueOf((long) i), Integer.valueOf(0));
           
BigDecimal bigDecimal_i2 = BigDecimal.valueOf(Long.valueOf((long) (-(i + 2))), Integer.valueOf(0));
           
BigDecimal bigDecimal_divide = bigDecimal2.divide(bigDecimal_i,MathContext.DECIMAL64);
           
BigDecimal bigDecimal_divide2 = bigDecimal2.divide(bigDecimal_i2, MathContext.DECIMAL64);
           
BigDecimal bigDecimal1_add = (BigDecimal) obj4.add(bigDecimal_divide, MathContext.DECIMAL64);
           
obj42 = bigDecimal1_add.add(bigDecimal_divide2, MathContext.DECIMAL64);
           
//System.out.println("obj42 = "+ obj42);
           
j += j2;
           
i += 4;
           
obj5 = obj6;//str
            //System.out.println("j = " + j);
       
}
       
else {
           
break;
       
}
       
if (((Integer.valueOf(obj5.hashCode()).intValue()) & 15) >= 0) {
            BigDecimal objlongValue = obj42.scaleByPowerOfTen(Integer.valueOf((
int) (7 + ((((1 + j) * j) * (2 + j)) % 6))));
           
//System.out.println("objlongValue = "+ objlongValue);
           
long longValue = objlongValue.longValue();
           
//System.out.println("longValue = "+ longValue);
            //System.out.print(".");
           
if ((longValue % 1000000) + 124750 == j)//124873 - 124750 = 123;
           
{
               
//System.out.println("K = " + k);
               
System.out.println("j = "+ j);
               
System.out.println("str = " + obj5);
           
}
        }
    }
}

暴力枚举结果为:

 

在手机上测试输入80 结果还是错误,但是可以知道正确的分支判断为if ((longValue % 1000000) + 124750 == j)

然后反编译定位到smali代码处进行动态调试

 

然后输入一些值,比较v4和v10的变化,可以判断是6位的正整数,从还原的代码逻辑中也可以知道输入的值会被转为long类型,最后结果如下所示:

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值