- UID
- 70756
注册时间2010-11-1
阅读权限85
最后登录1970-1-1
见习版主
TA的每日心情 | 擦汗 2016-4-19 21:35 |
---|
签到天数: 3 天 [LV.2]偶尔看看I
|
本帖最后由 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:[r8] |
- 000000014340D0E5 | 66:C1DA 0B | rcr dx,B |
- 000000014340D0E9 | 6549:8B11 | mov rdx,qword ptr gs:[r9] |
复制代码
在从 peb 中读取到 OSBuildNumber(0x120)
- 0000000143361881 | 49:8B08 | mov rcx,qword ptr ds:[r8] |
- 0000000143361884 | F6DE | neg dh |
- 0000000143361886 | 66:98 | cbw |
- 0000000143361888 | 66:8B01 | mov ax,word ptr ds:[rcx] |
复制代码
之后 vmp 开始根据 OSBuildNumber 进行 有关 syscall index 的计算了
但假如 OSBuildNumber 发生错误,或者说不对的情况下会出现什么情况呢
首先读取了 ntdll.dll 的 dos头,也就是 si == "MZ"(0x5A4D)
- 00000001433937FF | 49:8B03 | mov rax,qword ptr ds:[r11] |
- 0000000143393802 | 40:86F1 | xchg cl,sil |
- 0000000143393805 | 66:8B30 | mov si,word ptr ds:[rax] |
复制代码
判断完之后再读到 pe头 的 偏移
- 00000001433B014F | 48:8B4C25 00 | mov rcx,qword ptr ss:[rbp] |
- 00000001433B0154 | 44:8B09 | mov r9d,dword ptr ds:[rcx] |
复制代码
然后再读取到 pe头, 也就是 r9d == "PE"(0x4550)
- 00000001433CF1BF | 48:8B4C25 00 | mov rcx,qword ptr ss:[rbp] |
- 00000001433CF1C4 | 6641:81E1 E077 | and r9w,77E0 |
- 00000001433CF1CA | 41:80C9 52 | or r9b,52 |
- 00000001433CF1CE | 44:8B09 | mov r9d,dword ptr ds:[rcx] |
复制代码
判断完之后再读 Resource(IMAGE_DATA_DIRECTORY) 的 VirtualAddress
- 0000000143397320 | 49:8B03 | mov rax,qword ptr ds:[r11] |
- 0000000143397323 | 44:8B08 | mov r9d,dword ptr ds:[rax] |
- 0000000143397326 | 41:0FBCD4 | bsf edx,r12d |
复制代码
之后再读取 Resource(IMAGE_DATA_DIRECTORY) 的 Size
- 0000000143397320 | 49:8B03 | mov rax,qword ptr ds:[r11] |
- 0000000143397323 | 44:8B08 | mov r9d,dword ptr ds:[rax] |
- 0000000143397326 | 41:0FBCD4 | bsf edx,r12d |
复制代码
之后再从.rsrc开始如下比较
- 0000000141FE03DE | 66:8378 FC 46 | cmp word ptr ds:[rax-4],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:[rax-2],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:[rax],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:[rax+2],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:[rax+4],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:[rax+6],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:[rax+8],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:[rax+A],73 | 73:'s'
- 000000014204D96B | E9 C85DFBFF | jmp diskgenius_0884_x64.142003738 |
- -->
- 000000014200373E | 66:8378 0C 69 | cmp word ptr ds:[rax+C],69 | 69:'i'
- 0000000142003743 | 0F85 A4696500 | jne diskgenius_0884_x64.14265A0ED |
- 0000000142003749 | 66:8378 0E 6F | cmp word ptr ds:[rax+E],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:[rax+10],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:[rax+12],0 |
- 000000014265A0DC | 0F85 0B000000 | jne diskgenius_0884_x64.14265A0ED |
- 000000014265A0E2 | 66:8378 14 00 | cmp word ptr ds:[rax+14],0 |
- 000000014265A0E7 | 0F84 57F5F4FF | je diskgenius_0884_x64.1425A9644 |
- -->
复制代码
最后获取到版本的地址
- 00000001425A9644 | 49:8D4448 1A | lea rax,qword ptr ds:[r8+rcx*2+1A] | rax:L"leVersion", r8+rcx*2+1A:L"10.0.18362.418 (WinBuild.160101.0800)"
复制代码
开始读地址内容
- 00000001433A5949 | 4C:8B1B | mov r11,qword ptr ds:[rbx] |
- 00000001433A594C | 6640:0FBED7 | movsx dx,dil |
- 00000001433A5951 | 6641:8B33 | mov si,word ptr ds:[r11] |
- -->
- 00000001433548B2 | 66:8B10 | mov dx,word ptr ds:[rax] | 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:[r8] | rcx:L"18362.418 (WinBuild.160101.0800)", [r8]:L"18362.418 (WinBuild.160101.0800)"
- 000000014334E25E | 66:D3CA | ror dx,cl |
- 000000014334E261 | 66:8B01 | mov ax,word ptr ds:[rcx] | rcx:L"18362.418 (WinBuild.160101.0800)"
- -->
复制代码
几次相同的,直到读完到版本号,如18362. 读到 (.)0x2e 结束
- 000000014342F6E3 | 49:8B30 | mov rsi,qword ptr ds:[r8] | rsi:L"17134.799 (WinBuild.160101.0800)", [r8]:L"17134.799 (WinBuild.160101.0800)"
- 000000014342F6E6 | 66:8B16 | mov dx,word ptr ds:[rsi] | rsi:L"17134.799 (WinBuild.160101.0800)"
- 000000014342F6E9 | 41:0FB7C8 | movzx ecx,r8w |
复制代码
然后把得到的18362转成十六进制数 // 即 r11w = [r8 + 8] == 0x47ba
- 00000001433311CC | 6645:8B18 | mov r11w,word ptr ds:[r8] |
- 00000001433311D0 | 6641:8B40 02 | mov ax,word ptr ds:[r8+2] |
- 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:[r8+8],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:[r8] |
复制代码
--------------------------------------------------
另注意到 该样本(如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:[rsp+rcx],rdx |
- 0000000143401AB4 | D2F0 | shl al,cl |
复制代码
之后从vm字节码读取到 700C5C064835B726 放入 r8
- 00000001432E6CF9 | 49:8B11 | mov rdx,qword ptr ds:[r9] |
- 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:[r8],rdx |
复制代码
之后再从vm字节码读取一个地址 00000001432F7C60 放入 r8 // 注意到上面的 r8 = r8 - 8
- 000000014341F308 | 49:8B11 | mov rdx,qword ptr ds:[r9] |
- 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:[r8],rdx |
复制代码
之后从该地址读取到 684B8EFD1F4CBE6B 放入 r8 // 同上 注意到上面的 r8 = r8 - 8
- 00000001434243C6 | 49:8B28 | mov rbp,qword ptr ds:[r8] |
- 00000001434243C9 | 41:12C4 | adc al,r12b |
- 00000001434243CC | 48:8B4425 00 | mov rax,qword ptr ss:[rbp] |
- 00000001434243D1 | 49:8900 | mov qword ptr ds:[r8],rax |
- 00000001434243D4 | 66:0FABED | bts bp,bp |
复制代码
再调用加法得到 D857EB0367827591 = 684B8EFD1F4CBE6B + 700C5C064835B726 放入 r8 + 8
再存放 eflags 到 r8 = 0xa92
- 000000014338579C | 49:8B00 | mov rax,qword ptr ds:[r8] |
- 000000014338579F | 4D:8B50 08 | mov r10,qword ptr ds:[r8+8] |
- 00000001433857A3 | 49:03C2 | add rax,r10 |
- 00000001433857A6 | E9 E7B30300 | jmp diskgenius_0884_x64.1433C0B92 |
- 00000001433C0B92 | 49:8940 08 | mov qword ptr ds:[r8+8],rax |
- -->
- 00000001433C0BA1 | 9C | pushfq |
- 00000001433C0BA2 | 41:8F00 | pop qword ptr ds:[r8] |
复制代码
保存 eflags 到 vm_context(rcx = 0x20) = 0xa92
- 00000001433D9CD3 | 49:8B10 | mov rdx,qword ptr ds:[r8] |
- 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:[r9] |
- 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:[rsp+rcx],rdx |
复制代码
轮转 vm_context 之后
- mov reg0, qword ptr ss:[rsp+reg1*1]
- sub r8, 0x08
- mov qword ptr ds:[r8], reg0
- -->
- mov reg0, qword ptr ds:[r8]
- movzx reg1, byte ptr ds:[r9]
- decrypt reg1
- mov qword ptr ss:[rsp+reg0*1], reg1
复制代码
从 vm字节码 读取 79BA102F4FDAB902 放入 r8
- 00000001433C22B9 | 49:8B11 | mov rdx,qword ptr ds:[r9] |
- 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:[r8],rdx |
- 再从 vm字节码 读取 00000001432F7C68 放入 r8
- [code]0000000143340A1F | 49:8B11 | mov rdx,qword ptr ds:[r9] |
- 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:[r8],rdx |
复制代码
然后从 vm字节码读出来的地址 再读 8645EFD1F142DF47 放入 r8
- 000000014332107B | 49:8B28 | mov rbp,qword ptr ds:[r8] |
- 000000014332107E | D2C8 | ror al,cl |
- 0000000143321080 | C0FC BD | sar ah,BD |
- 0000000143321083 | 48:8B4425 00 | mov rax,qword ptr ss:[rbp] |
- 0000000143321088 | 41:0FBFEA | movsx ebp,r10w |
- 000000014332108C | 6641:8BEA | mov bp,r10w |
- 0000000143321090 | 49:8900 | mov qword ptr ds:[r8],rax |
复制代码
调用 vm_add 得到一个大数 0x100000001411D9849 = 0x79BA102F4FDAB902 + 0x8645EFD1F142DF47
将 0x00000001411D9849 放入 r8 + 8
将 eflag=203 放入 r8
- 00000001432FCAF2 | 49:8B00 | mov rax,qword ptr ds:[r8] |
- 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:[r8+8] |
- 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:[r8+8],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:[r8] |
- 00000001432FCB31 | 6641:0FBEEA | movsx bp,r10b |
- 00000001432FCB36 | 6644:0FA3E5 | bt bp,r12w |
- 00000001432FCB3B | 41:8B29 | mov ebp,dword ptr ds:[r9] |
复制代码
注意到这里:
已经两次了,从这里我们可以看到 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:[rsp+rcx],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:[rsp+rcx],rdx |
- 0000000143401AB4 | D2F0 | shl al,cl |
复制代码
将当前 r8 保存一次 [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:[r8],r11 |
复制代码
开始把 vm_context的数据 复制到
再保存到 vm_context(rcx = 0xc8)
- 00000001433D9CD3 | 49:8B10 | mov rdx,qword ptr ds:[r8] |
- ...
- 00000001433D9CE9 | 41:0FB609 | movzx ecx,byte ptr ds:[r9] |
- ...
- 00000001433D9D30 | 48:89140C | mov qword ptr ss:[rsp+rcx],rdx |
复制代码
读取vm_context(r10 = 0xb8) = 000000000014F8D0 ] 到 r8
- 000000014332B11F | 45:0FB611 | movzx r10d,byte ptr ds:[r9] |
- ..
- 000000014332B173 | 4A:8B1414 | mov rdx,qword ptr ss:[rsp+r10] |
- ..
- 000000014332B18C | 49:8910 | mov qword ptr ds:[r8],rdx |
复制代码
再保存到 vm_context(rcx = 0xd0)
- 000000014332C492 | 49:8B10 | mov rdx,qword ptr ds:[r8] |
- ...
- 000000014332C4A6 | 41:0FB609 | movzx ecx,byte ptr ds:[r9] |
- ...
- 000000014332C500 | 48:89140C | mov qword ptr ss:[rsp+rcx],rdx |
复制代码
读取 vm_context(r10 = 0xa8) = 0000000000000019 到 r8
- 0000000143428847 | 4A:8B1414 | mov rdx,qword ptr ss:[rsp+r10] |
- ..
- 0000000143428866 | 49:8910 | mov qword ptr ds:[r8],rdx |
复制代码
再保存 [r8] = 0x19 到 vm_context(0xd8) = 0x19
- 0000000143301512 | 49:8B10 | mov rdx,qword ptr ds:[r8] |
- ...
- 0000000143301521 | 41:0FB609 | movzx ecx,byte ptr ds:[r9] |
- ...
- 00000001432DADFE | 48:89140C | mov qword ptr ss:[rsp+rcx],rdx |
复制代码
再保存 vm_context(0x30) = 0xd 到 r8
- 00000001433F73CD | 45:0FB611 | movzx r10d,byte ptr ds:[r9] |
- ...
- 00000001433F7412 | 4A:8B1414 | mov rdx,qword ptr ss:[rsp+r10] |
- ...
- 00000001433F742D | 49:8910 | mov qword ptr ds:[r8],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:[r8] |
- ...
- 00000001433B7435 | 41:8B68 04 | mov ebp,dword ptr ds:[r8+4] |
- ...
- 00000001433B7451 | 41:F7D3 | not r11d |
- ...
- 00000001433B745E | F7D5 | not ebp |
- 00000001433B7460 | 44:0BDD | or r11d,ebp |
- ...
- 00000001433B746C | 45:8958 08 | mov dword ptr ds:[r8+8],r11d |
- ...
- 00000001433B7474 | 9C | pushfq |
- ...
- 00000001433B747B | 41:8F00 | pop qword ptr ds:[r8] |
复制代码
再保存 B 到 vm_context(rcx = 0x80)
- 00000001433AF9F5 | 49:8B10 | mov rdx,qword ptr ds:[r8] |
- ...
- 00000001433AFA02 | 41:0FB609 | movzx ecx,byte ptr ds:[r9] |
- ...
- 00000001433AFA51 | 48:89140C | mov qword ptr ss:[rsp+rcx],rdx |
复制代码
再将 A 进行如下运算
记
C = not(A) and not(A) // ~A & ~A 11111111
D = eflag_1(0x206)
- 00000001432EC217 | 41:8B30 | mov esi,dword ptr ds:[r8] |
- ...
- 00000001432EC21E | 41:8B48 04 | mov ecx,dword ptr ds:[r8+4] |
- ...
- 00000001432EC234 | F7D6 | not esi |
- ...
- 00000001432EC23B | F7D1 | not ecx |
- ...
- 00000001432EC240 | 23F1 | and esi,ecx |
- ...
- 00000001432EC24C | 41:8970 08 | mov dword ptr ds:[r8+8],esi |
- ...
- 00000001432EC254 | 9C | pushfq |
- ...
- 00000001432EC25C | 41:8F00 | pop qword ptr ds:[r8] |
复制代码
再保存 D 到 vm_context(rcx = 0x50)
- 00000001432DF562 | 49:8B10 | mov rdx,qword ptr ds:[r8] |
- ...
- 00000001432DF571 | 41:0FB609 | movzx ecx,byte ptr ds:[r9] |
- ...
- 00000001432DF5B9 | 48:89140C | mov qword ptr ss:[rsp+rcx],rdx |
复制代码
再保存 C 到 vm_context(rcx = 0x800)
- 0000000143335C30 | 41:8B10 | mov edx,dword ptr ds:[r8] |
- ...
- 0000000143335C51 | 41:0FB609 | movzx ecx,byte ptr ds:[r9] |
- ...
- 0000000143335C96 | 89140C | mov dword ptr ss:[rsp+rcx],edx |
- 从 vm字节码 读到 8594
- 000000014339D78A | 41:0FB729 | movzx ebp,word ptr ds:[r9] |
- ...
- 00000001432D824C | 6641:8928 | mov word ptr ds:[r8],bp |
复制代码
从 vm字节码 读取 地址 00000001432F7C70 // 看到这,读者应该能想到接下来会从该地址读一个数,然后调用vm_add
- 00000001433534B1 | 49:8B11 | mov rdx,qword ptr ds:[r9] |
- ...
- 0000000143353513 | 49:8910 | mov qword ptr ds:[r8],rdx |
复制代码
从 地址 00000001432F7C70 读到 7A72
- 000000014336814D | 49:8B30 | mov rsi,qword ptr ds:[r8] |
- ...
- 000000014336815C | 66:8B16 | mov dx,word ptr ds:[rsi] |
- ...
- 0000000143368168 | 49:81C0 06000000 | add r8,6 |
- 000000014336816F | 6641:8910 | mov word ptr ds:[r8],dx |
复制代码
调用加法 得到 10006 注意到 使用的 ax 即 6 // 看到这,熟悉vmp运算的会不会想到什么呢
- 00000001433B1A2D | 6641:8B00 | mov ax,word ptr ds:[r8] |
- ...
- 00000001433B1A3C | 6641:8B48 02 | mov cx,word ptr ds:[r8+2] |
- ...
- 00000001433B1A49 | 49:81E8 06000000 | sub r8,6 |
- ...
- 00000001433B1A5B | 66:03C1 | add ax,cx |
- 00000001433B1A5E | 6641:8940 08 | mov word ptr ds:[r8+8],ax |
- 00000001433B1A63 | 9C | pushfq |
- ...
- 00000001433B1A68 | 41:8F00 | pop qword ptr ds:[r8] |
复制代码
保存vm_add的eflag vm_context(rcx=0x8) = 0x207之后
再从 vm_context(r10=0x50) 读 D 放入到 r8 中
- 00000001432DA68E | 45:0FB611 | movzx r10d,byte ptr ds:[r9] |
- ...
- 00000001432DA6D7 | 4A:8B1414 | mov rdx,qword ptr ss:[rsp+r10] |
- ...
- 00000001432DA6E6 | 49:81E8 08000000 | sub r8,8 |
- 00000001432DA6ED | 49:8910 | mov qword ptr ds:[r8],rdx |
复制代码
同上,再从 vm_context(r10=0x50) 读 D 放入到 r8 中
- 00000001432D8671 | 45:0FB611 | movzx r10d,byte ptr ds:[r9] |
- ...
- 00000001432D86BC | 4A:8B1414 | mov rdx,qword ptr ss:[rsp+r10] |
- ...
- 00000001432D86C4 | 49:81E8 08000000 | sub r8,8 |
- ...
- 00000001432D86D2 | 49:8910 | mov qword ptr ds:[r8],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:[r8] |
- ...
- 00000001432EB8CD | 49:8B70 08 | mov rsi,qword ptr ds:[r8+8] |
- ...
- 00000001432EB8D5 | 48:F7D0 | not rax |
- ...
- 00000001432EB8E3 | 48:F7D6 | not rsi |
- 00000001432EB8E6 | 48:0BC6 | or rax,rsi |
- ...
- 00000001432EB8EC | 49:8940 08 | mov qword ptr ds:[r8+8],rax |
- ...
- 0000000143397AEB | 9C | pushfq |
- 0000000143397AEC | 41:8F00 | pop qword ptr ds:[r8] |
复制代码
保存 F 到 vm_context(0x78) = 0x286
- 000000014335D166 | 49:8B10 | mov rdx,qword ptr ds:[r8] |
- 000000014335D169 | 49:81C0 08000000 | add r8,8 |
- ...
- 000000014335D174 | 41:0FB609 | movzx ecx,byte ptr ds:[r9] |
- ...
- 00000001433F478C | 48:89140C | mov qword ptr ss:[rsp+rcx],rdx |
复制代码
从 vm字节码 读取 E4A190D9B51BE79E 到 r8
- 00000001433B871A | 49:8B11 | mov rdx,qword ptr ds:[r9] |
- 00000001433B871D | 49:81C1 08000000 | add r9,8 |
- ...
- 0000000143424FC9 | 49:81E8 08000000 | sub r8,8 |
- 0000000143424FD0 | 49:8910 | mov qword ptr ds:[r8],rdx |
- ...
- 0000000143424FDF | 41:8B29 | mov ebp,dword ptr ds:[r9] |
复制代码
再从 vm字节码 读取 00000001432F7C72 到 r8 // 和上面一样
- 00000001433F8ED2 | 49:8B11 | mov rdx,qword ptr ds:[r9] |
- 00000001433F8ED8 | 49:81C1 08000000 | add r9,8 |
- ...
- 00000001433F8F39 | 49:81E8 08000000 | sub r8,8 |
- ...
- 00000001433F8F42 | 49:8910 | mov qword ptr ds:[r8],rdx |
复制代码
再从 上面的地址 00000001432F7C72 读 1B5E6F264AE41821
- 000000014337A88E | 49:8B28 | mov rbp,qword ptr ds:[r8] |
- ...
- 000000014337A899 | 48:8B4425 00 | mov rax,qword ptr ss:[rbp] |
- ...
- 000000014337A8A9 | 49:8900 | mov qword ptr ds:[r8],rax |
复制代码
再调用加法得到
记
G = FFFFFFFFFFFFFFBF
H = 0x282
- 0000000143324E65 | 49:8B00 | mov rax,qword ptr ds:[r8] |
- ...
- 0000000143324E73 | 4D:8B50 08 | mov r10,qword ptr ds:[r8+8] |
- 0000000143324E77 | 49:03C2 | add rax,r10 |
- ...
- 0000000143324E86 | 49:8940 08 | mov qword ptr ds:[r8+8],rax |
- ...
- 0000000143324E92 | 9C | pushfq |
- ...
- 0000000143324E9E | 41:8F00 | pop qword ptr ds:[r8] |
复制代码
保存 H 到 vm_context(rcx=0x88)
- 0000000143344BE9 | 49:8B10 | mov rdx,qword ptr ds:[r8] |
- ...
- 0000000143344BF6 | 49:81C0 08000000 | add r8,8 |
- 0000000143344BFD | 41:0FB609 | movzx ecx,byte ptr ds:[r9] |
- ...
- 0000000143401AB0 | 48:89140C | mov qword ptr ss:[rsp+rcx],rdx |
复制代码
再计算 J = not(E) & not(G) // (~E & ~G) // = 0
K = 0x246
- 000000014332BAA5 | 4D:8B18 | mov r11,qword ptr ds:[r8] |
- ...
- 000000014332BAB3 | 49:8B48 08 | mov rcx,qword ptr ds:[r8+8] |
- ...
- 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:[r8] |
复制代码
保存 K 到 vm_context(rcx=0x98)
- 00000001433D9CD3 | 49:8B10 | mov rdx,qword ptr ds:[r8] |
- ...
- 00000001433D9CDF | 49:81C0 08000000 | add r8,8 |
- ...
- 00000001433D9CE9 | 41:0FB609 | movzx ecx,byte ptr ds:[r9] |
- ...
- 00000001433D9D30 | 48:89140C | mov qword ptr ss:[rsp+rcx],rdx |
复制代码
然后进行shr运算 // 有所了解的读者,应该很熟悉了
- 000000014340D9CE | 49:8B10 | mov rdx,qword ptr ds:[r8] |
- ...
- 000000014340D9D7 | 41:8A48 08 | mov cl,byte ptr ds:[r8+8] |
- ...
- 000000014340D9DE | 49:81E8 06000000 | sub r8,6 |
- ...
- 000000014340D9E6 | 48:D3EA | shr rdx,cl |
- ...
- 000000014340D9F4 | 49:8950 08 | mov qword ptr ds:[r8+8],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
-----------------------------------
待续....
|
评分
-
查看全部评分
|