对于黑客来说,漏洞是最有价值的资产,所以一旦发现个漏洞并开发了针对该漏洞的攻击技术,则黑客们就希望能够尽可能长时间的利用该漏洞。所以对于黑客们来说,如何能够防止他们所利用的攻击工具不被发现就显得非常重要了。

一般来说,黑客们会在以下4种情况下利用漏洞时会被发现: 

1.和其他已经被检测出的恶意软件的功能或原理有重叠部分;

2.因为本身的攻击性能不稳定而被检测到;

3.在漏洞利用时,由于其恶意程序被安全产品模拟的虚拟运行环境所诱骗,从而被发现,例如安全产品所使用的蜜罐技术;

4.恶意软件的开发者自己将漏洞公开了;

本文我们会把重点放在第3点上,即如何防止恶意运行程序被PageHeap监控到。

PageHeap的工作原理

PageHeap是存在于Windows的SDK/WDK中一种分析内存工具,其作用就是很快地检测出内存堆栈的运行是否正常。

为了实现这一点,它用另一个分配器来替换内存堆栈。此分配器将通过VirtualAlloc分配每一次的运行内存,这样每一次的内存消耗将至少减少一个页面的大小(一般情况下为4Kb)。

除此之外,返回的地址也将被减去请求的大小,这样便可导致缓冲区溢出(包括栈溢出和堆溢出)。这样一来,就防止了许多字节数较大应用情境。

所以,PageHeap就破坏了许多恶意软件运行的基础,让大多数漏洞所依赖堆栈内存分配不复存在。比如为了改变进程,而添加过多的代码,就很容易溢出被检测到。 

对PageHeap的反检测

一旦PageHeap开始运行,那内存的堆分配将会慢很多。因为,堆分配的初始目的就是尽可能快地分配各种不同大小的内存。

所以,如果PageHeap开始运行,会通过VirtualAlloc向内核请求每一次的分配,这样内存消耗就会越来越多,最后发生内存不足或整体性能下降。另外,这些分配会让内存分配的时间变得很长。

由于window.performance.now()计数器在大多数JavaScript引擎中都可用,因此可以用它来检测这个分配时间。window.performance.now()计数器能实时采集、分析系统内的应用程序、服务、驱动程序等的性能数据,以此来分析系统的瓶颈、监视组件的表现,最终帮助用户进行系统的合理调配。

因为Chrome和Firefox拥有自己的分配器,所以这种方法仅限于Windows。

以IE11和Edge为例,当我们在这两个浏览器总寻找分配不同数量字节的函数时,可以使用Uint8Array,它是一个使用ArrayBuffer创建的TypedArray。

当创建ArrayBuffer时,将直接使用我们指定的值调用msvcrt!malloc。我们将分别使用0x10和0x1000代表小值和大值,大值将始终触发对VirtualAlloc的调用。

下面我们将试着在20ms内为小值和大值分配尽可能多的Uin8Array,代码如下:

function doFor(fun, time) {
    var i = 0;
    var store = new Array();
    var startTime = performance.now();
    do {
        for(var j=0; j<100; j++)
            store.push(fun());
        i++;
    } while((performance.now() - startTime) < time);
    return i;}function allocPageBA() {
    return new Uint8Array(0x1000);}function allocSmallBA() {
    return new Uint8Array(0x10);}var bigRet = doFor(allocPageBA, ALLOC_TIME);var smallRet = doFor(allocSmallBA, ALLOC_TIME);alert(bigRet);alert(smallRet);

不过在上图中,我们还引入了其它的不相关的分配代码,为了解决这个问题,我们会创建一个预先分配Array的对象,然后将对象存储在那里,这样就不会生成不必要的分配代码了。

另外,在保存分配的对象时,为防止垃圾回收站释放这些不必要的代码,可能会发生一些错误:

function NoAllocStore(count) {
    this.count = count;
    this.array = new Array(count);
    for(var i=0; i<count; i++) {
        this.array[i] = 0x41414141;
    }
    this.index = 0;}NoAllocStore.prototype.store = function(obj) {
    if (this.index >= this.count) {
         alert("bad");
         throw false;
    }
    this.array[this.index] = obj;
    this.index++;}

我们运行了好几次以上的代码,并比较了两个浏览器在禁用PageHeap情况下的页面配置。

在IE11中分配如下:

更详细地的信息如下:

非常明显的是,在启用了PageHeap之后,分布显得更加密集了,这样在分配时间上就更为确定,这可以归因于页面分配比堆分配更耗时。

所以对于黑客们来说,就需要使用系统仿真器或调试器测量每次malloc调用后执行的总指令数(ring0和ring3)。

而在Edge上,分布是非常相似的,但你可以注意到它们更加分离。

也就是说,根据内存分配的时间原理,黑客们可以在40ms的时间上限内,来分析PageHeap是否存在,如果分配的时间超过了40ms,则你的恶意程序可能就被监控了。

本文翻译自:http://snf.github.io/2017/05/04/exploit-protection-i-page-heap/如若转载,请注明原文地址: http://www.4hou.com/web/15783.html
源链接

Hacking more

...