⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sehbpx.asm

📁 此为本书的配套光盘.本书结合实例
💻 ASM
字号:
;******************************************
;coded by ljtt
;******************************************
;演示检测BPX断点
;******************************************
;---------------------------------------AntiBpx1.asm------------------------------------------------
COMMENT	$
	编译使用:
	\masm32\bin\ml /c /coff antibpx1.asm
	\masm32\bin\Link /SECTION:.text,ERW /SUBSYSTEM:WINDOWS antibpx1.obj
$

.586P
.MODEL FLAT,STDCALL
OPTION CASEMAP:NONE

include		e:\masm32\include\windows.inc
include		e:\masm32\include\kernel32.inc
include		e:\masm32\include\user32.inc
include		e:\masm32\include\comctl32.inc

includelib	e:\masm32\lib\kernel32.lib
includelib	e:\masm32\lib\user32.lib
includelib	e:\masm32\lib\comctl32.lib

.Data                                        
szDebugMsg			db	0Dh,0Ah,0Dh,0Ah
					db	'你可以通过在以下API函数中设置断点来进行测试:'
					db	0Dh,0Ah,0Dh,0Ah
					db	'MessageBoxA',0Dh,0Ah,'MessageBeep',0Dh,0Ah
					db	0Dh,0Ah,0Dh,0Ah,0
szNoFoundTracerMsg	db	'我没有发现被跟踪...:)',0
szFoundTracerMsg	db	'我发现你了!....你在跟踪我....哈哈...',0
szTitle				db	'样例:利用SEH技术进行反跟踪',0

SafeEsp				dd	0
CallLevel			dd	0
ReturnAddrEsp		dd	255 dup(0)

hKernel32			dd	0
szKernel32Dll		db	'KERNEL32.DLL',0
szSleepEx			db	'SleepEx',0
szFormat			db	'KERNEL32.SleepEx : %08lX',0
szText				db	255 dup(0)


.Code
			assume	fs:nothing
;---------------------------------------------主程序开始------------------------------------------------
Main:
			; 建立异常处理机制:结构化异常处理
			push	xMyHandler
			push	fs:[0]
			mov		fs:[0],esp			; 
			mov		[SafeEsp],esp

			invoke	MessageBoxA,NULL,addr szDebugMsg,addr szTitle,MB_OK

			; 故意产生一个异常
			int		3h					; 异常!!将被系统捕获,系统将调用我们的异常处理过程 xApiHandler
			nop
			; 运行在 start_anti_trace 到 stop_anti_trace 之间的代码时,都处在
			; 程序通过SEH机制建立的单步调试状态,程序将对每一条指令进行识别(包括API函数中的指令),
			; 如果这些指令中存在断点,都将被程序发现。
start_anti_trace:	;===反跟踪开始===
			invoke	MessageBeep,100
			invoke	LoadLibraryA,addr szKernel32Dll
			mov		[hKernel32],eax
			invoke	GetProcAddress,[hKernel32],addr szSleepEx
			invoke	wsprintf,addr szText,addr szFormat,eax
			invoke	MessageBoxA,NULL,addr szText,addr szTitle,MB_OK
stop_anti_trace:	;===反跟踪结束===

			; 如果在以上进行反跟踪的代码执行中没有设置断点,程序将执行到此处,
			; 并且显示"没有发现跟踪者...:)"的提示信息
			invoke	MessageBoxA,NULL,addr szNoFoundTracerMsg,addr szTitle,MB_OK
			jmp		stop_self_trace_addr
found_tracer:
			; 如果在以上进行反跟踪的代码执行中发现设置断点,程序将执行到此处,
			; 并且显示"我发现你了....!"等提示信息(可能仅在此测试样例中我会这样做 :)
			invoke	MessageBoxA,NULL,addr szFoundTracerMsg,addr szTitle,MB_OK

stop_self_trace_addr:
			; 解除自己建立的SEH结构化异常处理,然后结束进程
			mov		esp,[SafeEsp]
			pop		fs:[0]
			add		esp,4
			invoke	ExitProcess,0
;---------------------------------------------主程序结束------------------------------------------------

;--------------------------------------------异常处理函数------------------------------------------------
xMyHandler	proc	C uses ebx esi edi pExcept:DWORD,pFrame:DWORD,pContext:DWORD,pDispatch:DWORD
			mov		esi,pExcept
			assume	esi:ptr EXCEPTION_RECORD
			mov		edi,pContext
			assume	edi:ptr CONTEXT

			; 如果发生严重错误,则不进行处理直接返回,从而转向下一级异常处理程序
			test	[esi].ExceptionFlags,1
			jnz		lm0_continue_search

			; 如果异常进行展开,则不进行处理直接返回。
			test	[esi].ExceptionFlags,6
			jnz		lm0_unwind

			; 对"软断点异常"进行处理
			cmp		[esi].ExceptionCode,EXCEPTION_BREAKPOINT
			jz		lm0_start_self_trace

			; 对"单步异常"进行处理
			cmp		[esi].ExceptionCode,EXCEPTION_SINGLE_STEP
			jz		lm0_self_trace

			; 其他情况,都直接返回,转向下一级异常处理程序
lm0_continue_search:
lm0_unwind:	mov		eax,ExceptionContinueSearch
			jmp		lm0_ret

lm0_start_self_trace:
			; 开始启动单步自跟踪,即初始化变量、设置TF标志等
			mov		[CallLevel],0					; 初始化 CALL层级
lm0_trap_it:or		byte ptr [edi+1].regFlag,01h	; 设置 TF 标志
lm0_modify_drx_reg:
			mov		[edi].iDr0,0
			and		[edi].iDr6,0FFFF0FF0h
			mov		[edi].iDr7,0h					; 清除调试寄存器设置的信息
			mov		[edi].ContextFlags,CONTEXT_FULL OR CONTEXT_DEBUG_REGISTERS
			jmp		lm0_continue_exec

lm0_self_trace:
			; 判断是否自跟踪到达结束地址,是,则停止单步自跟踪
			mov		ebx,[edi].regEip
			cmp		ebx,stop_anti_trace
			jnz		@F								; 不是,则跳转
			mov		[CallLevel],0					; 初始化CALL层级
			and		byte ptr [edi+1].regFlag,00h	; 复位 TF 标志,停止单步自跟踪
			jmp		lm0_modify_drx_reg				; 

@@:			lea		eax,[ebx+5]						; 获取下下一条要执行的指令地址到 EAX 寄存器
			cmp		byte ptr [ebx],0E8h				; 判断下一条要执行的指令是否为 CALL x 指令
			jz		lm0_do_call_instr
			inc		eax
			cmp		word ptr [ebx],015FFh			; 判断下一条要执行的指令是否为 CALL [x] 指令
			jz		lm0_do_call_instr
			cmp		byte ptr [ebx],0C2h				; 判断下一条要执行的指令是否为 ret n 指令
			jz		lm0_do_ret_instr
			cmp		byte ptr [ebx],0C3h				; 判断下一条要执行的指令是否为 retn 指令
			jz		lm0_do_ret_instr
			cmp		byte ptr [ebx],0CCh				; 判断下一条要执行的指令是否为 INT 3h 指令
			jz		lm0_do_int3_instr
			cmp		word ptr [ebx],08964h			; 判断下一条要执行的指令是否为修改FS:[0]之类指令
			jz		lm0_do_fs_instr
			jmp		lm0_trap_it						; 都不是以上的指令,则继续进行单步自跟踪

lm0_do_fs_instr:									; 
			mov		al,byte ptr [ebx+2]
			and		al,11100111b
			cmp		al,00000101b					; 判断下一条要执行的指令是否为 mov fs:[0],reg 指令
			jnz		lm0_do_other_fs_instr
			movzx	eax,byte ptr [ebx+2]
			and		eax,00011000b
			shr		eax,3
			not		eax
			and		eax,00000011b
			mov		eax,[edi+eax*4].regEbx
			cmp		eax,xMyHandler
			jz		@F
			mov		eax,[eax+4]
			mov		[ApiHandler],eax
			jmp		lm0_skip_this_instr
@@:			mov		[ApiHandler],0
lm0_skip_this_instr:
			lea		eax,[ebx+7]
			mov		[edi].regEip,eax
			jmp		lm0_trip_it


lm0_do_other_fs_instr:								; 针对其他修改FS:[x]的指令,改用调试寄存器断点跟踪
			mov		ebx,[CallLevel]
			mov		eax,[ReturnAddrEsp+ebx*4]
			mov		eax,[eax]						; 取得最后一个CALL调用的返回地址
			dec		[CallLevel]
lm0_bp_trace:
			mov		[edi].iDr0,eax					; 在CALL指令的返回地址处设置调试寄存器断点
			and		[edi].iDr6,0FFFF0FF0h
			mov		[edi].iDr7,155h
			mov		[edi].ContextFlags,CONTEXT_FULL OR CONTEXT_DEBUG_REGISTERS
			jmp		lm0_continue_exec				; 继续

lm0_do_int3_instr:
			mov		[edi].regEip,found_tracer		; 发现设置API函数断点,则修改CONTEXT.EIP
			mov		eax,[SafeEsp]
			mov		[edi].regEsp,eax				; 修改CONTEXT.ESP
			jmp		lm0_modify_drx_reg				; 

lm0_do_ret_instr:
			dec		[CallLevel]						; 下一步将执行 ret 指令, CALL层级 减一
			jmp		lm0_trap_it						; 继续进行单步自跟踪

lm0_do_call_instr:
			; 通过判断CALL层级,可以知道是否已经执行进入到API函数内
			cmp		[CallLevel],0					; 
			jnz		lm0_bp_trace					; 对API函数内部的CALL调用不再进行单步自跟踪,
													; 而改用调试寄存器断点自跟踪方式

			inc		[CallLevel]						; 下一步将执行 CALL 指令, CALL 层级 加一
			mov		ebx,[CallLevel]
			mov		eax,[edi].regEsp
			sub		eax,4							; 计算 CALL 返回地址的CONTEXT.ESP堆栈指针
			mov		[ReturnAddrEsp+ebx*4],eax		; 保存
			jmp		lm0_trap_it						; 继续进行单步自跟踪

lm0_continue_exec:
			mov		eax,ExceptionContinueExecution
lm0_ret:	ret
xMyHandler	endp

End Main                        ;End of code, Main is the entrypoint

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -