加壳软件测试,VMProtect2.04加壳程序从入门到精通

1110186f52c5be249dd8e3230cf65ae5.png

类型:加壳脱壳大小:13.5M语言:中文 评分:4.2

标签:

立即下载

第 7 页 虚拟执行环境与调试器检测

3.3.虚拟执行环境与调试器检测

在前面所有的节里面的内容全部都是贯穿的,没有一个地方遗漏下来的在解析,但是这一节和上一节的结尾并没有连接在一起,不是我想藏着捏着搞流水账脱文出来,实在是没有精力一条一条的去说。我已经想吐了,没有心情继续写下去了,越是想着全盘托出,有些地方老是更有压力害怕遗漏了东西。还有一个是想赶快结稿的心理也有一些。再说,VMP的ANTI检测是很有趣的一个部分,当你知道下面有一节很有趣,而一直绕在上面的基础地方,实在也有点心急。总之,如果你发现我有遗漏了没有解说的地方就自己去看好了。下面我们就直接来到ANTI部分:

3.3.1.VMware

0013F78C 00000000 ....

0013F790 0043B7B2 C. ; RETURN from NOTEPAD.00435E6A to NOTEPAD.0043B7B2

0013F794 0013FF98 .

VM_FS:[EBPSTACK] ;读取FS:[0]的数据

0013F78C |0013FFE0 .

0013F790 \0043B7B2 C. ; RETURN from NOTEPAD.00435E6A to NOTEPAD.0043B7B2

0013F794 0013FF98 .

0013F784 00000000 ....

0013F788 0013F78C .

0013F78C 0013FFE0 .

0013F790 0043B7B2 C. ; RETURN from NOTEPAD.00435E6A to NOTEPAD.0043B7B2

0013F794 0013FF98 .

VM_SEH

0013F78C |0013FFE0 . ; Pointer to next SEH record

0013F790 \0043B7B2 C. ; SE handler

0013F794 0013FF98 .

这是VM构建新的SEH。读取FS:[0]的原来的SEH地址,然后放入新的进去VM_SEH伪指令里实现的,不明白的自己去看SEH相关资料。构建好SEH后程序调用VM_EXIT,

0013F770 00000000 ....

0013F774 0013FF98 .

0013F778 564D5868 hXMV

0013F77C 00005658 XV..

0013F780 [0042536C lSB. ; RETURN from NOTEPAD.00426E8B to NOTEPAD.0042536C

0013F784 31921C56 V1

0013F788 0042536C lSB. ; RETURN from NOTEPAD.00426E8B to NOTEPAD.0042536C

0013F78C 0013FFE0 . ; Pointer to next SEH record

0013F790 0043B7B2 C. ; SE handler

0013F794 0013FF98 .

VM_EXIT

接下来程序在

0042536C . ED IN EAX,DX ; I/O command

这条指令这里就卡死了。为什么呢?因为VM_EXIT中有着给各个寄存器赋值的操作,其中这里他就构建了一个VMware的后门指令检测。在这里算是VMP的第一个正规的ANTI来了。执行这条指令时候的CPU状态和VMware后门检测的源码:

CPU - main thread, module NOTEPAD

EAX 564D5868

ECX 0000000A

EDX 00005658

EBX 00000000

ESP 0013F78C

EBP 0013FF98

ESI 0013FF8C ASCII "ntdll.dll"

EDI 0013FF70

EIP 0042536C NOTEPAD.0042536C

VMware的后门指令检测。这个么不用问为什么。这个就是后门

mov eax, 564D5868h

mov ebx, 00000000h

mov ecx, 0000000Ah

mov edx, 00005658h

in eax, dx

这个检测很普通,由于只有在VMware下这条指令才有返回值,否则就是一次异常。而我们是在真实环境下的。这个太普通了。我根本没有用什么虚拟机。想深入了解的自己google资料看。

我是没有在VMware调试VMP,所以它必定异常出错,现在就可以看到刚才构建的SEH的作用了。去SEH地址下断,然后忽略异常继续调试。

0043B7B2 .^\E9 7DD2FFFF JMP 00438A34 ; VMware SEH

我们来到了这里继续调试,在SEH中,将保存当前的结构,重新初始化一个VM,并在这个VM里面修改掉context结构中EIP指针。要看懂修改的伪指令,还是复习一下SEH回调函数:

首先看好SEH回调函数的参数,它一共有4个参数:

SEH_Handler proc _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext

对应VMP里的SEH地址看看具体数据

0013F3C4 [7C9232A8 2| ; RETURN to ntdll.7C9232A8

0013F3C8 0013F4AC . ;第一个参数:ExceptionRecord指针

0013F3CC 0013F78C . ;第二个参数:SEH指针

0013F3D0 0013F4C0 . ;第三个参数:Context指针

0013F3D4 0013F480 . ;第四个参数:DispatcherContext指针

附CONTEXT结构环境:

代码:typedefstruct_CONTEXT{

/*000*/DWORD ContextFlags;

/*004*/DWORD Dr0;

/*008*/DWORD Dr1;

/*00C*/DWORD Dr2;

/*010*/DWORD Dr3;

/*014*/DWORD Dr6;

/*018*/DWORD Dr7;

/*01C*/FLOATING_SAVE_AREAFloatSave;

/*08C*/DWORD SegGs;

/*090*/DWORD SegFs;

/*094*/DWORD SegEs;

/*098*/DWORD SegDs;

/*09C*/DWORD Edi;

/*0A0*/DWORD Esi;

/*0A4*/DWORD Ebx;

/*0A8*/DWORD Edx;

/*0AC*/DWORD Ecx;

/*0B0*/DWORD Eax;

/*0B4*/DWORD Ebp;

/*0B8*/DWORD Eip; ;B8的偏移量位置是Eip

/*0BC*/DWORD SegCs;

/*0C0*/DWORD EFlags;

/*0C4*/DWORD Esp;

/*0C8*/DWORD SegSs;

/*0CC*/ BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];

/*2CC*/}CONTEXT;

先用理论来说一下:

1)第三个参数得到context结构地址0013F4C0。

