日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

安卓代码跟踪方式学习笔记

發布時間:2025/3/15 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 安卓代码跟踪方式学习笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、代碼跟蹤的介紹&使用工具

代碼跟蹤常用于調試程序中,跟蹤并了解程序的執行軌跡和執行邏輯。這樣來說,對Java這樣的高級語言來說,我們容易理解也容易調試。但是像一些低級語言,例如ASM、Smali來說難度就很大了,因為反匯編這樣的語言,我們需要一次性記住很多亂七八糟的關鍵詞才能成功,因而代碼跟蹤的技術就誕生了,并且在一些大程序中的運用更為廣泛,同時也是現在逆向一些大而復雜的Android?-app極為重要的一種手段。
相信很多人都玩過PC端,對OD的動態調試也應該特別熟悉。OD很強大,其中的F2(斷點),F8(單步走)使得調試程序事半功倍,我相信用過得沒有說不好的吧。而Android-app與PC?software的性質是不同的。在Android-app里是把Apk文件Dump成字節碼,分析,修改,再重新編譯。有一個很大的不同點就是Android-app但是正是由于開源,使得Dump出來的字節碼是“死”的,這是Java的一個特性。幸運的是,Apktool很好的解決了這個問題,它的出現使得Android-app的調試得到了轉機,受益的是大家。
既然不能進行完全的調試,想到的辦法是用系統的log函數來呈現程序運行到關鍵時候的關鍵信息來達到相應的效果。比如說,你想知道程序運行到某個時候某個變量里裝的是什么,就可以用log的方式顯示。
獲取Android程序的log信息一共有幾種方式。最好的選擇當時是用DDMS,因為它和Android?SDK是一伙的!它可以顯示很多系統的log信息以及一些其他的亂七八糟的信息。同時,可以設置過濾器來進行標簽過濾、log等級(error,warning,info,debug,verbose)過濾、進程過濾,也能結束進程。相當強大。如圖:

二、跟蹤方法

1.Logging大法
因為Apps沒有控制臺所以它們只能通過Android?的API中的log函數來進行輸出。
關于android/util/Log的介紹如下:
Log?extends?Object
一共有5個方法:Log.v()?Log.d()?Log.i()?Log.w()?and?Log.e(),它們分別對應:
int??ASSERT??Priority?constant?for?the?println?method.
int??DEBUG??Priority?constant?for?the?println?method;?use?Log.d.
int??ERROR??Priority?constant?for?the?println?method;?use?Log.e.
int??INFO??Priority?constant?for?the?println?method;?use?Log.i.
int??VERBOSE??Priority?constant?for?the?println?method;?use?Log.v.
int??WARN??Priority?constant?for?the?println?method;?use?Log.w
Log.d一般來說是用的最多的。(本來log.v是最多的,但是log.v并不參加編譯)
寫一個測試類來分析Java代碼如下:
代碼: public?class?Log?{public?Log()?{}public?static?void?Log(String?msg){Log(msg,?"Log");}public?static?void?Log(Object?XX){Log("Log",?XX.toString());}public?static?void?Log(Object?XX,?String?tag){Log(tag,?XX.toString());}public?static?void?Log(String?tag,?String?msg){Log.d(tag,?msg);}public?static?void?ToastLog(Context?contx,?String?msg,?int?duration){Toast.makeText(contx,?msg,?duration).show();} } 反匯編成Smali代碼如下:
代碼: #?direct?methods .method?public?constructor?<init>()V.registers?1.prologue.line?8invoke-direct?{p0},?Ljava/lang/Object;-><init>()Vreturn-void .end?method.method?public?static?Log(Ljava/lang/Object;)V.registers?3.parameter?"XX".prologue.line?17const-string?v0,?"Log"invoke-virtual?{p0},?Ljava/lang/Object;->toString()Ljava/lang/String;move-result-object?v1invoke-static?{v0,?v1},?Lcom/Ericky/Log;->Log(Ljava/lang/String;Ljava/lang/String;)V.line?18return-void .end?method.method?public?static?Log(Ljava/lang/Object;Ljava/lang/String;)V.registers?3.parameter?"XX".parameter?"tag".prologue.line?22invoke-virtual?{p0},?Ljava/lang/Object;->toString()Ljava/lang/String;move-result-object?v0invoke-static?{p1,?v0},?Lcom/Ericky/Log;->Log(Ljava/lang/String;Ljava/lang/String;)V.line?23return-void .end?method.method?public?static?Log(Ljava/lang/String;)V.registers?2.parameter?"msg".prologue.line?12const-string?v0,?"Log"invoke-static?{v0,?p0},?Lcom/Ericky/Log;->Log(Ljava/lang/String;Ljava/lang/String;)V.line?13return-void .end?method.method?public?static?Log(Ljava/lang/String;Ljava/lang/String;)V.registers?2.parameter?"tag".parameter?"msg".prologue.line?28invoke-static?{p0,?p1},?Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I.line?29return-void .end?method.method?public?static?ToastLog(Landroid/content/Context;Ljava/lang/String;)V.registers?3.parameter?"contx".parameter?"msg".prologue.line?33const/4?v0,?0x5invoke-static?{p0,?p1,?v0},?Lcom/Ericky/Log;->ToastLog(Landroid/content/Context;Ljava/lang/String;I)V.line?34return-void .end?method.method?public?static?ToastLog(Landroid/content/Context;Ljava/lang/String;I)V.registers?4.parameter?"contx".parameter?"msg".parameter?"duration".prologue.line?40invoke-virtual?{p0},?Landroid/content/Context;->getApplicationContext()Landroid/content/Context;.line?41invoke-static?{p0,?p1,?p2},?Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;move-result-object?v0invoke-virtual?{v0},?Landroid/widget/Toast;->show()V.line?42return-void .end?method 取出第一個方法:
代碼: .method?public?static?Log(Ljava/lang/Object;)V.registers?3 .parameter?"XX".prologue.line?17const-string?v0,?"Log"invoke-virtual?{p0},?Ljava/lang/Object;->toString()Ljava/lang/String;move-result-object?v1invoke-static?{v0,?v1},?Lcom/Ericky/Log;->Log(Ljava/lang/String;Ljava/lang/String;)V.line?18return-void .end?method 在這個方法里的第一個參數就是標簽,在DDMS中是可以過濾的。因此,可以利用這個特點插入我們要加的信息,從而輕松的定位到關鍵的地方。在實際操作的過程中,可以打開android?API的文檔,對著看。通常的做法是用Log.d,還要用到toString()這個API,同時需要2個變量,一個變量存放你的標簽以及另一個存放你的對象。值得注意的是,即使你根本不用這個2個變量,也需要將.locals和.registers的數量增加。修改完了之后記得檢查好代碼,至少我們自己能讀懂它。
還有一點需要我們注意,當你改完之后最好在根目錄下運行,否則記得還要改class的路徑。不然的話有可能出現ClassDefNotFound錯誤,程序強制退出。下面是修改的代碼:
const-string?v0,?"Ericky?tag"
const-string?v1,?"important?log?message"
invoke-static?{v0,?v1},?Lcom/Ericky/Log;->Log(Ljava/lang/String;Ljava/lang/String;)V
這是一個簡單的例子,但是有的時候我們是需要顯示更多的字符串,那我們應該怎么辦呢?需要用到一個StringBuilder類。StringBuilder類的用法在我之前的一篇文章中已經有用到了,很容易理解。 http://bbs.pediy.com/showthread.php?t=194955
2.棧跟蹤法

