JAR破解原理
首先來了解下利用java實(shí)現(xiàn)短信發(fā)送的原理,這個(gè)使用的是j2me的可選包Wireless Messaging API(WMA,JSR120)來進(jìn)行操作的,這是個(gè)敏感API,在未取得授權(quán)或認(rèn)證,使用之前必須提示使用者是否要進(jìn)行操作。對(duì)于有的型號(hào)的手機(jī)可以直接設(shè)置程序是否可以進(jìn)行短信操作。所以一般來說,不會(huì)出現(xiàn)無緣無故發(fā)出短信而扣費(fèi)的情況,除非你設(shè)置了總是允許操作這項(xiàng)(相信沒幾個(gè)人會(huì)這么做)。當(dāng)然很多免費(fèi)短信軟件如悠信,XROSE什么的都是利用的這個(gè)API啦。
由于設(shè)置了短信的游戲中目的只是為了收費(fèi),而且一般一條短信的價(jià)格都不菲,但是很多地方不發(fā)短信又無法繼續(xù)進(jìn)行游戲,那么,如果想繼續(xù)免費(fèi)玩下去,就得對(duì)短信操作進(jìn)行處理。(一般來說發(fā)短信和連網(wǎng)不一樣,不是必須發(fā)才可以實(shí)現(xiàn)結(jié)果的,同樣是進(jìn)下一關(guān),網(wǎng)絡(luò)下載就是必須進(jìn)行的操作,而短信買關(guān)就不一樣,那關(guān)其實(shí)是存在的,但是必須進(jìn)行這一操作才可繼續(xù)玩)
首先是工具,必備的工具就是java反編譯軟件,UE或HEX等16進(jìn)制編輯器,另外為了方便查看字節(jié)碼還需要jclasslib。
首先我們來看一段代碼,一般的短信發(fā)送都是類似的,當(dāng)然,你也可以利用這個(gè)自己寫個(gè)免費(fèi)發(fā)短信的東西:)
import java.io.IOException;
import java.io.PrintStream;
import javax.microedition.io.Connection;
import javax.microedition.io.Connector;
import javax.wireless.messaging.*;
class SMSXX
{
String ph;
String s = "發(fā)送的內(nèi)容";
boolean isSend = false;
void sendSms()
{
MessageConnection messageconnection = null;
try
{
String s1 = "sms://" + phoneNum;
TextMessage textmessage;
(textmessage = (TextMessage)(messageconnection = (MessageConnection)Connector.open(s1)).newMessage("text")).setAddress(s1);
textmessage.setPayloadText(s);
messageconnection.send(textmessage);
doSendOk();
}
catch(IOException _ex)
{
doSendFalse(); }
}
void doSendOk()
{
System.out.println("Send Ok");
isSend = true;
}
void doSendFalse()
{
System.out.println("Send False");
isSend = false;
}
}
通常,發(fā)送成功之后會(huì)有個(gè)判斷或者是進(jìn)行接著的方法,有的發(fā)送的方法本身就返回boolean變量,如果發(fā)送成功就返回true,反之就返回false。上面的例子屬于一般情況,我們可以用以下幾個(gè)思路來考慮。
1.發(fā)送成功后會(huì)運(yùn)行doSendOk()方法,而發(fā)送失敗就會(huì)運(yùn)行doSendFalse(),那么我們只要把這兩個(gè)方法的位置換一下,那么即使發(fā)送失敗,那么程序仍然會(huì)運(yùn)行doSendOk()方法。我們用jclasslib打開該class,然后查看sendSms()方法,看字節(jié)碼:
0 aconst_null
1 astore_1
2 new #31 <java/lang/StringBuffer>
5 dup
6 ldc #33 <sms://>
8 invokespecial #36 <java/lang/StringBuffer.<init>>
11 aload_0
12 getfield #18 <SMSXX.phoneNum>
15 invokevirtual #40 <java/lang/StringBuffer.append>
18 invokevirtual #44 <java/lang/StringBuffer.toString>
21 astore_2
22 aload_2
23 invokestatic #50 <javax/microedition/io/Connector.open>
26 checkcast #52 <javax/wireless/messaging/MessageConnection>
29 dup
30 astore_1
31 ldc #54 <text>
33 invokeinterface #58 <javax/wireless/messaging/MessageConnection.newMessage> count 2
38 checkcast #60 <javax/wireless/messaging/TextMessage>
41 dup
42 astore_3
43 aload_2
44 invokeinterface #65 <javax/wireless/messaging/Message.setAddress> count 2
49 aload_3
50 aload_0
51 getfield #22 <SMSXX.s>
54 invokeinterface #68 <javax/wireless/messaging/TextMessage.setPayloadText> count 2
59 aload_1
60 aload_3
61 invokeinterface #72 <javax/wireless/messaging/MessageConnection.send> count 2
66 aload_0
67 invokevirtual #75 <SMSXX.doSendOk>
70 goto 78 (+8)
73 astore_2
74 aload_0
75 invokevirtual #78 <SMSXX.doSendFalse>
78 return
我們需要利用的就是67行和75行這兩段,我們只要把這兩段的位置換一下就OK。用HEX打開,定位(怎么定位請(qǐng)看我的另一篇文章,快速定位需要修改的16進(jìn)制位置),
67行為:B6004B
75行為:B6004E
我們把004B和004E兩個(gè)位置換下,保存,然后反編譯看看,是不是OK了,接下來我們要做的是為了確保不發(fā)出短信出去(當(dāng)然在有提示的時(shí)候按否也是一樣的,但是為防止按錯(cuò)還是保險(xiǎn)起見)把sms://這個(gè)改成其他字符吧,比如kim:// :),這樣一運(yùn)行到發(fā)短信的地方就發(fā)生異常,程序就運(yùn)行catch中的doSendOk()了。
另外一種思路要你對(duì)流程很了解,不直接修改發(fā)送的代碼,而是看doSendOk()和doSendFalse()這兩個(gè)方法,既然發(fā)不出去會(huì)運(yùn)行 doSendFalse(),而doSendFalse()和doSendOk()二者只是一個(gè)變量的區(qū)別,那么我們把doSendFalse()中的 isSend = false改成 isSend = true,不就是和doSendOk()只是方法名之間的區(qū)別了嗎,同樣道理,改完后再把sms改成其他東西。(具體過程略,大家自己想想吧)。