<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

                    原文地址:http://drops.wooyun.org/mobile/4296

                    0x01 Android簽名機制


                    將APK重命名為zip文件,然后可以看到有個META-INF的文件夾,里面有三個文件,分別名為MANIFEST.MF、CERT.SF和CERT.RSA,這些就是使用signapk.jar生成的簽名文件。

                    1、 MANIFEST.MF文件:

                    程序遍歷update.apk包中的所有文件(entry),對非文件夾非簽名文件的文件,逐個生成SHA1的數字簽名信息,再用Base64進行編碼。具體代碼見這個方法:

                    #!java
                    private static Manifest addDigestsToManifest(JarFile jar)
                    

                    關鍵代碼是

                    #!java
                    for (JarEntry entry: byName.values()) {
                         String name = entry.getName();
                         if (!entry.isDirectory() && !name.equals(JarFile.MANIFEST_NAME) &&
                             !name.equals(CERT_SF_NAME) && !name.equals(CERT_RSA_NAME) &&
                             (stripPattern == null ||!stripPattern.matcher(name).matches())){
                             InputStream data = jar.getInputStream(entry);
                             while ((num = data.read(buffer)) > 0) {
                             md.update(buffer, 0, num);
                           }
                           Attributes attr = null;
                           if (input != null) attr = input.getAttributes(name);
                           attr = attr != null ? new Attributes(attr) : new Attributes();
                           attr.putValue("SHA1-Digest", base64.encode(md.digest()));
                           output.getEntries().put(name, attr);
                        }
                    }
                    

                    之后將生成的簽名寫入MANIFEST.MF文件。關鍵代碼如下:

                    #!java
                    Manifest manifest = addDigestsToManifest(inputJar);
                    je = new JarEntry(JarFile.MANIFEST_NAME);
                    je.setTime(timestamp);
                    outputJar.putNextEntry(je);
                    manifest.write(outputJar);
                    

                    2、 生成CERT.SF文件:

                    對前一步生成的Manifest,使用SHA1-RSA算法,用私鑰進行簽名。關鍵代碼如下:

                    #!java
                    Signature signature = Signature.getInstance("SHA1withRSA");
                    signature.initSign(privateKey);
                    je = new JarEntry(CERT_SF_NAME);
                    je.setTime(timestamp);
                    outputJar.putNextEntry(je);
                    writeSignatureFile(manifest,
                    new SignatureOutputStream(outputJar, signature));
                    

                    3、 生成CERT.RSA文件:

                    生成MANIFEST.MF沒有使用密鑰信息,生成CERT.SF文件使用了私鑰文件。那么我們可以很容易猜測到,CERT.RSA文件的生成肯定和公鑰相關。 CERT.RSA文件中保存了公鑰、所采用的加密算法等信息。核心代碼如下:

                    #!java
                    je = new JarEntry(CERT_RSA_NAME);
                    je.setTime(timestamp);
                    outputJar.putNextEntry(je);
                    writeSignatureBlock(signature, publicKey, outputJar);
                    

                    在程序中獲取APK的簽名時,通過signature方法進行獲取,如下:

                    #!java
                    packageInfo = manager.getPackageInfo(pkgname,PackageManager.GET_SIGNATURES);
                    signatures = packageInfo.signatures;
                    for (Signature signature : signatures) {
                        builder.append(signature.toCharsString());
                    }
                    signature = builder.toString();
                    

                    所以一般的程序就是在代碼中通過判斷signature的值,來判斷APK是否被重新打包過。

                    0x02 簽名繞過方式


                    在講簽名繞過的方式前,需要先明確DEX校驗和簽名校驗:

                    1.將apk以壓縮包的形式打開刪除原簽名后,再簽名,安裝能夠正常打開,但是用IDE(即apk改之理,會自動反編譯dex)工具二次打包,卻出現非正常情況的,如:閃退/彈出非正版提示框。可以確定是dex文件的校驗

                    2、將apk以壓縮包的形式打開刪除原簽名再簽名,安裝之后打開異常的,則基本可以斷定是簽名檢驗。如果在斷網的情況下同樣是會出現異常,則是本地的簽名檢驗;如果首先出現的是提示網絡沒有連接,則是服務器端的簽名校驗.

                    2.1.Java層校驗

                    獲取簽名信息和驗證的方法都寫在android的java層。實例如下:

                    1、使用APKIDE反編譯APK,不做任何操作,然后直接回編譯,安裝后運行,提示如下:

                    enter image description here

                    2、在APKIDE中搜索signatures(或者搜索錯誤提示),定位到簽名驗證的代碼處。

                    enter image description here

                    3、此處就是獲取簽名的,然后找程序判斷簽名的地方,進行修改,如下圖,if-nez是進行判斷的地方,將ne修改為eq。即if-eqz v2, :cond_0。則程序就可以繞過本地的簽名交易。

                    enter image description here

                    enter image description here

                    2.2.NDK校驗

                    將關鍵代碼放到so中,在底層獲取簽名信息并驗證。因為獲取和驗證的方法都封閉在更安全的so庫里面,能夠起到一定意義上的保護作用。實例如下:

                    1、使用APKIDE反編譯APK,不做任何操作,然后直接回編譯,安裝后運行,程序直接退出,無任何提示。

                    2、在APKIDE中搜索signatures(或者搜索錯誤提示),定位到簽名驗證的代碼處。

                    enter image description here

                    3、使?用JD-GUI打開AppActivity,可以看到,此處是獲取包名,然后進?行MD5計算。

                    enter image description here

                    4.在程序中搜索getSignature,發現并沒有調?用此函數的地?方,猜測在so?文件中,搜索loadLibrary。

                    enter image description here

                    5.在代碼中可以查找,可以找到調?用的是libcocos2dcpp.so

                    6.使?用IDA打開libcocos2dcpp.so,然后搜索getSiganture,找到調?用此函數的地方。

                    enter image description here

                    從代碼中可以看到,此函數調?用了org.cocos2dx.cpp.AppActivity.getSignature

                    enter image description here

                    7、查看F5代碼,發現此函數是判斷簽名的函數,然后我們雙擊此函數的調?者,部分代碼如下。

                    enter image description here

                    8、從上圖可以看出,只需要修改BEQ loc_11F754,讓其不跳轉到jjni——>error,就可以繞過簽名校驗。 查看HEX,使?010editor跳到0011F73E,修改D0為D1。成功繞過簽名校驗。

                    enter image description here

                    2.3.服務器驗證

                    在android的java層獲取簽名信息,上傳服務器在服務端進行簽名然后返回驗證結果。

                    如下圖,網絡驗證時,如果網絡沒連接,一般都會提示錯誤。

                    enter image description here

                    既然是網絡驗證,肯定要把驗證信息發送到服務端,然后進行驗證,先看個簡單的實例,下次會有個難度大的。

                    1、手機配置好抓包,然后抓包。第一種圖是正常的APK的時候的數據包,第二個圖是反編譯的APK的數據包,通過對比,發現cookie中的public_key不一樣,那么我們替換一下,發現可以正常使用APK的功能了。

                    enter image description here

                    enter image description here

                    2、將正確的public_key添加到APK中。打開反編譯的代碼,搜索signatures,定位到簽名的代碼。

                    enter image description here

                    可以看到,代碼將signatures的值傳遞到V4中,然后傳遞到Utils->mPublicKey函數中,于是我們將正確的public_key傳給V4。

                    enter image description here

                    然后重新打包,重新安裝就可以了。

                    0x03.總結


                    java層的校驗很容易就可以破解掉,在so層實現校驗相對來說分析會更難點,而網絡驗證,如果僅僅是字符串的比較,那么也很容易破解掉。

                    碼子碼的太累了。。

                    后面還有幾篇正在寫的文章,包括so分析等等。

                    摘抄: http://www.blogjava.net/zh-weir/archive/2011/07/19/354663.html

                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频