本發(fā)明涉及一種android應(yīng)用加固方法,屬于信息安全技術(shù)領(lǐng)域。
背景技術(shù):
從谷歌2007年推出android系統(tǒng)至今,android市場(chǎng)飛速發(fā)展,但android平臺(tái)編譯生成的應(yīng)用apk極易受到攻擊。攻擊者通過(guò)反編譯、逆向工程等技術(shù)破解android應(yīng)用,竊取應(yīng)用代碼和用戶(hù)數(shù)據(jù),給應(yīng)用使用帶來(lái)很多不安全因素。因此,針對(duì)android系統(tǒng)的防逆向就非常重要。通過(guò)對(duì)應(yīng)用的加固,達(dá)到保護(hù)應(yīng)用代碼、反破解、反逆向、反植入等目的,從而保障android應(yīng)用的原生性和完整性。
從android2.3開(kāi)始,代碼混淆技術(shù)開(kāi)始使用。通過(guò)混淆源java代碼或者smali文件等方式。代碼混淆在一定程度上減低了代碼的可讀性,保護(hù)了代碼,可以抵抗對(duì)應(yīng)用代碼的靜態(tài)分析,但是不能抵抗反編譯或調(diào)試攻擊,實(shí)際加固效果較差。
軟件加殼技術(shù)是android加固技術(shù)中重要的一項(xiàng)。軟件加殼對(duì)源程序進(jìn)行壓縮或者加密。應(yīng)用程序運(yùn)行時(shí),首先運(yùn)行殼程序,對(duì)被壓縮或加密的源程序進(jìn)行解壓縮或解密,還原出源程序并加載至內(nèi)存執(zhí)行。隨著對(duì)android應(yīng)用和脫殼技術(shù)的研究,簡(jiǎn)單的壓縮或者加密以及很難抵抗外在攻擊,加固比較容易被突破。但過(guò)于復(fù)雜的加密也會(huì)減低程序的運(yùn)行效率。軟件加殼隱藏了應(yīng)用程序源代碼,有效地保護(hù)了應(yīng)用程序。但“殼”程序自身也需要保護(hù),防止被攻擊者攻擊。
技術(shù)實(shí)現(xiàn)要素:
本發(fā)明的目的是為了保護(hù)android應(yīng)用程序,保護(hù)應(yīng)用不被靜態(tài)和動(dòng)態(tài)分析,克服現(xiàn)有加固方法的不足,提出一種android應(yīng)用加固方法,對(duì)應(yīng)用程序代碼進(jìn)行加密,對(duì)關(guān)鍵部分代碼二次加密,實(shí)現(xiàn)保護(hù)應(yīng)用代碼與運(yùn)行安全目的。
本發(fā)明的設(shè)計(jì)原理為:本發(fā)明涉及一種android應(yīng)用加固方法,屬于信息安全技術(shù)領(lǐng)域。本發(fā)明包括代碼加密、動(dòng)態(tài)防御、完整性校驗(yàn)、動(dòng)態(tài)加載四個(gè)模塊。加密過(guò)程對(duì)android應(yīng)用程序class.dex加密,對(duì)核心代碼二次加密,并對(duì)加密后的簽名認(rèn)證,將加密的結(jié)果嵌入資源文件。動(dòng)態(tài)防御過(guò)程,檢測(cè)調(diào)試器和模擬器,檢測(cè)到被調(diào)試或運(yùn)行在模擬器中退出應(yīng)用程序。開(kāi)啟子進(jìn)程,子進(jìn)程和主進(jìn)程相互ptrace監(jiān)控,子進(jìn)程循環(huán)檢測(cè)調(diào)試器和模擬器,被調(diào)試則結(jié)束進(jìn)程。完整性檢測(cè)模塊,認(rèn)證簽名信息,防止資源和代碼被篡改。代碼解密模塊提取隱藏在圖片中的加密信息,解密得到中間數(shù)據(jù),對(duì)其中的核心代碼部分二次解密,將解密后的結(jié)果直接加載至內(nèi)存執(zhí)行。
本發(fā)明的技術(shù)方案是通過(guò)如下步驟實(shí)現(xiàn)的:
步驟1,應(yīng)用程序加密時(shí),解壓需要保護(hù)的android應(yīng)用apk文件,獲取代碼文件classes.dex,提取classes.dex中核心的方法代碼,采用對(duì)稱(chēng)加密方法加密核心代碼得到加密數(shù)據(jù),將加密數(shù)據(jù)添加特殊起止標(biāo)志位后,替換class.dex中關(guān)鍵代碼,生成新的dex文件。
步驟2,設(shè)定另一密鑰k2,將步驟1中生成的dex文件加密,將加密后的文件嵌入資源文件。
步驟3,對(duì)嵌入后的資源文件做簽名,將兩次加密密鑰k1、k2,簽名驗(yàn)證信息和解密程序、文件提取程序存入到so文件中,重新打包應(yīng)用程序,簽名生成新的apk文件。
步驟4,動(dòng)態(tài)防御。應(yīng)用程序運(yùn)行時(shí),主進(jìn)程檢測(cè)當(dāng)前系統(tǒng)運(yùn)行環(huán)境是否為模擬器或調(diào)試機(jī)、當(dāng)檢測(cè)到運(yùn)行在模擬器和調(diào)試機(jī)、直接退出程序運(yùn)行;主進(jìn)程fork出子進(jìn)程,主進(jìn)程和子進(jìn)程相互ptrace監(jiān)控;子進(jìn)程定時(shí)檢測(cè)調(diào)試機(jī)和模擬器,檢測(cè)到應(yīng)用正在被調(diào)試,子進(jìn)程退出,主進(jìn)程監(jiān)控到子進(jìn)程已退出時(shí),退出應(yīng)用程序。
步驟5,完整性檢測(cè)。提取so文件中的簽名信息、驗(yàn)證簽名信息是否正確。
步驟6,動(dòng)態(tài)加載。應(yīng)用程序運(yùn)行時(shí),提取資源文件中的加密文件和so庫(kù)中的密鑰k1、k2,利用k2對(duì)加密文件解密,得到中間代碼,定位到關(guān)鍵代碼加密位置,提取關(guān)鍵代碼的加密數(shù)據(jù),利用k1對(duì)關(guān)鍵代碼解密,獲取原始class.dex代碼,加載至內(nèi)存。
有益效果
相比于現(xiàn)有的代碼混淆加固方法,代碼只是增加了代碼看閱讀難度,代碼保護(hù)程度較弱,本發(fā)明對(duì)代碼進(jìn)行加密,能夠更好的保護(hù)代碼。
相比于軟件加殼的加固方法,本發(fā)明對(duì)普通的代碼一次加密,對(duì)關(guān)鍵代碼二次加密,有效地保護(hù)了代碼,特別是關(guān)鍵代碼的保護(hù)。同時(shí)將加密的結(jié)果和密鑰通過(guò)水印的方式嵌入圖片,保護(hù)了加密結(jié)果。
附圖說(shuō)明
圖1為本發(fā)明一種android應(yīng)用加固方法原理圖;
圖2為應(yīng)用加密模塊流程圖;
圖3為動(dòng)態(tài)防御模塊主進(jìn)程檢測(cè)流程圖;
圖4為動(dòng)態(tài)防御模塊子進(jìn)程檢測(cè)流程圖;
圖5為應(yīng)用解密模塊流程圖。
具體實(shí)施方式
為了更好的說(shuō)明本發(fā)明的目的和優(yōu)點(diǎn),下面結(jié)合實(shí)施例對(duì)本發(fā)明方法的實(shí)施方式做進(jìn)一步詳細(xì)說(shuō)明。
具體流程為:
步驟1,關(guān)鍵代碼加密。
步驟1.1,提取android應(yīng)用apk壓縮文件中的classes.dex文件。
步驟1.2,定位核心代碼,核心代碼部分包括:程序activity、service生命周期代碼,程序登錄等涉及密鑰與驗(yàn)證的代碼、程序核心算法代碼。分別提取各段核心代碼。
步驟1.3,采用密鑰k1,對(duì)每塊關(guān)鍵代碼進(jìn)行aes加密。
步驟1.4,將各段加密后的代碼加上起止標(biāo)識(shí)位,替換原代碼,重新計(jì)算dex文件長(zhǎng)度和校驗(yàn)值。
步驟2,dex文件加密。
步驟2.1,對(duì)步驟1生成的dex,使用密鑰k2加密,將加密結(jié)果嵌入資源文件。
步驟2.2,將嵌入加密結(jié)果的資源文件利用hmac-md5簽名校驗(yàn),簽名密鑰使用k1+k2(字符串拼接),hash校驗(yàn)值、兩次加密密鑰k1、k2和用于提取資源文件中的代碼、解密代碼存儲(chǔ)到so文件中。
步驟3修改androidmanifest.xml中application,將apk資源文件和自定義的殼dex文件和so文件重新打包和簽名、生成新的apk文件。
步驟4動(dòng)態(tài)防御。
步驟4.1,通過(guò)proc文件系統(tǒng)讀取/proc/pid/status文件就存儲(chǔ)了進(jìn)程號(hào)為pid的進(jìn)程狀態(tài),定時(shí)檢測(cè)/proc/pid/status中的tracerpid,若該字段不為0時(shí)表示調(diào)試進(jìn)程的pid,若檢測(cè)到tracerpid不為0,則應(yīng)用正在被調(diào)試。調(diào)試應(yīng)用時(shí),應(yīng)用程序運(yùn)行在虛擬中。相比于真實(shí)設(shè)備,虛擬機(jī)存在一些特殊的文件,/system/bin/qemu-props,/system/lib/libc_malloc_debug_qemu.so文件和目錄/sys/qemu_trace,分別檢測(cè)這三個(gè)文件或目錄是否存在,若存在,則認(rèn)為運(yùn)行在模擬器中。當(dāng)檢測(cè)到被調(diào)試或運(yùn)行在模擬器中,則直接殺死主進(jìn)程,退出應(yīng)用程序。
步驟4.2,使用fork函數(shù)fork出子進(jìn)程,主進(jìn)程和子進(jìn)程分別調(diào)用ptrace,相互監(jiān)控。子進(jìn)程利用pipe管道通信向主進(jìn)程注入一段字符串,主進(jìn)程讀取子進(jìn)程注入消息,當(dāng)一定時(shí)間內(nèi)沒(méi)有讀取到字符串,則子進(jìn)程啟動(dòng)異常,直接退出應(yīng)用程序
步驟4.3子進(jìn)程循環(huán)檢測(cè)調(diào)試機(jī)和模擬器。利用步驟4.1方法檢測(cè)是否被調(diào)試。另外,當(dāng)使用ida調(diào)試應(yīng)用時(shí),android_server監(jiān)聽(tīng)23946端口。檢測(cè)/proc/net/tcp文件,當(dāng)23946端口正在被android_server占用時(shí),檢測(cè)到應(yīng)用正在被ida調(diào)試。當(dāng)利用ida調(diào)試器來(lái)過(guò)反調(diào)試時(shí),采取的方式是單步調(diào)試。相比于正常運(yùn)行,單步調(diào)試的運(yùn)行速度要慢的多,正常代碼指令的速度一般在1000ms,檢測(cè)代碼執(zhí)行的時(shí)間,設(shè)定經(jīng)驗(yàn)閾值2000ms,當(dāng)時(shí)間間隔超過(guò)閾值,則認(rèn)為正在被反調(diào)試。通過(guò)以上流程,當(dāng)檢測(cè)到被反調(diào)試時(shí),子進(jìn)程退出,主進(jìn)程在監(jiān)控到子進(jìn)程已經(jīng)退出時(shí),直接退出應(yīng)用程序。
步驟5,完整性檢測(cè)。使用jni(javanativeinterface)調(diào)用機(jī)制訪問(wèn)so庫(kù)文件,提取so文件中的k1和k2以及簽名校驗(yàn)值,利用k1+k2計(jì)算包含加密結(jié)果的資源文件的hmac-md5值,比較so文件中的簽名校驗(yàn)值,如果兩個(gè)值不同,則應(yīng)用代碼遭到篡改,退出應(yīng)用程序。
步驟6,動(dòng)態(tài)加載。
步驟6.1,從資源文件中提取被加密的原始dex文件
步驟6.2,提取密鑰k2,對(duì)步驟5.1提取加密,得到中間結(jié)果。
步驟6.3,提取密鑰k1,掃描中間結(jié)果,發(fā)現(xiàn)標(biāo)識(shí)字符串0x6d61696e0x76312e30,讀取接下來(lái)的8位字符長(zhǎng)度以及長(zhǎng)度對(duì)于的二進(jìn)制流,利用k1對(duì)提取出的二進(jìn)制流解密,將解密結(jié)果替換中間結(jié)果中的包括標(biāo)識(shí)字符串、長(zhǎng)度和二進(jìn)制流部分。掃描整個(gè)中間結(jié)果,使用dexclassloader類(lèi)加載器將解密出的二進(jìn)制代碼直接加載到內(nèi)存,不生成中間文件,完成解密工作。
以上所述的具體描述,對(duì)發(fā)明的目的、技術(shù)方案和有益效果進(jìn)行了進(jìn)一步詳細(xì)說(shuō)明,所應(yīng)理解的是,以上所述僅為本發(fā)明的具體實(shí)施例而已,并不用于限定本發(fā)明的保護(hù)范圍,凡在本發(fā)明的精神和原則之內(nèi),所做的任何修改、等同替換、改進(jìn)等,均應(yīng)包含在本發(fā)明的保護(hù)范圍之內(nèi)。