V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
banxi1988
V2EX  ›  程序员

欢迎挑战:一个反编译的后的函数计算结果出错的问题

  •  
  •   banxi1988 ·
    banxi1988 · 2015-03-03 11:17:47 +08:00 · 3863 次点击
    这是一个创建于 3554 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我曾经使用 dex2jar 反编译了某一个Android 应用.
    然后,导入 Jar,然后一些类可以正常使用,OK
    但是,仔细检查发现了问题:
    就是反编译后的结果与应用之前计算的结果不同.
    比如如下反编译后的EncryptUtil 类中方法:

    public static String toParam(String var0, String var1) {
            try {
                String var3 = "param=" + of_encrypt(var0, var1) + "&param2=" + getMd5_2(var0);
                return var3;
            } catch (Exception var4) {
                return "param=error&param2=error";
            }
        }
    

    对于以下代码:

    System.out.println("myAllParams="+EncryptUtil.toParam(originalParam1,xxdm));
    System.out.println("myAllParams2="+EncryptUtil.toParam(originalParam1,xxdm));
    System.out.println("myParam2_1="+EncryptUtil.getMd5_2(param));
    System.out.println("myParam2_2="+EncryptUtil.getMd5_2(param));
    

    按道理,也就是 toParam 方法调用之后的 param2的结果, 应该与 直接调用 getMd5_2的结果一样,
    可以结果确不是一样的.
    上面代码输出如下:

    myAllParams=param=2tb3nq2qay2o2s45ch2mqawf2twpf52pqe5m1vc4lm1ltd391o6vsm1oseh62ojcs92ridda1tjxn41r68rl1pz0hl2qbqoo2s4j8q2hdhkv291ui72il9zc003erq&param2=6d749a8bf841a5d3d772832367d5c0e6
    
    myAllParams2=param=2tb3nq2qay2o2s45ch2mqawf2twpf52pqe5m1vc4lm1ltd391o6vsm1oseh62ojcs92ridda1tjxn41r68rl1pz0hl2qbqoo2s4j8q2hdhkv291ui72il9zc003erq&param2=6d749a8bf841a5d3d772832367d5c0e6
    
    myParam2_1=7aac8cb9cdf9898077a262d324dd86b5
    
    myParam2_2=7aac8cb9cdf9898077a262d324dd86b5
    

    但是其实上面对于 param2的计算都是错误的
    正确的计算结果 ,也就是原来应用的计算结果是:
    param2=338f3b6b250342cc5b1117a6346b0c89

    直接从反编译出来的代码看不出是什么导致了问题:
    但是感觉 调用toParam 跟直接调用 getMd5_2有差别

    于是尝试分析最原始的 toParam 的 smali 代码
    如下:

    .method public static toParam(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
        .locals 3
        .param p0, "as_str"    # Ljava/lang/String;
        .param p1, "as_key"    # Ljava/lang/String;
    
        .prologue
        .line 34
        :try_start_0
        new-instance v1, Ljava/lang/StringBuilder;
    
        const-string v2, "param="
    
        invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V
    
        invoke-static {p0, p1}, LEncryptUtil;->of_encrypt(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    
        move-result-object v2
    
        invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    
        move-result-object v1
    
        const-string v2, "&param2="
    
        invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    
        move-result-object v1
    
        invoke-static {p0}, LEncryptUtil;->getMd5_2(Ljava/lang/String;)Ljava/lang/String;
    
        move-result-object v2
    
        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;
        :try_end_0
        .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0
    
        move-result-object v1
    
        .line 37
        :goto_0
        return-object v1
    
        .line 36
        :catch_0
        move-exception v1
    
        move-object v0, v1
    
        .line 37
        .local v0, "e":Ljava/lang/Exception;
        const-string v1, "param=error&param2=error"
    
        goto :goto_0
    .end method
    

    还是没有发现可疑的地方
    欢迎任何线索,指点

    第 1 条附言  ·  2015-03-03 13:00:22 +08:00
    上面代码有误:
    修正如下:EncryptUtil.getMd5_2(originalParam1
    getMd5_2的方法如下:
    ```java
    public static String getMd5_2(String var0) throws Exception {
    String var1 = "";
    String[] var2 = getMd5(var0).split("");
    int var3 = var2.length;

    for(int var4 = 0; var4 < var3; ++var4) {
    if(var4 != 3 && var4 != 10 && var4 != 17 && var4 != 25) {
    var1 = var1 + var2[var4];
    }
    }

    return getMd5(var1);
    }
    ```
    其中 getMd5是标准的 MD5实现


    所以现在目前问题,还是回到,就是反编译出来 的 getMd5_2方法
    跟应用本来的方法返回的结果不同:
    getMd5_2 相应的 smali 代码如下:



    我仔细看了下,对于 smali 代码感觉也没有明显的问题.
    14 条回复    2015-03-04 18:57:27 +08:00
    exch4nge
        1
    exch4nge  
       2015-03-03 11:37:44 +08:00   ❤️ 1
    看了半天没明天楼主的意思……是我理解能力差么……
    clino
        2
    clino  
       2015-03-03 11:46:24 +08:00   ❤️ 1
    要么是偷别人的东西要么是黑别人的东西?
    Sinute
        3
    Sinute  
       2015-03-03 11:55:07 +08:00   ❤️ 1
    反编译的逻辑不一定就是正确的
    我以前就踩过一个坑
    反编译结果类似
    ```
    v0 += "0";
    ```
    实际应该是
    ```
    v0 = "0" + v0;
    ```
    一层一层进去慢慢调吧
    yangff
        4
    yangff  
       2015-03-03 12:00:33 +08:00 via Android   ❤️ 1
    你一个用的originalParam1一个用的param。。
    banxi1988
        5
    banxi1988  
    OP
       2015-03-03 13:02:39 +08:00
    @yangff 已经修正,谢谢指出.

    @Sinute 我需要研究的是一个2次自定义 md5的结果的,试了几种方式,结果都不理想,
    附言,提供了详细的相关代码, 还请帮助指点分析一二. 谢谢.
    banxi1988
        6
    banxi1988  
    OP
       2015-03-03 13:05:03 +08:00
    @exch4nge
    有附言了,再看看理解 不.
    就是原应用中有一个方法,一个字符经过这个方法的调用 得出来的值是"a"
    但是我用反编译出来的 jar 再用同一个字符串调用些方法得出来的不是"a"
    invite
        7
    invite  
       2015-03-03 13:19:57 +08:00
    把jar包拿出来大家一起看看。
    kaizixyz
        8
    kaizixyz  
       2015-03-03 15:02:27 +08:00   ❤️ 1
    EncryptUtil类名都有。为何要用反编译的。Google之啦~
    banxi1988
        9
    banxi1988  
    OP
       2015-03-03 17:15:20 +08:00
    @kaizixyz 这个 Google 过没有相同对应的,
    再说在 明显是自己写的 EncryptUtil,
    写 Java 的,估计很多都有自己的 StringUtil 或者,EncryptUtil,
    类名相同而已,也不是某一个开源库的类.
    不过,还是谢谢指点.
    sinsin
        10
    sinsin  
       2015-03-03 18:51:41 +08:00
    这个反编译的Md5_2真没看懂吔。。。
    * getMd5(var0).split(""),这里用空白RegExp("")来split,得到的是一个包含var0每个字符的数组,而且最前面还多送个空白元素?
    RecursiveG
        11
    RecursiveG  
       2015-03-03 21:33:09 +08:00
    有没有原版getMd5_2的输入输出?
    durrrr
        12
    durrrr  
       2015-03-04 10:50:47 +08:00 via iPad
    of_encrypt 是不是做了什么全局操作?比如改变字符编码什么的。
    我觉得最该贴出来的代码是这个。
    banxi1988
        13
    banxi1988  
    OP
       2015-03-04 16:07:59 +08:00
    @durrrr 这个 of_encrypt 没有改变全局的操作.
    或者说 getMd5_2 也没有读取全局变量的操作.
    getMd5_2引用的其他自定义函数也只是 生成标准 MD5字符串的操作.

    昨天我自己尝试解析了下 smali 代码,然后调用生成的结果 ,跟 dex2jar 生成的代码,调用产生的结果是一样的.


    @RecursiveG
    getMd5_2方法的
    一个原版的输入: "nj=2014&yxid=01"
    输出:"7bbc20a3bad140e7fcdc52442d3c7b9d"
    RecursiveG
        14
    RecursiveG  
       2015-03-04 18:57:27 +08:00
    这是个结果正确的代码,但是原因还是不明。。。
    感觉像是 @sinsin 说的,`split("")` 的时候前面多送了个空白元素。
    但是我实际测试的时候没有多送啊。。。。。
    难道是行为不一样?
    ``` java
    public static String getMd5_2(String originStr){
    String mystr=Standard_MD5_lowercase(originStr);
    String result="";
    for(int i=0;i<mystr.length();i++){
    if(i==2||i==9||i==16|i==24)continue;
    result+=mystr.charAt(i);
    }
    return Standard_MD5_lowercase(result);
    }
    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2825 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 11:47 · PVG 19:47 · LAX 03:47 · JFK 06:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.