2)context结构基地址+B8得到Eip存储地址。

3)把安全的返回地址放入Eip位置。

4)SEH异常返回,程序从新的Eip地址开始执行。

下面来看伪指令的操作过程:

0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8

VM_PUSHdw_IMMEDIATEb

0013F3C0 0000000C ....

0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8

VM_PUSHdw_IMMEDIATEb

0013F3BC 00000008 ...

0013F3C0 0000000C ....

0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8

VM_PUSHdw_EBP

0013F3B8 0013F3BC .

0013F3BC 00000008 ...

0013F3C0 0000000C ....

0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8

VM_ADDdw_EBPSTACK

0013F3BC 0013F3C4 .

0013F3C0 0000000C ....

0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8

VM_ADDdw_EBPSTACK

0013F3C0 0013F3D0 .

0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8

这是1)阶段,加8获得参数的位置,加C获得第三个参数:

0013F3C0 0013F3D0 .

0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8

0013F3C8 0013F4AC .

0013F3CC 0013F78C .

0013F3D0 0013F4C0 .

0013F3D4 0013F480 .

VM_COPYdw_EBPSTACK

0013F3C0 0013F4C0 .

0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8

这是1)阶段,获得context结构地址0013F4C0

0013F3B8 0013F4C0 .

0013F3BC 000000B8 ...

0013F3C0 00436C7D }lC.

0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8

VM_ADDdw_EBPSTACK

0013F3BC 0013F578 x. ; ASCII "lSB"

0013F3C0 00436C7D }lC.

0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8

这是2)阶段,context结构B8偏移量位置是Eip位置

VM_MOVdw_MEMORYdw_EBPSTACKdw

这是3)阶段,本来Eip位置是发生异常的指令地址:

0013F578 0042536C lSB. ; RETURN from NOTEPAD.00426E8B to NOTEPAD.0042536C

经过修改后,放入了返回后的执行地址:

0013F578 00436C7D }lC.

0013F398 F32B430A .C+

0013F39C 00000000 ....

0013F3A0 00000246 F..

0013F3A4 7C9232BC 2|

0013F3A8 0013F4C0 .

0013F3AC 00000000 ....

0013F3B0 0013F3E4 .

0013F3B4 00000000 ....

0013F3B8 7C9232BC 2|

0013F3BC 00000000 ....

0013F3C0 00000000 ....

0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8

VM_EXIT

这是4)阶段。最后调用VM_EXIT返回,里面给寄存器赋值,让系统从SEH返回,而返回后eip指针被修改,我们就需要从新放入的地址00436C7D拦截程序跟踪。接下来重新初始化VM。我们继续走起了。现在前面放置的SEH已经无用了,释放掉恢复原来的SEH,直接放伪指令的实现过程了,不明白的查SEH资料:

0013F788 00000000 ....

VM_FS:[EBPSTACK] ;FS:[O]的值取出来,得到当前的SEH结构存储地址

0013F788 0013F78C .

VM_MOVdw_EBPreg_EBPSTACK ;移动EBP指针下去,到达SEH结构存执地址

0013F788 00000000 ....

0013F78C 0013FFE0 . ; Pointer to next SEH record

0013F790 0043B7B2 C. ; SE handler

VM_SEH ;恢复原来的SEH,0013FFE0放入FS:[0]

3.3.2.单步模式

这个检测方法用伪指令来实现可以说是非常非常的猥琐。这招对于一般的人来说毫无意义,因为都是直接运行或者从来不进伪指令里面去,很容易就过了,反倒是碰到我这样F7单步走VM的人来说,不小心就中招了。总之十分猥琐的方法。

0013F78C 00000000 ....

0013F790 0041F070 pA. ; RETURN from NOTEPAD.00423165 to NOTEPAD.0041F070

0013F794 0013FF98 .

VM_FS:[EBPSTACK] ;读取FS:[0]的值当前SEH结构

0013F78C |0013FFE0 .

0013F790 \0041F070 pA. ; RETURN from NOTEPAD.00423165 to NOTEPAD.0041F070

0013F794 0013FF98 .

0013F784 00000000 ....

0013F788 0013F78C .

0013F78C 0013FFE0 .

0013F790 0041F070 pA. ; RETURN from NOTEPAD.00423165 to NOTEPAD.0041F070

0013F794 0013FF98 .

VM_SEH

0013F78C |0013FFE0 . ; Pointer to next SEH record

0013F790 \0041F070 pA. ; SE handler

0013F794 0013FF98 .

构建新的SEH结构,现在的异常处理程序地址是0041F070

下面VM会进行一次OR操作,标志位00000293 OR 00000100=00000393并把结果压入EFLAGS寄存器,伪指令过程如下:

0013F77C 0013F780 .

0013F780 00000008 ...

0013F784 00000100 ...

0013F788 00000293 ..

0013F78C 0013FFE0 . ; Pointer to next SEH record

0013F790 0041F070 pA. ; SE handler

0013F794 0013FF98 .

VM_ADDdw_EBPSTACK

0013F780 0013F788 .

0013F784 00000100 ...

0013F788 00000293 ..

VM_COPYdw_EBPSTACK

0013F780 00000293 ..

0013F784 00000100 ...

0013F788 00000293 ..

VM_NANDdw

0013F784 FFFFFC6C l

0013F788 00000293 ..

VM_PUSHdw_EBP

VM_COPYdw_EBPSTACK

0013F780 FFFFFC6C l

0013F784 FFFFFC6C l

0013F788 00000293 ..

VM_NANDdw

0013F784 00000393 ..

0013F788 00000293 ..

VM_PUSHdw_EBP

0013F780 0013F784 .

0013F784 00000393 ..

0013F788 00000293 ..

VM_PUSHdw_IMMEDIATEb

0013F77C 00000004 ...

0013F780 0013F784 .

0013F784 00000393 ..

0013F788 00000293 ..

VM_ADDdw_EBPSTACK

0013F780 0013F788 .

0013F784 00000393 ..

0013F788 00000293 ..

VM_MOVdw_MEMORYdw_EBPSTACKdw

0013F788 00000393 ..

0013F758 00000286 ..

0013F75C 0013FF8C . ; ASCII "ntdll.dll"

0013F760 00000206 ..

0013F764 00426C00 .lB.

0013F768 0000000A ....

0013F76C 00000000 ....

0013F770 0013FF98 .

0013F774 00000000 ....

0013F778 00005658 XV..

0013F77C 0013FF70 p.

0013F780 0013FF8C . ; ASCII "ntdll.dll"

0013F784 00428173 sB.

0013F788 00000393 ..

VM_EXIT

在VM_EXIT中,最后一个数据00000393是

00428173 9D POPFD ; *

被压入了EFLAGS寄存器,现在我们可以看看00000100这个OR操作数影响的是Trap Flag(TF)位,这个过程就是把标志位的TF位置1。根据Intel资料:

TF (bit 8) Trap flag — Set to enable single-step mode for debugging;

clear to disable single-step mode.

也就是VM设置单步模式(single-step mode)。下面我们来回头进好好看看00428173这个过程的详细代码:

00428173 |. 9D POPFD ; *

00428174 |. 0F31 RDTSC

00428176 |. 90 NOP

00428177 |. 9C PUSHFD

00428178 |. C70424 0A429C MOV DWORD PTR SS:[ESP],489C420A

0042817F |. 9C PUSHFD

00428180 \. E9 58030100 JMP 004384DD

这段代码你要是一条一条的F7走下去,完全没有问题。能够一直走到JMP 004384DD这里,然后程序就开始初始化VM,看不到任何的问题。而事实上你已经中招了。接下来就等着看被VMP发现的提示框吧。

而如果你直接在进入这个00428173的过程前来一个F9,比如说VM_EXIT伪指令处。你就会发现程序被拦截下来了

00428173 |. 9D POPFD ; * single-step mode

00428174 |. 0F31 RDTSC

00428176 |. 90 NOP ;*************************

00428177 |. 9C PUSHFD

00428178 |. C70424 0A429C MOV DWORD PTR SS:[ESP],489C420A

0042817F |. 9C PUSHFD

00428180 \. E9 58030100 JMP 004384DD

在NOP指令这里,程序就被拦截下来了。看一下OD下角的提示框显示:

Break on single-step trap set by application - Shift+Run/Step to pass exception to the program

来说说原理,由于OD这样的Ring3调试器,F7单步靠的就是TF标志位,所以如果你单步走这段代码。VM程序设置的TF位就会和OD调试器的TF位相同,OD以为是自己的单步调试,就不会触发这个异常,而一旦你F9运行程序,OD才会发现:哦,原来这里调试的程序自己设置一个TF单步异常!注意看OD给的提示消息:中断在应用程序设置的单步陷阱-Shift+Run/Step跳过程序异常

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值