2014年3月28日星期五

内存/硬断点之编程实现

#include "stdafx.h"

/*
硬件断点很有用,它的原理就不说了。
在调试的时候很容易做到:ba wX 0xXXXXXXXX.
在编程的时候如何做到呢?
当然是改变内存的属性了。
这个包括全局的变量和堆上申请的内存。
栈上的内存被非法篡改,理论上不属于这个范畴了,是另一个说法:栈溢出等。
注意:全局的变量一般所在的节的内存属性都是可写的。
可以利用异常处理/或者自己发出异常,然后捕获,获取发生时的信息。

made by correy
made at 2014.03.28
email:kouleguan at hotmail dot com
homepage:http://correy.webs.com

觉得有效的利用此属性的办法还是老老实实的用VirtualAlloc 申请一片内存(当某个变量等).
至少申请的内存的大小是页的倍数.

全局的变量还得另想办法.修改PE文件的格式等.
*/

#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h> 

int test[2];

void test_global_variable()
    /*
    功能:使全局变量不可以写.
    目的:以编程的手段实现一种断点.
    */
{
    DWORD OldProtect = 0;
    BOOL B = VirtualProtect(&test[0], sizeof(int), PAGE_READONLY, &OldProtect); 
    if (!B) {
        int x = GetLastError();
    }    

    /*
    这个也是不可以的.
    可能是内存属性的划分是以页为单位进行的.
    */
    test[1] = 1;

    /*
    把上面的测试给屏蔽了.
    运行到这里访问发生了异常.
    可以用异常处理的办法处理捕获然后再恢复内存属性.
    */
    test[0] = 1;    
}

void test_heap()
    /*
    功能:测试堆的非法访问的拦截.
    结果:测试成功,满足要求.
    */
{
    char * c = (char *) HeapAlloc(GetProcessHeap(), 0, 2);
    if (c == NULL) {
        return;
    }

    * c = 9;//测试应该成功.

    DWORD OldProtect = 0;
    BOOL B = VirtualProtect(c, 1, PAGE_READONLY, &OldProtect); 
    if (!B) {
        int x = GetLastError();
    }

    /*
    应该失败.
    假定这里是非法修改内存,如别的指令的内存溢出越界等.
    这里满足要求,弹出了异常界面.
    */
    * c = 1;

    /*
    把上面的测试给屏蔽了.
    运行到这里访问发生了异常.
    可能是内存属性的划分是以页为单位进行的.
    */
    c++;
    * c = 1;
}

int wmain(int argc, wchar_t *argv[])
{   
    //test_global_variable();

    test_heap();

    /*
    相信:VirtualAlloc和GlobalAlloc/LocalAlloc/NEW的内存在理论上也应该成功.
    但是栈上的局部变量建议不要这样做,也不应该这样做.
    */

    return 0;
}

没有评论:

发表评论