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

2015-03-03 11:17:47 +08:00
 banxi1988

我曾经使用 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

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

3737 次点击
所在节点    程序员
14 条回复
exch4nge
2015-03-03 11:37:44 +08:00
看了半天没明天楼主的意思……是我理解能力差么……
clino
2015-03-03 11:46:24 +08:00
要么是偷别人的东西要么是黑别人的东西?
Sinute
2015-03-03 11:55:07 +08:00
反编译的逻辑不一定就是正确的
我以前就踩过一个坑
反编译结果类似
```
v0 += "0";
```
实际应该是
```
v0 = "0" + v0;
```
一层一层进去慢慢调吧
yangff
2015-03-03 12:00:33 +08:00
你一个用的originalParam1一个用的param。。
banxi1988
2015-03-03 13:02:39 +08:00
@yangff 已经修正,谢谢指出.

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

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/174117

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX