Anti-Debug检测int3断点源码
本帖最后由 JoyChou 于 2013-5-9 13:10 编辑今天看到zxcfvasd发了一篇关于int检测的CM文章
然后给大家分享下怎么实现的。
这里用VS写了一个内嵌的汇编代码
C代码:
#include <windows.h>
BOOL DetectFuncBreakpoints();
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
if (DetectFuncBreakpoints())
{
MessageBox(NULL, "检测到int3断点", "结果", MB_OK);
return 0;
}
else
{
MessageBox(NULL, "没有检测到int3断点", "结果", MB_OK);
}
return 0;
}
BOOL DetectFuncBreakpoints()
{
BOOL bFoundOD;
bFoundOD=FALSE;
DWORD dwAddr;
dwAddr = (DWORD)GetProcAddress(LoadLibrary("user32.dll"),"MessageBoxA"); //将FARPROC类型转换成DWORD
__asm
{
cld ;检测代码开始
mov edi,dwAddr
mov ecx,100;100bytes
mov al,0CCH ;字母前面必须有0
repne scasb
jnz ODNotFound
mov bFoundOD,1
ODNotFound:
}
return bFoundOD;
}
再发一个win32汇编写的吧
;检测时,BP MessageBoxA
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
.const
szKernelDlldb 'user32.dll',0
szAPIMessbox db 'MessageBoxA',0
szCaption db '结果',0
szFound db '发现API断点',0
szNotFound db '未发现断点',0
.code
start:
invoke GetModuleHandle,addr szKernelDll
invoke GetProcAddress,eax,addr szAPIMessbox;API地址
cld ;检测代码开始
mov edi,eax ;API开始位置
mov ecx,100H;检测100字节
mov al, 55H
xor al, 99H ;55和99异或等于0xCC
repne scasb
cmp ecx, 0h
jnz debugger_found
invokeMessageBox,NULL,addr szNotFound,addr szCaption,MB_OK
jmp exit
debugger_found: invokeMessageBox,NULL,addr szFound,addr szCaption,MB_OK
exit: invokeExitProcess,NULL
end start
首先我们得知道一个问题,当用OD调试的时候,我们F2或者下bp断点的时候,即是下int3断点OD载入分析:比如我们在00401000 F2下断,此时应该00401000地址应该是CC 18204000因为OD做了对int3的隐藏,我们看到的还是是68,而不是我们下断时的CC,当然这也是为了我们方便。
说这么多是为了理解00401021|.F2:AE repne scas byte ptr es: 这句话因为当等于我们下断的时,此时数据窗口并不等于CC。这也是我调试的觉得有点困惑的地方,分享一下。
00401000 >/$68 18204000 push APISoftB.00402018 ; /pModule = "user32.dll"
00401005|.E8 5A000000 call <jmp.&KERNEL32.GetModuleHandleA> ; \GetModuleHandleA
0040100A|.68 23204000 push APISoftB.00402023 ; /ProcNameOrOrdinal = "MessageBoxA"
0040100F|.50 push eax ; |hModule
00401010|.E8 55000000 call <jmp.&KERNEL32.GetProcAddress> ; \GetProcAddress
00401015|.FC cld
00401016|.8BF8 mov edi,eax
00401018|.B9 00010000 mov ecx,0x100
0040101D|.B0 55 mov al,0x55
0040101F|.34 99 xor al,0x99
00401021|.F2:AE repne scas byte ptr es:
000401023|.83F9 00 cmp ecx,0x0 ;ecx不等于0表示检测到int3断点
00401026|.75 15 jnz short APISoftB.0040103D
00401028|.6A 00 push 0x0 ; /Style = MB_OK|MB_APPLMODAL
0040102A|.68 2F204000 push APISoftB.0040202F ; |Title = "结果"
0040102F|.68 40204000 push APISoftB.00402040 ; |Text = "未发现断点"
00401034|.6A 00 push 0x0 ; |hOwner = NULL
00401036|.E8 1D000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
0040103B|.EB 13 jmp short APISoftB.00401050
0040103D|>6A 00 push 0x0 ; /Style = MB_OK|MB_APPLMODAL
0040103F|.68 2F204000 push APISoftB.0040202F ; |Title = "结果"
00401044|.68 34204000 push APISoftB.00402034 ; |Text = "发现API断点"
00401049|.6A 00 push 0x0 ; |hOwner = NULL
0040104B|.E8 08000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
00401050|>6A 00 push 0x0 ; /ExitCode = 0
00401052\.E8 07000000 call <jmp.&KERNEL32.ExitProcess> ; \ExitProcess
对代码段的int3检测
#include <windows.h>
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS32 pNtHeaders;
PIMAGE_SECTION_HEADER pSectionHeader;
DWORD dwBaseImage = (DWORD)GetModuleHandle(NULL); //获取当前进程的基址
pDosHeader = (PIMAGE_DOS_HEADER)dwBaseImage;
pNtHeaders = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader + pDosHeader->e_lfanew);
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pNtHeaders + sizeof(pNtHeaders->Signature) + sizeof(IMAGE_FILE_HEADER) +
(WORD)pNtHeaders->FileHeader.SizeOfOptionalHeader);
DWORD dwAddr = pSectionHeader->VirtualAddress + dwBaseImage; //获取代码段在内存中的地址
DWORD dwCodeSize = pSectionHeader->SizeOfRawData; //获取代码段对齐后的大小
BOOL bFound = FALSE;
__asm
{
cld ;检测代码开始
mov edi,dwAddr
mov ecx,10h ;检测0x10个字节测试,原则应该是dwCodeSize大小
mov al,0CCH ;字母前面必须有0
repne scasb
jnz NotFound
mov bFound,1
NotFound:
}
if (bFound)
{
MessageBoxA(NULL, "检测到断点", "结果", 0);
}
else
{
MessageBoxA(NULL, "没有检测到断点", "结果", 0);
}
return 0;
}
最后说下原理:
先得到函数的地址,设置一个检测的字节长度(我这里设的0x100),然后就一直搜索0xCC,如果发现了就表示检测到了。反之亦然。
不过只能检测bp断点和F2(int3断点),硬件等断点是检测不到的,硬件断点可以用CONTEXT结构体里面的iDr0,iDr1,iDr2,iDr3成员检测,这里就不多说了。
跳过检测方法:
1、修改检测时的跳转
2、下 hr等强点的断点
网上很多关于int3检测的资料,所以大家想学习的善于利用好搜索功能能学到很多东西的。
感谢楼主分享代码。。。 前来膜拜。。。学习了!
real金龟子 发表于 2013-4-23 20:07 static/image/common/back.gif
前来膜拜。。。学习了!
金龟子大大辛苦了
感谢楼主分享 bambooqj 发表于 2013-4-23 20:18 static/image/common/back.gif
前排膜拜技术贴。。。
只是混个脸熟 我有时候下硬件执行也被检测了 daiandy 发表于 2013-4-24 16:46 static/image/common/back.gif
我有时候下硬件执行也被检测了
怎么会呢
前排支持围观,话说VMP处理一下关键位置,CC检测也相当了得。不知道硬件断点如何检测,求楼主爆料,我等菜鸟好学习
页:
[1]
2