能力值:
( LV5,RANK:60 )
|
-
-
2 楼
还有一个我一直想不通的问题。就是,为什么这个壳可以双变单,不是异常之后就调试解密吗。双变单是在解密页面之前就变了。patch几个点就能解密是什么原理啊。那他原本的调试运行不就没有意义了吗。最开始的研究都是强制解密之后再脱离。
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
应该是与rdtsc有关吧
|
能力值:
( LV3,RANK:20 )
|
-
-
4 楼
异常以后可以获取线程的context,然后把dr寄存器都清零了,硬件断点也就没了。虚拟机处理rdtsc是有个bug的,有时候会利用这个来反虚拟机。清零dr寄存器不是直接读写的,而是改写异常的context,异常结束后系统会自动把异常的context写入到真实的异常。建议你找2篇SEH的文章看看
|
能力值:
( LV5,RANK:60 )
|
-
-
5 楼
仔细想了下,可能不是反调试的问题,对SetThreadContext这类函数用到的堆栈内存下断点,是不会断下来的。内存断点会挂掉,硬件断点没反应。drx7=0x155,可以百度到原理,说的是有的调试器无法处理程序本身设置的硬件断点,但是前提是前面4个drx都是写的代码的地址,触发单步异常然后捕获,这里对前面4个drx的处理只是清零,这一点不明白。另外不是虚拟机的问题,不进入这个处理,完全正常运行。对于双变单,刚才看了下剩下的教程贴,有的版本是子进程自己解压然后自己加密,然后被父进程调试解压,调试加密,可能单变双patch的是这个。
|
能力值:
( LV3,RANK:20 )
|
-
-
6 楼
清零了硬件断点不就没了么,所以断不下了
你自己用c++写个demo试试嘛
|
能力值:
( LV5,RANK:60 )
|
-
-
7 楼
这个是反硬件断点保护,不是简单的清零,dr7=0x155,4个drx都用上了,但是写的值是0,我觉得无意义,按理简单清零应该drx7直接写0。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | __asm
{
xor eax,eax;
cdq;
push e_handler;
push dword ptr fs:[eax];
mov fs:[eax],esp;
int 3;
hwbp1: nop
hwbp2: nop
hwbp3: nop
hwbp4: nop
div edx
nop
pop dword ptr fs:[0]
add esp,4
cmp al,4;
jne rt_label;
jmp rf_label;
e_handler:
xor eax,eax;
;ExceptionRecord
mov ecx,dword ptr[esp+0x04]
;Contextrecord
mov edx,dword ptr[esp+0x0c]
;ContextEIP
inc byte ptr[edx+0xb8];
;ExceptionCode
mov ecx,dword ptr[ecx];
;1.EXCEPTION_INT_DIVIDE_BY_ZERO
cmp ecx,0xc0000094;
jne Ex_next2;
;Context_eip
inc byte ptr[edx+0xb8];
mov dword ptr[edx+0x04],eax;dr0
mov dword ptr[edx+0x08],eax;dr1
mov dword ptr[edx+0x0c],eax;dr2
mov dword ptr[edx+0x10],eax;dr3
mov dword ptr[edx+0x14],eax;dr6
mov dword ptr[edx+0x18],eax;dr7
ret
;2.EXCEPTION_BREAKPOINT
Ex_next2:
cmp ecx,0x80000003;
jne Ex_next3;
mov dword ptr[edx+0x04],offset hwbp1;dr0
mov dword ptr[edx+0x08],offset hwbp2;dr1
mov dword ptr[edx+0x0c],offset hwbp3;dr2
mov dword ptr[edx+0x10],offset hwbp4;dr3
mov dword ptr[edx+0x18],0x155;dr7
ret
;3.EXCEPTION_SINGLE_STEP
Ex_next3:
cmp ecx,0x80000004
jne rt_label
;CONTEXT_Eax
inc byte ptr[edx+0xb0]
ret
}by shellwolf
|
这个才是用到了0x155,相当于改变了程序流程,记录程序自己踩到自己设的硬件断点次数。
单独清零drx0~drx3,然后把drx7莫名其妙的写成0x155,感觉无意义,但是armadillo是这么做的。
好像对硬件断点的检测是我自己弄错了,我自己写了个玩具插件恢复drx的值的时候掉了一句话,所以出问题了,我还以为是反调试。但是内存断点还是不明白什么原理。有一个异常处理很复杂,看不懂。还用到了Unwind。
c++写SEH程序用到了try except关键字(我也不明白),但是实际上这是很复杂的宏来转换的,SEH只有汇编形式的demo才容易看请。c++没试过。
|
|
|