有時候破解的時候,我們會找一些關鍵的注冊字符串,例如“Register、failed、limit、pro”等等,但是很多程序其實在剛啟動的時候就檢測完了用戶的合法性,所以可能造成定位不準確。一些混淆過的程序一般都是這樣的。這時候我們就可以用棧跟蹤法了,可以查看堆棧,能看到它所調用的方法,查看堆棧代碼:
invoke-static?{},?Ljava/lang/Thread;->dumpStack()V
它的標簽為:System.err??實際效果:
代碼: java.lang.Throwable:?stack?dumpat?java.lang.Thread.dumpStack(Thread.java:612)at?com.lohan.testbed.SomeClass.superFun(SomeClass.java:113)at?com.lohan.testbed.Main.onCreate(Main.java:48)at?android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)at?android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)at?android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)at?android.app.ActivityThread.access$2300(ActivityThread.java:125)at?android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)at?android.os.Handler.dispatchMessage(Handler.java:99)at?android.os.Looper.loop(Looper.java:123)at?android.app.ActivityThread.main(ActivityThread.java:4627)at?java.lang.reflect.Method.invokeNative(Native?Method)at?java.lang.reflect.Method.invoke(Method.java:521)at?com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)at?com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)at?dalvik.system.NativeStart.main(Native?Method) 從第三行可以知道dumpStack實際上是在SomeClass類中的superFun()函數里。然后superFun()函數又是在onCreate()函數里。以此類推。不過值得一提的是,如果app被混淆了,并且debugging?信息被刪除了或者是被重命名了,會出現“Unknown?source”,但是還是可以判斷的。
3.線程和處理器
很多時候app用了大量線程之間的通信導致了棧跟蹤法變得不是那么有效了,這個時候如果你還是打印出堆棧的信息的話,只會追溯到最后的那個線程的消息處理器,而原始的那個線程就被隱藏了。當然可以通過手工來追溯,方法是根據代碼中的一些函數類似于sendMessage()等等。這里有個更簡單的方式:
代碼: //?在handleMessage()?中的smali代碼 invoke-static?{v0},?Lsample/thread/messaging/ThreadMessaging;->access$0(Lsample/thread/messaging/ThreadMessaging;)Landroid/os/Handler; move-result-object?v2 invoke-virtual?{v2},?Landroid/os/Handler;->obtainMessage()Landroid/os/Message; move-result-object?v1 //假設v2是你的處理器 invoke-virtual?{v2},?Landroid/os/Handler;->getLooper()Landroid/os/Looper; move-result-object?v2 invoke-virtual?{v2},?Landroid/os/Looper;->getThread()Ljava/lang/Thread; move-result-object?v2 invoke-virtual?{v2},?Ljava/lang/Thread;->getName()Ljava/lang/String; move-result-object?v2 但是2個線程如果同時在運行,這個方法就不好使了,原因就留給大家去思考了。
4.“遺留下的寶藏”

這個方法雖然說跟運氣脫不了干系,但在實際的運用中還是比較廣泛的。因為程序員是人,是人就會有疏忽。在編寫程序的時候,程序員會用很多的log來調試他自己寫的程序是否正確,因此就給逆向人員留下了一筆寶貴的財富。當然,很有可能有一個Boolean類型調試變量來控制是否輸出log信息,類似下面:
代碼: public?class?MyClass?{private?Context?myContext;private?boolean?DebugMode;public?MyClass(Context?c){myContext?=?c;DebugMode?=?false;}public?void?someMethod(){SharedPreferences?settings?=?PreferenceManager.getDefaultSharedPreferences(myContext);if?(?DebugMode?)Log.d("someMethod",?"running?someMethod?now!");SharedPreferences.Editor?editor?=?settings.edit();try?{editor.putString("mobileID",?getMobileID());}catch?(Exception?e)?{e.printStackTrace();}????editor.commit();} } 那我們只需要找到DebugMode的位置,把它置成“1”即可。
5.SmaliDebugging(APKtools)
如果log信息都被程序員刪除了,那怎么辦?此時此刻,我們不得不拿出神器Apktools來調試一段一段的smali語句了,根據官方介紹,還可以單步走。是不是很誘人呢?具體可以看:http://code.google.com/p/android-apktool/wiki/SmaliDebugging
6.JDB神器
這是一個很強大的工具,應該是類似GNU或者GDB調試器。打開DDMS獲取端口,然后連接調試器。
在Linux下的命令:
jdb?-attach?localhost:8616
在Windows下的命令:
jdb?-connect?com.sun.jdi.SocketAttach:hostname=localhost,port=8616
出現這樣的文字說明成功了:
代碼: Set?uncaught?java.lang.Throwable Set?deferred?uncaught?java.lang.Throwable Initializing?jdb?... 三、總結
當然還有更多更好的方法,希望大牛們繼續補充。學習Android已經1個多星期了,菜鳥一枚。很多地方難免有疏漏之處或者錯誤,歡迎各位童鞋指正,也歡迎多多交流,共同學習進步。
By?Ericky

