百度空间 | 百度首页 
 
查看文章
 
基于硬件断点检测溢出
2009年11月10日 星期二 18:53

YYY。。溢出懂点点。有问题还指正。。

   我们要知道,EIP指向的是可执行节,否则我们可以认为这是一次恶意攻击。SHELLCODE一般是会调用一些系统调用的

,我们可以从这里入手来检测。
栈回溯: 通过HOOK常见的API,判断其返回地址来判断。
           缺点: 一些API没HOOK(没HOOK W版本,或者漏了NTDLL.DLL),伪造EBP。
这里我们提出一种办法来检测。
首先,API是在某个模块里,一般搜索API会使用到 某个模块的基地址
1 通过PEB获取。
2 SEH获得:默认的异常处理函数时在KERNEL32.DLL里面的,SEH链最后一个异常处理函数的地址,以64K对齐向上查

找MZ标记获取基地址
3 TEB: TEB(FS:[0X18]) + 0X1C是kernel32的地址空间,接着搜MZ标记。

我们重点是针对第一种办法,后面俩中我们去掉MZ标记就可以了。
去掉MZ标记
BOOL NO_MZ_PE(ULONG pid)
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
HANDLE hProcess;
ULONG Modulebase, dwOldProtect = 0;;
USHORT ReadFromProcess=0,WriteToMemory=0;

hProcess = OpenProcess(PROCESS_ALL_ACCESS,TRUE,pid);
if(hProcess==NULL)
{
   printf("failed to open process!!\n");
   return FALSE;
}

hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pid );
if( hModuleSnap == INVALID_HANDLE_VALUE )
{
   printf("CreateToolhelp32Snapshot failed!!\n");
   return( FALSE );
}

me32.dwSize = sizeof( MODULEENTRY32 );
if( !Module32First( hModuleSnap, &me32 ) )
{
   CloseHandle( hModuleSnap );
   return( FALSE );
}
do
{
   if(!strcmpi(me32.szModule,"kernel32.dll"))
   {
    Modulebase=(DWORD)me32.modBaseAddr;
    printf("module :%s found at :%x\n","kernel32.dll",Modulebase);
    break;
   }
} while( Module32Next( hModuleSnap, &me32 ) );

VirtualProtectEx(hProcess,(PVOID)Modulebase, 2, PAGE_READWRITE, &dwOldProtect);

if(!WriteProcessMemory(hProcess,(PVOID)Modulebase, (void *)&WriteToMemory, 2, NULL))
   printf("Write MZ Failed!!\n");

ReadProcessMemory(hProcess,
           (LPCVOID)((char*)(Modulebase+0x3c)), //Offset To NT Header
      &ReadFromProcess,
      sizeof(USHORT),
      NULL);

VirtualProtectEx(hProcess,(PVOID)(Modulebase+ReadFromProcess), 2, PAGE_READWRITE, &dwOldProtect);
if(!WriteProcessMemory(hProcess,(PVOID)(Modulebase+ReadFromProcess), (void *)&WriteToMemory, 2, NULL))
   printf("Write MZ Failed!!\n");

CloseHandle(hProcess);
CloseHandle( hModuleSnap );
return( TRUE );
}


通过PEB获取基地址比较简单,很多SHELLCODE都用。
返回地址异常的判断
1 根据 NT_TIB中的栈信息: 不可靠,可被修改
2 根据EBP+X来得到返回地址判断所在模块,不可靠,因为SHELLCODE可能复制到.DATA段

我们简单的这么认为: EIP不是在已知的模块内,或者在可读可写(非.TEXT之类的),栈内就是可能的溢出

为了定位API,SHELLCODE会访问PEB来获取模块基地址
一般会有如下的代码
mov eax, fs:0x30
mov eax,[eax+0xc]
mov esi,[eax+0x1c]
lodsd
mov eax,[eax+0x08] /// kernel32地址

只要我们对 eax+0x08 下一个读类型的硬件断点就可以了。这样 mov eax,[eax+0x08] 就会符合条件断下来我们通

过挂接INT 1,分析EIP就可以了。
DR0-DR3是设置断点的地址 ,我们可以吧剩余的断在常见API上。
可能在多线程的环境下,我们需要 DR7的 GD,全局检测启用,位13,防止线程切换时,DRX被切换。
R/W位(21,20),11表示读写
LEN 一般是双字对齐吧,11就可以
DR7中,将保留位15,14,12,11填0,10填1


类别:默认分类 | 添加到搜藏 | 浏览() | 评论 (0)
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu