Android5.1.1 - APK簽名校驗分析和修改源碼繞過簽名校驗


Android5.1.1 - APK簽名校驗分析和修改源碼繞過簽名校驗

作者:尋禹@阿里聚安全


 

APK簽名校驗分析

找到PackageParser類,該類在文件“frameworks/base/core/java/android/content/pm/PackageParser.java”中。PackageParser類的collectCertificates方法會對APK進行簽名校驗,在該方法會遍歷APK中的所有文件,並對每個文件進行校驗。下面是該方法的部分源碼:

APK是一個ZIP格式的文件所以使用ZIP相關的類進行讀寫。上面代碼中調用了loadCertificates方法,這個方法返回一個二維數組,如果APK中的文件簽名校驗失敗那么loadCertificates方法會返回一個空數組(可能是null,可能是數組長度為0),按照上面代碼的邏輯如果數組為空則會拋出異常。

loadCertificates方法的代碼見下:

上面代碼中is是JarFile.JarFileInputStream類的對象。loadCertificates方法中調用了readFullyIgnoringContents方法,在readFullyIgnoringContents方法中會調用JarFile.JarFileInputStream.read方法讀取APK中一項的數據,在read方法中會校驗讀取到的數據項的簽名,如果簽名校驗失敗,則會拋出SecurityException類型的異常,即簽名校驗失敗。

JarFile類在“libcore/luni/src/main/java/java/util/jar/JarFile.java”文件中。

上面代碼中調用了StrictJarFile.getCertificateChains方法,下面是它的代碼:

上面代碼中isSigned的值是這么來的:

當證書讀取成功,並且當前APK經過了簽名,則isSigned為true。

回到StrictJarFile.getCertificateChains方法中,當isSigned為true時會調用JarVerifier.getCertificateChains方法,下面是它的代碼:

下面是類成員變量verifiedEntries的聲明:

verifiedEntries是一個鍵值對,鍵是APK中經過了簽名的文件名,如:classes.dex文件,值是證書數組。如果向已經簽過名的APK中新添加一個文件然后安裝這個APK,當程序邏輯執行到JarVerifier.getCertificateChains方法中時,在verifiedEntries變量中無法找到新添加的文件名(因為這個新文件是在APK簽名之后添加),那么JarVerifier.getCertificateChains方法將返回null。


 

繞過簽名校驗

源碼修改點一

找到PackageParser.loadCertificates方法,下面是部分源碼:

將上面代碼catch塊中的throw語句替換為:return null;

下面是修改后的代碼:

代碼修改完后,當APK中文件簽名校驗失敗時不會拋出異常,APK還會繼續安裝。

源碼修改點二

找到PackageParser.collectCertificates方法,找到代碼中調用loadCertificates方法的地方:

將上面的throw語句替換為:continue;

修改后的代碼:

代碼修改完后,當遇到APK中沒有經過簽名的文件時不會拋出異常,APK還會繼續安裝。

 

作者:尋禹@阿里聚安全,更多技術文章,請訪問阿里聚安全博客


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM