攻防:如何防止动态hook绕过jni签名校验

简介: 攻我们知道jni校验签名也不可靠,可以被动态hook绕过。代码如下:


我们知道jni校验签名也不可靠,可以被动态hook绕过。代码如下:


class HookSignHandler(var base : Any) : InvocationHandler {
    companion object{
        internal var signature = "xxx"
        fun hook(context: Context){
            try{
                var activityThreadClass = Class.forName("android.app.ActivityThread")
                var currentActicityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread")
                var currentActivityThread = currentActicityThreadMethod.invoke(null)
                var sPackageManagerField = activityThreadClass.getDeclaredField("sPackageManager")
                sPackageManagerField.isAccessible = true;
                var sPackageManager = sPackageManagerField.get(currentActivityThread)
                var iPackageManagerInterface = Class.forName("android.content.pm.IPackageManager")
                var proxy = Proxy.newProxyInstance(iPackageManagerInterface.classLoader, arrayOf(iPackageManagerInterface), HookSignHandler(sPackageManager))
                sPackageManagerField.set(currentActivityThread, proxy)
                var pm = context.packageManager
                var mPMField = pm.javaClass.getDeclaredField("mPM")
                mPMField.isAccessible = true
                mPMField.set(pm, proxy)
            }
            catch (e : Exception){
                Log.e("hook", "hook", e)
            }
        }
    }
    override fun invoke(proxy: Any?, method: Method, args: Array<out Any>): Any {
        if("getPackageInfo".equals(method.name)){
            ...
        }
        return method.invoke(base, *args)
    }
}
复制代码


只要得到了签名的signature,并且在application中添加


HookSignHandler.Companion.hook(this);
复制代码


这时无论java层还是jni层,当获取getPackageManager()时,它的mPM都是已经被代理的对象,这样当执行getPackageInfo()函数(实际上是执行mPM的对应函数)就会返回设置好的signature,而不是当前app的签名,这样就绕过了。



那么怎么防止这种手段? 那就是每次使用getPackageManager()时都检查一下它是否被代理。代码如下:


try {
    Field mPM = getPackageManager().getClass().getDeclaredField("mPM");
    mPM.setAccessible(true);
    if(Proxy.isProxyClass(mPM.get(getPackageManager()).getClass())){
        Toast.makeText(this, "hook!!", Toast.LENGTH_LONG).show();
    }
} catch (Exception e) {
    e.printStackTrace();
}
复制代码


Proxy本身提供了一个函数isProxyClass来检查当前对象的类是否是代理类。

我们将mPM对象获取到,用isProxyClass验证它的class即可。

那么这个这就涉及到了动态代理proxy的原理了。


动态代理


首先,动态代理一定需要一个接口,就是说代理的类必须实现某个接口,否则无法代理该类。比如上面的mPM就是实现接口android.content.pm.IPackageManager

这是为什么?这也与动态代理的原理有关。

简单来说,当我们设置动态代理后,实际上会自动生成一个类


public final class $Proxy0 extends Proxy implements XXXXX
{
    public $Proxy0(InvocationHandler paramInvocationHandler) throws 
    {
        super(paramInvocationHandler);
    }
 ...
}
复制代码


这样就一下子清晰了,因为实现了同一个接口,所以可以设置给原对象而不产生问题。

但是它又继承了Proxy类,而且可以看到构造函数中将之前创建的InvocationHandler也传进来了,这样就可以调用到原对象的函数了。


它的详细代码就不展示和一一解释了,简单来说就是它实现了接口,在每个函数中再去执行InvocationHandler的invoke,就实现了代理。


这也是为什么动态代理一定需要一个接口的原因。


Proxy.newProxyInstance()函数就是创建一个$Proxy0这个类的对象,然后设置给原对象,就代理上了。

那么isProxyClass的原理就清晰了,我们只要知道这个对象是不是继承Proxy即可。代码:


public static boolean isProxyClass(Class<?> cl) {
    return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
}
复制代码


可以看到使用了isAssignableFrom,那么再来说一说这个函数。


isAssignableFrom和instanceof

这两个作用类似,从例子上看:B extends A

A.class.isAssignableFrom(B.class);  表示A是B的父类,注意两边都是Class

b instanceOf A  判断A是否是b对象的类。这里b是B类的对象。A是B的父类,所以也一样是b对象的类


目录
相关文章
|
6月前
|
JSON 小程序 数据安全/隐私保护
小程序动态调试-解密加密数据与签名校验
本文主要讲解微信小程序加密、验签的情况下如何进行动态调试已获取签名以及加密信息
|
3月前
|
IDE 测试技术 API
使用京东API接口适用于的环境及验证调用合法性的方法
在电商领域,京东API接口支持商品信息查询、订单处理等功能。开发者需确保在稳定服务器端环境使用,选择合适编程语言及框架,并具备足够网络带宽处理能力。开发环境应配备IDE或代码编辑器及所需库。测试环境需充分验证API稳定性与可靠性。合法性验证包括:正确使用App Key和App Secret进行鉴权;掌握签名规则并在请求中添加签名;遵守请求频率限制;理解并遵循数据使用协议。遵循这些指导原则可保证API调用的合法性和稳定性。
|
5月前
|
开发框架 Java .NET
WAF攻防-权限控制&代码免杀&异或运算&变量覆盖&混淆加密&传参
WAF攻防-权限控制&代码免杀&异或运算&变量覆盖&混淆加密&传参
|
4月前
|
移动开发 JavaScript
thinkPHP5.0开发微信H5页面分享接口signature验证失败,signature与微信 JS 接口签名校验工具返回结果不一致
thinkPHP5.0开发微信H5页面分享接口signature验证失败,signature与微信 JS 接口签名校验工具返回结果不一致
84 0
|
6月前
|
算法 Android开发
安卓逆向 -- 绕过SO层签名验证
安卓逆向 -- 绕过SO层签名验证
150 1
|
6月前
|
存储 安全 Android开发
Android安全启动学习(三):AVB校验的内容、怎么校验、AVB的作用
Android安全启动学习(三):AVB校验的内容、怎么校验、AVB的作用
508 0
|
11月前
|
Python
关于SSTI模块注入的常见绕过方法
关于SSTI模块注入的常见绕过方法
225 0
|
JavaScript 程序员 数据安全/隐私保护
gojoy参数的生成过程,反调试,以及混淆js
该文章主要提供交流学习使用,请勿利用其进行不当行为! 如本篇文章侵犯了贵公司的隐私,请联系我立刻删除!
87 0
|
安全 Windows
4.4 x64dbg 绕过反调试保护机制
在Windows平台下,应用程序为了保护自己不被调试器调试会通过各种方法限制进程调试自身,通常此类反调试技术会限制我们对其进行软件逆向与漏洞分析,我们以第一种`IsDebuggerPresent`反调试为例,该函数用于检查当前程序是否在调试器的环境下运行。函数返回一个布尔值,如果当前程序正在被调试,则返回True,否则返回False。函数通过检查特定的内存地址来判断是否有调试器在运行。具体来说,该函数检查了`PEB(进程环境块)`数据结构中的`_PEB_LDR_DATA`字段,该字段标识当前程序是否处于调试状态。如果该字段的值为1,则表示当前程序正在被调试,否则表示当前程序没有被调试。
305 0
4.4 x64dbg 绕过反调试保护机制