android應用程式fps meter[幀數顯示]的分析 —— SurfaceFlinger被注入統計程式碼 (1)
fps meter是常用的檢測幀率的軟體,該軟體需要root許可權才能工作,一直比較好奇它一個apk是如何知道系統當前的幀率情況的,就針對此apk分析了一下其工作原理。
Apk組成
首先看一下apk的組成,apk檔案就是一個壓縮包,可以解壓縮軟體如winrar解壓檢視,也可以用[apktools]反編譯apk,以供進一步分析。
從執行結果和程式碼組織上的推測
- java程式碼主要負責上層控制和顯示。
- bin0和lib0.so是一個真正獲取fps的binary工作程序的程式碼
- jni層的libnp_read.so,負責和工作程序橋接,通過pipe與工作程序通訊,上報分析的資料給java層顯示。
Apk的靜態分析
Apk的包組成結構如上圖。常規的dex/res/lib目錄下的內容外,還要看一下res/raw和assets目錄下是否有東西,這裡通常是藏汙納垢的場所。fps meter這個apk中,在res/raw/下有bin0和lib0.so 兩個檔案。
使用[dex2jar]反編譯java程式碼,檢視其中的資訊。對於這個apk,可以看到它使用了[RootTools]的jar庫,來實現通過su過的shell執行一些命令或binary程式。從dex檔案的常量字元中可以看到,這個apk中使用的庫是v2.2版本,該版本的原始碼可以在[https://code.google.com/p/roottools/source/checkout
Java程式碼:
接下來我們可以分析java程式碼。java程式碼都已經被加擾過了,不過如果你有足夠的耐心並足夠仔細,還是能從中讀出很多內容。對java程式碼的分析,一般都是從activity/Application或service的onCreate方法入手(對外的介面不可能加擾,這些方法還是存在的),可以對照AndroidManifest.xml找到入口的Activity及Service,再檢視相關資訊
在FPSMActivity的onCreate中,如下兩句:
t.a(this, 2131034112, "0", "744"); t.a(this, 2131034113, "0.so", "744");
這是混淆過的程式碼,不過從引數來分析,這是呼叫RootTools的installBinary()方法,可以直接對照RootTools的原始碼來看。這個方法的作用是將apk的res/raw下的bin0和lib0.so分別安裝到/data/data/com.aatt.fpsm/files/下,分別命名為0和0.so。
FPSMService的onStartCommand方法中,可以看到這個機制就是建立一個pipe:/data/data/com.aatt.fpsm/pipe,不停的從這個pipe中讀取資料,顯示在前端建立的的浮動window中。可以在adb shell中,
busybox dumphex /data/data/com.aatt.fpsm/pipe
驗證幀率的值,剛好是從這個pipe中讀入的。
其他位置未看到特別有用的資訊。
JNI程式碼:
Jni庫libnp_reader的分析,主要是一些Java的native方法的實現,並沒有看到特別異常的現象。
$ arm-linux-androideabi-readelf -s libnp_read.so
Symbol table '.dynsym' contains 69 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_finalize
2: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit
3: 00000ed5 32 FUNC GLOBAL DEFAULT 7 Java_com_aatt_fpsm_FPSMSe
4: 00000000 0 FUNC GLOBAL DEFAULT UND umask
5: 00000000 0 FUNC GLOBAL DEFAULT UND mknod
6: 000017c4 8 FUNC WEAK DEFAULT 7 __aeabi_unwind_cpp_pr1
7: 00000ef5 16 FUNC GLOBAL DEFAULT 7 Java_com_aatt_fpsm_FPSMSe
8: 00000000 0 FUNC GLOBAL DEFAULT UND remove
9: 00000f05 40 FUNC GLOBAL DEFAULT 7 Java_com_aatt_fpsm_FPSMSe
10: 00000000 0 FUNC GLOBAL DEFAULT UND read
11: 00004004 4 OBJECT GLOBAL DEFAULT 16 fd
12: 00004008 4 OBJECT GLOBAL DEFAULT 16 trash
13: 000017cc 8 FUNC GLOBAL DEFAULT 7 __aeabi_unwind_cpp_pr0
14: 00000f2d 36 FUNC GLOBAL DEFAULT 7 Java_com_aatt_fpsm_FPSMSe
15: 00000000 0 FUNC GLOBAL DEFAULT UND open
16: 00000f51 20 FUNC GLOBAL DEFAULT 7 Java_com_aatt_fpsm_FPSMSe
17: 00000000 0 FUNC GLOBAL DEFAULT UND close
18: 00000f65 36 FUNC GLOBAL DEFAULT 7 Java_com_aatt_fpsm_FPSMSe
19: 0000400c 4 OBJECT GLOBAL DEFAULT 16 value
20: 00004004 0 NOTYPE GLOBAL DEFAULT ABS _edata
21: 00004004 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
22: 00004010 0 NOTYPE GLOBAL DEFAULT ABS _end
23: 00000000 0 FUNC WEAK DEFAULT UND __gnu_Unwind_Find_exidx
24: 00000000 0 FUNC GLOBAL DEFAULT UND abort
25: 00000000 0 FUNC GLOBAL DEFAULT UND memcpy
26: 000017bc 8 FUNC WEAK DEFAULT 7 __aeabi_unwind_cpp_pr2
27: 00001d88 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Restore_VFP_
28: 00001d78 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Restore_VFP
29: 00001d98 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Restore_VFP_
30: 00001da8 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Restore_WMMX
31: 00001e30 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Restore_WMMX
32: 00001d64 20 FUNC GLOBAL DEFAULT 7 restore_core_regs
33: 0000134c 68 FUNC GLOBAL DEFAULT 7 _Unwind_VRS_Get
34: 000013b8 68 FUNC GLOBAL DEFAULT 7 _Unwind_VRS_Set
35: 00000000 0 NOTYPE WEAK DEFAULT UND __cxa_begin_cleanup
36: 00000000 0 NOTYPE WEAK DEFAULT UND __cxa_type_match
37: 00001f64 916 FUNC GLOBAL DEFAULT 7 __gnu_unwind_execute
38: 00000000 0 NOTYPE WEAK DEFAULT UND __cxa_call_unexpected
39: 000017d4 856 FUNC GLOBAL DEFAULT 7 _Unwind_VRS_Pop
40: 00001d90 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Save_VFP_D
41: 00001d80 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Save_VFP
42: 00001da0 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Save_VFP_D_1
43: 00001dec 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Save_WMMXD
44: 00001e44 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Save_WMMXC
45: 00001b2c 8 FUNC GLOBAL DEFAULT 7 _Unwind_GetCFA
46: 00001b34 164 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_RaiseExcepti
47: 00001bd8 28 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_ForcedUnwind
48: 00001bf4 108 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Resume
49: 00001c60 32 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Resume_or_Re
50: 00001c80 4 FUNC GLOBAL DEFAULT 7 _Unwind_Complete
51: 00001c84 32 FUNC GLOBAL DEFAULT 7 _Unwind_DeleteException
52: 00001ca4 192 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Backtrace
53: 00001d64 20 FUNC GLOBAL DEFAULT 7 __restore_core_regs
54: 00001e58 36 FUNC GLOBAL DEFAULT 7 ___Unwind_RaiseException
55: 00001e58 36 FUNC GLOBAL DEFAULT 7 _Unwind_RaiseException
56: 00001e7c 36 FUNC GLOBAL DEFAULT 7 ___Unwind_Resume
57: 00001e7c 36 FUNC GLOBAL DEFAULT 7 _Unwind_Resume
58: 00001ea0 36 FUNC GLOBAL DEFAULT 7 ___Unwind_Resume_or_Rethr
59: 00001ea0 36 FUNC GLOBAL DEFAULT 7 _Unwind_Resume_or_Rethrow
60: 00001ec4 36 FUNC GLOBAL DEFAULT 7 ___Unwind_ForcedUnwind
61: 00001ec4 36 FUNC GLOBAL DEFAULT 7 _Unwind_ForcedUnwind
62: 00001ee8 36 FUNC GLOBAL DEFAULT 7 ___Unwind_Backtrace
63: 00001ee8 36 FUNC GLOBAL DEFAULT 7 _Unwind_Backtrace
64: 000022f8 64 FUNC GLOBAL DEFAULT 7 __gnu_unwind_frame
65: 00002338 44 FUNC GLOBAL DEFAULT 7 _Unwind_GetRegionStart
66: 00002364 56 FUNC GLOBAL DEFAULT 7 _Unwind_GetLanguageSpecif
67: 0000239c 8 FUNC GLOBAL DEFAULT 7 _Unwind_GetDataRelBase
68: 000023a4 8 FUNC GLOBAL DEFAULT 7 _Unwind_GetTextRelBase
從elf資訊可以見到,這個庫主要是JNI的實現及將unwind實現包含在庫中,unwind庫一般是用作異常處理的,用它可以獲取函式的呼叫棧資訊。
這裡由於使用pipe,則懷疑這裡需要跨程序通訊;而此pipe的通訊使用是apk私有的pipe,則推論此apk通過rootTool中提供的Shell類來執行su後的shell,su的作用是通過linux開的後門,允許使用者程式通過setuid系統呼叫,更改使用者id,達到root效果。su root後,執行一個native程式,native程式應該就是res/raw/下的bin0。初步懷疑pipe的寫端是這個bin0,bin0的symbol資訊:
$ readelf.exe -s bin0
Symbol table '.dynsym' contains 32 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FUNC GLOBAL DEFAULT UND __libc_init
2: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit
3: 00000000 0 FUNC GLOBAL DEFAULT UND snprintf
4: 00000000 0 FUNC GLOBAL DEFAULT UND fopen
5: 00000000 0 FUNC GLOBAL DEFAULT UND fgets
6: 00000000 0 FUNC GLOBAL DEFAULT UND strstr
7: 00000000 0 FUNC GLOBAL DEFAULT UND strtok
8: 00000000 0 FUNC GLOBAL DEFAULT UND strtoul
9: 00000000 0 FUNC GLOBAL DEFAULT UND fclose
10: 00000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail
11: 00000000 0 OBJECT GLOBAL DEFAULT UND __stack_chk_guard
12: 00000000 0 FUNC GLOBAL DEFAULT UND memcpy
13: 00000000 0 FUNC GLOBAL DEFAULT UND ptrace
14: 00000000 0 FUNC GLOBAL DEFAULT UND waitpid
15: 00000000 0 FUNC GLOBAL DEFAULT UND opendir
16: 00000000 0 FUNC GLOBAL DEFAULT UND readdir
17: 00000000 0 FUNC GLOBAL DEFAULT UND atoi
18: 00000000 0 FUNC GLOBAL DEFAULT UND sprintf
19: 00000000 0 FUNC GLOBAL DEFAULT UND strcmp
20: 00000000 0 FUNC GLOBAL DEFAULT UND closedir
21: 00000000 0 FUNC GLOBAL DEFAULT UND dlsym
22: 00000000 0 FUNC GLOBAL DEFAULT UND strlen
23: 0000c000 0 NOTYPE GLOBAL DEFAULT ABS _edata
24: 0000c000 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
25: 0000c004 0 NOTYPE GLOBAL DEFAULT ABS _end
26: 00000000 0 FUNC WEAK DEFAULT UND __gnu_Unwind_Find_exidx
27: 00000000 0 FUNC GLOBAL DEFAULT UND abort
28: 00000000 0 FUNC GLOBAL DEFAULT UND raise
29: 00000000 0 NOTYPE WEAK DEFAULT UND __cxa_begin_cleanup
30: 00000000 0 NOTYPE WEAK DEFAULT UND __cxa_type_match
31: 00000000 0 NOTYPE WEAK DEFAULT UND __cxa_call_unexpected
我們通過ps來看一下執行時的程序情況,並沒有看到此bin0程序,看樣子不像是常駐記憶體的,那麼它太不可能是pipe的write端。
從elf的symbol來看,此bin檔案應該會使用dlsym和ptrace。使用ptrace的話,基本可以確定,這個bin檔案會通過PTRACE_ATTACH到別的程序中,然後修改別的程序資料或程式碼,以達到自己的目的。ptrace的執行過程應該就是分析的關鍵,接下來需要從ptrace入手。
小結
這個fps meter沒有按照android應用程式的開發規範,通過使用SDK和NDK開發java和jni程式碼實現,而是使用第三方庫,通過su獲取root許可權,執行自己的可執行binary程式,apk自己實現的庫或binary程式,以android資源的形式打包在apk中。這種執行方式,對使用者安全及系統穩定來說,是一個危險的動作。
本小結簡單瞭解了此apk的內容,下節將詳細介紹下apk資源包中bin檔案通過ptrace感染android系統程序的過程。
相關推薦
android應用程式fps meter[幀數顯示]的分析 —— SurfaceFlinger被注入統計程式碼 (1)
fps meter是常用的檢測幀率的軟體,該軟體需要root許可權才能工作,一直比較好奇它一個apk是如何知道系統當前的幀率情況的,就針對此apk分析了一下其工作原理。 Apk組成 首先看一下apk的組成,apk檔案就是一個壓縮包,可以解壓縮軟體如winrar解壓檢視,也可
android應用程式第一次啟動時顯示引導介面
市面上好多優秀的應用(舉例新浪微博、UC瀏覽器)都採用了歡迎頁面與使用嚮導的方式給使用者帶來了良好的使用者體驗。 一般來說使用者第一次安裝應用或者安裝了新版本後第一次進入應用都會顯示成 歡迎頁面-使用嚮導-主介面 的方式 使用者沒有安裝新版本或者不是第一次進入的時候都
瀏覽器判別下載安裝/開啟Android應用程式
摘要: 通過手機瀏覽器直接開啟Android應用程式。 如果本地已經安裝了指定Android應用,就直接開啟它; 如果沒有安裝,則直接下載該應用的安裝檔案(也可以跳轉到下載頁面)。 之前寫過一篇blog,介紹如何通過點選手機瀏覽器中的連結,直接開啟本地Android App。 實現方式
Android應用程式框架講解
在我們的android的程式中會有很多的檔案,那麼這些檔案到底是有什麼作用呢? 我們編譯android專案,可以使用eclipse和AS,首先介紹一下eclipse中的框架 1、src檔案:存放的是應用程式使用到的java檔案 2、gen檔案:系統自動生成的目錄。不需要程式設計師進行
android應用程式的介面程式設計
要點 android的介面與view元件 view元件和viewgroup元件 android控制程式的三種方式 通過繼承view開發自定義view android常見的佈局管理器 文字框元件:textview和edittext 按鈕元件:button 特殊按鈕元件:radiobut
Android應用程式進行系統簽名
有時寫一個程式需要呼叫系統的庫,如果許可權不夠,是用不了庫裡面一些方法的 。這時就需要將apk進行系統簽名。 簡單常用的方法: 1,在apk的AndroidMani
Android應用程式簽名打包(AS)
使用Android studio對Android應用簽名步驟: 第一步: 第二步: 第三步: 第四步: 數字證書建立完成後,點選OK----->點選Next------>Finish。 注意:生成後的數字證書千萬不能丟失,還有密碼也不能忘記了
怎麼獲取Android應用程式的上下文
前面我做了一個類似於騰訊QQ一樣的聊天應用,在這個應用裡面,有很多activity,而這些activity之間經常要進行互相啟動、往復跳轉、還有就是通過Notification啟動。當activity多了之後,如果設定他的模式為單例模式,或者不設定模式。在反覆啟動後會出現數據不同步、fc等各種未知的
Android 應用程式崩潰日誌捕捉
程式崩潰是應用迭代中不可避免的問題,即使有著5年或者10年經驗的程式猿也無法完全保證自己的程式碼沒有任何的bug導致崩潰,現在有一些第三方平臺可以幫助我們蒐集應用程式的崩潰,比如友盟,詳情如下圖 雖然能夠看到崩潰的日誌以及機型等,但還是不是很方便,如果需要精確定位的話需要使用者提供崩潰的時間點、機型
轉老羅 Android應用程式資源的查詢過程分析
原文地址 http://blog.csdn.net/luoshengyang/article/details/8806798 轉載請說明 我們知道,在Android系統中,每一個應用程式一般都會配置很多資源,用來適配不同密
轉自老羅 Android應用程式資源的編譯和打包過程分析
原文地址 http://blog.csdn.net/luoshengyang/article/details/8744683 轉載自老羅,轉載請說明 我們知道,在一個APK檔案中,除了有程式碼檔案之外,還有很多資原始檔。這些資原始檔是通過An
轉自 老羅 Android應用程式資源管理器(Asset Manager)的建立過程分析
原文地址在 http://blog.csdn.net/luoshengyang/article/details/8791064 原創老羅,轉載請說明 在前面一篇文章中,我們分析了Android應用程式資源的編譯和打包過程,最終得到的應用程式資源就與
模組化惡意Android應用程式偽裝成語音工具,通過調查收集PII資料
“這些惡意應用程式和惡意軟體的觀察變體自10月份開始逐一部署,其演變包括規避技術及其感染行為分為幾個階段,”趨勢科技在他們的分析中表示。 在嘗試通過虛假調查收集使用者的個人身份資訊(PII)並提供禮品卡作為獎勵以填寫它們時,已經觀察到被稱為AndroidOS_FraudBot.OPS的惡意軟體。此外,惡意應
ubuntu中ffmpeg修改視訊FPS,幀數
1. 降低FPS,增加視訊時長 說對於輸入檔案是40幀的媒體,我們可以通過 ffmpeg -r 80 -i input output ffmpeg -r 20-i input output 使其輸出檔案的時長分別為原來的一半和兩倍,即播放速度為原來的兩倍和一半。
android應用程式的混淆打包(轉)
target=android-8 proguard.config=proguard.cfg Eclipse會通過此配置在工程目錄生成proguard.cfg檔案 2 . 生成keystore (如已有可直接利用) 按照下面的命令列 在D:\Program
android應用程式安裝後點擊開啟帶來的問題
前幾天專案組反饋回來一個這樣的情況就是我在安裝應用之後點選了開啟 然後按home鍵 這個時候應用程式進入後臺 我點選手機桌面的時候圖片啟動應用程式 程式重新再次啟動 而不是後臺的程式返回到前臺; /
Android應用程式啟動詳解(二)從原始碼瞭解App的啟動過程
本文承接《Android應用程式啟動詳解(一)》繼續來學習應用程式的啟動的那些事。上文提到startActivity()方法啟動一個app後經過一翻過程就到了app的入口方法ActivityThread.main()。其實我們在之前的文章中《Android的訊息機制(二)之L
Android 應用程式開發環境搭建說明
之前開發一直用的Eclipse,今年接了個Android 車載POS機專案,系統使android 7.1 的,然後準備更新sdk發現已經停止更新了,儘管之前SDK的更新也很辛苦,國內google被牆了,只能利用國內的某些映象網站實現Android SDK線上更新。然後查閱論壇,才發現我已經落伍了,
(轉載)Android應用程式簽名系統的簽名(SignApk.jar)
1. 在安卓工具箱中,下載SignApk.jar。 2. 拿到終端上系統的簽名(由定製系統的廠商提供): 3. 在應用程式的專案中配置: androidManifest.xml中新增android:sharedUserId="android.uid.system"
Android應用程式內部啟動Activity過程 startActivity 的原始碼分析
上文介紹了Android應用程式的啟動過程,即應用程式預設Activity的啟動過程,一般來說,這種預設Activity是在新的程序和任務中啟動的;本文將繼續分析在應用程式內部啟動非預設Activity的過程的原始碼,這種非預設Activity一般是在原來的程序