2014.12.4



原文地址: http://www.kanxue.com/bbs/showthread.php?t=195202

總結

以上是生活随笔為你收集整理的安卓代码跟踪方式学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 韩国伦理片观看 | www色网| 日本黄色录像 | 91精品国产91久久久 | 国产亚洲色婷婷久久99精品91 | 亚洲大片免费看 | 欧洲精品在线观看 | 欧美人体一区二区三区 | 日本中文字幕在线观看视频 | 国产精品亲子伦对白 | 美女午夜影院 | 少妇色欲网 | 草草影院在线观看视频 | 岛国免费视频 | 色综合中文网 | 欧美日韩高清不卡 | 9l蝌蚪porny中文自拍 | 污片免费观看 | 欧美又粗又长 | 欧美色图另类 | 久久久国产精 | 欧美成人一二三 | www.伊人.com| 韩日产理伦片在线观看 | 国产精品美女网站 | 国产精品制服丝袜 | 久久久在线免费观看 | 国产51精品| 超清av在线 | 在线播放视频高清在线观看 | 老外一级黄色片 | 雪白的扔子视频大全在线观看 | 日本理论片午伦夜理片在线观看 | 五月色丁香 | ww黄色 | 一区二区三区国产在线观看 | 夜间福利在线 | 久久精品无码一区二区三区 | 亚洲精品国产精品国自产观看浪潮 | 茄子av| 91黄色大片 | 操人小视频 | 国产乱真实合集 | 丝袜av电影 | 日本东京热一区二区 | 麻豆蜜臀 | 先锋av资源在线 | 国产成人精品视频在线 | 日本人极品人妖高潮 | 密臀av一区二区 | 亚洲日本精品一区 | 国产精品不卡一区二区三区 | 国产精品主播视频 | 欧美巨鞭大战丰满少妇 | 免费操片| 亚洲私拍 | 免费看一级视频 | 欧美一级高潮片 | 欧美中文字幕第一页 | 亚洲成人一二三 | 古装做爰无遮挡三级聊斋艳谭 | 秋霞视频在线 | 在线视频观看一区二区 | 九九热在线视频 | 大尺度电影在线 | 亚洲一区二区三区视频 | 亚洲一区久久久 | 在线视频激情小说 | 麻豆av毛片 | 日本精品人妻无码免费大全 | 亚洲第一页在线 | 福利色导航 | 蜜臀av性久久久久蜜臀aⅴ流畅 | 国模私拍在线观看 | 中文字幕第22页 | 在线免费观看av网 | 丁香在线 | 精品国产一区二区不卡 | 青青草在线视频免费观看 | 欧美猛交xxx | 一二三精品| 亚洲综合第一区 | 麻豆传媒网站在线观看 | 中文在线观看免费高清 | 成人免费在线视频 | 国产香蕉精品视频 | 欧美综合亚洲图片综合区 | 丰满少妇高潮一区二区 | 日本天堂一区 | 麻豆成人在线观看 | 高清视频免费在线观看 | 三年中文在线观看免费观看 | 在线天堂www在线国语对白 | 成人免费一级 | 青青色在线 | 久久久久久久伊人 | 日本激情视频在线 | 亚洲做受高潮无遮挡 | 亚洲污污视频 |