您的位置:首页 > 其它

J2ME游戏破解心得之二

2009-12-29 15:17 375 查看
上一次一篇《J2ME游戏破解心得暨反编译字节码操作研究》记录了我破解一款RPG游戏的短信计费代码,不出一个月,被许许多多的网站转载,而且没有注明出处。当然,这到不是最重要的,重要的是大家学会了破解的方法。
最近在破解另一个深受大家喜爱的游戏时(名字我还是不提了),遇到了和上次不同的问题,虽然都是发送短信计费,但代码的结构和逻辑发生了比较大的变化。上次破解时,关于发送短信的判断比较简单,就是成功了就返回成功,失败了捕捉异常返回失败,破解点也就显得简单,只需把返回失败的地方改成返回成功就行了。而这次是使用了一个匿名的线程类,发送时启动一个线程去处理,外部通过一些发送的状态变量值来判断。该类对应的文件是b.class,而匿名的线程类被编译到b$1.class中。b$1.class文件反编译出的代码如下:

public void run()
{
try
{
b.if = true;
MessageConnection messageconnection = null;
String s = "sms://" + b.access$000(b.this);
System.out.println(s);
messageconnection = (MessageConnection)Connector.open(s);
TextMessage textmessage = (TextMessage)messageconnection.newMessage("text");
textmessage.setPayloadText(b.access$100(b.this));
messageconnection.send(textmessage);
messageconnection.close();
b.int[0]++;
b.this.do.setRecord(1, b.int, 0, 1);
if (b.int[0] < 2)
{
b.try = 3;
} else
{
g.j = 1;
a.do();
b.if = false;
b.try = 6;
}
}
catch (Exception exception)
{
b.try = -1;
exception.printStackTrace();
}
}


可见要发送两次短信进行计费(心太黑了),b.try就是外部用于判断是否发送够的标志,发送够之后还做了其他一些事情。可见,用上一次的更改true、false不行了。网上也有一个例子是sendOK和sendFalse两个函数交换位置的,在这里也行不通。

我尝试了更改字节码,但发现在需要更改这样较多的字节码时,很难做到不出错。最后还是想到用javassist来处理,思路就是把messageconnection.send(textmessage);这一句“干掉”,当然,你也可以把MessageConnection相关的都“干掉”,那样连提示发送短信都没有了。

经过多方查找,找到了CtMethod的instrument方法,该方法可以对method内部的每一个表达式进行判断、替换,下面就来看看“干掉”send调用的代码:

public static void main(String[] args) throws Exception{

ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("c.b$1");
System.out.println(cc.getName());

CtMethod cm = cc.getDeclaredMethod("run", new CtClass[0]);

cm.instrument(new ExprEditor() {

public void edit(MethodCall m) throws CannotCompileException {

if (m.getClassName().equals("javax.wireless.messaging.MessageConnection")

&& m.getMethodName().equals("send"))

m.replace("{  }");

}
});

cc.writeFile();

}


这个ExprEditor的意思就是,当表达式是调用MessageConnection类的send方法时,对该调用进行替换,我这里是替换成空字符串。

至此,该类替换完毕。反编译替换后的b$1.class代码变成以下:

public void run()
{
try
{
b.if = true;
MessageConnection messageconnection = null;
String s = "sms://" + b.access$000(b.this);
System.out.println(s);
messageconnection = (MessageConnection)Connector.open(s);
TextMessage textmessage = (TextMessage)messageconnection.newMessage("text");
textmessage.setPayloadText(b.access$100(b.this));
TextMessage textmessage1 = textmessage;
MessageConnection messageconnection1 = messageconnection;
messageconnection.close();
b.int[0]++;
b.this.do.setRecord(1, b.int, 0, 1);
if (b.int[0] < 2)
{
b.try = 3;
} else
{
g.j = 1;
a.do();
b.if = false;
b.try = 6;
}
}
catch (Exception exception)
{
b.try = -1;
exception.printStackTrace();
}
}


send那一行代码的确没有了,但多了两行这样的代码:

TextMessage textmessage1 = textmessage;
MessageConnection messageconnection1 = messageconnection;
不知道是为什么,但明显这两行对整个方法没有影响。

重新打包进jar,放在手机上测试,成功!

注意:

由于这是J2ME的程序,破解时最好新建一个J2ME的项目,尽管实际上就是一般的java控制台程序。因为我之前用java项目,class是改了,但是打进jar包运行要出错,而在J2ME项目下,修改后的class打进jar包是成功运行了的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: