wai1216 发表于 2019-12-14 21:18:46

[2019/12/21更新]一些有关vmp3.x

本帖最后由 wai1216 于 2019-12-21 18:28 编辑

1.有关syscall

首先描述如下 A/B/C 三套方案

// A x86
LoadLibraryA kernel32.dll
LoadLibraryA ntdll.dll
IsDebuggerPresent
CheckRemoteDebuggerPresent
CloseHandle // 0xdeadc0de
int3 --> NtQueryInformationProcess 0x1e
NtSetInformationThread 0x11
VirtualProtect N
LocalAlloc 0x68 bytes
...

// B x64
LoadLibraryA kernel32.dll
LoadLibraryA ntdll.dll
IsDebuggerPresent
CheckRemoteDebuggerPresent
NtQueryInformationProcess 0x1e
NtSetInformationThread 0x11
VirtualProtect N
LocalAlloc 0xd0 bytes
...

// C x64
LocalAlloc 0x160 bytes
// anti debug
GetModuleHandleA kernel32.dll
GetModuleHandleA ntdll.dll
IsDebuggerPresent
CheckRemoteDebuggerPresent
syscall 0x19 // NtQueryInformationProcess 0x1e
syscall 0xd// NtSetInformationThread 0x11
NtQuerySystemInformation 0x23
NtQuerySystemInformation 0xb
LocalAlloc // ModuleInformation buffer size
NtQuerySystemInformation 0xb
LocalFree
// check file
GetModuleFileNameW
syscall 0x33 // NtOpenFile
syscall 0x4a // NtCreateSection
syscall 0x28 // NtMapViewOfSection
syscall 0x2a // NtUnmapViewOfSection
syscall 0xf// NtClose
syscall 0xf// NtClose
syscall 0x50 // NtProtectVirtualMemory   ==> N == NumberOfSections
...


先说syscall,vmp呢
在3.x的时候使用了syscall去实现一些anti,像C(如下DiskGenius_0884_x64英文版)的样本所描述的一样
如果熟悉syscall调用的话,应该能看来这几个index是win10 x64上的syscall编号
附上调用表(https://github.com/j00ru/windows-syscalls) // 比如 NtQueryInformationProcess 在 win7 x64 上为 0x16
当然有些时候使用vmp3.x也会加出像B一样的代码

走syscall在r3层处理起来不是很容易,有次xjun师傅告诉过我,他怎么做的处理,使得还是走r3进行检测
后来由于一些原因,我分析了下

通过目标文件DiskGenius_0884_x64的英文版来简明阐述一下,原理:
DiskGenius_0884_x64.exe
MD5 74378fdb9ae9685b8b4137df3a134e93
SHA1 ef7e6d7010235610920a346c99acdc5ffda39ed1


GetModuleHandleA ntdll.dll

IsDebuggerPresent
之间开始说起 LocalAlloc 以后再说

注意到这里 vmp 通过调用 GetModuleHandleA 去获取到 ntdll.dll 的地址
当然能获取到 kernel/nt 的方式很多,比如前段时间看过的一个叫sprotect壳样本就采用的从 ldr链 去得到的地址,读 next节点 的方式倒是蛮巧妙

获取到 ntdll.dll 的地址之后, vmp 从 teb 读取到 peb 的地址
000000014340D0E2 | 4D:8B08                  | mov r9,qword ptr ds:                           |
000000014340D0E5 | 66:C1DA 0B               | rcr dx,B                                             |
000000014340D0E9 | 6549:8B11                | mov rdx,qword ptr gs:                            |
在从 peb 中读取到 OSBuildNumber(0x120)
0000000143361881 | 49:8B08                  | mov rcx,qword ptr ds:                            |
0000000143361884 | F6DE                     | neg dh                                             |
0000000143361886 | 66:98                  | cbw                                                |
0000000143361888 | 66:8B01                  | mov ax,word ptr ds:                           |
之后 vmp 开始根据 OSBuildNumber 进行 有关 syscall index 的计算了
但假如 OSBuildNumber 发生错误,或者说不对的情况下会出现什么情况呢
首先读取了 ntdll.dll 的 dos头,也就是 si == "MZ"(0x5A4D)
00000001433937FF | 49:8B03                  | mov rax,qword ptr ds:                           |
0000000143393802 | 40:86F1                  | xchg cl,sil                                          |
0000000143393805 | 66:8B30                  | mov si,word ptr ds:                           |
判断完之后再读到 pe头 的 偏移
00000001433B014F | 48:8B4C25 00             | mov rcx,qword ptr ss:                           |
00000001433B0154 | 44:8B09                  | mov r9d,dword ptr ds:                           |
然后再读取到 pe头, 也就是 r9d == "PE"(0x4550)
00000001433CF1BF | 48:8B4C25 00             | mov rcx,qword ptr ss:                           |
00000001433CF1C4 | 6641:81E1 E077         | and r9w,77E0                                       |
00000001433CF1CA | 41:80C9 52               | or r9b,52                                          |
00000001433CF1CE | 44:8B09                  | mov r9d,dword ptr ds:                           |
判断完之后再读 Resource(IMAGE_DATA_DIRECTORY) 的 VirtualAddress
0000000143397320 | 49:8B03                  | mov rax,qword ptr ds:                           |
0000000143397323 | 44:8B08                  | mov r9d,dword ptr ds:                           |
0000000143397326 | 41:0FBCD4                | bsf edx,r12d                                       |
之后再读取 Resource(IMAGE_DATA_DIRECTORY) 的 Size
0000000143397320 | 49:8B03                  | mov rax,qword ptr ds:                           |
0000000143397323 | 44:8B08                  | mov r9d,dword ptr ds:                           |
0000000143397326 | 41:0FBCD4                | bsf edx,r12d                                       |
之后再从.rsrc开始如下比较
0000000141FE03DE | 66:8378 FC 46            | cmp word ptr ds:,46                           | 46:'F'
0000000141FE03E3 | 0F85 049D6700            | jne diskgenius_0884_x64.14265A0ED                  |
      000000014265A0ED | 48:FFC1                  | inc rcx                                              |
      000000014265A0F0 | 48:83C0 02               | add rax,2                                          |
      000000014265A0F4 | 6641:3BCD                | cmp cx,r13w                                          |
      000000014265A0F8 | 48:3BCA                  | cmp rcx,rdx                                          | rdx:L"fibers-l2-1-1"
      000000014265A0FB | E9 9011A0FF            | jmp diskgenius_0884_x64.14205B290                  |
0000000141FE03E9 | 66:8378 FE 69            | cmp word ptr ds:,69                           | 69:'i'
0000000141FE03EE | E9 2F410100            | jmp diskgenius_0884_x64.141FF4522                  |
-->
0000000141FF4522 | 0F85 C55B6600            | jne diskgenius_0884_x64.14265A0ED                  |
0000000141FF4528 | 66:8338 6C               | cmp word ptr ds:,6C                           | 6C:'l'
0000000141FF452C | E9 E9636700            | jmp diskgenius_0884_x64.14266A91A                  |
-->
000000014266A91A | 0F85 CDF7FEFF            | jne diskgenius_0884_x64.14265A0ED                  |
000000014266A920 | 66:8378 02 65            | cmp word ptr ds:,65                           | 65:'e'
000000014266A925 | E9 F56BD6FF            | jmp diskgenius_0884_x64.1423D151F                  |
-->
00000001423D151F | 0F85 C88B2800            | jne diskgenius_0884_x64.14265A0ED                  |
00000001423D1525 | 66:8378 04 56            | cmp word ptr ds:,56                           | 56:'V'
00000001423D152A | E9 E1B30100            | jmp diskgenius_0884_x64.1423EC910                  |
-->
00000001423EC910 | 0F85 D7D72600            | jne diskgenius_0884_x64.14265A0ED                  |
00000001423EC916 | 66:8378 06 65            | cmp word ptr ds:,65                           | 65:'e'
00000001423EC91B | E9 35F12600            | jmp diskgenius_0884_x64.14265BA55                  |
-->
000000014265BA55 | 0F85 92E6FFFF            | jne diskgenius_0884_x64.14265A0ED                  |
000000014265BA5B | 66:8378 08 72            | cmp word ptr ds:,72                           | 72:'r'
000000014265BA60 | E9 FB1E9FFF            | jmp diskgenius_0884_x64.14204D960                  |
-->
000000014204D960 | 0F85 87C76000            | jne diskgenius_0884_x64.14265A0ED                  |
000000014204D966 | 66:8378 0A 73            | cmp word ptr ds:,73                           | 73:'s'
000000014204D96B | E9 C85DFBFF            | jmp diskgenius_0884_x64.142003738                  |
-->
000000014200373E | 66:8378 0C 69            | cmp word ptr ds:,69                           | 69:'i'
0000000142003743 | 0F85 A4696500            | jne diskgenius_0884_x64.14265A0ED                  |
0000000142003749 | 66:8378 0E 6F            | cmp word ptr ds:,6F                           | 6F:'o'
000000014200374E | E9 2B9C3D00            | jmp diskgenius_0884_x64.1423DD37E                  |
-->
00000001423DD37E | 0F85 69CD2700            | jne diskgenius_0884_x64.14265A0ED                  |
00000001423DD384 | 66:8378 10 6E            | cmp word ptr ds:,6E                        | 6E:'n'
00000001423DD389 | E9 43CD2700            | jmp diskgenius_0884_x64.14265A0D1                  |
-->
000000014265A0D1 | 0F85 16000000            | jne diskgenius_0884_x64.14265A0ED                  |
000000014265A0D7 | 66:8378 12 00            | cmp word ptr ds:,0                           |
000000014265A0DC | 0F85 0B000000            | jne diskgenius_0884_x64.14265A0ED                  |
000000014265A0E2 | 66:8378 14 00            | cmp word ptr ds:,0                           |
000000014265A0E7 | 0F84 57F5F4FF            | je diskgenius_0884_x64.1425A9644                     |
-->

最后获取到版本的地址
00000001425A9644 | 49:8D4448 1A             | lea rax,qword ptr ds:                   | rax:L"leVersion", r8+rcx*2+1A:L"10.0.18362.418 (WinBuild.160101.0800)"

开始读地址内容
00000001433A5949 | 4C:8B1B                  | mov r11,qword ptr ds:                           |
00000001433A594C | 6640:0FBED7            | movsx dx,dil                                       |
00000001433A5951 | 6641:8B33                | mov si,word ptr ds:                           |
-->
00000001433548B2 | 66:8B10                  | mov dx,word ptr ds:                           | rax:L"0.0.18362.418 (WinBuild.160101.0800)"
00000001433548B5 | 48:81C5 06000000         | add rbp,6                                          |
00000001433548BC | 45:86D2                  | xchg r10b,r10b                                       |
00000001433548BF | 41:80EA 03               | sub r10b,3
--->
000000014334E25B | 49:8B08                  | mov rcx,qword ptr ds:                            | rcx:L"18362.418 (WinBuild.160101.0800)", :L"18362.418 (WinBuild.160101.0800)"
000000014334E25E | 66:D3CA                  | ror dx,cl                                          |
000000014334E261 | 66:8B01                  | mov ax,word ptr ds:                           | rcx:L"18362.418 (WinBuild.160101.0800)"
-->

几次相同的,直到读完到版本号,如18362.读到 (.)0x2e 结束
000000014342F6E3 | 49:8B30                  | mov rsi,qword ptr ds:                            | rsi:L"17134.799 (WinBuild.160101.0800)", :L"17134.799 (WinBuild.160101.0800)"
000000014342F6E6 | 66:8B16                  | mov dx,word ptr ds:                           | rsi:L"17134.799 (WinBuild.160101.0800)"
000000014342F6E9 | 41:0FB7C8                | movzx ecx,r8w                                        |
然后把得到的18362转成十六进制数 // 即 r11w = == 0x47ba
00000001433311CC | 6645:8B18                | mov r11w,word ptr ds:                            |
00000001433311D0 | 6641:8B40 02             | mov ax,word ptr ds:                            |
00000001433311D5 | 40:F6DE                  | neg sil                                              |
00000001433311D8 | 49:81E8 06000000         | sub r8,6                                             |
00000001433311DF | 66:C1FE A3               | sar si,A3                                          |
00000001433311E3 | 41:22F4                  | and sil,r12b                                       |
00000001433311E6 | 66:03F7                  | add si,di                                          |
00000001433311E9 | 6641:F7D3                | not r11w                                             |
00000001433311ED | 49:0BF5                  | or rsi,r13                                           |
00000001433311F0 | 66:F7D0                  | not ax                                             |
00000001433311F3 | 66:C1FE 1E               | sar si,1E                                          |
00000001433311F7 | 6644:0BD8                | or r11w,ax                                           |
00000001433311FB | 6645:8958 08             | mov word ptr ds:,r11w                        |
0000000143331200 | 48:63F7                  | movsxd rsi,edi                                       |
0000000143331203 | 48:0FBFF4                | movsx rsi,sp                                       |
0000000143331207 | 9C                     | pushfq                                             |
0000000143331208 | 49:33F2                  | xor rsi,r10                                          |
000000014333120B | 41:8F00                  | pop qword ptr ds:                              |


--------------------------------------------------
另注意到 该样本(如C所描述)中的 NtQueryInformationProcess 会check以下两点
1.RetValue == 0xC0000353 ( STATUS_PORT_NOT_SET)
2.*ReturnLength != NULL // ReturnLength == ProcessInformation 即 r8 == rsp + xx
其实对于第二点的check并不是太严密,check的数值是否为0,但如果看过wrk相关代码的会知道
#define ARGUMENT_PRESENT(x) ((x) != NULL)
if (ARGUMENT_PRESENT (ReturnLength) )
{
   *ReturnLength = sizeof(HANDLE);
}
--------------------------------------------------

2.有关calc
以check IsDebuggerPresent的返回值为例
首先将 retvalue = vm_context(rcx = 0) = 11111111
0000000143401AAA | 40:32F9                  | xor dil,cl                                           |
0000000143401AAD | 40:1AC4                  | sbb al,spl                                           |
0000000143401AB0 | 48:89140C                | mov qword ptr ss:,rdx                     |
0000000143401AB4 | D2F0                     | shl al,cl                                          |
之后从vm字节码读取到 700C5C064835B726 放入 r8
00000001432E6CF9 | 49:8B11                  | mov rdx,qword ptr ds:                            |
00000001432E6CFC | 40:B5 8B               | mov bpl,8B                                           |
00000001432E6CFF | 48:0FBBF5                | btc rbp,rsi                                          |
00000001432E6D03 | 48:D3C5                  | rol rbp,cl                                           |
00000001432E6D06 | 49:81C1 08000000         | add r9,8                                             |
00000001432E6D0D | 66:0FC1ED                | xadd bp,bp                                           |
00000001432E6D11 | 48:33D7                  | xor rdx,rdi                                          |
00000001432E6D14 | 40:FECD                  | dec bpl                                              |
00000001432E6D17 | 0FBFEC                   | movsx ebp,sp                                       |
00000001432E6D1A | 48:FFC2                  | inc rdx                                              |
00000001432E6D1D | 40:0F91C5                | setno bpl                                          |
00000001432E6D21 | 48:D1CA                  | ror rdx,1                                          |
00000001432E6D24 | 6640:0FB6EC            | movzx bp,spl                                       |
00000001432E6D29 | 48:F7D2                  | not rdx                                              |
00000001432E6D2C | FFC5                     | inc ebp                                              |
00000001432E6D2E | 48:FFC2                  | inc rdx                                              |
00000001432E6D31 | 48:F7D2                  | not rdx                                              |
00000001432E6D34 | 66:0FBEE8                | movsx bp,al                                          |
00000001432E6D38 | 40:0F9DC5                | setge bpl                                          |
00000001432E6D3C | 48:FFC2                  | inc rdx                                              |
00000001432E6D3F | 48:33FA                  | xor rdi,rdx                                          |
00000001432E6D42 | 49:81E8 08000000         | sub r8,8                                             |
00000001432E6D49 | 48:3BFE                  | cmp rdi,rsi                                          |
00000001432E6D4C | D3DD                     | rcr ebp,cl                                           |
00000001432E6D4E | 49:8910                  | mov qword ptr ds:,rdx                            |
之后再从vm字节码读取一个地址 00000001432F7C60 放入 r8 // 注意到上面的 r8 = r8 - 8
000000014341F308 | 49:8B11                  | mov rdx,qword ptr ds:                            |
000000014341F30B | F9                     | stc                                                |
000000014341F30C | FFCD                     | dec ebp                                              |
000000014341F30E | 49:81C1 08000000         | add r9,8                                             |
000000014341F315 | 41:0FBFEC                | movsx ebp,r12w                                       |
000000014341F319 | 48:33D7                  | xor rdx,rdi                                          |
000000014341F31C | 0FB7E9                   | movzx ebp,cx                                       |
000000014341F31F | E9 F695FFFF            | jmp diskgenius_0884_x64.14341891A                  |
-->
0000000143418949 | 66:0F4BE8                | cmovnp bp,ax                                       |
000000014341894D | 49:0FB7EA                | movzx rbp,r10w                                       |
0000000143418951 | 48:FFC2                  | inc rdx                                              |
0000000143418954 | 66:0FBAFD E8             | btc bp,E8                                          |
0000000143418959 | 66:BD F749               | mov bp,49F7                                          |
000000014341895D | 66:C1DD 98               | rcr bp,98                                          |
0000000143418961 | 48:33FA                  | xor rdi,rdx                                          |
0000000143418964 | 40:C0E5 8C               | shl bpl,8C                                           |
0000000143418968 | 45:3AE4                  | cmp r12b,r12b                                        |
000000014341896B | 41:22E8                  | and bpl,r8b                                          |
000000014341896E | 49:81E8 08000000         | sub r8,8                                             |
0000000143418975 | 49:8910                  | mov qword ptr ds:,rdx                            |
之后从该地址读取到 684B8EFD1F4CBE6B 放入 r8 // 同上 注意到上面的 r8 = r8 - 8
00000001434243C6 | 49:8B28                  | mov rbp,qword ptr ds:                            |
00000001434243C9 | 41:12C4                  | adc al,r12b                                          |
00000001434243CC | 48:8B4425 00             | mov rax,qword ptr ss:                           |
00000001434243D1 | 49:8900                  | mov qword ptr ds:,rax                            |
00000001434243D4 | 66:0FABED                | bts bp,bp                                          |
再调用加法得到 D857EB0367827591 = 684B8EFD1F4CBE6B + 700C5C064835B726 放入 r8 + 8
再存放 eflags 到 r8 = 0xa92
000000014338579C | 49:8B00                  | mov rax,qword ptr ds:                            |
000000014338579F | 4D:8B50 08               | mov r10,qword ptr ds:                        |
00000001433857A3 | 49:03C2                  | add rax,r10                                          |
00000001433857A6 | E9 E7B30300            | jmp diskgenius_0884_x64.1433C0B92                  |
00000001433C0B92 | 49:8940 08               | mov qword ptr ds:,rax                        |
-->
00000001433C0BA1 | 9C                     | pushfq                                             |
00000001433C0BA2 | 41:8F00                  | pop qword ptr ds:                              |
保存 eflags 到 vm_context(rcx = 0x20) = 0xa92
00000001433D9CD3 | 49:8B10                  | mov rdx,qword ptr ds:                            |
00000001433D9CD6 | D3C8                     | ror eax,cl                                           |
00000001433D9CD8 | 0FBAF0 48                | btr eax,48                                           |
00000001433D9CDC | 48:F7D8                  | neg rax                                              |
00000001433D9CDF | 49:81C0 08000000         | add r8,8                                             |
00000001433D9CE6 | 0F91C4                   | setno ah                                             |
00000001433D9CE9 | 41:0FB609                | movzx ecx,byte ptr ds:                           |
00000001433D9CED | 44:3BCE                  | cmp r9d,esi                                          |
00000001433D9CF0 | 49:81C1 01000000         | add r9,1                                             |
00000001433D9CF7 | 48:C1E8 B0               | shr rax,B0                                           |
00000001433D9CFB | 66:0FB3C8                | btr ax,cx                                          |
00000001433D9CFF | 40:32CF                  | xor cl,dil                                           |
00000001433D9D02 | 66:0FB6C1                | movzx ax,cl                                          |
00000001433D9D06 | 49:0FBFC4                | movsx rax,r12w                                       |
00000001433D9D0A | FEC9                     | dec cl                                             |
00000001433D9D0C | 66:0FB6C0                | movzx ax,al                                          |
00000001433D9D10 | D0C9                     | ror cl,1                                             |
00000001433D9D12 | B0 3F                  | mov al,3F                                          | 3F:'?'
00000001433D9D14 | FEC1                     | inc cl                                             |
00000001433D9D16 | 66:C1D0 E6               | rcl ax,E6                                          |
00000001433D9D1A | F6D9                     | neg cl                                             |
00000001433D9D1C | F6D4                     | not ah                                             |
00000001433D9D1E | D0C1                     | rol cl,1                                             |
00000001433D9D20 | 1C 36                  | sbb al,36                                          |
00000001433D9D22 | 41:22C4                  | and al,r12b                                          |
00000001433D9D25 | 33C5                     | xor eax,ebp                                          |
00000001433D9D27 | 40:32F9                  | xor dil,cl                                           |
00000001433D9D2A | 0FB7C3                   | movzx eax,bx                                       |
00000001433D9D2D | 48:63C2                  | movsxd rax,edx                                       |
00000001433D9D30 | 48:89140C                | mov qword ptr ss:,rdx                     |
轮转 vm_context 之后
mov reg0, qword ptr ss:
sub r8, 0x08
mov qword ptr ds:, reg0
-->
mov reg0, qword ptr ds:
movzx reg1, byte ptr ds:
decrypt reg1
mov qword ptr ss:, reg1
从 vm字节码 读取 79BA102F4FDAB902 放入 r8
00000001433C22B9 | 49:8B11                  | mov rdx,qword ptr ds:                            |
00000001433C22BC | 45:84D6                  | test r14b,r10b                                       |
00000001433C22BF | 49:81C1 08000000         | add r9,8                                             |
00000001433C22C6 | 48:33D7                  | xor rdx,rdi                                          |
00000001433C22C9 | 49:0FBFE8                | movsx rbp,r8w                                        |
00000001433C22CD | 41:0FB7E8                | movzx ebp,r8w                                        |
00000001433C22D1 | 40:0F91C5                | setno bpl                                          |
00000001433C22D5 | 48:FFC2                  | inc rdx                                              |
00000001433C22D8 | 48:D3CD                  | ror rbp,cl                                           |
00000001433C22DB | 48:D1CA                  | ror rdx,1                                          |
00000001433C22DE | 6641:0FB6E9            | movzx bp,r9b                                       |
00000001433C22E3 | 48:8BE8                  | mov rbp,rax                                          |
00000001433C22E6 | 48:87ED                  | xchg rbp,rbp                                       |
00000001433C22E9 | 48:F7D2                  | not rdx                                              |
00000001433C22EC | 40:86ED                  | xchg bpl,bpl                                       |
00000001433C22EF | 6641:0FBEEE            | movsx bp,r14b                                        |
00000001433C22F4 | 49:0FBFE8                | movsx rbp,r8w                                        |
00000001433C22F8 | 48:FFC2                  | inc rdx                                              |
00000001433C22FB | 0FBFEE                   | movsx ebp,si                                       |
00000001433C22FE | 66:0FBEEB                | movsx bp,bl                                          |
00000001433C2302 | 48:F7D2                  | not rdx                                              |
00000001433C2305 | 0FB7E9                   | movzx ebp,cx                                       |
00000001433C2308 | 48:FFC2                  | inc rdx                                              |
00000001433C230B | F5                     | cmc                                                |
00000001433C230C | 48:33FA                  | xor rdi,rdx                                          |
00000001433C230F | 4C:0FACDD DE             | shrd rbp,r11,DE                                    |
00000001433C2314 | 6644:0FA3D5            | bt bp,r10w                                           |
00000001433C2319 | 66:D3FD                  | sar bp,cl                                          |
00000001433C231C | 49:81E8 08000000         | sub r8,8                                             |
00000001433C2323 | 81CD 90020B23            | or ebp,230B0290                                    |
00000001433C2329 | 40:C0FD E9               | sar bpl,E9                                           |
00000001433C232D | 49:8910                  | mov qword ptr ds:,rdx                            |
再从 vm字节码 读取 00000001432F7C68 放入 r8
0000000143340A1F | 49:8B11                  | mov rdx,qword ptr ds:                            |
0000000143340A22 | 66:81DD 244A             | sbb bp,4A24                                          |
0000000143340A27 | 66:0FCD                  | bswap bp                                             |
0000000143340A2A | 48:81ED 42028E63         | sub rbp,638E0242                                     |
0000000143340A31 | 49:81C1 08000000         | add r9,8                                             |
-->
0000000143340A86 | 48:C1ED 75               | shr rbp,75                                           |
0000000143340A8A | 49:8910                  | mov qword ptr ds:,rdx                            |
然后从 vm字节码读出来的地址 再读 8645EFD1F142DF47 放入 r8
000000014332107B | 49:8B28                  | mov rbp,qword ptr ds:                            |
000000014332107E | D2C8                     | ror al,cl                                          |
0000000143321080 | C0FC BD                  | sar ah,BD                                          |
0000000143321083 | 48:8B4425 00             | mov rax,qword ptr ss:                           |
0000000143321088 | 41:0FBFEA                | movsx ebp,r10w                                       |
000000014332108C | 6641:8BEA                | mov bp,r10w                                          |
0000000143321090 | 49:8900                  | mov qword ptr ds:,rax                            |
调用 vm_add 得到一个大数 0x100000001411D9849 = 0x79BA102F4FDAB902 + 0x8645EFD1F142DF47
将 0x00000001411D9849 放入 r8 + 8
将 eflag=203 放入 r8
00000001432FCAF2 | 49:8B00                  | mov rax,qword ptr ds:                            |
00000001432FCAF5 | 41:C1EA 49               | shr r10d,49                                          |
00000001432FCAF9 | 66:C1F5 4B               | shl bp,4B                                          |
00000001432FCAFD | 41:C0E2 EB               | shl r10b,EB                                          |
00000001432FCB01 | 4D:8B50 08               | mov r10,qword ptr ds:                        |
00000001432FCB05 | 40:80CD C5               | or bpl,C5                                          |
00000001432FCB09 | 40:D2DD                  | rcr bpl,cl                                           |
00000001432FCB0C | 49:03C2                  | add rax,r10                                          |
00000001432FCB0F | 6641:8BEB                | mov bp,r11w                                          |
00000001432FCB13 | 49:8940 08               | mov qword ptr ds:,rax                        |
00000001432FCB17 | 6641:0F48EA            | cmovs bp,r10w                                        |
00000001432FCB1C | 66:0FCD                  | bswap bp                                             |
00000001432FCB1F | 66:0FB6E8                | movzx bp,al                                          |
00000001432FCB23 | 9C                     | pushfq                                             |
00000001432FCB24 | 0FBFEB                   | movsx ebp,bx                                       |
00000001432FCB27 | 0FB7E8                   | movzx ebp,ax                                       |
00000001432FCB2A | 40:0F96C5                | setbe bpl                                          |
00000001432FCB2E | 41:8F00                  | pop qword ptr ds:                              |
00000001432FCB31 | 6641:0FBEEA            | movsx bp,r10b                                        |
00000001432FCB36 | 6644:0FA3E5            | bt bp,r12w                                           |
00000001432FCB3B | 41:8B29                  | mov ebp,dword ptr ds:                            |


注意到这里:
已经两次了,从这里我们可以看到 vmp3.x的一些变化,比如说读数的方式上变成了这种形式
Read A1
Read pA2
Read A2 From pA2
A = (uint64_t)(A1 + A2)
Save Eflag
由此可见 vmp3.x 为了改变运算,增加了多少 vm字节码 的空间


保存 eflag = 203 到 vm_context(rcx = 0x88)
00000001433F4789 | 41:3BD6                  | cmp edx,r14d                                       |
00000001433F478C | 48:89140C                | mov qword ptr ss:,rdx                     |
00000001433F4790 | 66:0FBAF0 6B             | btr ax,6B                                          |
保存 计算出来的00000001411D9849 到 vm_context(rcx == 0xc0)
0000000143401AAD | 40:1AC4                  | sbb al,spl                                           |
0000000143401AB0 | 48:89140C                | mov qword ptr ss:,rdx                     |
0000000143401AB4 | D2F0                     | shl al,cl                                          |
将当前 r8 保存一次 == 000000000014F880
000000014333829B | 4D:8BD8                  | mov r11,r8                                           |
000000014333829E | 41:80FF B5               | cmp r15b,B5                                          |
00000001433382A2 | 2C BE                  | sub al,BE                                          |
00000001433382A4 | 49:81E8 08000000         | sub r8,8                                             |
00000001433382AB | F6D0                     | not al                                             |
00000001433382AD | 4D:8918                  | mov qword ptr ds:,r11                            |
开始把 vm_context的数据 复制到
再保存到 vm_context(rcx = 0xc8)
00000001433D9CD3 | 49:8B10                  | mov rdx,qword ptr ds:                            |
...
00000001433D9CE9 | 41:0FB609                | movzx ecx,byte ptr ds:                           |
...
00000001433D9D30 | 48:89140C                | mov qword ptr ss:,rdx                     |
读取vm_context(r10 = 0xb8) = 000000000014F8D0 ] 到 r8
000000014332B11F | 45:0FB611                | movzx r10d,byte ptr ds:                        |
..
000000014332B173 | 4A:8B1414                | mov rdx,qword ptr ss:                     |
..
000000014332B18C | 49:8910                  | mov qword ptr ds:,rdx                            |
再保存到 vm_context(rcx = 0xd0)
000000014332C492 | 49:8B10                  | mov rdx,qword ptr ds:                            |
...
000000014332C4A6 | 41:0FB609                | movzx ecx,byte ptr ds:                           |
...
000000014332C500 | 48:89140C                | mov qword ptr ss:,rdx                     |
读取 vm_context(r10 = 0xa8) = 0000000000000019 到 r8
0000000143428847 | 4A:8B1414                | mov rdx,qword ptr ss:                     |
..
0000000143428866 | 49:8910                  | mov qword ptr ds:,rdx                            |
再保存 = 0x19 到 vm_context(0xd8) = 0x19
0000000143301512 | 49:8B10                  | mov rdx,qword ptr ds:                            |
...
0000000143301521 | 41:0FB609                | movzx ecx,byte ptr ds:                           |
...
00000001432DADFE | 48:89140C                | mov qword ptr ss:,rdx                     |
再保存 vm_context(0x30) = 0xd 到 r8
00000001433F73CD | 45:0FB611                | movzx r10d,byte ptr ds:                        |
...
00000001433F7412 | 4A:8B1414                | mov rdx,qword ptr ss:                     |
...
00000001433F742D | 49:8910                  | mov qword ptr ds:,rdx                            |
不知道 这两个 0x19 0xd 有没有引起读者的注意呢

