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

来源:互联网 发布:淘宝高仿警官证制作 编辑:程序博客网 时间:2024/06/05 02:24

首先解压,在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 algorithmu 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的。