Minisoyo社区's Archiver

lshjava 发表于 2008-2-29 20:00

用HALO2进行短信破解的心得!

坛里关于手机短信游戏破解的文章有很多,而且很有水平,令人高山仰止!实不想班门弄斧,恐招千夫所指!但HALO2的推出给破解工作带来了许多便利,有必要向新手们介绍下,本人水平有限,文中不足之处请多多包涵!郑重声明:文中所引用的例子谨作为学习交流,并无它意!
  用HALO2打开底下城与勇士.jar,点击"类编辑器",在"编辑"选项中选"全文查找",在搜索栏中填入"MessageConnection",搜索方式选"By total class",开始搜索!(图1)
[attach]436608[/attach]
搜索结果如下:(图2)
[attach]436609[/attach]
  其中"类名  j  "是指该方法在JAR包根目录下的j.class.
   "方法名  f  "就是指该方法名为"f" .
   "签名"是对该方法的描述,是区别于同一个class文件里同名方法唯一表述.我们反编译j.class,找到这个"f"方法,它的起首行"private void f(int i1)"表明它的使用权限为"私有的"(private),而public指公共的,friendly 指友好的,protected指受保护的!具体的说明请参考专业的教材.void是指该方法的返回类型,也就是别的方法调用该方法所得到的东西,void意味着“什么也不返回",但也可返回一些变量值或其它结果.具体的要结合程序分析.比如"boolean"就表示它返回的就是布尔值,即真(true)和假(false).具体的说明也请参考专业的教材.括号里的(int i1)是该方法的自变量列表.自变量列表规定了我们在调用这个方法时传递给它的东西.对于本方法int i1是指:给该方法传递一个整型变量(int),变量名是i1.
  让我们双击这个搜索结果来到j.class下的private void f(int i1)方法.点击这个"f"方法(不是它的下层目录"[0]code"!!! )上面所说的东西如图3.
[attach]436610[/attach]
以下是反编译后程序:
  private void f(int i1)
    {
        b = i1;
        a = false;
        MessageConnection messageconnection = null;
        Object obj = null;
        if(l == 0)
        {
            h = "sms://" + d[0];
            i = "JG " + e + " " + f + "#" + g;
            l = 1;
        } else
        if(l == 1)
        {
            h = "sms://" + d[1];
            i = "62 " + e + " " + f + "#" + g;
            l = 0;
        }
        try
        {
            TextMessage textmessage;
            (textmessage = (TextMessage)(messageconnection = (MessageConnection)Connector.open(h)).newMessage("text")).setPayloadText(i);
            messageconnection.send(textmessage);
        }
        catch(Exception _ex)
        {
            b = 0;
        }
        try
        {
            messageconnection.close();
        }
        catch(Exception _ex) { }
        a = true;
    }
  其中:try
        {
            TextMessage textmessage;
            (textmessage = (TextMessage)(messageconnection = (MessageConnection)Connector.open(h)).newMessage("text")).setPayloadText(i);
            messageconnection.send(textmessage);
        }
        catch(Exception _ex)
        {
            b = 0;
        }是检查是否进行了发送短信动作,如果没发送就抛出异常并将变量b赋值为0(b = 0).
  

   而下一段:
try
        {
            messageconnection.close();
        }
        catch(Exception _ex) { }
        a = true
   是检查是否发送短信完毕,如果没完毕就抛出异常,如果完毕了就将变量a赋值为 true( a = true).就是说只有a = true才可以享受到发送短信后的服务!该方法的任务就是返回a和b两个变量,其他的都是多余的,都可以删除!
   用HALO2的代码编辑修改后,该方法变成了:
aload_0
iload_1
putfield j/b I
aload_0
iconst_1
putfield j/a Z
return
反编译后程序:
private void f(int i1)
    {
        b = i1;
        a = true;
    }
  我们在模拟器上试验下,发现还是没破解成功!而且屏幕显示"正在购买....请稍等片刻......",和原来的一样!即是说游戏另有陷阱,所以这就是用HALO自动破解失败的原因!
   好的那我们换个角度来思考!请看以下这段文字:public static String c[] = {
        "购买成功,您的游戏币已增加5000!<br>", "购买成功,欢迎进入赌场体验!<br>", "购买成功,杀伤力已经加倍!<br>", "购买成功,升级后能获得加倍的技能点!<br>", "购买成功,接下来打怪获得的经验值比之前增加一倍!<br>", "购买成功,接下来的强化装备属性100%成功!<br>", "隐藏职业已开启,请返回选择职业!<br>"   
   这就是发送短信成功后所显示的信息!我就想找到调用这段文字的方法,看看判断短信发送成功的条件是怎样的.这个方法是静态(static)类型的,在HALO2里就是<clinit>这段:
anewarray java/lang/String
dup
iconst_0
ldc "购买成功,您的游戏币已增加5000!<br>"
aastore
dup
iconst_1
ldc "购买成功,欢迎进入赌场体验!<br>"
aastore
dup
iconst_2
ldc "购买成功,杀伤力已经加倍!<br>"
aastore
dup
iconst_3
ldc "购买成功,升级后能获得加倍的技能点!<br>"
aastore
dup
iconst_4
ldc "购买成功,接下来打怪获得的经验值比之前增加一倍!<br>"
aastore
dup
iconst_5
ldc "购买成功,接下来的强化装备属性100%成功!<br>"
aastore
dup
bipush 6
ldc "隐藏职业已开启,请返回选择职业!<br>"
aastore
putstatic j/c [Ljava/lang/String;
最后这句:"putstatic j/c [Ljava/lang/String"的"putstatic"我把它理解为把数据放入寄存器(堆栈?),(我没专门学过任何高级语言,只是小时候玩学习机时,接触了些FBASIC语言.不知这样解释对否?请高手不要见笑!)那getstatic就应该是把数据从寄存器里取出,而j/c [Ljava/lang/String就是存放以上数据的地址的标签.我们在HALO2里的类编辑器搜索j/c [Ljava/lang/String;会有两个结果,其中一个就是上面那段,不用理会.还有个d方法在j.class,即是这段:
private void d()
    {
        switch(d)
        {
        case 2: // '\002'
        default:
            break;

        case 0: // '\0'
            String s = "";
            switch(e)
            {
            case 2: // '\002'
                s = s + "购买后伤害倍数为:" + 2 * a.cF + "倍";
                break;

            case 4: // '\004'
                s = s + "购买后经验值倍数为:" + 2 * a.cE + "倍";
                break;

            case 3: // '\003'
                s = s + "购买后技能点倍数为:" + 2 * a.cG + "倍";
                break;
            }
            a.a(c[e] + s, b[1], b[2], b[3], b[4]);
            a(-2, 4);
            d = 1;
            return;
其中"a.a(c[e] + s, b[1], b[2], b[3], b[4]);"调用了j/c [Ljava/lang/String;具体代码为
getstatic j/c [Ljava/lang/String;意思是取出这段文字!
  这个private void d()方法又被谁调用的?我们再往上找,而private void d()的标签是"j/d()V".  "j"表示该方法位于JAR包根目录下的j.class."/d"表示它的方法名."()"表示调用该方法时没有东西传递给它,所以括号里是空的."V"表示该方法返回类型是void,V就是void的缩写.或者点击图3标签前面进入常量池,用"ctrl+c"复制标签(需自己添加路径和方法名),再用"ctrl+v"粘贴到搜索栏里!经过搜索发现public final void a(Graphics g1)调用了private void d()方法.如下:
public final void a(Graphics g1)
    {
        f++;
        j++;
        k++;
        g1.setFont(k.a);
        switch(c)
        {
        case 0: // '\0'
            b();
            b(g1);
            break;

        case 2: // '\002'
            c();
            c(g1);
            break;

        case 10: // '\n'
            d();
            d(g1);
            break;

        case 11: // '\013'
            e();
            e(g1);
            break;
        }
        i = 0;
    }
分析后得知:只有变量c = 10时,程序才能执行private void d()方法,即:
case 10: // '\n'
            d();
            d(g1);
            break;
就是说只有c = 10,程序才会认为短信发送成功!变量c的标签是 j/c I,后面的"I"表示该变量的数据类型.现在我们回到那个发送短信的方法private void f(int i1),看看变量c是如何变化的!经过搜索发现方法private void f(int i1)被public final void a()调用,而public final void a()又被r.class的public final void run()调用了,run()方法是Thread(线程)类下的,可以使用thread的start方法来调用它.那我们搜索谁调用run()方法时在搜索栏里输入"invokevirtual java/lang/Thread/start()V"经过搜索发现有4个结果,分析后只有j.class下的private void e(int i1)方法调用了r.class的public final void run().那我们看下private void e(int i1)方法:
private void e(int i1)
    {
        if(i1 == 0)
        {
            c(2);
            Thread thread;
            (thread = new r(this)).start();
            f = 0;
            return;
        }
它在(thread = new r(this)).start()前先调用了c方法(c(2);),并且给c方法传递了一个整数"2",而c方法的标签是 j/c(I)V ,就是如下的方法:
private void c(int i1)
    {
        c = i1;
        d = 0;
        j = -1;
        k = -1;
    }
里面的变量c就是我们上面提到的,"c = i1;"就是变量c的值等于给c方法传递的那个整数"2".我们只要把private void e(int i1)方法里的c(2)改为c(10)就完成破解了!可能有人问private void e(int i1)方法和public final void a(Graphics g1)方法没关联啊!你只要继续搜索private void e(int i1)的调用者就发现public final void a(Graphics g1)最终调用了private void e(int i1),我就不一一介绍了!我对这个游戏有些疑问,按我的理解这个游戏哪怕是正常的发送短信也无法成功开启服务的啊!难到还有其他机关?想请教下BB,飞鹰,KIM这些高手们,这也是我用这个游戏作例子的目的!因本人水平有限,文中不足之处也请赐教!
  本来还想用雪鲤鱼的几个短信+联网收费游戏做例子,介绍下破解简单联网收费游戏的一些心得,但本文的篇幅已超出预计了,唯有等有空再发上来了,说实话,写教材太难了,打字都打得手痛了!我写这篇文章只是希望朋友们能了解下HALO2的搜索功能.对于破解的思路和方法,各人有各人的方法,目前论坛里发的破解版使用的方法就比我的好.呵呵,当时我破解是为了移植到我的MOTO 小C上的,但这游戏的内存要求太高了,我的小C没法运行.我就没留意到这个破解版,走了些弯路!

[[i] 本帖最后由 nbycy 于 2008-2-29 20:42 编辑 [/i]]

云星 发表于 2008-2-29 20:02

支持 学习
图挂了:099

天空之城 发表于 2008-2-29 20:20

浮云...             :091

天空之城 发表于 2008-2-29 20:22

需要这方面的一点知识才行啊~  真佩服楼主~

阿飛 发表于 2008-2-29 20:24

正好我要學...:091

feng798 发表于 2008-2-29 20:25

了解,谢谢分享!

z357135481 发表于 2008-2-29 20:47

羡慕中:眼睛

wsfrbss 发表于 2008-2-29 20:49

看了半天,还是一头雾水:流汗 搞了半天也没成功 ,还是请楼主帮我破解这个游戏
[attach]436656[/attach]

乂文文乂 发表于 2008-2-29 23:44

看的一头雾水阿...
想学不过看完已经想睡了....
大大真强...:流汗

Fingolfin 发表于 2008-3-1 13:19

了解,谢谢分享!

look2212 发表于 2008-3-1 17:56

支持教程,感谢分享

cshiong 发表于 2008-3-1 18:39

`

      好强啊,虽说看不懂……   :091

寒洛 发表于 2008-3-1 18:40

:098 大学以下的不要看了

lshjava 发表于 2008-3-1 18:58

我也是小学生啊!

蓝罐曲奇 发表于 2008-3-2 15:10

好奇问一下,
阁下有没有遇到过混合语言编的游戏?
:流汗

无比帅呆 发表于 2008-3-2 15:15

水平有限,看不懂啊。感谢分享破解经验

markde 发表于 2008-3-3 16:27

比较晕,不过支持!

天空之城 发表于 2008-3-3 16:29

发帖再看~

19830802 发表于 2008-3-3 17:28

谢谢分享

litemanen9000 发表于 2008-3-3 19:30

貌似没怎么看懂..:哭泣

页: [1] 2 3 4 5 6 7

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.