android軟件破解的工具:
smali.jar——google官方提供,主要作用是把smali文件打包成class.dex文件
baksmali.jar——google官方提供,主要作用是把*.odex文件反編譯為smali文件
apktool.jar——第三方提供?用于解析*.apk文件,生成smali文件和解析資源文件
signapk.jar——apk簽名工具
ddms——ADT中的一個(gè)調(diào)試工具
破解工具的使用方法:
http://sin90lzc.iteye.com/blog/1198173
除了這些破解工具之外,還需要對(duì)smali語法有一定的了解。下面的網(wǎng)址對(duì)smali的語法有詳細(xì)的說明:
http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html
最后,最好對(duì)Android的應(yīng)用開發(fā)有一定的了解,至少對(duì)Android的四大組件有深刻的認(rèn)識(shí):Activity,Service,ContentProvider,BroadcastReceiver
Android應(yīng)用程序在某些機(jī)器上不能運(yùn)行、崩潰的原因不外乎以下幾點(diǎn):
原因一:該應(yīng)用程序需要依賴于生產(chǎn)廠商的框架(像三星,它對(duì)android的framework做過大量的修改)
錯(cuò)誤提示:找不到field,找不到對(duì)應(yīng)的方法,找不到相應(yīng)的類
解決途徑:
1.在smali中嘗試屏蔽掉相應(yīng)的field,method,或類的調(diào)用,然后進(jìn)行大量測(cè)試,確保不影響正常使用
2.反編譯framework,找到缺少的field,method,類的相應(yīng)smali文件,根據(jù)smali文件編寫java源碼。(當(dāng)smali文件比較小的時(shí)候,這個(gè)方法才可行,否則盡量避免用這種方法)
3.實(shí)在無招的情況下,只能把第三方的framework的smali文件復(fù)制到自己的framework里面(非常槽糕的方法)。
4.對(duì)于應(yīng)用程序需要依賴第三方低層的功能實(shí)現(xiàn)時(shí),而我們的低層卻沒有這樣的功能(比如說視頻通話等),此時(shí)可以使用上面的方法一解決,也可以參考技術(shù)四。
原因二:資源文件不存在,像color,drawable,string等等的資源
錯(cuò)誤提示:資源文件找不到
解決途徑:
在技巧一中有詳細(xì)說明。
原因三:應(yīng)用程序需要一些函數(shù)庫的支持(在目錄/system/lib中缺少相應(yīng)的函數(shù)庫)。
錯(cuò)誤提示:一般都會(huì)拋出UnSatisfiedException異常,后面緊跟所缺函數(shù)庫的庫名。
解決途徑:
1.在第三方的函數(shù)庫中找到對(duì)應(yīng)的so文件,然后復(fù)制到自己的函數(shù)庫中。
2.如果函數(shù)庫與函數(shù)庫之間有著各種耦合的時(shí)候,方法一可能就會(huì)不適用了(看運(yùn)氣唄)。這時(shí)候就只能反編譯so文件了(這個(gè)是C/C++的反編譯的應(yīng)用了,需要再學(xué)習(xí))
原因四:應(yīng)用程序沒有相應(yīng)的權(quán)限
錯(cuò)誤提示:nopermission
解決途徑:
1.在AndroidMenifest.xml文件中添加<user-permision />添加相應(yīng)的權(quán)限
原因五:由于應(yīng)用程序本身的一些安全機(jī)制或條件判斷影響程序的表現(xiàn)
解決途徑:
1.反編譯成smali文件,使用技巧三的方法跟蹤程序的運(yùn)行,耐心地分析程序的邏輯,找到可疑smali代碼,屏蔽或修改代碼。
原因六:數(shù)據(jù)庫的結(jié)構(gòu)不一樣
錯(cuò)誤提示:缺少某個(gè)字段或類型不匹配
場(chǎng)情:比如android的音樂播放器與三星的音樂播放器,它們的數(shù)據(jù)庫結(jié)構(gòu)由MediaProvider.apk這個(gè)包提供。然而兩者在MediaProvider.apk中關(guān)于數(shù)據(jù)庫結(jié)構(gòu)的定義是不一樣的,三星音樂播放器需要更多的字段去保存信息。
解決途徑:
1.拿上面場(chǎng)情為例,反編譯MediaProvider.apk,從smali文件中找到組件ContentProvider的定義(smali文件), 在該smali文件中找到關(guān)于SQL生成表結(jié)構(gòu)的字符串(如:create table...),修改該SQL語句來適合三星音樂播放器的需要,然后重新打包回apk文件。
原因七:應(yīng)用程序需要引用第三方提供商自定義的框架(比如,三星的/system/framework目錄下有twframework.jar、twframework-res.apk,這個(gè)就是三星的UI框架)
錯(cuò)誤提示:
解決途徑:
1.屏蔽AndroidMenifest.xml文件中<uses-library android:name="sec_feature" />的代碼,一般這樣改動(dòng)是不可行的。
2.在/system/etc/permission目錄下添加庫的聲明,如添加touchwiz.xml文件,文件內(nèi)容如下:
<?xml version="1.0" encoding="utf-8"?>
<permissions>
<library name="touchwiz" file="/system/framework/twframework.jar"/>
</permissions>
最后,還需要把三星的twframework.jar、twframework-res.apk復(fù)制到/system/framework目錄下
反編譯或破解的技巧總結(jié):
一、對(duì)無應(yīng)用程序源碼的情況下,對(duì)資源文件的增刪改。
概述:在無程序源碼,不重新編譯的情況下,刪除或修改資源文件都是非常簡(jiǎn)單的一件事情,網(wǎng)上也有很多的文章提到過。但是網(wǎng)上卻找不到在不重新編譯的情況下添加資源文件的方法。
在不重新編譯的情況下添加資源文件的步驟:
1.按正常的應(yīng)用程序開發(fā)添加資源。比如,要添加一個(gè)string資源,在values/strings.xml上加上:
<string name="newstring">content</string>
2.一個(gè)編譯后的apk會(huì)在values目錄下多生成了一個(gè)public.xml文件,這個(gè)文件記錄了每個(gè)資源的引用編號(hào)。以添加string資源為例, 在public.xml文件中找到<public type="string" ...>中最后一個(gè)元素,在這個(gè)元素后添加
<public type="string" name="newstring" id="0x7f0700a0" /><!--此時(shí)id就是string資源newstring的引用編號(hào),注意該id應(yīng)該是public.xml文件中是唯一值-->
3.修改smali文件,使用新增的資源
invoke-virtual {p0}, Lcom/sini/SfsdfsActivity;->getResources()Landroid/content/res/Resources;
move-result-object v0
const v1, 0x7f0700a0
invoke-virtual {v0, v1}, Landroid/content/res/Resources;->getString(I)Ljava/lang/String;
二、編寫smali文件
概述:自己一手一腳去寫smali文件是件超級(jí)困難的事情,如何快速地得到smali代碼呢?
技巧:使用eclipse開發(fā)工具,新建一個(gè)Android項(xiàng)目,用正常的開發(fā)方式寫一段java代碼(這個(gè)代碼就是你想在smali中完成的東西)。使 用eclipse的run->Android Application選項(xiàng) 生成apk文件,再把a(bǔ)pk文件反編譯,找到需要的smali代碼,然后復(fù)制這段代碼到需要的地方。NOTIC:復(fù)制的時(shí)候需要注意smali的變量 v0,v1...的正確性。
三、跟蹤程序運(yùn)行
概述:沒源碼=寸步難行!為了能跟蹤無源碼的apk程序的運(yùn)行,只能辛苦地修改smali添加跟蹤信息了。值得慶幸的是,android本身自帶有方便的日志API(Log.i()\Log.w()...);
技巧:按技巧二的方法得到Log.i()的smali代碼,然后把這段代碼插入到你想跟蹤信息的地方。
四、只修改smali中影響UI的代碼,保留功能代碼(適用于必須得把smali寫回java源碼的情況)
概述:這里最好的例子就是破解三星的通話界面。三星的通話界面程序Phone.apk中包含了視頻通話的功能,這個(gè)功能又需要依賴三星的一些低層實(shí)現(xiàn)。而 我們的系統(tǒng)中沒有視頻通話的功能,也沒有相應(yīng)的低層實(shí)現(xiàn)。但Phone.apk的主要功能是打電話,而這個(gè)功能android本身就自帶的。也就是說三星 的Phone.apk與android的Phone.apk的核心功能是一樣的,只是UI不太一樣而已。此時(shí)應(yīng)該只修改smali中的影響UI的代碼,屏 蔽掉
smali中對(duì)視頻通話的調(diào)用。
技巧:找到程序中影響UI的Actvity,然后根據(jù)smali文件的內(nèi)容,寫java源碼
在PHP中查找中文字符,有兩種方案。
1、中文字符是gbk(gb2312)
有兩種解決方法
第一種:
將PHP保存為ASCII編碼,然后使用strpos查找,如:
strpos($curl_res, ‘哈哈’)
第二種:
將PHP保存為UTF-8無BOM編碼,然后轉(zhuǎn)換字符串編碼為UTF-8,再查找,如:
$curl_res = mb_convert_encoding($curl_res, ‘utf-8′, ‘gbk’);
mb_strpos($curl_res, ‘哈哈’);
2、中文字符是UTF-8
有兩種解決方法
第一種:
將PHP保存為UTF-8無BOM編碼,然后使用strpos查找,如:
strpos($curl_res, ‘哈哈’)
第二種:
將PHP保存為ASCII編碼,然后轉(zhuǎn)換字符串編碼為gbk,再查找,如:
$curl_res = mb_convert_encoding($curl_res, ‘gbk’, ‘utf-8′);
mb_strpos($curl_res, ‘哈哈’);
應(yīng)該可以看出一些規(guī)律,就是:函數(shù)中的中文字符串參數(shù)的編碼和PHP文件保存格式的編碼一致,在使用函數(shù)時(shí)要考慮到!
我生成的那個(gè)html文件被EmEditor認(rèn)為UTF-8 with Signature。而好用的那個(gè)html文件被EmEditor認(rèn)為UTF-8 without Signature.
對(duì)于這兩種UTF-8格式的轉(zhuǎn)換,我查看了網(wǎng)上信息,點(diǎn)擊記事本,EmEditor等文本編輯器的另存為,當(dāng)選擇了UTF-8的編碼格式時(shí),Add a Unicode Signature(BOM)這個(gè)選項(xiàng)被激活,只要選擇上,我的文件就可以存為UTF-8 with Signature的格式。可是,問題就在于,我用java怎么讓我的文件直接生成為 UTF-8 with Signature的格式。
開始上google搜索UTF-8 with Signature,BOM,Add a Unicode Signature等關(guān)鍵字。
http://www.unicode.org/unicode/faq/utf_bom.html#BOM
我大致了解了他們兩個(gè)的區(qū)別。
Q: What is a BOM?
A: A byte order mark (BOM) consists of the character code U+FEFF at the beginning of a data stream, where it can be used as a signature defining the byte order and encoding form, primarily of unmarked plaintext files. Under some higher level protocols, use of a BOM may be mandatory (or prohibited) in the Unicode data stream defined in that protocol.
http://mindprod.com/jgloss/bom.html
BOM
Byte Order Marks are special characters at the beginning of a Unicode file to indicate whether it is big or little endian, in other words does the high or low order byte come first. These codes also tell whether the encoding is 8, 16 or 32 bit. You can recognise Unicode files by their starting byte order marks, and by the way Unicode-16 files are half zeroes and Unicode-32 files are three-quarters zeros. Unicode Endian Markers
Byte-order mark Description
EF BB BF UTF-8
FF FE UTF-16 aka UCS-2, little endian
FE FF UTF-16 aka UCS-2, big endian
00 00 FF FE UTF-32 aka UCS-4, little endian.
00 00 FE FF UTF-32 aka UCS-4, big-endian.
There are also variants of these encodings that have an implied endian marker.
Unfortunately, often applications, even Javac.exe, choke on these byte order marks. Java Readers don't automatically filter them out. There is not much you can do but manually remove them.
http://cache.baidu.com/c?word=java%2Cbom&url=http%3A//tgdem530%2Eblogchina%2Ecom/&b=0&a=1&user=baidu
c、UTF的字節(jié)序和BOM
UTF-8以字節(jié)為編碼單元,沒有字節(jié)序的問題。UTF-16以兩個(gè)字節(jié)為編碼單元,在解釋一個(gè)UTF-16文本前,首先要弄清楚每個(gè)編碼單元的字節(jié)序。 例如收到一個(gè)“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16字節(jié)流“594E”,那么這是 “奎”還是“乙”?
Unicode規(guī)范中推薦的標(biāo)記字節(jié)順序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一個(gè)有點(diǎn)小聰明的想法:
在UCS編碼中有一個(gè)叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,所以不應(yīng)該出現(xiàn)在實(shí)際傳輸中。UCS規(guī)范建議我們?cè)趥鬏斪止?jié)流前,先傳輸字符"ZERO WIDTH NO-BREAK SPACE"。
這樣如果接收者收到FEFF,就表明這個(gè)字節(jié)流是Big-Endian的;如果收到FFFE,就表明這個(gè)字節(jié)流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被稱作BOM。
UTF-8不需要BOM來表明字節(jié)順序,但可以用BOM來表明編碼方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF(讀者可以用我們前面介紹的編碼方法驗(yàn)證一下)。所以如果接收者收到以EF BB BF開頭的字節(jié)流,就知道這是UTF-8編碼了。
Windows就是使用BOM來標(biāo)記文本文件的編碼方式的。
原來BOM是在文件的開始加了幾個(gè)字節(jié)作為標(biāo)記。有了這個(gè)標(biāo)記,一些協(xié)議和系統(tǒng)才能識(shí)別。好,看看怎么加上這寫字節(jié)。
終于在這里找到了
http://mindprod.com/jgloss/encoding.html
UTF-8
8-bit encoded Unicode. neé UTF8. Optional marker on front of file: EF BB BF for reading. Unfortunately, OutputStreamWriter does not automatically insert the marker on writing. Notepad can't read the file without this marker. Now the question is, how do you get that marker in there? You can't just emit the bytes EF BB BF since they will be encoded and changed. However, the solution is quite simple. prw.write( '\ufeff' ); at the head of the file. This will be encoded as EF BB BF.
DataOutputStreams have a binary length count in front of each string. Endianness does not apply to 8-bit encodings. Java DataOutputStream and ObjectOutputStream uses a slight variant of kosher UTF-8. To aid with compatibility with C in JNI, the null byte '\u0000' is encoded in 2-byte format rather than 1-byte, so that the encoded strings never have embedded nulls. Only the 1-byte, 2-byte, and 3-byte formats are used. Supplementary characters, (above 0xffff), are represented in the form of surrogate pairs (a pair of encoded 16 bit characters in a special range), rather than directly encoding the character.
prw.write( '\ufeff' );就是這個(gè)。
于是我的代碼變?yōu)椋?br /> public void htmlWrite(String charsetName) {
try {
out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(outFileName), "UTF-8"));
out.write('\ufeff');
out.write(res);
out.flush();
if (out != null) {
out.close();
}
} catch (Exception e) {
try {
if (out != null) {
out.close();
}
} catch (IOException e1) {
System.out.print("write errors!" + e);
}
System.out.print("write errors!" + e);
}
}
問題解決。