WoWMimic v47 Changes
Many of you will know by now that WoWMimic v47 is out. A few interesting changes, nothing really substantial though.
- GetCursorPos and SetCursorPos are now also hooked using VEH.
- ZwQueryVirtualMemory is now hooked at the return statement so values are modified AFTER the function is called. They have fixed one hole, but introduced another. Still hooked with VEH.
- ZeGetContextThread hook is still present but not longer activated. They have also updated their hook body, fixing one hole, but again, introducing another (see if you can spot it).
- They have implemented some VERY lame ‘obfuscation’ attempts. Really quite a poor job, 5 minutes tops to figure out the mess, or 30 or so seconds if you know what you’re looking at.
All in all quite disappointing. They broke the previous version of WardenMimic but only because they changed the offset at which they were hooking, and I was being nice and lowering the false positive rate by putting in lots of checks to detect only that exact build. Anyway, new WardenMimic incoming soon (when I don’t feel lazy).
Update:
Thanks to Harko for pointing out that GetCursorPos and SetCursorPos are still hooked with JMP hooks. It seems they implemented support for it in their VEH but didn’t actually hook it using VEH for some reason. Much like their unused changes to NtGetContextThread. Kinda retarded really….
Full code:
PrivatePaste Copy
; MimicVectoredHandler
169B379E | 55 | PUSH EBP | ; Standard stack frame setup
169B379F | 8BEC | MOV EBP, ESP | ; Standard stack frame setup
169B37A1 | 81C4 00FFFFFF | ADD ESP, -100 | ; Sub ESP 100. Room for local variables.
169B37A7 | 60 | PUSHAD | ; Preserve all registers
169B37A8 | E8 00000000 | CALL 169B37AD | ; Obfuscation. ‘Calls’ next line and pushes the address of that line onto stack.
169B37AD | 5B | POP EBX | ; Pop address (of current line) back off and into EBX
169B37AE | 81EB 75164000 | SUB EBX, 401675 | ; Subtract 401675 from EBX (169B37AD) (Final: 165B2138)
169B37B4 | 8B75 08 | MOV ESI, DWORD PTR [EBP+8] | ; Get pExceptionInfo
169B37B7 | 8B7E 04 | MOV EDI, DWORD PTR [ESI+4] | ; Get pExceptionInfo->pContext
169B37BA | 8B36 | MOV ESI, DWORD PTR [ESI] | ; Get pExceptionInfo->pExceptionRecord
169B37BC | 8B87 B8000000 | MOV EAX, DWORD PTR [EDI+B8] | ; Get EIP
169B37C2 | 3B83 CD104000 | CMP EAX, DWORD PTR [EBX+4010CD] | ; Compare EIP to address of GetCursorPos.
169B37C8 | 75 0E | JNZ 169B37D8 | ; If not equal go to ContinueSearchRet
169B37CA | 8D83 F8164000 | LEA EAX, DWORD PTR [EBX+4016F8] | ; Get address of GetCursorPos_Hook
169B37D0 | 8987 B8000000 | MOV DWORD PTR [EDI+B8], EAX | ; Move address into EIP
169B37D6 | EB 4C | JMP 169B3824 | ; Go to ContinueExecRet
169B37D8 | 3B83 D1104000 | CMP EAX, DWORD PTR [EBX+4010D1] | ; Compare EIP to address of SetCursorPos
169B37DE | 75 0E | JNZ 169B37EE | ; If not equal go to ContinueSearchRet
169B37E0 | 8D83 2D174000 | LEA EAX, DWORD PTR [EBX+40172D] | ; Get address of SetCursorPos_Hook
169B37E6 | 8987 B8000000 | MOV DWORD PTR [EDI+B8], EAX | ; Move address into EIP
169B37EC | EB 36 | JMP 169B3824 | ; Go to ContinueExecRet
169B37EE | 3B83 84134000 | CMP EAX, DWORD PTR [EBX+401384] | ; Compare EIP to address of ZwQueryVirtualMemory_Retn
169B37F4 | 75 0E | JNZ 169B3804 | ; If not equal go to ContinueSearchRet
169B37F6 | 8D83 50174000 | LEA EAX, DWORD PTR [EBX+401750] | ; Get address of ZwQueryVirtualMemory_Hook
169B37FC | 8987 B8000000 | MOV DWORD PTR [EDI+B8], EAX | ; Move address into EIP
169B3802 | EB 20 | JMP 169B3824 | ; Go to ContinueExecRet
169B3804 | 3B83 8C134000 | CMP EAX, DWORD PTR [EBX+40138C] | ; Compare EIP to address of ZwGetContextThread_Hook. Currently not used/enabled.
169B380A | 75 0E | JNZ 169B381A | ; If not equal go to ContinueSearchRet
169B380C | 8D83 88174000 | LEA EAX, DWORD PTR [EBX+401788] | ; Get address of ZwGetContextThread_Hook.
169B3812 | 8987 B8000000 | MOV DWORD PTR [EDI+B8], EAX | ; Move address into EIP
169B3818 | EB 0A | JMP 169B3824 | ; Go to ContinueExecRet
169B381A | 61 | POPAD | ; Restore registers
169B381B | B8 00000000 | MOV EAX, 0 | ; Move EXCEPTION_CONTINUE_SEARCH into return value
169B3820 | C9 | LEAVE | ; Standard function prologue
169B3821 | C2 0400 | RETN 4 | ; Return
169B3824 | 61 | POPAD | ; Restore registers
169B3825 | B8 FFFFFFFF | MOV EAX, -1 | ; Move EXCEPTION_CONTINUE_EXECUTION into return value
169B382A | C9 | LEAVE | ; Standard function prolugue
169B382B | C2 0400 | RETN 4 | ; Return
; GetCursorPos_Hook
169B3830 | E8 00000000 | CALL 169B3835 | ; Obfuscation. ‘Calls’ next line and pushes the address of that line onto stack.
169B3835 | 5A | POP EDX | ; Pop address (of current line) back off and into EDX
169B3836 | 81EA FD164000 | SUB EDX, 4016FD | ; Subtract 4016FD from EDX (169B3835) (Final: 165B2138)
169B383C | 83BA 09104000 01 | CMP DWORD PTR [EDX+401009], 1 | ; Compare some internal flag to 1
169B3843 | 75 15 | JNZ 169B385A | ;
169B3845 | 8B4C24 04 | MOV ECX, DWORD PTR [ESP+4] | ; Get lpPoint
169B3849 | 8B82 0D104000 | MOV EAX, DWORD PTR [EDX+40100D] | ; Get custom mouse x
169B384F | 8901 | MOV DWORD PTR [ECX], EAX | ; Set lpPoint->x to custom mouse x
169B3851 | 8B82 11104000 | MOV EAX, DWORD PTR [EDX+401011] | ; Get custom mouse y
169B3857 | 8941 04 | MOV DWORD PTR [ECX+4], EAX | ; Set lpPoint->y to custom mouse y
169B385A | 8B82 CD104000 | MOV EAX, DWORD PTR [EDX+4010CD] | ; Get address of GetCursorPos
169B3860 | 83C0 02 | ADD EAX, 2 | ; Jump over invalid instruction
169B3863 | FFE0 | JMP NEAR EAX | ; Jump to GetCursorPos (+2)
; SetCursorPos_Hook
169B3865 | E8 00000000 | CALL 169B386A | ; Obfuscation. ‘Calls’ next line and pushes the address of that line onto stack.
169B386A | 5A | POP EDX | ; Pop address (of current line) back off and into EDX
169B386B | 81EA 32174000 | SUB EDX, 401732 | ; Subtract 401732 from EDX (169B386A) (Final: 165B2138)
169B3871 | 83BA 09104000 01 | CMP DWORD PTR [EDX+401009], 1 | ; Compare some internal flag to 1
169B3878 | 75 03 | JNZ 169B387D | ; Jump if not equal to RetnCallOrig
169B387A | C2 0800 | RETN 8 | ; Return without calling original
169B387D | 8B82 D1104000 | MOV EAX, DWORD PTR [EDX+4010D1] | ; Get address of SetCursorPos
169B3883 | 83C0 02 | ADD EAX, 2 | ; Jump over invalid instruction
169B3886 | FFE0 | JMP NEAR EAX | ; Jump to SetCursorPos (+2)
; ZwQueryVirtualMemory_Hook
169B3888 | E8 00000000 | CALL 169B388D | ; Obfuscation. ‘Calls’ next line and pushes the address of that line onto stack.
169B388D | 5A | POP EDX | ; Pop address (of current line) back off and into EDX
169B388E | 81EA 55174000 | SUB EDX, 401755 | ; Subtract 401755 from EDX (169B388D) (Final: 165B2138)
169B3894 | 50 | PUSH EAX | ; Preserve EAX
169B3895 | 8B4424 14 | MOV EAX, DWORD PTR [ESP+14] | ; Get pMemoryBasicInformation
169B3899 | 8B48 04 | MOV ECX, DWORD PTR [EAX+4] | ; Get pMemoryBasicInformation->Allocationbase
169B389C | 3B8A 21104000 | CMP ECX, DWORD PTR [EDX+401021] | ; Compare to MimicModuleBase
169B38A2 | 75 18 | JNZ 169B38BC | ; If not equal jump to LocRetn
169B38A4 | C700 00000000 | MOV DWORD PTR [EAX], 0 | ; Zero out pMemoryBasicInformation->BaseAddress
169B38AA | C740 04 00000000 | MOV DWORD PTR [EAX+4], 0 | ; Zero out pMemoryBasicInformation->AllocationBase
169B38B1 | C740 10 00000100 | MOV DWORD PTR [EAX+10], 10000 | ; Set pMemoryBasicInformation->State to MEM_FREE
169B38B8 | 58 | POP EAX | ; Restore EAX
169B38B9 | C2 1800 | RETN 18 | ; Return
169B38BC | 58 | POP EAX | ; Restore EAX
169B38BD | C2 1800 | RETN 18 | ; Return
; ZwGetContextThread_Hook
169B38C0 | 8B4C24 08 | MOV ECX, DWORD PTR [ESP+8] | ; Get pContext
169B38C4 | C741 04 00000000 | MOV DWORD PTR [ECX+4], 0 | ; Zero out DR0
169B38CB | C741 08 00000000 | MOV DWORD PTR [ECX+8], 0 | ; Zero out DR1
169B38D2 | C741 0C 00000000 | MOV DWORD PTR [ECX+C], 0 | ; Zero out DR2
169B38D9 | C741 10 00000000 | MOV DWORD PTR [ECX+10], 0 | ; Zero out DR3
169B38E0 | C2 0800 | RETN 8 | ; Return