• 记大神的一次反汇编/更新


    首先解压,在assets文件夹下在找到了要汇编的文件:appmgr.jar,这个文件在安装后在/data/data/<package name>/files/文件夹下会生成一个appmgr.apk,

    「其实只是一个存放代码的资源文件,安装的时候重命名了,以apk结尾罢了。」

    -------------2014.10.9修正---------------

    上面打中文引号的这句话有待考究,如果直接解压得到classes.dex,那个dex只有6kB,而安装后提取的classes.dex有278.23KB,这篇文章用到的是后者。

    解压这个apk文件,得到classes.dex,拖到IDA Pro 6.1以上版本里面去,可以识别成Android的dex文件。

    鉴于要找signature_md5的算法,用alt+t查找「signature_md5」字符串,找到:

    CODE:0001ACCE                 const-string/jumbo              v1, aSignature_md5 # "signature_md5"//定义一个aSignature_md5字符串,放到v1寄存器 
    //Dalvik指令集看这里

    接下来对v1做了这些事情:

    从JSON里拿到一个键值对放到v2,v1里;

    move-result-object,把数据放回v1里;

    check-cast,转换成String格式;

    定义逗号,放到v8里;//为什么会有逗号出现?

    用v8里的逗号,调用String的split方法 split v1,注意split返回的是分割后的数组

    把split之后的数组放到v11里;

    下面就不太重要了因为定义了Edition_brief这个变量,下面追踪v11:

    array-length开始,把v11的数组长度放到v9里去;

    下面if-ge, greater or equal,v2>=v9就跳转到loc_1AD72,注意v2上面定义了是0;就是如果长度等于零则跳转,注意这个v9是JSON里拿到的字符串分割成数组的长度;

    if-nez,not equal zero,v8!=0就跳转到loc_1AD72,注意上面刚定义v8等于0,这里有些迷糊;

    下一句从packageInfo_signatures得到签名放到v13,v10;

    注意Arrays.toString(ref);和xx.toString();是不同的。

    xx.toString();输出的东西是[@XXXXX一串,而且好像每次都不一样,大神猜测是地址,网上有人说是HASH。

    数值数组是不能够整体输出的,

    你可以使用循环输出
    for(i=0;i<10;i++)
    System.out.println(a[i]+" ");

    而借助Arrays.toString(a)就节省了上面的循环步骤,而一步输出(当然,调用函数的内部进行了处理)。

    然后注意v13中存储了v13,v13又给了v23,v23经过一系列转换格式,最后用一个ad.a(ref)得到了signature_md5;

    然后倒数第三行,v11和v2给了v24;

    v23和v24比较,亦即PackageInfo_signatures经过ad.a(ref)后,与JSON中的MD5比较。

    到此可以看到要找的函数就是ad.a(byte [] x );

    此时用dex2jar把dex反编译成jar,放到jd-gui里,找到ad.a():

    TIP:昨天才发现函数名冒号后面的代表返回类型。a这个函数里是这样的:

    可是循着w.f()找过去发现没有getMD5()。

    大神提议用Notepad++的搜索文件中的字符串功能搜索360 apk整个文件反编译出的smali,不知道他怎么想到的。

    找到了。下面就是追踪混淆代码了,需要极大的耐心。

    evt.c(),然后找到evg.b(),

    找到eua.d();本来在eua里找这个a(paramArrayOfByte)怎么也找不到,转念一想才想起来应该在b所在的函数evg里找!

    最后找到了。

    这个真需要很大耐心。我的话恐怕某一步早就放弃了,因为难以接受弄了半天弄不出的结果。大神牛B。

    2014年8月7日。

    --------------------------2014年10月30日---------------------------

    昨天花时间跟了一下另一个混淆了的应用的某个算法,最后跟到了,记录一下。

    首先是用jd-gui从混淆的类中跟到的相关的一系列程序片段(只是思路,并没有遵循语法):

    //chasing the signmd5 algorithm
    
    u localu = (u)localIterator.next();
    localJSONObject2.put("signmd5", localu.a(this.a));//start from here,find localu.a(this.a)!
    
    this.c = paramJSONObject.getString("PackageName");
    private long d = -1L;
    //localu.a(this.a)
      public long a(Context paramContext)
      {
        if (this.d == -1L)
        {
          PackageInfo localPackageInfo = j.a(paramContext, this.c);
          if (localPackageInfo != null)
            this.d = j.a(j.a(localPackageInfo.signatures[0].toCharsString().getBytes()));
        }
        return this.d;
      }
    //the first j.a(byte[] paramArrayOfByte) returns us a String
    //the second j.a(String paramArrayOfByte) returns us a long int,which is presented to this.d
    
    
    //j.a(byte[] paramArrayOfByte)
      public static String a(byte[] paramArrayOfByte)
      {
        try
        {
          MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");
          localMessageDigest.update(paramArrayOfByte);
          String str = b(localMessageDigest.digest());
          return str;
        }
        catch (NoSuchAlgorithmException localNoSuchAlgorithmException)
        {
          return "";
        }
        catch (Exception localException)
        {
        }
        return "";
      }    
      
    //j.a(String paramArrayOfByte)
      public static long a(String paramString)
      {
        long l1 = 0L;
        int i = 8;
        if ((TextUtils.isEmpty(paramString)) || (paramString.length() < 32))
          return -1L;
        String str = paramString.substring(i, 24);
        int j = 0;
        long l2 = l1;
        while (j < i)
        {
          l2 = l2 * 16L + Integer.parseInt(str.substring(j, j + 1), 16);
          j++;
        }
        while (i < str.length())
        {
          l1 = l1 * 16L + Integer.parseInt(str.substring(i, i + 1), 16);
          i++;
        }
        return 0xFFFFFFFF & l1 + l2;
      }
    //j.a(Context paramContext, String paramString)
      public static PackageInfo a(Context paramContext, String paramString)
      {
        try
        {
          PackageInfo localPackageInfo = paramContext.getPackageManager().getPackageInfo(paramString, 64);
          return localPackageInfo;
        }
        catch (Exception localException)
        {
        }
        return null;
      }
    //b(localMessageDigest.digest());
        public static String b(byte[] paramArrayOfByte)
      {
        if (paramArrayOfByte == null)
          return "";
        StringBuilder localStringBuilder = new StringBuilder(2 * paramArrayOfByte.length);
        for (int i = 0; i < paramArrayOfByte.length; i++)
        {
          localStringBuilder.append(b[((0xF0 & paramArrayOfByte[i]) >>> 4)]);
          localStringBuilder.append(b[(0xF & paramArrayOfByte[i])]);
        }
        return localStringBuilder.toString();
      }

    可以看出只是要找到“localu.a(this.a)”,localu是u这个类的对象,所以到u里面找a的各种方法。

    好了最后找到之后写成Android代码:

    package com.larry.baidusignmd5;
    
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    
    import android.app.Activity;
    import android.content.Context;
    import android.content.pm.PackageInfo;
    import android.os.Bundle;
    import android.text.TextUtils;
    import android.util.Log;
    
    public class MainActivity extends Activity {
    //    Context context = getApplicationContext();// is it right?
        Context context = MainActivity.this;
        private long signmd5 = -1L;
        String two = null;
        private static final char[] b = { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
                97, 98, 99, 100, 101, 102 };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            String pkgName = "com.phantomz.lightball";
            PackageInfo localPackageInfo = one(context, pkgName);
            byte[] sig = localPackageInfo.signatures[0].toCharsString().getBytes();
            two = two(sig);
            signmd5 = three(two);
            String stringmd5 = Long.toString(signmd5);
            Log.d("signmd5",stringmd5);
        }
    
        // j.a(Context paramContext, String paramString)
        public static PackageInfo one(Context paramContext, String paramString) {
            try {
                PackageInfo localPackageInfo = paramContext.getPackageManager()
                        .getPackageInfo(paramString, 64);
                return localPackageInfo;
            } catch (Exception localException) {
            }
            return null;
        }
    
        // j.a(byte[] paramArrayOfByte)
        public static String two(byte[] paramArrayOfByte) {
            try {
                MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");
                localMessageDigest.update(paramArrayOfByte);
                String str = b(localMessageDigest.digest());
                return str;
            } catch (NoSuchAlgorithmException localNoSuchAlgorithmException) {
                return "";
            } catch (Exception localException) {
            }
            return "";
        }
    
        // b(localMessageDigest.digest());
        public static String b(byte[] paramArrayOfByte) {
            if (paramArrayOfByte == null)
                return "";
            StringBuilder localStringBuilder = new StringBuilder(
                    2 * paramArrayOfByte.length);
            for (int i = 0; i < paramArrayOfByte.length; i++) {
                localStringBuilder.append(b[((0xF0 & paramArrayOfByte[i]) >>> 4)]);
                localStringBuilder.append(b[(0xF & paramArrayOfByte[i])]);
            }
            return localStringBuilder.toString();
        }
    
        // j.a(String paramArrayOfByte)
        public static long three(String paramString) {
            long l1 = 0L;
            int i = 8;
            if ((TextUtils.isEmpty(paramString)) || (paramString.length() < 32))
                return -1L;
            String str = paramString.substring(i, 24);
            int j = 0;
            long l2 = l1;
            while (j < i) {
                l2 = l2 * 16L + Integer.parseInt(str.substring(j, j + 1), 16);
                j++;
            }
            while (i < str.length()) {
                l1 = l1 * 16L + Integer.parseInt(str.substring(i, i + 1), 16);
                i++;
            }
            return 0xFFFFFFFF & l1 + l2;
        }
    }

    好了。可以看出同样是读signature,但是也是要读本地安装的signature;而原来的应用中似乎是可以读下载应用的signature的。

  • 相关阅读:
    数据建模学习笔记-1-《高质量数据库建模 1-重大意义》
    sqoop中,如果数据中本身有换行符,会导致数据错位
    telnet时显示:允许更多到 telnet 服务器的连接。请稍候再试
    Eclipse首字母快捷设置
    error: bad symbolic reference. A signature in HiveContext.class refers to term hive
    在IT的路上,我在成长
    uglifyjs-webpack-plugin 插件,drop_console 默认为 false(不清除 console 语句),drop_debugger 默认为 true(清除 debugger 语句)
    读《精通正则表达式(第三版)》笔记
    vue cli 3.x 设置4个空格缩进
    正则表达式 学习资料
  • 原文地址:https://www.cnblogs.com/larrylawrence/p/3832433.html
Copyright © 2020-2023  润新知