李青
【摘要】 隨著智能終端的普及,Android平臺的市場占有率已經躍居世界首位,基于Android的應用開發日益增多。但由于Android系統的開源性和開放性,在給開發帶來巨大方便的同時,也給一些惡意開發者破解和修改Android應用留有可乘之機。這些惡意開發者通過利用反向工程工具來修改他人的應用后,冠以自己的名稱對外進行發布銷售,嚴重損害了原作者的利益,更有甚者在其中穿插了黃色反動信息,嚴重違反了國家的法律政策。本文提出通過提取Android應用代碼特征后,利用組件相似度檢測、Java類布局比較、代碼控制流比較以及文本相似度比較四個維度來進行盜版應用自動檢測。并基于該方法對Android應用發布平臺反盜版的系統架構進行了設計實現。
【關鍵詞】 Android應用 版權保護 反向工程 代碼特征
一、引言
依賴著整個手機行業從功能機時代跨越至智能機時代的科技飛躍,Android操作系統已經迅速崛起,成為全球市場占有率首位的智能移動終端操作系統。它的使用涵蓋了智能手機、平板電腦、電視機頂盒以及其他嵌入式便攜電子設備。
Android操作系統在如此短的時間內取得了巨大的市場成功,很大一部分要歸功于系統的開放性和易于上手的開發套件。Google公司為Android開發者提供了手把手的起步文檔、簡單易用的開發套件和在線論壇。系統基于Linux開發,代碼開源可讀,任何個人和第三方廠商都可以很快速的寫出一個屬于自己的應用。也正是因為系統的開放性和技術的透明,不良開發者可以比較容易的對應用進行反向工程,對原有應用進行小規模篡改,替換內部的資源文件,改頭換面后作為自己的應用推向市場,從而從中獲利。
對于各類應用發布平臺而言,盜版應用會導致平臺內應用大量同質化,產品品質下降,同時降低平臺聲譽,帶來法律風險。從長遠來看,這種行為更嚴重擾亂了Android應用市場秩序,且影響整個產業鏈的健康發展。
令人擔憂的是,當下各種應用發布平臺僅能做到對版權文檔進行書面審核和人工測試。這種測試主觀因素高,且費時費力。鑒于此,本文設計了一套較有效的借助代碼特征分析和數據庫存儲比對的自動化工具來進行輔助檢測。
二、Android應用篡改和盜版方式分析
知己知彼,百戰不殆。只有深入了解不良開發者如何篡改應用,才能從源頭上抑制他們的欺騙手段。通常不良開發者有兩類。
一類是“盜版商”,他們獲取利益的主要手段是將市面上的應用進行小規模的修改,重新包裝,然后作為一款新的應用進行上市推廣。通常他們會首先獲取Android應用的可執行文件(apk文件),通過反向工程工具(例如APKTools)進行反編譯。在反編譯后得到資源文件、配置文件、smali代碼和動態鏈接庫文件。其中,資源文件是安卓應用在執行過程中所需要的一些圖片、布局和字符串等文件;配置文件是Android應用的權限設置和一些基本程序信息;smali代碼實質上為反編譯后的代碼,但是可讀性較差,如果原作者在編譯時使用了代碼混淆,smali基本不可讀懂;動態鏈接庫為程序運行過程中需要調用的一些外部函數。從反編譯后得到的這些素材來看,修改者最容易做到的是直接替換資源文件,特別是更換圖片或者字符串(參見圖1)。而更有能力的開發者,在源代碼未被混淆的前提下,則可以通過修改配置文件和smali代碼,繞過一些校驗功能,并增加一些自己的功能代碼,使得新的程序與原有程序在體驗上有一定差異。
另一類是“翻版商”,他們和“盜版商”的最大區別是:“盜版商”通常沒有應用的源碼,他們的主要盜版工具是反向編譯;而“翻版商”實際上是原版應用的作者或者獲得了原版應用的源碼。“翻版商”可以對源碼進行大量的類名替換或者函數名替換、注入新的代碼邏輯或者修改資源以后,將原應用改頭換面作為一款新的應用推向市場。“翻版商”通過將一款應用復制為多款應用來躲避應用市場的監督管控,達到大量吸費的目的。
但無論上述哪種不良開發者,通常都會從成本出發,避免對應用進行過于復雜的修改。一般的做法是直接替換資源文件,使應用的體驗有直接的變化。如果一款應用只是部分借鑒了另一款應用的思路或者功能,但是算法和架構完全自行重寫,那么就不能夠認為是惡意盜版。這就好比OICQ和ICQ的關系,不能認為他們功能類似,就認定前者盜版后者。因此,“盜版程序”和“翻版程序”從代碼分析上來看,基本特征都得以保留。這也為接下來子反盜版之路中的“證據”捕捉,提供了足夠的信息。(圖1)
三、四種代碼相似度判定維度介紹
針對上述不良開發者通用的盜版手段,本文將著重從反編譯后的代碼尋找蛛絲馬跡,以此來判定兩個Android應用是否在整體上相似。這可以從四個方面入手。
3.1 組件相似度
在Android操作系統中,應用程序執行的單元是系統預定義的各種組件。組件相似度檢測可通過解析安裝包中的配置文件內容來得到程序的各個組件聲明和之相關聯的參數及資源信息,最終進行相似度比較。
確切的說,Android操作系統提供給開發者預先封裝好的類作為應用程序中的基本組件,它們是:Activity、Service、Content Provider和BroadcastReceiver。而在組件之間,Android系統提供了Intent作為內部信息傳送方式。任何Android應用,都需要通過繼承、調用和擴展以上四大基本組件來構造自己。
同時,Android系統要求開發者在一個配置文件(AndroidManifest.xml,參見代碼1)中將自己定義的組件以及組件間用于通信的Intent全部聲明出來。該配置文件同時還定義了整個應用所需要的系統權限。
因此,通過解析反編譯后的AndroidManifest.xml便可以知道,一個應用中有多少個自定義Activity、Service、Content Provider和BroadcastReceiver,同時也能知道,他們之間誰和誰交互了哪些Intent。
對于普通的修改者而言,這個方法幾乎完全可以決定源碼拷貝是否存在。而對于有能力替換所有文件名稱甚至類定義的不良開發者而言(雖然從成本考慮通常不會如此,且迄今為止smali注入基本都僅限于函數級,該假設僅為了考慮到所有可能性),以上各種組件聲明、組件和組件之間的通信關系,也能給兩個應用的相似度判斷帶來很大的幫助。
代碼1. AndroidManifest.xml樣例
3.2 Java類布局比較
Android操作系統的代碼開發是基于Linux和Java的。 Java語法中,每定義一個類,都需要指定這個類所在的包(Package),以及該Package下的各層目錄。這是一種樹型結構,表示了包、目錄路徑和類的關系。樹的根節點代表程序的根目錄(即最頂層的包),分支節點代表程序子目錄,葉子節點是具體的類。
通過反編譯后的smali代碼,可以推導出軟件的整體類布局樹,然后通過樹路徑相似度矩陣算法或者編輯距離算法比較得出Java類布局相似度。
3.3代碼控制流比較
一個應用包含的自定義函數少則數十個,多則上萬個。這些函數之間有著錯綜復雜的調用關系。把函數的調用關系抽象出來,可以得到一個有向圖。圖中每個節點代表一個函數,有向邊代表與之相連的兩個節點(函數)之間存在調用關系。這樣的有向圖,在本文中被定義為代碼控制流。(見圖2)
圖2. 代碼控制流比較
較有能力的不良開發者可以通過smali注入來進行函數級的修改。然而與一個應用中數量巨大的函數調用關系相比,這點修改在代碼控制流相似度比較中通常顯得微不足道。
3.4 文本相似度比較
文本相似度比較已經廣泛應用于信息檢索、機器翻譯、自動問答等系統。目前可以搜索到的算法就有余弦算法、BM25算法、Nakatsu算法和LD算法等多種。
反編譯后的smali代碼本質依然是文本文檔,將傳統文本的比較方法借鑒到代碼比較中也不算是完全的創新手段。相信大多數程序員都有過使用diff命令或者BeyondCompare這樣的工具進行代碼比較。只是此處的文本相似度更具備函數級的針對性,而非diff命令的逐行文本精確匹配方式。
我們已經在文章中多次強調,不良開發者不會投入巨大的精力去修改通篇代碼。并且在現實中,也沒有人有能力去通過修改smali來完全替換類級別的構造。如果原作者在編譯過程中開啟了代碼混淆,反編譯后的smali代碼將完全不可讀。考慮到以上這些因素,在代碼層面上,引入文本相似度比較手段,針對作者自定義的函數進行相關性統計,在協助判定兩個應用的相似度上,是相當有效的手段。
四、基于多維度的應用相似度判定算法
正如前文中描述的,通過反編譯應用的APK包,可以得到該應用的配置文件、smali代碼、資源文件和動態鏈接庫。忽略掉容易被替換的資源文件和不會被改變的動態鏈接庫。上述四個維度相似度的判定將主要利用配置文件和smali代碼。其中:
1、通過比較兩個應用的配置文件(AndroidManifest.xml)中組件和組件間的通信關系(Intent),可以得到組件相似度的最終值,設為A。
2、解析smali代碼中各文件的頭部信息,查找關鍵字為.class之后的內容,便可得到包和目錄路徑(參見代碼2)。將路徑信息抽象為路徑樹后,利用樹相似度比較算法,可以得到應用的Java類布局相似度,設為B。
3、通過分析smali代碼和smali語法說明可以知道,smali代碼中函數調用都是以invoke-xxxx{parameter}, methodtocall的格式進行的。以invoke-作為關鍵字查找,定位到methodtocall(被調用函數)[2],便可以得到代碼控制流圖(參見代碼2),然后使用同構圖算法進一步得到應用的代碼控制流相似度,設為C。
4、最后,使用invoke-查找出所有的函數調用行,通過空格分解出關鍵字,分別定義為操作符、參數、被調函數。在去除操作符、參數、系統函數調用等可能干擾文本特征的因素后,利用余弦相似度算法(當然,其他文本相似度比較算法也可)對兩組應用的smali代碼進行文本相似度檢測,則可以得到文本相似度,設為D。
根據應用的特質和應用平臺自身的情況,可以將上述四種比較結果直接輸出進行可視化比較,考慮有2個維度的相似度在80%以上即可判定為相似。通常情況下,組件相似度和文本相似度比較能夠快速的定位到直接替換資源文件的“盜版軟件”,而Java類布局相似度和代碼控制流相似度能夠準確定位替換了源碼函數名和類名的“翻版軟件”。(代碼2)
五、應用相似度判定系統設計
以上算法使用了四個維度相似度判定后的方式,這為實際生產使用提供了可操作性。對于一個應用發布平臺而言,在系統設計和實現時需要兼顧成本和效率。
對于每一個進入系統的應用,反編譯該應用后,系統應當存儲應用的組件結構、組件關系、樹形結構、有向圖結構、配置文件和smali文件關鍵字向量。在日常的業務流程中,通常需要在線進行應用特征查找和比對,考慮到應用發布的數量巨大,這些數據也并非結構化數據,使用針對大數據和文本處理設計的Nosql數據庫能夠較好的降低成本提高效率。而出于快速響應的要求,在運算方面,建議使用多服務器并行的算法,利用分布式運算來縮小整體運算時間,提升用戶感知。使用Map-reduce的算法加多臺刀片機可能要比使用少量的多CPU小型機要更加經濟和有效[3]。
應用相似度的最終結果可以使用報表或者圖形化界面展示,作為應用發布平臺流程環節中的參考。應用發布平臺既可以在應用申報過程中利用該能力判定一款新應用是否與平臺中已有應用重合。也可以反向利用該能力,在某款平臺中應用需要重傳包體的時候,檢測包體是否被改動過,避免二次測試浪費人力。
六、結束語
隨著Android陣營的日益強大,Android應用市場的管理也將越來越規范化。對于各應用發布平臺而言,如何有效的保障平臺內應用水準,縮短應用審批流程,提高應用上線速度,將決定其成敗。
本文使用了組件相似度比較、Java類布局比較、代碼控制流比較和文本相似度比較四個維度,探測應用相似度,最終輸出報表或者圖形化界面,供應用評審人員參考和查證。應用發布平臺可以在以較低的成本建設該能力平臺后,使用該能力進行應用的初步篩選盜版和簡化應用二次測試過程,從而減少人力成本,提高審核效率。然而,Android作為Java語言的延伸產品,想要完全防止代碼反編譯和篡改幾乎不可能。技術的進步會使應用篡改的手段更加豐富,防范和鑒別不良應用的方式也需要隨著時代和科技的進步不斷的優化和擴展。
參 考 文 獻
[1] Android-apktool A tool for reverse engineering Android apk files[EB/OL]. http://code.google.com/p/android-apktool 2003-11-11.
[2] Smali An assembler/disassemble for Androids dex format[EB/OL]. https://code.google.com/p/smali. 2013-11-11.
[3]潘偉,利用文本余弦相似度實現Android應用的版權保護[J],中國新通信,2014(2),P53-55.
[4] Cosine similarity From Wikipedia, the free encyclopedia[EB/OL]. http://en.wikipedia.org/wiki/Cosine_similarity. 2014-4-14.
[5] How to avoid reverse engineering of an APK file? [EB/OL]. http://stackoverflow.com/questions/13854425/how-to-avoid-reverse-engineering-of-an-apk-file. 2013-2-8