重打包并通过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签名信息

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值