PS:本系列文章中所涉及到的技術、數據和接口地址,僅供學習交流,務必不可做壞事或者是用於商業用途!否則后果自負!
來源:http://blog.csdn.net/zhaokaiqiang1992
- 逆向工程
- 代碼框架解析
- TcpDump抓包
- WireShake分析數據包
逆向工程
既然是做高仿,當然需要逆向工程了,由於Android是基於Java的,所以反編譯的難度並不大,各種資料很豐富,所以這里就簡單介紹。
我們在反編譯的時候,可以按照下面的流程進行
- 使用apktool將apk進行反編譯,獲取到res中的布局文件、drawable中的圖片資源,AndroidManifest.xml中的組件聲明和權限聲明,values中的常量值等數據
- 將apk改為zip后綴,解壓獲取到classes.dex文件,然后使用dex2jar工具將其反編譯,獲取到classes.jar文件,然后使用JD-GUI進行查看即可
這個是通常的反編譯流程,但是呢,我還要介紹一些其他的東西。第一步流程中,沒有太多東西,一般都能獲取到我們想要的資源,但是在把dex轉化成jar的過程中,使用上面的做法可以查看到java源碼,但是,dex2jar對Android中的switch語句解析的不是很完全,所以看起來會非常費勁,我們以“煎蛋”逆向工程之后的某個類舉例,下面是使用dex2jar,然后使用JD-GUI查看的com.danielstudio.app.wowtu.a.ae類中的方法a
protected void a(g paramg) { if (isCancelled()); do { return; w.e().remove(this.b.a); } while (!(h.a(paramg)); String str1 = (String)paramg.c(); String str2 = str1.split("\\|")[1]; if (!(str1.split("\\|")[2].trim().equals("0"))) switch (this.c) { default: case 1: case 0: } while (true) { while (true) { while (true) { this.a.c(this.d); com.danielstudio.app.wowtu.f.e.a(w.c(this.a), str2); } w.a(this.a).add(this.b.a); com.danielstudio.app.wowtu.c.e locale2 = this.b; locale2.i = (1 + locale2.i); } w.b(this.a).add(this.b.a); com.danielstudio.app.wowtu.c.e locale1 = this.b; locale1.j = (1 + locale1.j); } }
上面的這種代碼格式非常難看,基本看不出原來的運行邏輯,所以再給大家介紹一個反編譯的工具,叫做Procyon,用法也很簡單,
幫助 java -jar decompiler.jar 反編譯單個class文件 java -jar procyon-decompiler-0.5.24.jar AutoCloseableExample.class 反編譯整個Jar包 java -jar procyon-decompiler.jar -jar myJar.jar -o out
下面是使用Procyon對相同的類進行反編譯之后的代碼
protected void a(final g g) { if (!this.isCancelled()) { w.g.remove(this.b.a); if (h.a(g)) { final String s = (String)g.c(); final String s2 = s.split("\\|")[1]; if (!s.split("\\|")[2].trim().equals("0")) { switch (this.c) { case 1: { this.a.e.add(this.b.a); final e b = this.b; ++b.i; break; } case 0: { this.a.f.add(this.b.a); final e b2 = this.b; ++b2.j; break; } } this.a.c(this.d); } com.danielstudio.app.wowtu.f.e.a(this.a.b, s2); } } }
代碼邏輯這么清晰,有沒有被驚艷到呀~
所以說,不能光知道那些人人皆知的工具,有很多其他的工具也是非常的好用的。
代碼框架解析
好啦,現在我們得到我們想要的源代碼了,我們來簡單的分析一下
如果大家下載過”煎蛋”的話,應該能看出來,UI上使用的是非常新的設計風格,也就是Material Design設計風格。但是真正的Material Design需要Android L版本的支持,所以要考慮兼容性,就要用到最新的support.v7兼容包和其他兼容組件,這點在上面的包結構中也有所體現。
com.afollestad.materialdialogs這個包,從名字上也可以看是個Material Design風格的Dialog,是為了保持風格的統一。
com.danielstudio.app.wowtu這個包,則是煎蛋App的核心包,里面是具體的邏輯代碼,我們需要重點分析的東西都在這里面
loopj.android.http這個包是不是很熟悉?這是android-async-http,一個非常出名的網絡請求的開源框架,這是整個項目的網絡請求核心包
com.nostra13.universalimageloader這個包不必我多廢話了,加載圖片的框架,功能很強大
在下面的那些包就是用於分享的第三方SDK了,比如QQ和新浪的,umeng則是用來渠道統計和升級的第三方SDK
最下面的uk.co.senab.phtotview則是一個很強大的圖片顯示控件,可以根據手勢自由放縮
到目前為止,我們已經知道了這個App的主要框架了,下面我簡單的說下要高仿的整體框架。
網絡請求方面,我傾向於使用Volley,因為這個庫針對復雜網絡情況下頻繁的小數據量請求進行了優化,所以對煎蛋這種內容類的App比較合適。
在圖片加載方面,UIL雖然可以勝任這個工作,但是,我准備試一試FaceBook新推出的Fresco圖片加載框架,之前我翻譯過一篇關於Fresco的官方介紹,詳情請戳FaceBook推出的Android圖片加載庫-Fresco。
其他的框架,比如butter knife ,也准備試一下,雖然感覺在這個項目里面沒有必要使用IOC框架,但是之前的項目使用的都是AFinal,所以准備入手一下,試試好用不啦~
其實主要的框架也就暫時想到這么多,更多的還需要一邊做一邊引入,更多的是View的開源項目,熟練的使用Githun哦~
TcpDump抓包
其實,上面做的這些工作都很簡單,更重要的是,我們如何去獲取數據接口,沒有接口,我們如何高仿呢,是不?由於煎蛋App是經過混淆的,大部分核心代碼難以閱讀,所以呢,我給大家介紹下如何在Android設備上使用TcpDump進行抓包。
TcpDump是Linux里面很強大的網絡數據采集工具,也就是我們常說的抓包工具,抓包可以干很多壞事啦,不過,我們都是乖小孩~
因為Android系統本身就是以Linux 2.6 kenal作為內核的,所以我們可以使用TcpDump進行抓包。
首先呢,我們需要把TcpDump上傳到我們的測試機上去,我使用的是eng工程模式的Nexus5測試機,使用Genymotion虛擬機沒有成功,可能是因為TcpDump不能運行在x86架構的虛擬機上,ADT原生的虛擬機是ARM架構,應該可以使用,但是我的打開太慢,就沒有測試,如果你要使用真機,要確保是eng工程模式。
有了測試機之后,adb連接上,然后使用下面命令查看連接設備是否成功
1
|
kaiqiangzhaoMacBook:~ zhaokaiqiang$ adb devices List of devices attached 16e8718e device
|
連接成功之后,使用下面命令將TcpDump上傳到/data/local/tcpdump路徑
1
|
kaiqiangzhaoMacBook:~ zhaokaiqiang$ adb push ~/Desktop/tcpdump /data/local/tcpdump 4189 KB/s (1801155 bytes in 0.419s) kaiqiangzhaoMacBook:~ zhaokaiqiang$
|
然后使用下面命令修改權限
1
|
kaiqiangzhaoMacBook:~ zhaokaiqiang$ adb shell chmod 777 /data/local/tcpdump
|
到此為止,我們的TcpDump就部署成功了。
我們簡單介紹幾個常用命令。
下面的命令是用來抓包的最簡單的命令
1
|
adb shell /data/local/tcpdump -n -s 0
|
-n 代表不把網絡地址轉換成名字
-s 0 抓取數據包時默認抓取長度為68字節。加上-s 0 后可以抓到完整的數據包
因為我們網絡請求很多,我們需要進行過濾,比如要獲取所有10.10.10.1 的主機收到的和發出的所有的數據包
1
|
kaiqiangzhaoMacBook:~ zhaokaiqiang$ adb shell /data/local/tcpdump -n -s 0 host 10.10.10.1
|
TcpDump還有很多強大的用法,我就不一一解釋了,在我的收藏文章有,大家留言就得了。Android相關問題的好文章整理
我們使用的命令是下面這樣的
1
|
adb shell /data/local/tcpdump -n -s 0 -w /sdcard/jiandan.pcap host 10.10.10.your ip
|
這樣我們就可以把所有和當前ip進行通訊的包抓到,然后保存到/sdcard/jiandan.pcap文件,等着我們用下面的WireShake進行分析了
WireShake分析數據包
經過上面的一步,我們已經抓到了煎蛋App和服務器之間的通訊包,抓包時,有幾點需要注意:
- 盡量減少測試機上的App數量,避免無用數據混淆視聽
- 抓包盡量簡短有效,在App請求的時候開始抓,請求完畢馬上停止
這樣,我們就可以得到我們的pcap格式的數據包了,下一步就是使用WireShake進行數據分析。
WireShake也很強大,但是我們這里只是簡單的使用,更多強大功能自己去摸索。
我們可以使用下面的命令把文件下載下來
1
|
adb pull /sdcard/jiandan.pcap ~/Desktop/jiandan.pcap
|
下面是一個抓包的數據,用WireShark打開后,如下
注意紅方框的地方。一般來說,資訊類App獲取數據都是使用Http協議的接口,而對實時性要求比較高的App,比如股票行情類的,則是使用Socket通訊,顯示在這里就是使用的是TCP協議。我們可以看到,本地ip和42.120.48.125進行了Http通訊,點開下面的包數據,就可以在請求文本里面看到我們的完整的請求URL,這個就是獲取段子的接口,使用page進行分頁。
其實按照這種方法,我們能夠把基本上所有的使用Http協議的接口抓取出來,但是還有更好的辦法,一般來說,這些地址都是硬編碼在代碼里面的,知道了一個地址格式,我們就可以直接搜索查找出其他類似的接口,比如,我們把第一步反編譯出來的類文件放在Eclipse中的Java項目里面,然后全項目查找關鍵詞oxwlxojflwblxbsapi試試
果然出現了很多的接口地址,這樣我們就可以省下很大力氣,具體接口測試不多說,自己去試。
其實一開始我想做煎蛋客戶端,是通過Jsoup解析Web網址實現的,而且也解析成功了,能夠正常使用,但是后來突發奇想,想看看代碼怎么寫的,就順便看了下,成功獲取到接口之后,能夠更加方便的使用,所以就直接用了。
這個項目的段子功能模塊,已經基本完成,后續功能正在做,希望這個項目能成為新手的很好的學習資料
,我也很用心的在做,如果你看了代碼,有所收獲,那是極好的,如果你發現我寫的代碼性能不好,或者是有更好的解決方案,希望你能告訴我,提交issue或者是pull request,我想把這個項目做的比9GAG項目更好。
下面是完成的功能
- 段子顯示
- 評論數量顯示
- 評論詳情顯示
- 評論過多隱藏樓層
- 加載動畫
- 左滑退出
- 投票
- 正在完善的其他功能…
本項目的github地址:https://github.com/ZhaoKaiQiang/JianDan
感謝煎蛋的開發者DanielWangDev
- 本文固定鏈接: http://www.ithtw.com/2407.html
- 轉載請注明: leehom 2015年04月25日 於 IT十萬為什么 發表