高 琦 劉克勝 常 超 邱世萬(wàn)
基于自修改字節(jié)碼的Android軟件保護(hù)技術(shù)研究
高 琦 劉克勝 常 超 邱世萬(wàn)
(合肥電子工程學(xué)院 安徽 合肥 230037)
隨著侵權(quán)現(xiàn)象的不斷發(fā)生,加強(qiáng)Android軟件的保護(hù)已成為一個(gè)研究熱點(diǎn)。對(duì)軟件逆向工程及其對(duì)抗措施進(jìn)行分析和評(píng)價(jià),指出重點(diǎn)的研究領(lǐng)域;針對(duì)Android軟件逆向工程,在研究APK安裝原理及dex文件格式的基礎(chǔ)上,采取軟件運(yùn)行時(shí)自修改dalvik字節(jié)碼的方案有效改變了代碼的執(zhí)行流程,增加了代碼的迷惑性。通過實(shí)驗(yàn)實(shí)現(xiàn)對(duì)軟件關(guān)鍵模塊的隱藏,使分析者無法得到正確的代碼流程,證明了該方法在軟件保護(hù)領(lǐng)域具有可行性,為軟件保護(hù)提供了新的思路。
Android 軟件保護(hù) 字節(jié)碼 dex文件 代碼自修改
Android軟件市場(chǎng)發(fā)展十分迅猛,根據(jù)360公司2014年的統(tǒng)計(jì)數(shù)據(jù)[1],僅國(guó)內(nèi)37個(gè)大型市場(chǎng)中,軟件數(shù)達(dá)50萬(wàn)以上的就有6個(gè),其中3個(gè)市場(chǎng)的軟件數(shù)超百萬(wàn)。但市場(chǎng)繁榮的背后隱藏著嚴(yán)重的版權(quán)保護(hù)問題,如游戲廠商“Dead Trigge”因軟件盜版而被迫免費(fèi)出售軟件的案例曾引起廣泛熱議[2],給開發(fā)商帶來巨大損失。更為嚴(yán)重的問題是,軟件破解的方法被大量用于惡意代碼的編寫,如偽裝成合法應(yīng)用竊取用戶敏感信息的惡意軟件[3],不但侵犯了開發(fā)者的版權(quán),更損害了用戶的利益和個(gè)人隱私。文獻(xiàn)[4]詳細(xì)說明了這種惡意軟件從合法逆向、代碼分析、惡意篡改到重打包生成APK并發(fā)布的整個(gè)過程。
程序自修改(SMC)是一種允許代碼在運(yùn)行時(shí)對(duì)自身進(jìn)行修改的技術(shù)手段,最早由日本研究者于2003年提出[5],現(xiàn)在已比較成熟[6],相關(guān)文獻(xiàn)[7,8]將此方法進(jìn)行改進(jìn)以應(yīng)對(duì)動(dòng)態(tài)分析技術(shù)的發(fā)展,取得了理想效果。2013年,Bluebox Scurity網(wǎng)站的一篇文章[9]為自修改技術(shù)在Android移動(dòng)端的應(yīng)用提供了啟示。本文在分析Android軟件靜態(tài)分析技術(shù)的基礎(chǔ)上,重點(diǎn)研究了APK在系統(tǒng)中的安裝及APK的可執(zhí)行文件格式,掌握了dalvik字節(jié)碼在系統(tǒng)中的存放形式,并將SMC技術(shù)原理與Android系統(tǒng)架構(gòu)和軟件格式相結(jié)合,提出了一種基于自修改dalvik字節(jié)碼的Android軟件保護(hù)方案,并編寫實(shí)例進(jìn)行了測(cè)試。一方面,將SMC技術(shù)用于Android系統(tǒng),擴(kuò)展了其應(yīng)用范圍,另一方面,本文實(shí)現(xiàn)的方法可以有效地提高Android平臺(tái)軟件對(duì)抗逆向工程的能力。
1.1 Android軟件逆向工程
逆向工程,通常也稱之為Android靜態(tài)分析,指的是采用詞法分析、語(yǔ)法分析等手段生成軟件的反匯編代碼,分析員通過閱讀代碼掌握程序功能的一類技術(shù)。在實(shí)際操作中,分析員通常會(huì)采用動(dòng)靜結(jié)合的方法開展分析,但靜態(tài)分析仍在其中起主要作用。靜態(tài)分析的基本方法是代碼的反匯編和語(yǔ)法分析,通過分析代碼獲取目標(biāo)軟件各功能模塊及其實(shí)現(xiàn)方法。
Android平臺(tái)軟件通常基于Java語(yǔ)言編寫,經(jīng).class文件轉(zhuǎn)化成.dex文件,并被dalvik虛擬機(jī)所解釋。反匯編程序基于dex文件格式編寫,將Java代碼反匯編生成一種smali格式的語(yǔ)言文件,該文件分別為程序的每一個(gè)抽象類、普通類、內(nèi)部類或接口生成一個(gè)對(duì)應(yīng)的smali文件,按原代碼的組織形式呈現(xiàn)在用戶面前。常用的反匯編工具是baksmali、apktool和dex2jar。
1.2 對(duì)抗逆向工程的Android軟件保護(hù)技術(shù)
如何有效保護(hù)軟件版權(quán)一直是開發(fā)商關(guān)注的重點(diǎn),圍繞該問題業(yè)界提出了大量解決方案。目前,對(duì)抗逆向分析的方法大致可以歸為以下幾類:
(1) 核心模塊隱藏:修改dex文件特殊字段的值可以實(shí)現(xiàn)關(guān)鍵方法的隱藏,但字段值的改變很容易被有經(jīng)驗(yàn)的分析者發(fā)現(xiàn);動(dòng)態(tài)加載函數(shù)也允許將部分代碼以資源形式隱藏在本地或云端,但與云端的交互受網(wǎng)絡(luò)條件和用戶資費(fèi)承受能力的制約;利用Java語(yǔ)言的反射機(jī)制[10]實(shí)現(xiàn)函數(shù)功能也能隱藏代碼意圖,但通常仍不可避免地需要將相關(guān)參數(shù)存儲(chǔ)于云端。
(2) 軟件完整性校驗(yàn):對(duì)dex文件或整個(gè)APK計(jì)算hash值,結(jié)果存儲(chǔ)于云端或資源文件中,每次運(yùn)行時(shí)都計(jì)算該hash值,與存儲(chǔ)的值進(jìn)行比較。但是這種方法可以通過修改代碼邏輯使之失效。
(3) 破壞代碼可讀性: “append”函數(shù)允許逐個(gè)字符地產(chǎn)生字符串?dāng)?shù)組,以增大分析者提取關(guān)鍵字段的難度;也可以通過使用goto指令實(shí)現(xiàn)代碼的亂序;dexguard或proguard等工具對(duì)軟件進(jìn)行的處理,隱藏了類和方法的名稱,使分析者無法直接判斷代碼作用。
(4) 使用NDK:原生代碼的逆向分析難度遠(yuǎn)遠(yuǎn)大于Java層代碼,因此軟件的核心功能通過C代碼實(shí)現(xiàn)可以增強(qiáng)保護(hù)。
(5) 加殼:對(duì)關(guān)鍵代碼進(jìn)行加密處理。
(6) 逆向工具對(duì)抗:對(duì)逆向工具進(jìn)行分析,尋找其缺陷,有針對(duì)性地破壞其功能。Manifest欺騙通過在AndroidManifest文件的
綜合對(duì)上述六種方法的分析,目前逆向工程的對(duì)抗技術(shù)主要存在兩點(diǎn)不足:
一是代碼閱讀的難度雖然增大,但執(zhí)行流程沒有改變,有經(jīng)驗(yàn)的分析者完全有能力克服閱讀上的障礙,因此,需要在提高代碼不可讀性、改變代碼執(zhí)行流程方面加以研究;
二是針對(duì)逆向工具對(duì)抗的方法具有時(shí)效性,隨著分析技術(shù)的不斷發(fā)展,對(duì)抗方法也需要不斷改進(jìn),因此,軟件保護(hù)的重點(diǎn)應(yīng)當(dāng)是對(duì)代碼本身的保護(hù)。
基于此分析,本文主要研究通過軟件運(yùn)行時(shí)修改代碼執(zhí)行流程的方法保護(hù)代碼。
APK是Android平臺(tái)的軟件安裝包,DEX文件是可執(zhí)行的Android程序。本節(jié)結(jié)合Android4.0版本源代碼研究了系統(tǒng)對(duì)APK安裝包進(jìn)行的處理過程,并分析了dex文件格式,為自修改dalvik字節(jié)碼提供了理論基礎(chǔ)。
2.1 APK的安裝過程
分析APK文件的安裝過程,重點(diǎn)研究APK安裝后代碼及數(shù)據(jù)的存放,梳理軟件在系統(tǒng)中的運(yùn)行模式,為正確定位dalvik字節(jié)碼的內(nèi)存地址提供理論支撐。
系統(tǒng)軟件包packageinstaller.apk接收到系統(tǒng)的Intent后開始軟件的安裝。分析源碼發(fā)現(xiàn)這一過程的最終落腳點(diǎn)是frameworksasecmdinstalldcommands.c中的方法install(),該方法執(zhí)行完畢后通過socket向系統(tǒng)上層報(bào)告軟件安裝信息。
APK文件本質(zhì)是一個(gè)壓縮包,包含META-INF(簽名信息)、res(資源文件)、AndroidManifest.xml(配置文件)、classes.dex(Dalvik字節(jié)碼)、resources.arsc(二進(jìn)制資源文件)、lib(原生庫(kù))等內(nèi)容。APK安裝時(shí),系統(tǒng)首先將APK復(fù)制于/data/app目錄下,然后分別將APK的數(shù)據(jù)部分和dex可執(zhí)行程序文件部分存于/data/data和/data/ dalvik-cache目錄,其中數(shù)據(jù)部分包括databases數(shù)據(jù)庫(kù)目錄、cache緩存數(shù)據(jù)目錄、file應(yīng)用程序控制的文件目錄、lib庫(kù)目錄。Android程序首次啟動(dòng)時(shí),Dalvik虛擬機(jī)通過依存關(guān)系樹優(yōu)化程序代碼,包括將APK中dex格式優(yōu)化為odex格式,并刪除原dex文件。odex文件是Android平臺(tái)的可運(yùn)行文件,比dex文件體積小。這種優(yōu)化可以加快軟件啟動(dòng)速度,減少對(duì)RAM的占用。
2.2 dex文件與odex文件的格式
Dex文件是軟件的可執(zhí)行程序在內(nèi)存中的存放形式,修改dalvik字節(jié)碼的本質(zhì)是對(duì)dex文件的修改,研究該文件格式,重點(diǎn)是研究函數(shù)的字節(jié)碼在文件中的存放位置和存放格式,為自修改dalvik字節(jié)碼的實(shí)現(xiàn)提供框架支撐。
Android4.1以前版本的源碼的文檔dex-format.html記錄了dex的文件格式,本文主要結(jié)合Android4.0版本源碼對(duì)相關(guān)內(nèi)容進(jìn)行分析和梳理。
Odex文件被視為dex文件的超集,其文件結(jié)構(gòu)如圖1所示。
圖1 Odex文件結(jié)構(gòu)
綜合代碼中對(duì)odex文件的敘述,可以用如下的結(jié)構(gòu)對(duì)其進(jìn)行定義,其中header是文件頭,dexfile是dex文件。
struct ODEXFile{
DexOptHeader header;
//文件頭
DEXFile dexfile ;
//dex文件
Dependences dependlib ;
//庫(kù)
ChunkDexClassLookup classlook;
//輔助數(shù)據(jù)
ChunkRegisterMapPool Registerpool;
//輔助數(shù)據(jù)
ChundEnd end;
//文件結(jié)束
}
源碼中的dalvik/libdex/DexFile.h文件對(duì)該結(jié)構(gòu)體的各個(gè)要素在dalvik虛擬機(jī)中的映射作了定義。文件頭結(jié)構(gòu)DexOptHeader中,dexOffset代表dex文件頭偏移,dexLength代表dex文件總長(zhǎng)度。
struct DexOptHeader {
//odex文件頭
u1 magic[8];
/* includes version number */
u4 dexOffset;
/* file offset of DEX header */
u4 dexLength;
u4 depsOffset;
/* offset of optimized DEX dependency table */
u4 depsLength;
u4 optOffset;
/* file offset of optimized data tables */
u4 optLength;
u4 flags;
/* some info flags */
u4 checksum;
/* adler32 checksum covering deps/opt */
};
結(jié)構(gòu)體的dexOffset字段記錄了dex的基地址偏移。
Android系統(tǒng)對(duì)dex文件結(jié)構(gòu)的定義如圖2所示。
圖2 Dex文件結(jié)構(gòu)
Dalvik虛擬機(jī)在源碼中將文件映射為DexFile結(jié)構(gòu)體:
struct DexFile {
/* directly-mapped ″opt″ header */
const DexOptHeader* pOptHeader;
/* pointers to directly-mapped structs and arrays in base DEX */
const DexHeader* pHeader;
const DexStringId* pStringIds;
const DexTypeId* pTypeIds;
const DexFieldId* pFieldIds;
const DexMethodId* pMethodIds;
const DexProtoId* pProtoIds;
const DexClassDef* pClassDefs;
const DexLink* pLinkData;
……
}
其中DexHeader是文件頭,它的methodIdsSize、mehtodIdsOff、classDefsSize、classDefsOff指針分別代表DexMethodId(方法結(jié)構(gòu)體)及DexClassDef(類結(jié)構(gòu)體)字段的大小和偏移。
struct DexHeader {
//dex文件頭
u1 magic[8];
/* includes version number */
u4 checksum;
/* adler32 checksum */
u1 signature[kSHA1DigestLen];
/* SHA-1 hash */
u4 fileSize;
/* length of entire file */
u4 headerSize;
/* offset to start of next section */
u4 endianTag;
u4 linkSize;
u4 linkOff;
u4 mapOff;
u4 stringIdsSize;
u4 stringIdsOff;
u4 typeIdsSize;
u4 typeIdsOff;
u4 protoIdsSize;
u4 protoIdsOff;
u4 fieldIdsSize;
u4 fieldIdsOff;
u4 methodIdsSize;
u4 methodIdsOff;
u4 classDefsSize;
u4 classDefsOff;
u4 dataSize;
u4 dataOff;
};
DexClassDef有一個(gè)classDataOff字段,指向一個(gè)DexClassData結(jié)構(gòu)體,該結(jié)構(gòu)體的directMethods字段又指向一個(gè)描述程序中調(diào)用的方法的DexMethod結(jié)構(gòu)體,聲明如下:
struct DexMethod{
//方法信息
u4 methodIdx;
u4 accessFlags;
u4 codeOff;
}
codeOff字段指向DexCode結(jié)構(gòu)體,它的定義為:
struct DexCode {
//方法的實(shí)現(xiàn)代碼
u2 registersSize;
u2 insSize;
u2 outsSize;
u2 triesSize;
u4 debugInfoOff;
/* file offset to debug info stream */
u4 insnsSize;
/* size of the insns array, in u2 units */
u2 insns[1];
}
其中insns字段內(nèi)存儲(chǔ)了該方法的dalvik字節(jié)碼,進(jìn)行字節(jié)碼修改,主要就是尋找這個(gè)字段,并修改該字段的內(nèi)容。
2.3 Android原生程序及其調(diào)用
原生代碼運(yùn)行在系統(tǒng)庫(kù)層,對(duì)dalvik字節(jié)碼的修改只能通過原生代碼實(shí)現(xiàn), 通過Java語(yǔ)言的JNI調(diào)用與原生庫(kù)進(jìn)行交互,利用NDK編程生成動(dòng)態(tài)鏈接文件實(shí)現(xiàn)對(duì)字節(jié)碼的修改。
NDK(native development kit)是Android平臺(tái)對(duì)C和C++代碼的支持,Android自誕生起就表達(dá)了對(duì)C代碼的支持,NDK將這種支持加以具體實(shí)現(xiàn)。它包含一系列動(dòng)態(tài)庫(kù)開發(fā)工具,集成交叉編譯,通過mk文件對(duì)CPU、平臺(tái)等硬件條件進(jìn)行透明化處理,生成.so文件并與Java層生成的文件隨應(yīng)用一起打包入APK壓縮包,向市場(chǎng)發(fā)布。但Andoid明確表示NDK只支持部分功能,無法實(shí)現(xiàn)全C代碼的Android軟件。NDK編程的優(yōu)點(diǎn)在于代碼重用和代碼保護(hù),可以增加代碼跨硬件的可移植性,或增大分析者逆向獲取源代碼結(jié)構(gòu)的難度;它的缺點(diǎn)在于代碼復(fù)雜度的大幅增加,可能給開發(fā)者帶來不便和風(fēng)險(xiǎn)。因此,編程人員往往只對(duì)關(guān)鍵代碼或?qū)ο到y(tǒng)性能有較高要求的部分才使用C代碼實(shí)現(xiàn),如涉及顯示器的操作[11,12]。
Java本地調(diào)用JNI是Java語(yǔ)言平臺(tái)的組成部分,它提供了對(duì)C代碼的支持,使得原生庫(kù)像普通Java方法一樣為主程序所調(diào)用,同時(shí)JNI也提供了原生代碼對(duì)java代碼的調(diào)用方案。它有一套與Java語(yǔ)言相對(duì)的數(shù)據(jù)類型、數(shù)據(jù)結(jié)構(gòu)及函數(shù)標(biāo)記。在JNI平臺(tái)的支持下,Android應(yīng)用可以通過靈活地調(diào)用C代碼實(shí)現(xiàn)更多功能。如圖3所示。
圖3 JNI調(diào)用示意圖
JNI的書寫步驟包括:
(1) 編寫帶native聲明方法的Java類;
(2) 使用Javac編譯Java類;
(3) 使用Javah+Java生成頭文件;
(4) 跟據(jù)頭文件,實(shí)現(xiàn)本地代碼;
(5) 編譯生成動(dòng)態(tài)連接庫(kù)。
本節(jié)設(shè)計(jì)了一段示例代碼,該示例軟件的作用是對(duì)數(shù)據(jù)進(jìn)行簡(jiǎn)單加密,即把用戶輸入的數(shù)據(jù)按1.8倍輸出,用以加密數(shù)據(jù)。同時(shí),在逆向分析時(shí),攻擊者通過靜態(tài)分析得出的結(jié)論卻是用戶輸入的數(shù)據(jù)被直接輸出,未進(jìn)行乘法處理,從而無法分析出軟件的真實(shí)流程。圖4是示例軟件的設(shè)計(jì)思路。
圖4 軟件設(shè)計(jì)
為了更加清晰地展示實(shí)驗(yàn)內(nèi)容,該軟件只實(shí)現(xiàn)了關(guān)鍵代碼,修飾性的代碼全部去除。
3.1 執(zhí)行流程
(1) Java層主函數(shù)代碼設(shè)計(jì)
創(chuàng)建包c(diǎn)om.tim.parsetest,涉及的具體操作的實(shí)現(xiàn)代碼在類文件SetDataMethod中實(shí)現(xiàn);
設(shè)計(jì)一個(gè)方法setdata(),供主函數(shù)調(diào)用;
設(shè)計(jì)一個(gè)方法setdatahidden(),作為調(diào)用setdata ()時(shí),軟件實(shí)際運(yùn)行的代碼;
在主界面MainActivity中調(diào)用方法setdata();
本實(shí)驗(yàn)中,為了使實(shí)驗(yàn)內(nèi)容更加直觀,為輸入數(shù)據(jù)賦值“1.0”,直接在界面輸出結(jié)果值。
(2) 啟動(dòng)C層代碼
Android系統(tǒng)通過System.loadlibrary()函數(shù)調(diào)用動(dòng)態(tài)鏈接庫(kù).so文件,并首先執(zhí)行JNI_Onload()函數(shù)。該函數(shù)主要目的是進(jìn)行JNI版本的聲明和代碼初始化,相當(dāng)于一個(gè)初始化函數(shù)。
本實(shí)驗(yàn)在JNI_Onload()函數(shù)內(nèi)調(diào)用動(dòng)態(tài)鏈接庫(kù)parsingdex. so,該動(dòng)態(tài)鏈接庫(kù)的作用是在C層完成字節(jié)碼的修改和替換。確保在軟件調(diào)用動(dòng)態(tài)鏈接庫(kù)時(shí),setdatahidden()對(duì)setdata()的替換可以在C層代碼初始化期間完成,不需要顯性地在Java層調(diào)用該方法,從而確保了setdatahidden()函數(shù)在代碼執(zhí)行路徑中不出現(xiàn)。
(3) 尋找對(duì)應(yīng)方法的DexCode結(jié)構(gòu)體
由上文2.2節(jié)的分析,DexCode結(jié)構(gòu)體中存儲(chǔ)了方法對(duì)應(yīng)的字節(jié)碼,因此代碼執(zhí)行替換操作之前必須正確尋找和定位setdata()與setdatahidden()對(duì)應(yīng)的的DexCode結(jié)構(gòu)體。
第一步,定位odex文件,獲取odex文件的基地址odexbase。先是跟據(jù)odex文件在系統(tǒng)中的存諸路徑及格式構(gòu)造odex文件名:
odexname=/data/dalvik-cache/data@app@com.tim.parsetest-%d.apk@classes.d
然后調(diào)用getmodulebase()方法搜索本進(jìn)程的proc/self/ maps文件獲取odex的基地址。
第二步,獲取odex內(nèi)存塊大小odexsize。通過getmodulesize()方法獲取系統(tǒng)maps文件內(nèi)odex所占內(nèi)存的起始值和結(jié)束值,它們的差值就是odex的大小。
第三步,獲取dex文件位置dexbase。調(diào)用getdexstart()方法,在odex文件頭讀取dex文件偏移字段dexoffset的值,采用odexbase+dexoffset的方法得到dex內(nèi)存塊基址。讀取maps文件的偽代碼可如下所示:
fp=fopen(proc/self/maps);
while(fgets(line,fp)=1){
if(strstr(line,odex文件名)=1){
讀取該行地址信息;
}
}
fclose;
第四步,解析dex文件頭。對(duì)DexFile結(jié)構(gòu)體的關(guān)鍵字段賦值,方便下一步操作。
第五步,調(diào)用getmethod()方法,尋找DexCode結(jié)構(gòu)體。在系統(tǒng)中搜索該結(jié)構(gòu)體的流程如圖5所示。
圖5 DexCode結(jié)構(gòu)體的確定過程
通過枚舉類結(jié)構(gòu)DexClassDef,確定對(duì)應(yīng)SetDataMethod類的DexClassDef結(jié)構(gòu)體,同理,枚舉DexMethod確定setdata()與setdatahidden()方法的DexMethod結(jié)構(gòu)體。
(4) 修改讀寫權(quán)限
要想隱性地修改setdata()方法的dalvik字節(jié)碼,必須調(diào)用mprotect()函數(shù)為相應(yīng)內(nèi)存區(qū)間增加PROT_WRITE聲明,賦予軟件將字節(jié)碼寫入setdata()的權(quán)限。
(5) 實(shí)現(xiàn)字節(jié)碼的寫入
以字符串?dāng)?shù)組的形式逐個(gè)替換setdata()方法的insns[]字段??捎萌缦聜未a表示:
mprotect(dex,PROT_READ|PROT_WRITE|PROT|EXEC);
for(i=0;i insns_setdata[i] = insns_setdatahidden[i]; } mprotect(dex,PROT_READ|PROT_WRITE); //恢復(fù)權(quán)限的目的是防止軟件在運(yùn)行時(shí)出現(xiàn)不可預(yù)知的錯(cuò)誤 3.2 實(shí)驗(yàn)結(jié)果 對(duì)代碼進(jìn)行編譯和組建,生成dalvikmodifytest.apk文件。 利用工具ApkIDE對(duì)文件進(jìn)行逆向,分析其軟件功能。為了直觀地展現(xiàn)結(jié)果,APK文件在組建時(shí)未做任何混淆。 (1) 靜態(tài)分析 對(duì)軟件進(jìn)行逆向,發(fā)現(xiàn)主程序調(diào)用了setdata()方法,參數(shù)1.0,逆向代碼如下: invoke-virtual {v0, v2, v3}, Lcom/tim/parsetest/SetDataMethod;-> setdata(D)V Setdata()方法中,輸入的參數(shù)1.0被直接存入data域,此時(shí),data=1.0,逆向代碼為: iput-object v0, p0, Lcom/tim/parsetest/SetDataMethod;->data:Ljava/jang/ Double; 隨后getdata()方法將data值直接輸出: iget-object v0, p0, Lcom/tim/parsetest/SetDataMethod;->data:Ljava/jang/ Double; return v0; 從逆向分析判斷,軟件將1.0存入data域后,通過getdata()直接輸出,其結(jié)果應(yīng)與輸入?yún)?shù)一致,為1.0。從分析過程來看,setdatahidden()方法并未被調(diào)用。 (2) 實(shí)際運(yùn)行 在Android 4.0版本系統(tǒng)中運(yùn)行該APK,界面中輸出了getdata()函數(shù)的運(yùn)行結(jié)果如圖6所示。 圖6 真實(shí)的實(shí)驗(yàn)結(jié)果與逆向分析結(jié)果不符 按照逆向工程的步驟得出的結(jié)果是1.0,但實(shí)際運(yùn)行的卻是輸入數(shù)據(jù)1.8倍的結(jié)果1.8,說明該軟件并未執(zhí)行setdata()方法,而是在調(diào)用setdata()方法時(shí),執(zhí)行了setdatahidden()方法的字節(jié)碼。因此,軟件的關(guān)鍵加密模塊setdatahidden()被隱藏,受到了保護(hù)。 本實(shí)驗(yàn)成功地迷惑了逆向分析者,實(shí)現(xiàn)了對(duì)dalvik字節(jié)碼的自修改,更改了代碼的執(zhí)行流程,增加了代碼的迷惑性,證實(shí)了該方法在軟件保護(hù)領(lǐng)域?qū)鼓嫦蚬こ痰目尚行浴?/p> 本文分析了軟件逆向工程及其對(duì)抗,將研究點(diǎn)關(guān)注于增加代碼迷惑性和改變代碼執(zhí)行流程,在研究了APK安裝過程、dex文件結(jié)構(gòu)及JNI調(diào)用的基礎(chǔ)上,編寫了一個(gè)簡(jiǎn)單的示例代碼實(shí)現(xiàn)了自修改dalvik字節(jié)碼,并證實(shí)了該方案在軟件保護(hù)上的可用性和廣闊前景。 下一步主要有兩個(gè)方面的工作,一是采用更加成熟的方法實(shí)現(xiàn)字節(jié)碼寫入,以防止可能出現(xiàn)的內(nèi)存塊溢出;二是進(jìn)一步研究該方法在對(duì)抗軟件動(dòng)態(tài)分析方面的可行性。 [1] 360互聯(lián)網(wǎng)中心.2013年中國(guó)手機(jī)安全狀況報(bào)告[EB/OL].(2014-02-11).[2014-09-11].http://awhzfien7r.l5.yunpan.cn/lkl QPERX j6bcPGgA. [2] Android Police.Just How Bad Is App Piracy On Android Anyway? Hint: We’re Asking The Wrong Question[EB/OL].(2012-07-31).[2014-09-11].http://www.androidpolice.com/2012/07/31/editorial-just-how-bad-is-app-piracy-on-android-anyways-hint-were-asking-the-wrong-question/. [3] 360互聯(lián)網(wǎng)中心.2014年第一期中國(guó)移動(dòng)支付安全報(bào)告[EB/OL].(2014 -03-11).[2014-9-11].http://aqvs9knlja.l5.yanpan.cn/lk/Q4VgpLKMLV9Xq. [4] 伍景珠.基于Android平臺(tái)的軟件保護(hù)方案的研究與實(shí)現(xiàn)[D].北京:北京郵電大學(xué),2013. [5] Kanzaki Y,Monden A.Computer Software and Applications Conference[C].Dallas,USA:COMPSAC,2003. [6] 徐江凌.基于反跟蹤和自修改代碼技術(shù)的軟件保護(hù)系統(tǒng)設(shè)計(jì)[D].成都:電子科技大學(xué),2010. [7] 王祥根,司端鋒,馮登國(guó).一種基于自修改代碼技術(shù)的軟件保護(hù)方法[J].中國(guó)科學(xué)院研究生院學(xué)報(bào),2009,26(5):688-694. [8] 高兵,林果園,王瑩.基于代碼自修改的軟件反跟蹤技術(shù)結(jié)構(gòu)[J].信息網(wǎng)絡(luò)安全,2014(5):46-51. [9] Patrick Schulz.Android Security Analysis Challenge Tampering Dalvik Bytecode During Runtime[EB/OL].(2013-03-25).[2014-09-11].http://blog.bluebox.com/2013/03/25/android-security-analysis-challenge-tampering-dalvik-bytecode-during-runtime/. [10] 李興華.Java開發(fā)實(shí)戰(zhàn)經(jīng)典[M].北京:清華大學(xué)出版社,2009:576-606. [11] 馬建設(shè),趙雪紅,蘇萍,等.基于Android系統(tǒng)的視頻播放器開發(fā)[J].計(jì)算機(jī)應(yīng)用與軟件,2013,30(11):136-137,175. [12] 楊倩,楊明趙.Android顯示服務(wù)器——SurfaceFlinger研究[J].計(jì)算機(jī)應(yīng)用與軟件,2014,31(6):324-326. RESEARCH ON ANDROID SOFTWARE PROTECTION BASED ON SELF-MODIFYING BYTE CODE Gao Qi Liu Kesheng Chang Chao Qiu Shiwan (HefeiElectronicEngineeringInstitution,Hefei230037,Anhui,China) Along with the copyright infringement occurs continuously, to strengthen the protection of Android software has become a hot research topic. In this paper we carry out analysis and comment on software reverse engineering as well as its countermeasures, and point out the research focus. Aiming at reverse engineering of Android software, after studying APK installation principle and the format of DEX file, we employ the scheme of self-modifying Dalvik byte code during the operation of software to have effectively changed code execution process, and increased the perplexity of code. Through the experiment we realise the concealment of key software modules, and lead to the analyser failed in finding the correct code flow, this proves that the method has the feasibility in software protection field, and provides a new idea for software protection. Android Software protection Byte code Dex file Code self-modifying 2014-10-21。高琦,碩士生,主研領(lǐng)域:信息安全。劉克勝,教授。常超,博士生。邱世萬(wàn),碩士生。 TP311.54 A 10.3969/j.issn.1000-386x.2016.04.0544 結(jié) 語(yǔ)