注意到:
为了方便阅读,现在所给出的vmp原本本身的handle,未添加混淆代码的片段

之后就是继续读到r8,直到00000001433B742A
开始将 retvalue 进行not not or

A = not(retvalue) or not(retvalue) // (~(retvalue) | (~retvalue)) // EEEEEEEE
B = eflag_0(0x286)
00000001433B742A | 45:8B18                  | mov r11d,dword ptr ds:                           |
...
00000001433B7435 | 41:8B68 04               | mov ebp,dword ptr ds:                        |
...
00000001433B7451 | 41:F7D3                  | not r11d                                             |
...
00000001433B745E | F7D5                     | not ebp                                              |
00000001433B7460 | 44:0BDD                  | or r11d,ebp                                          |
...
00000001433B746C | 45:8958 08               | mov dword ptr ds:,r11d                         |
...
00000001433B7474 | 9C                     | pushfq                                             |
...
00000001433B747B | 41:8F00                  | pop qword ptr ds:                              |
再保存 B 到 vm_context(rcx = 0x80)
00000001433AF9F5 | 49:8B10                  | mov rdx,qword ptr ds:                            |
...
00000001433AFA02 | 41:0FB609                | movzx ecx,byte ptr ds:                           |
...
00000001433AFA51 | 48:89140C                | mov qword ptr ss:,rdx                     |
再将 A 进行如下运算

C = not(A) and not(A) // ~A & ~A 11111111
D = eflag_1(0x206)
00000001432EC217 | 41:8B30                  | mov esi,dword ptr ds:                            |
...
00000001432EC21E | 41:8B48 04               | mov ecx,dword ptr ds:                        |
...
00000001432EC234 | F7D6                     | not esi                                              |
...
00000001432EC23B | F7D1                     | not ecx                                              |
...
00000001432EC240 | 23F1                     | and esi,ecx                                          |
...
00000001432EC24C | 41:8970 08               | mov dword ptr ds:,esi                        |
...
00000001432EC254 | 9C                     | pushfq                                             |
...
00000001432EC25C | 41:8F00                  | pop qword ptr ds:                              |
再保存 D 到 vm_context(rcx = 0x50)
00000001432DF562 | 49:8B10                  | mov rdx,qword ptr ds:                            |
...
00000001432DF571 | 41:0FB609                | movzx ecx,byte ptr ds:                           |
...
00000001432DF5B9 | 48:89140C                | mov qword ptr ss:,rdx                     |
再保存 C 到 vm_context(rcx = 0x800)
0000000143335C30 | 41:8B10                  | mov edx,dword ptr ds:                            |
...
0000000143335C51 | 41:0FB609                | movzx ecx,byte ptr ds:                           |
...
0000000143335C96 | 89140C                   | mov dword ptr ss:,edx                     |
从 vm字节码 读到 8594
000000014339D78A | 41:0FB729                | movzx ebp,word ptr ds:                           |
...
00000001432D824C | 6641:8928                | mov word ptr ds:,bp                              |
从 vm字节码 读取 地址 00000001432F7C70 // 看到这,读者应该能想到接下来会从该地址读一个数,然后调用vm_add
00000001433534B1 | 49:8B11                  | mov rdx,qword ptr ds:                            |
...
0000000143353513 | 49:8910                  | mov qword ptr ds:,rdx                            |
从 地址 00000001432F7C70 读到 7A72
000000014336814D | 49:8B30                  | mov rsi,qword ptr ds:                            |
...
000000014336815C | 66:8B16                  | mov dx,word ptr ds:                           |
...
0000000143368168 | 49:81C0 06000000         | add r8,6                                             |
000000014336816F | 6641:8910                | mov word ptr ds:,dx                              |
调用加法 得到 10006 注意到 使用的 ax 即 6 // 看到这,熟悉vmp运算的会不会想到什么呢
00000001433B1A2D | 6641:8B00                | mov ax,word ptr ds:                              |
...
00000001433B1A3C | 6641:8B48 02             | mov cx,word ptr ds:                            |
...
00000001433B1A49 | 49:81E8 06000000         | sub r8,6                                             |
...
00000001433B1A5B | 66:03C1                  | add ax,cx                                          |
00000001433B1A5E | 6641:8940 08             | mov word ptr ds:,ax                            |
00000001433B1A63 | 9C                     | pushfq                                             |
...
00000001433B1A68 | 41:8F00                  | pop qword ptr ds:                              |
保存vm_add的eflag vm_context(rcx=0x8) = 0x207之后
再从 vm_context(r10=0x50) 读 D 放入到 r8 中
00000001432DA68E | 45:0FB611                | movzx r10d,byte ptr ds:                        |
...
00000001432DA6D7 | 4A:8B1414                | mov rdx,qword ptr ss:                     |
...
00000001432DA6E6 | 49:81E8 08000000         | sub r8,8                                             |
00000001432DA6ED | 49:8910                  | mov qword ptr ds:,rdx                            |
同上,再从 vm_context(r10=0x50) 读 D 放入到 r8 中
00000001432D8671 | 45:0FB611                | movzx r10d,byte ptr ds:                        |
...
00000001432D86BC | 4A:8B1414                | mov rdx,qword ptr ss:                     |
...
00000001432D86C4 | 49:81E8 08000000         | sub r8,8                                             |
...
00000001432D86D2 | 49:8910                  | mov qword ptr ds:,rdx                            |
采用 not not or 运算

E = not(D) or not(D) // (~(D) | ~(D)) //FFFFFFFFFFFFFDF9
F = eflag_2(0x286)
00000001432EB8C4 | 49:8B00                  | mov rax,qword ptr ds:                            |
...
00000001432EB8CD | 49:8B70 08               | mov rsi,qword ptr ds:                        |
...
00000001432EB8D5 | 48:F7D0                  | not rax                                              |
...
00000001432EB8E3 | 48:F7D6                  | not rsi                                              |
00000001432EB8E6 | 48:0BC6                  | or rax,rsi                                           |
...
00000001432EB8EC | 49:8940 08               | mov qword ptr ds:,rax                        |
...
0000000143397AEB | 9C                     | pushfq                                             |
0000000143397AEC | 41:8F00                  | pop qword ptr ds:                              |
保存 F 到 vm_context(0x78) = 0x286
000000014335D166 | 49:8B10                  | mov rdx,qword ptr ds:                            |
000000014335D169 | 49:81C0 08000000         | add r8,8                                             |
...
000000014335D174 | 41:0FB609                | movzx ecx,byte ptr ds:                           |
...
00000001433F478C | 48:89140C                | mov qword ptr ss:,rdx                     |
从 vm字节码 读取 E4A190D9B51BE79E 到 r8
00000001433B871A | 49:8B11                  | mov rdx,qword ptr ds:                            |
00000001433B871D | 49:81C1 08000000         | add r9,8                                             |
...
0000000143424FC9 | 49:81E8 08000000         | sub r8,8                                             |
0000000143424FD0 | 49:8910                  | mov qword ptr ds:,rdx                            |
...
0000000143424FDF | 41:8B29                  | mov ebp,dword ptr ds:                            |
再从 vm字节码 读取 00000001432F7C72 到 r8 // 和上面一样
00000001433F8ED2 | 49:8B11                  | mov rdx,qword ptr ds:                            |
00000001433F8ED8 | 49:81C1 08000000         | add r9,8                                             |
...
00000001433F8F39 | 49:81E8 08000000         | sub r8,8                                             |
...
00000001433F8F42 | 49:8910                  | mov qword ptr ds:,rdx                            |
再从 上面的地址 00000001432F7C72 读 1B5E6F264AE41821
000000014337A88E | 49:8B28                  | mov rbp,qword ptr ds:                            |
...
000000014337A899 | 48:8B4425 00             | mov rax,qword ptr ss:                           |
...
000000014337A8A9 | 49:8900                  | mov qword ptr ds:,rax                            |
再调用加法得到

G = FFFFFFFFFFFFFFBF
H = 0x282
0000000143324E65 | 49:8B00                  | mov rax,qword ptr ds:                            |
...
0000000143324E73 | 4D:8B50 08               | mov r10,qword ptr ds:                        |
0000000143324E77 | 49:03C2                  | add rax,r10                                          |
...
0000000143324E86 | 49:8940 08               | mov qword ptr ds:,rax                        |
...
0000000143324E92 | 9C                     | pushfq                                             |
...
0000000143324E9E | 41:8F00                  | pop qword ptr ds:                              |
保存 H 到 vm_context(rcx=0x88)
0000000143344BE9 | 49:8B10                  | mov rdx,qword ptr ds:                            |
...
0000000143344BF6 | 49:81C0 08000000         | add r8,8                                             |
0000000143344BFD | 41:0FB609                | movzx ecx,byte ptr ds:                           |
...
0000000143401AB0 | 48:89140C                | mov qword ptr ss:,rdx                     |
再计算 J = not(E) & not(G) // (~E & ~G) // = 0
K = 0x246
000000014332BAA5 | 4D:8B18                  | mov r11,qword ptr ds:                            |
...
000000014332BAB3 | 49:8B48 08               | mov rcx,qword ptr ds:                        |
...
000000014332BABA | 49:F7D3                  | not r11                                              |
...
000000014332BAC0 | 48:F7D1                  | not rcx                                              |
...
00000001433EBF35 | 4C:23D9                  | and r11,rcx                                          |
...
00000001433EBF46 | 9C                     | pushfq                                             |
00000001433EBF47 | 41:8F00                  | pop qword ptr ds:                              |
保存 K 到 vm_context(rcx=0x98)
00000001433D9CD3 | 49:8B10                  | mov rdx,qword ptr ds:                            |
...
00000001433D9CDF | 49:81C0 08000000         | add r8,8                                             |
...
00000001433D9CE9 | 41:0FB609                | movzx ecx,byte ptr ds:                           |
...
00000001433D9D30 | 48:89140C                | mov qword ptr ss:,rdx                     |
然后进行shr运算 // 有所了解的读者,应该很熟悉了
000000014340D9CE | 49:8B10                  | mov rdx,qword ptr ds:                            |
...
000000014340D9D7 | 41:8A48 08               | mov cl,byte ptr ds:                            |
...
000000014340D9DE | 49:81E8 06000000         | sub r8,6                                             |
...
000000014340D9E6 | 48:D3EA                  | shr rdx,cl                                           |
...
000000014340D9F4 | 49:8950 08               | mov qword ptr ds:,rdx                        |


至此,我们可以总结出来,当然之后的修改pc啥的由于篇幅原因没在进行描述
vmp3.x是怎样实现之前的运算的呢
记 A = CheckValue
那么有
B = ~A | ~A
C = ~B & ~B // 另记此时 D = eflag // 运算完 not not and 之后的 eflag
E = vm_add(tmp_data_0,*tmp_data1) = 6 // read from bytecode
F = ~D | ~D
G = vm_add(tmp_eflag_0,*tmp_eflag1) = 0x??????? // 比如 FFFFFFFFFFFFFDF9 // // read from bytecode
H = ~F & ~G
I = shr H,E

从这里就可以看出,vmp作者呢,为了避免之前的策略(模拟cpu的逻辑只做加法而导致的明码),到采用这样的逻辑
所需要增加的bytecode空间太明显了,所以加出来的能不大么


2019/12/21更新
3.有关File corrupted
回过头,我们继续来说C方案,也就是vmp中的 User-mode+Kernel-mode 选项
首先要提一点的是 调用 LocalFree 掉 ModuleInformation buffer 到 GetModuleFileNameW 因文件大小不同而导致运行时效还是有点影响 先不谈这个
如方案中所描述的一样,vmp 之后会校验文件完整性通过
GetModuleFileNameW
NtOpenFile
NtCreateSection
NtMapViewOfSection
..
去完成

