7种Android Native Anti Hook的实现思路
2019-10-04 15:56:25 Author: bbs.pediy.com(查看原文) 阅读量:266 收藏

[原创]7种Android Native Anti Hook的实现思路

1天前 603

[原创]7种Android Native Anti Hook的实现思路

(1) GOT_HOOK

(2) LDPRELOAD_HOOK

(3) INLINE_HOOK

(4) 异常HOOK

(5) ELF依赖库篡改注入

(6) LINKER_HOOK 

(7) UNICOR仿真器HOOK

(8) 实现代码

···HOOK原理 ··· :

篡改导入表中存储的,外部符号地址。

··· 检测手段 ··· :

(1)硬编码记录导入符号在外部SO中的偏移值,计算外部SO的模块基址相加后得到地址,与GOT表项值进行对比。

(缺点是外部SO可能更新地址发生变化)

(2)将硬编码改为动态解析,使用dlsmy()函数或自己实现地址解析后得到地址,与GOT表项值对比。

(没有第一种的缺点,灵活一些)

(3)一般在链接后GOT表值不会发生改变,可在初始化完成时,使用前面两个方法逐个校验,然后整体计算此时的GOT表的HASH值,

在后期运行时进行HASH校验。

(相比逐个校验,提高了执行效率、代码动作更小、增加了隐蔽性,甚至还可选择MD5 CRC以外的迷你HASH、或跳跃字节校验HASH)

··· 实现 ··· :

有了GOT项下标,符号名,所属库名,再过滤出哪些需要检测的重点GOT项,即可实现检测。

    STRUCT GOT{
        gotitem;                    // GOT项下标(预设)
        libname;                    // GOT项所属模块(预设)
        elfhash_sym_name;           // GOT项符号名(ELFHASH)(预设)
        gotitem;                    // GOT项内容(运行实时计算)
        sym_addr;                   // 手动解析获取的符号虚拟地址(运行实时计算)
    }GOT;

··· HOOK原理 ··· :

我没有实际测试过这种HOOK,

但可以想到,当导入了虚假的导入函数,GOT表项值会和真正的值不同

和GOT_HOOK表现的结果差不多。

··· 检测手段 ··· :

这样的话,检测LDPRELOAD_HOOK就类似检测GOT_HOOK

可以使用检测GOT时的第一种硬编码方法,

记录导入函数在导入SO中的偏移量然后加基址进行校验。

对于无法获取硬编码偏移量的系统库呢,

比如导入了虚假的fopen什么的,

我觉得可以预设一个重点库重点函数名单

比如弄一个libc.so的IO之类的高频函数列表,

手动算偏移来解决。

··· HOOK原理 ··· :

通过篡改函数的指令内容实现,

应该是最为通用有效的HOOK手段,

可以想到,通常的HOOK框架与工具,

最后应该都会通过这种原理来实现。

去检测框架特征肯定不如检测INLINE_HOOK有效,

就是搞起来会比较麻烦。

··· 检测手段 ··· : 

计算一份函数体的HASH,运行时/调用前/对被调函数做完整性校验。

原理并不复杂,但实际工程有很繁琐的问题,场景对灵活性要求很多,

例如:

A : 怎么确定哪些函数需要做HASH检测?

(人为设定?静态分析?动态沙箱统计?)

C : 什么时机做检测?如何在没有源代码的情况下插入检测代码,做到运行时每次调用前都会执行校验逻辑?

( 方案: 基于静态动态分析的结果进行HOOK?或者直接VMP?)

B : 这些函数有的是非导出没有符号或是C++名称粉碎的,怎么获取它们的地址范围?

( 方案: 全部函数都计算HASH一把梭?)

D : 如何跟壳与进行结合?

( 方案: 例如VMP?)

E:  准备的函数HASH数据存储在哪?

( 方案: 把检测逻辑单独写成一个库,HASH数据也放库里?放在外部配置文件中?在被检测库开辟的BUFFER中?)

F:  系统库没法提前知道HASH,被INLINE_HOOK了怎么检测?

( 方案: 把导入库的libcso符号替换为自己静态编译的libc内容?预设一份高频系统库函数名单在函数体中查跳转特征?)

G:  被检测的库更新了怎么办?

··· 实现 ··· : 

基础的信息是函数所属库名称、函数的起始结束地址、函数得HASH值


STRUCT FUNC{     libname;   // 所属模块(预设)     head;      // 函数起始偏移(预设)     end;       // 函数结束偏移(预设)     filehash;  // 函数哈希(预设)     md_base;   // 所属模块基址(运行时计算)     addr;      // 函数虚拟地址(运行时计算) }FUNC;

··· HOOK原理 ··· :

我没有实际测试过这种HOOK手段,

不过看到异常HOOK也会篡改函数指令内容,

所以检测异常HOOK可以使用检测INLINE_HOOK的方式,

应该是这样的。

··· HOOK原理 ··· :

修改ELF中的DYNAMIC结构,

添加一个DT_NEEDED,

从而增加额外的导入SO

··· 检测手段 ··· : 

篡改内容的这种,都可以做完整性校验。

也是提前计算好SO的关键区段的HASH,

运行时再次计算来对比,校验时机的问题,和INLINE_HOOK类似。

(感觉吧被注入这种事避免不了的,

别人HOOK我的代码还能检测检测,

别人想往进程里加载SO这个机会可太多了,

不改ELF也有N种方法,没什么办法

这里还有说一些额外的内容,

我们既然篡改DYNAMIC区段可以实现一些功能,

类似的,其他区段是不是也有薄弱的地方,

是不是也可以篡改它们实现某些功能?

有没有必要做一些校验和保护。

比如:

···函数调用这个流程不仅有GOT表,还有PLT表,

保护加固校验了GOT表和INLINE,那CRACKER从PLT表下手行不行?

···HASH表也在函数调用流程中, 

CRACKER改一下HASH表是不是也能实现HOOK的功能?

···INIT_ARRAY也在流程中,这块是不是也可以实现一些意想不到得功能?

···REL表修改了是不是能凭空添加一个导入函数?

··· 实现 ··· : 

struct {
    SEC dynsym;
    SEC dynstr;
    SEC hash;
    SEC reldyn;
    SEC relplt;
    SEC plt;
    SEC arm_extab;
    SEC arm_exidx;
    SEC rodata;
}LOAD1;
struct {
    SEC fini_array;
    SEC init_array;
    SEC dynamic;
}LOAD2;

··· HOOK原理 ···

我没有实际测试过这种HOOK手段,

不过可以脑补一下,

LINKER_HOOK能做什么,

应该可以控制GOT表内容,

可以添加与HOOK导入函数,

还有一些dlopen()相关的事。

··· 检测手段 ··· : 

CRACKER要对LINKER动手脚,

暂时我也没有想到什么好的办法,

对于GOT表相关的,

还是通过保护GOT表的手段去做。

dlopen()相关的

工程能力强的话可以自己实现dlopen,

在关键行为处使用,甚至替换掉哪些调用系统dlopen的部分。

··· HOOK原理 ···: 

效果像是HOOK了CPU一样, 

HOOK中的大杀器、杀手锏,

神挡杀神,X谁谁发抖。

··· 检测手段 ··· : 

基本没有办法,

不过可以思考,

在工程上提高CRACKER使用UNICOR的复杂度。

(1)目前检测代码这里写成了一个单独的SO库的形式,

(2)检测需要用户自己手动调用,HASH数据也需要参数传递。

(3)检测库本身被HOOK、被绕过、加保护的问题,

可以选择ANTIHOOK与壳融合,

或者静态编译libc导入函数,

代码中没有涉及,

这部分不在这一块实现了,

这个代码只作为验证。

(4)API只有一个,实现文中大部分功能。

形式为:

#pragma once
#include <stdint.h>
typedef struct ANTI_HOOK{
    uint32_t global_data[48000]; // 作为BUFFER存储文件HASH等预设数据
}ANTI_HOOK;

extern "C" bool anti_hook(
        ANTI_HOOK* global,       // anti_hook的参数
        bool is_close,           // 调用完是否关闭初始化的资源
        uint32_t* arr_func,      // 要检测的函数地址(数组)
        uint32_t count);         // 数组元素个数

----------------------------------------------------

方法并不唯一,应该会有更好的方式,但是没发现别人公开,只能写一些我能想到的。

若有错误希望能指出,共同学习进步~

----------------------------------------------------

[培训]《安卓高级研修班》彻底搞定函数抽取型壳!现在报名得源码和安卓8.1脱壳机!10月20日深圳专场不见不散!

最后于 15小时前 被爱吃菠菜编辑 ,原因:


文章来源: https://bbs.pediy.com/thread-254853.htm
如有侵权请联系:admin#unsafe.sh