1. 程式人生 > >重打包並通過java api hook來使簽名失效的工具demo分析

重打包並通過java api hook來使簽名失效的工具demo分析

0x00 背景

偶然在github上看到有人star了這個 https://github.com/xxxyanchenxxx/SigKill/blob/master/README.md
功能:一鍵繞過App簽名驗證。實現原理是Hook了PackaegManager,返回我們指定的簽名。

0x01 程式碼分析

實現手段就是重打包注入smali程式碼,hook應用內的簽名校驗方法。返回我們指定的簽名。

-1.0 通過keytool正常簽名的獲取方式:

C:\Users\Desktop                                                             
λ keytool -list -printcert -jarfile  android.helper.system-1
.apk 簽名者 #1: 簽名: 所有者: CN=Android Debug, O=Android, C=US 釋出者:
CN=Android Debug, O=Android, C=US 序列號: 1916b385 有效期開始日期: Tue Jan 13 22:26:20 GMT+08:00 2015, 截止日期: Wed Jan 13 22:26:20 GMT
+08:00 2016 證書指紋: MD5: 60:C9:08:38:FC:FA:2F:00:CE:88:7E:83:DC:23:56:E1 SHA1: 41:74:6C:63:3F:DF:51:47:EC:FD:A4:A9:EF:E0:AE:38:49:4D:29:57 SHA256: 54:79:FE:95:87:2B:03:4B:06:35:FA:C9:14:E6:73:7A:0C:4A:A5:36:5E:15:9A:4D:6B:8A:84:9C:DB:2B:77:5B 簽名演算法名稱: SHA256withRSA 版本: 3 擴充套件: #1: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: 87 57 7B B4 E1 23 98 73 B2 6F 67 A2 CC CA 92 C7 .W...#.s.og..... 0010: F6 77 84 BE .w.. ] ] C:\Users\Desktop λ echo 41:74:6C:63:3F:DF:51:47:EC:FD:A4:A9:EF:E0:AE:38:49:4D:29:57 | sed 's/://g' | tr '[:upper:]' '[:lower:]' 41746c633fdf5147ecfda4a9efe0ae38494d2957
  • 1.1我們先看看android程式是如何獲取自身簽名的:
/** 
 * 通過packageInfo.signatures獲取app簽名
 */  
public String getSignMd5Str() {  
    try {  
        PackageInfo packageInfo = mActivity.getPackageManager().getPackageInfo(mActivity.getPackageName(), PackageManager.GET_SIGNATURES);  
        Signature[] signs = packageInfo.signatures; 
        Signature sign = signs[0];  
        String signStr = encryptionMD5(sign.toByteArray());  
        return signStr;  
    } catch (PackageManager.NameNotFoundException e) {  
        e.printStackTrace();  
    }  
    return "";  
}  
  • 1.2我們從其注入的初試程式碼開始分析

第三步:在App的Application的attachBaseContext()函式中呼叫這行smali程式碼即可
smali: invoke-static {}, Lcom/yc/pm/SignatureKill;->kill()V


public class SignatureKill {
    public static void kill() {
        try {
            WebViewUpdateServiceStub.replaceService();
        }catch (Exception e){
            e.printStackTrace();
        }
        try {
            PackageManagerStub.replaceService();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

可以看到關鍵的函式就兩個
WebViewUpdateServiceStub.replaceService();和 PackageManagerStub.replaceService();

package com.yc.pm;

import android.content.pm.PackageInfo;
import android.os.IBinder;
import android.os.IInterface;
import android.util.Log;

import java.lang.reflect.Method;

/**
 * Created by yanchen on 18-1-28.
 */

public class PackageManagerStub extends MethodInvocationProxy<MethodInvocationStub<IInterface>> {
    private static String SERVICE = "package";

    public PackageManagerStub() {
        super(new MethodInvocationStub<>(getInterface()));
        init();

    }

    public static void replaceService(){
        PackageManagerStub serviceStub = new PackageManagerStub();
    }

    private static IInterface getInterface(){
        Object service =  Reflect.on("android.os.ServiceManager").
                call("getService",SERVICE).get();

        IInterface asInterface =  Reflect.on("android.content.pm.IPackageManager$Stub").call("asInterface",service).get();
        return asInterface;
    }

    private static IBinder getBinder(){
        return Reflect.on("android.os.ServiceManager").
                call("getService",SERVICE).get();
    }

    private void init(){
        addMethodProxy(new PackageManagerStub.GetPackageInfo());
        getBinder();

        try {
            BinderInvocationStub pmHookBinder = new BinderInvocationStub(getInvocationStub().getBaseInterface());
            pmHookBinder.copyMethodProxies(getInvocationStub());
            pmHookBinder.replaceService(SERVICE);
        }catch (Exception e){
            e.printStackTrace();
        }

        IInterface hookedPM = null;
        try {
            hookedPM = getInvocationStub().getProxyInterface();
            Object o = Reflect.on("android.app.ActivityThread").set("sPackageManager",hookedPM);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private static class GetPackageInfo extends MethodProxy {
        @Override
        public String getMethodName() {
            return "getPackageInfo";
        }

        @Override
        public Object call(Object who, Method method, Object... args) throws Throwable {
            PackageInfo result =  (PackageInfo)method.invoke(who,args);
            if(result != null){
                result.signatures = SignatureFake.getSignature();
            }
            return result;
        }
    }
}

可以看到通過反射替換來hook簽名 packageInfo.signatures的值。

總結:這類重打包注入程式碼的行為入侵性太強。如果能用VrituaApp 在VA的框架下進行hook。效果會好很多。

參考

https://www.jianshu.com/p/4f6d20076922 理解 Android Hook 技術以及簡單實戰
http://blog.csdn.net/manymore13/article/details/50717622 獲取apk簽名信息