这里主要是利用 NtMapViewOfSection 通过NtOpenFile GetModuleFileNameW 将原本文件再次映射到 内存空间中 进行对比校验 以至于 如果patch不好 就导致了那句熟悉的 File corrupted
之后就调用 NtProtectVirtualMemory 修改区段属性
注意通常修改属性的顺序为
.vmp0
.text
.rdata
.pdata
.reloc

接着 vmp 作者 会通过 LocalAlloc 去开辟 0x3e6c 大小的空间 作用以后再说 注意到这里我们所说的还是 x64 条件下
现在我们可以把C方案补充为如下形式了
LocalAlloc 0x160 bytes
// anti debug
GetModuleHandleA kernel32.dll
GetModuleHandleA ntdll.dll
IsDebuggerPresent
CheckRemoteDebuggerPresent
syscall 0x19 // NtQueryInformationProcess 0x1e
syscall 0xd// NtSetInformationThread 0x11
NtQuerySystemInformation 0x23
NtQuerySystemInformation 0xb
LocalAlloc // ModuleInformation buffer size
NtQuerySystemInformation 0xb
LocalFree
// check file
GetModuleFileNameW
syscall 0x33 // NtOpenFile
syscall 0x4a // NtCreateSection
syscall 0x28 // NtMapViewOfSection
syscall 0x2a // NtUnmapViewOfSection
syscall 0xf// NtClose
syscall 0xf// NtClose
syscall 0x50 // NtProtectVirtualMemory   ==> N == NumberOfSections
LocalAlloc 0x3e6c bytes
LocalFree
GetModuleHandleA VCRUNTIME140.dll
GetModuleHandleA api-ms-win-crt-stdio-l1-1-0.dll
GetModuleHandleA api-ms-win-crt-runtime-l1-1-0.dll
GetModuleHandleA api-ms-win-crt-heap-l1-1-0.dll
GetModuleHandleA api-ms-win-crt-math-l1-1-0.dll
GetModuleHandleA api-ms-win-crt-locale-l1-1-0.dll
GetModuleHandleA KERNEL32.dll
GetModuleHandleA NTDLL
GetModuleHandleA WTSAPI32.dll
GetModuleHandleA KERNEL32.dll
GetModuleHandleA NTDLL
GetModuleHandleA NTDLL
GetModuleHandleA NTDLL
GetModuleHandleA NTDLL
GetModuleHandleA NTDLL
GetModuleHandleA NTDLL
GetModuleHandleA NTDLL
GetModuleHandleA NTDLL
GetModuleHandleA NTDLL
GetModuleHandleA USER32.dll
CloseHandle // check 0x00000000DEADC0DE

之后,会遇到这样的代码
popfq
rdtsc
nop
push 0xXXXXXX
call 0xYYYYYY
此时,堆栈会出现这样的情况
rsp:
$ ==>             0000000000000346
$+8               00000000000000xx
$+10            0000000000000xxx
$+18            000000000000xxxx
$+20            00000000000xxxxx
$+28            0000000000xxxxxx
这里会遇到挺有意思的事情,就是将 eflags 赋值为 0x346




-----------------------------------
待续....

zyjsuper 发表于 2019-12-14 21:38:14

感谢分享 不错

bnjzzheng 发表于 2019-12-15 10:05:08

感谢发布原创作品,PYG有你更精彩!

无法无天2020 发表于 2019-12-15 14:22:33


感谢发布原创作品,PYG有你更精彩!

Arsage 发表于 2019-12-15 20:03:24

学习受教了。

不破不立 发表于 2019-12-15 20:34:21

vmp越来越看不懂了

kll545012 发表于 2019-12-17 14:17:20

感谢发布原创作品,PYG有你更精彩!

matali 发表于 2019-12-18 09:20:38

大神都玩透VmP了,**子还怎么变?

085304229 发表于 2019-12-18 11:25:06

虽然暂时看不懂,但是以后肯定能看懂。谢谢分享

Rooking 发表于 2019-12-18 12:25:31

只能膜拜 感觉已经被你玩烂了
页: [1] 2
查看完整版本: [2019/12/21更新]一些有关vmp3.x