mmmmar 发表于 2016-6-12 19:26

一次简单算法还原的感触

本帖最后由 mmmmar 于 2016-6-12 19:40 编辑

刚才就发了个帖子求一个助软件注册算法还原的帖子。结果好多都一眼看出来是计算机二级C语言掌上通的,本来上午写了个破解它的详细过程的帖子,突发奇想想加一个算法还原的方法,结果一弄弄了一下午。
中间一手残把浏览器给关了。。。打开一看虽然有还原功能但是插的图片都没了。刚才搜了下论坛有这方面的帖子,所以详细的教程就不发了,只说一下算法还原的方面。

刚刚知道自己哪出错了,忘了类型转换把byte类型的值加了255,我说结果的16进制里全是FF

计算机二级C语言掌上通注册码生成过程如下,位于Lcom/xqh/cexam/cc;的onPayFinish()方法中
iget-object v0, p0, Lcom/xqh/cexam/bf;->a:Lcom/xqh/cexam/MainActivity;

    invoke-virtual {v0}, Lcom/xqh/cexam/MainActivity;->i()Ljava/lang/String;

    move-result-object v0

    invoke-static {v0}, Lcom/xqh/cexam/cq;->b(Ljava/lang/String;)Ljava/lang/String;

    move-result-object v0

    iget-object v1, p0, Lcom/xqh/cexam/bf;->a:Lcom/xqh/cexam/MainActivity;

    iget-object v1, v1, Lcom/xqh/cexam/MainActivity;->u:Landroid/widget/EditText;

    invoke-virtual {v1, v0}, Landroid/widget/EditText;->setText(Ljava/lang/CharSequence;)V
可以看到,先调用MainActivity的i(),然后把返回结果当作参数传递给Lcom/xqh/cexam/cq的b()方法,b()方法的返回值就是注册码


先看MainActivity的i()方法
.method public i()Ljava/lang/String;
    .locals 3

    :try_start_0
    const-string v0, "phone"

    invoke-virtual {p0, v0}, Lcom/xqh/cexam/MainActivity;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;

    move-result-object v0

    check-cast v0, Landroid/telephony/TelephonyManager;

    new-instance v1, Ljava/lang/StringBuilder;

    const-string v2, "L"

    invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    invoke-virtual {v0}, Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;

    move-result-object v0

    invoke-virtual {v0}, Ljava/lang/String;->toUpperCase()Ljava/lang/String;

    move-result-object v0

    invoke-virtual {v1, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v0

    const-string v1, "8H6"

    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v0

    invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
    :try_end_0
    .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0

    move-result-object v0

   
    const/4 v1, 0x1
   
    invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
   
    move-result-object v2
   
    invoke-virtual {v2}, Landroid/widget/Toast;->show()V



    :goto_0
    return-object v0

    :catch_0
    move-exception v0

    const-string v0, "TH1109ZXN0914"

    invoke-virtual {v0}, Ljava/lang/String;->toUpperCase()Ljava/lang/String;

    move-result-object v0

    goto :goto_0
.end method
这段代码很简单,就在获取的DeviceID前后加了两个字符串

核心的简单算法,位于Lcom/xqh/cexam/cq
.method public static b(Ljava/lang/String;)Ljava/lang/String;
    .locals 5
#获取md5实例
    :try_start_0
    const-string v0, "MD5"

    invoke-static {v0}, Ljava/security/MessageDigest;->getInstance(Ljava/lang/String;)Ljava/security/MessageDigest;

    move-result-object v0

    new-instance v1, Ljava/lang/StringBuilder;

    const-string v2, "niat.xqh"

    invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    invoke-virtual {v1, p0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v1

    const-string v2, "c2exam86"

    invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v1

    invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v1
#加密后的字节数组
    invoke-virtual {v1}, Ljava/lang/String;->getBytes()[B

    move-result-object v1

    invoke-virtual {v0, v1}, Ljava/security/MessageDigest;->update([B)V

    invoke-virtual {v0}, Ljava/security/MessageDigest;->digest()[B

    move-result-object v2
   
    new-instance v3, Ljava/lang/StringBuffer;

    const-string v0, ""

    invoke-direct {v3, v0}, Ljava/lang/StringBuffer;-><init>(Ljava/lang/String;)V

    const/4 v0, 0x0

    move v1, v0

    :goto_0
    array-length v0, v2

    if-lt v1, v0, :cond_0

    invoke-virtual {v3}, Ljava/lang/StringBuffer;->toString()Ljava/lang/String;

    move-result-object v0

    const/4 v1, 0x4

    const/16 v2, 0x17

    invoke-virtual {v0, v1, v2}, Ljava/lang/String;->substring(II)Ljava/lang/String;

    move-result-object v0

    invoke-virtual {v0}, Ljava/lang/String;->toUpperCase()Ljava/lang/String;

    move-result-object v0

    return-object v0

    :cond_0
    aget-byte v0, v2, v1

    if-gez v0, :cond_1
#注意这里!!!!!!!!!!   把v0转换成了int型
    add-int/lit16 v0, v0, 0x100

    :cond_1
    const/16 v4, 0x10

    if-ge v0, v4, :cond_2

    const-string v4, "0"

    invoke-virtual {v3, v4}, Ljava/lang/StringBuffer;->append(Ljava/lang/String;)Ljava/lang/StringBuffer;

    :cond_2
    invoke-static {v0}, Ljava/lang/Integer;->toHexString(I)Ljava/lang/String;

    move-result-object v0

    invoke-virtual {v3, v0}, Ljava/lang/StringBuffer;->append(Ljava/lang/String;)Ljava/lang/StringBuffer;
    :try_end_0
    .catch Ljava/security/NoSuchAlgorithmException; {:try_start_0 .. :try_end_0} :catch_0

    add-int/lit8 v0, v1, 0x1

    move v1, v0

    goto :goto_0

    :goto_1
    const-string v1, "TH1109ZXN0914"

    invoke-virtual {v0}, Ljava/security/NoSuchAlgorithmException;->printStackTrace()V

    goto :goto_1

    :catch_0
    move-exception v0

    goto :goto_1
.end method
还原之后代码为:
public String b(String param){
      try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            String str = "niat.xqh"+param+"c2exam86";
            messageDigest.update(str.getBytes());
            byte[] result = messageDigest.digest();
            StringBuilder builder = new StringBuilder();
            int i= 0;
            while(i<result.length){
//刚开始写成了byte型,结果一直不对
                int v =result;
                if(v<0){
                  v+=256;
                }
                if(v<16){
                  builder.append("0");
                }
                builder.append(Integer.toHexString(v));
                i++;
            }
            String v3 = builder.toString();
            v3 = v3.substring(4,23);
            return v3.toUpperCase();

      } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
      }
      return "";
    }
smali码和java对比着看就很容易看懂了,折腾了整整一下午,去动态调试也没看出来什么,结果是变量类型的原因。

详细教程点这里!!!!!!

最后吐槽一下,这软件解锁之后的编程功能竟然是给装个C4droid,太无耻了吧

Tomatoman 发表于 2016-6-12 20:05

真不错~哈哈

wangqiustc 发表于 2016-6-12 20:17

来学习学习

天坑霸气 发表于 2016-6-12 21:49

66666666学习一下把
页: [1]
查看完整版本: 一次简单算法还原的感触