Posts Tagged ‘wardenmimic’

WardenMimic v20090723a

July 23rd, 2009

New build of WardenMimic. I held on to it because I got word of a new build in the near future, I wanted to give them a chance to maybe fix some of their shit. The changelog says they’ve improved their anti-detection, but my checks say otherwise. This is confirmed working on v54, but should work on previous builds too (shit, I think pretty much all of their builds are vulnerable to this particular hole).

There are still plenty more holes left though so don’t worry, I’m not taking all the fun away from Blizzard, just a bit of it.

WardenMimic v20090723a

Let the drama begin!

Update on Mimic

June 19th, 2009

Hey, as most of the people interested in the Mimic saga already know, a new version is out.  A bunch of people have contacted me to ask if I would be posting about it, so I figured I’d post an explanation as to why I may or may not be. Kynox has done a minor coverage of the update available here.

I may or may not do a full and in-depth coverage for three reasons:

  1. I think it has been proven beyond doubt now that Mimic is indeed full of shit when it comes to their anti-anti-cheat code.
  2. I think they have been given enough handouts for now.
  3. Working on my new project is simply much more fun.

That being said, if I get bored I might take a look at the changes, but all I will be doing is documenting them, and pointing out whether it as a whole is still detectable. I will no longer be handing them free anti-warden ideas, they’re on their own now.

WoWMimic v50

June 11th, 2009

Another WoWMimic build was released recently. I’ve reversed it yet again to bring you the gory details.

They’ve beefed up (by their standards) the obfuscation on this one. I put “by their standards” because they’re morons, and by the standards of any real reverser ‘beefed up’ is hardly the right term. It seems they’ve learned two new ‘tricks’, one they use once, another they use constantly. Both are very lame and very obvious and easy to undo though.

The first is this:

15DEBE67 | 5B            | POP     EBX                         | ; Pop address of current line into EBX

15DEBE68 | 81EB 471A4000 | SUB     EBX, 401A47                 | ; Subtract 401A47 from EBX (15DEBE67) (Final: 159EA420)

15DEBE6E | 8B83 F1194000 | MOV     EAX, DWORD PTR [EBX+4019F1] | ; Move 7CCAE98C into EAX

15DEBE74 | 35 8CE9CA7C   | XOR     EAX, 7CCAE98C               | ; Xor EAX (7CCAE98C) with 7CCAE98C. (Final: 0)

15DEBE79 | 8D8B C81A4000 | LEA     ECX, DWORD PTR [EBX+401AC8] | ; Move EBX (159EA420) + 401AC8 into ECX (Final: 15DEBEE8)

15DEBE7F | 8D0401        | LEA     EAX, DWORD PTR [ECX+EAX]    | ; Move ECX (15DEBEE8) + EAX (0) into EAX (Final: 15DEBEE8)

15DEBE82 | FFE0          | JMP     NEAR EAX                    | ; Jump NEAR to EAX (15DEBEE8). Another obfuscation attempt.

They have attempted to hide the jump address with some VERY basic math. Sorry guys, but you’re gonna have to do better than that.

Second trick:

; MimicVectoredHandler

15DEBE06 | 55            | PUSH    EBP       | ; Standard stack frame setup

15DEBE07 | 8BEC          | MOV     EBP, ESP  | ; Standard stack frame setup

15DEBE09 | 81C4 00FFFFFF | ADD     ESP, -100 | ; Sub ESP 100. Room for local variables

15DEBE0F | EB 50         | JMP     15DEBE61  | ; Jump over garbage and into an instruction. Obfuscation attempt.

; Original - Nice try… Not!

15DEBE60 | 2A60 E8 | SUB     AH, BYTE PTR [EAX-18] | ; Jump lands one byte into this instruction.

15DEBE63 | 0000    | ADD     BYTE PTR [EAX], AL    | ; Just reassemble the bytes to fix it.

15DEBE65 | 0000    | ADD     BYTE PTR [EAX], AL    | ; See below for one I prepared earlier!

; Fixed - Wow.. that was hard…

15DEBE61 | 60          | PUSHAD           | ; Preserve registers

15DEBE62 | EB 00000000 | CALL    15DCBE67 | ; Call next line

They’re attempting to confuse disassemblers by jumping into what seems to be the middle of an instruction. What they don’t seem to realize is that there are two very easy ways to undo this. One is to realign your disassembler for that chunk if it has that functionality. The other is to just dump out the bytes, assemble them externally (in OllyDbg or another tool that can assemble bytes into mnemonics), and just read from there.  Thanks to Nessox and Apoc for doing that for me because Olly was being a whore on my PC.  To put it simply, its no barrier to any reverser with half a brain.

Both obfuscation ‘techniques’ (if you can call them that) just reek of the work of an amateur. I still think they’re waiting for “one of china’s best hackers” to turn up for work.

As for actual changes to the implementation, there isn’t much, they seem to have wasted the last week or so on obfuscation which took them 1000x longer to write than it took me to reverse. Nevertheless, there is one notable change, which is to their ZwQueryVirtualMemory hook.

They no longer null out pMemoryBasicInformation->BaseAddress, but they have started nulling out pMemoryBasicInformation->RegionSize. The reason for this is both obvious and hilarious.

The previous build of WardenMimic (new one coming once I get some free time) worked by enumerating all regions of memory to look for the one that has been hidden. It is identified by detecting the unique return values which would never be returned in normal circumstances. Whilst the change breaks WardenMimic, it does so for all the wrong reasons. Not only do they obviously have no idea how a NtQueryVirtualMemory hook is actually supposed to work, they’ve fucked up and left another gaping hole AGAIN. That’s right, the hook is STILL detectable by Warden because the morons obviously don’t understand the first thing about Windows internals and virtual memory.

The rest of the APIs (GetCursorPos, SetCursorPos, NtGetContextThread) remain unhooked for the time being. (GetCursorPos and SetCursorPos still have the bug that was left there from the previous build.)

So, in summary, the changes are as followed:

  • Had another crack at obfuscating their anti-detection code and failed hard.
  • Attempted to fix their NtQueryVirtualMemory hook. Whilst they broke WardenMimic they fucked up their hook AGAIN and so Mimic is STILL DETECTABLE.

It’s pretty funny it took them this long just to push out such a simple new build. Really says something about either the quality of the developers or the quality of the customer service department. (Regardless though, the fail obfuscation attempts definitely say something about the developers. — In case you’re slow, its says they’re incompetent.)

Full code (with documentation) is available again. Anything marked as “Fixed” has been realigned so most of the obfuscation will not be apparent unless you reverse it yourself.

WoWMimic v50 Anti-Detection Code.

WoWMimic PvPAdvance v15

June 5th, 2009

More epic fail from the WoWMimic team with the release of PvPAdvance v15.

They have made ZERO improvements to their anti-detection since v14. That means that it can still be detected using  a  warden scan that’s already implemented. No new functionality is required, only a new hash.

The only thing they are currently doing to protect themselves is unlink their module from the linked list, but Warden doesn’t even use that list!*

Sigh. It seems like they’re never going to learn. Hopefully Blizzard will teach them the hard way, but given how lazy the Warden guy is, I can’t exatly say you should count on it.


*Whilst there is a scan in place that does in fact use that list through the use of Module32First/Module32Next, it is not currently activated. Thank you Kynox for catching and confirming that.

WoWMimic v48

June 4th, 2009

First things first, the current build of WardenMimic (here) still works!  Kinda sad they couldn’t fix that.

Anyway, some minor changes in this build but nothing exciting.

  • They have removed their hooks on GetCursorPos and SetCursorPos altogether (there are still implementations in their VEH code though which are unchanged from the previous build).
  • The hook on ZwGetContextThread is still disabled (and still has an implementation in their VEH code, unchanged from previous build).
  • NtQueryVirutalMemory is still hooked and its implementation remains unchanged from the previous build.

As WardenMimic demonstrates its still a highly detectable piece of software. They got lucky this time in that the Warden guy majorly fucked up the timing of his latest scan because he’s an incompetent dipshit. Unfortunately due to the fact that ZwQueryVirtualMemory is hooked with VEH he will actually have to do some work to detect them this time (though, I’ve already done all he needs to do and it only took me 10-15 minutes so fuck knows what’s taking him so long).

For details on the Warden scan aimed at Mimic please check out my friend Kynox’s blog here.

As usual, I have taken the liberty of dumping out the full code from the anti-detecton part of Mimic and documenting it.

Lastly, please keep in mind that all they’ve done for this build is remove the feature that was getting them detected this time. They still havn’t fixed the huge hole that I’m using in WardenMimic, so don’t use Mimic on accounts you don’t want to potentially loose.

Code Dump (PrivatePaste)

WoWMimic PvPAdvance v14

May 29th, 2009

Bored, so I took a look at the new version of WoWMimic PvPAdvance to see what they changed. Unfortunately v13 wouldn’t run on my PC,  so I don’t have anything to base it off, but when the next version comes out at least I will. I’m not surprised at all that there have been bans for this tool, its anti-detection is even worse than WOWMimic itselfs.

What they’re currently doing:

  1. Unlinking the module.

No. Seriously. That seems to be it.

They’re not hooking VirtualQuery (or any of its lower-level code paths), and they’re not even nulling out their PE header. This means that a Warden scan that is CURRENTLY IMPLEMENTED can be used to detect their module, all the Warden dev needs to do is add a new hash.

My guess is that with the bans from the previous version they made minor changes to their code, which changed the module hash at the point Warden was scanning, noticed they weren’t getting bans anymore, and assumed they fixed the problem. That, or they’re too lazy to fix it properly. Either way they’re idiots.

Epic fail. Quite disappointing really, that only took a minute or two to check and now I’m bored again.

WardenMimic v20090528a

May 28th, 2009

New version of WardenMimic for v47 of WoWMimic.


If you havn’t already you may want to check out my post detailing the changes to WoWMimic in v47 here.

Please let me know if you experience a false positive or false negative. For version 47 ONLY, do not report flase negatives for any other versions.

WoWMimic v47 Changes

May 27th, 2009

Many of you will know by now that WoWMimic v47 is out. A few interesting changes, nothing really substantial though.

  1. GetCursorPos and SetCursorPos are now also hooked using VEH.
  2. 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.
  3. 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).
  4. 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).


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

Presenting: WardenMimic

May 21st, 2009

Releasing the initial version of my latest project, dubbed WardenMimic. Its purpose is to basically ‘mimic’ Warden and try and detect WoWMimic. It will be fully in-process so it works within the constraints of Warden itself. Releasing it as a binary so the devs have to work for it this time, they’ve had enough charity handouts.

Simply run the loader, point it to WoW, and the module will spawn a console and let you know whether its detected WoWMimic or not. Go back to the loader, hit enter again, and the module will be unloaded for your convenience.

I will continually update this for any new WoWMimic builds until I get bored or they really pick up their game and make it too much trouble for me to bother (keeping in mind I’m a very lazy person).

Download here.

P.S. Has recieved limited testing. If it crashes please post your system specs (os, architecture, etc etc) plus a crash dump.


Huge credits to both Harko and Kynox for their help/input/etc.

In-process WoWMimic Detection

May 14th, 2009

The following is code that will detect if WoWMimic is running using fully in-process checks. That means that you can lock it down with guest mode, hide the window, etc all you want, this will still work, because we’re operating entirely inside WoW.exe’s address space.

Before we begin, huge thanks to Kynox for unpacking Melete (WoWMimic’s injected DLL).

WoWMimic needs a way for its DLL to communicate with its application component, it does this through shared memory. Here is the disassembled function responsible for setting this up. I have commented the virtualized API calls to make it apparent what is going on:

___:1002F630 ; =============== S U B R O U T I N E =======================================


___:1002F630 ; Attributes: bp-based frame


___:1002F630 sub_1002F630    proc near               ; CODE XREF: DllMain(x,x,x)+45p


___:1002F630 var_24          = dword ptr -24h

___:1002F630 var_20          = dword ptr -20h

___:1002F630 var_1C          = dword ptr -1Ch

___:1002F630 var_10          = dword ptr -10h

___:1002F630 var_8           = dword ptr -8

___:1002F630 var_4           = dword ptr -4


___:1002F630                 push    ebp

___:1002F631                 mov     ebp, esp

___:1002F633                 push    0FFFFFFFEh

___:1002F635                 push    offset dword_10070488

___:1002F63A                 push    offset __except_handler4

___:1002F63F                 mov     eax, large fs:0

___:1002F645                 push    eax

___:1002F646                 sub     esp, 14h

___:1002F649                 push    ebx

___:1002F64A                 push    esi

___:1002F64B                 push    edi

___:1002F64C                 mov     eax, dword_10072054

___:1002F651                 xor     [ebp+var_8], eax

___:1002F654                 xor     eax, ebp

___:1002F656                 push    eax

___:1002F657                 lea     eax, [ebp+var_10]

___:1002F65A                 mov     large fs:0, eax

___:1002F660                 xor     ebx, ebx

___:1002F662                 mov     [ebp+var_24], ebx

___:1002F665                 mov     [ebp+var_1C], ebx

___:1002F668                 xor     esi, esi

___:1002F66A                 mov     [ebp+var_20], esi

___:1002F66D                 mov     [ebp+var_4], ebx

___:1002F670                 push    offset a0xa0c82e ; “0xA0C82E”

___:1002F675                 push    ebx

___:1002F676                 push    2

___:1002F678                 call    near ptr 3E0000h ; OpenFileMappingW

___:1002F67D                 nop

___:1002F67E                 mov     edi, eax

___:1002F680                 mov     [ebp+var_1C], edi

___:1002F683                 cmp     edi, ebx

___:1002F685                 jz      short loc_1002F6D8

___:1002F687                 push    0Ch

___:1002F689                 push    ebx

___:1002F68A                 push    ebx

___:1002F68B                 push    2

___:1002F68D                 push    edi

___:1002F68E                 call    near ptr 3E0370h ; MapViewOfFile

___:1002F693                 nop

___:1002F694                 mov     esi, eax

___:1002F696                 mov     [ebp+var_20], esi

___:1002F699                 cmp     esi, ebx

___:1002F69B                 jz      short loc_1002F6D8

___:1002F69D                 push    ebx

___:1002F69E                 push    ebx

___:1002F69F                 mov     eax, [esi]

___:1002F6A1                 push    eax

___:1002F6A2                 push    offset loc_1002F570

___:1002F6A7                 push    ebx

___:1002F6A8                 push    ebx

___:1002F6A9                 call    near ptr 21092Eh ; CreateThread

___:1002F6AE                 nop

___:1002F6AF                 mov     dword_100730C0, eax

___:1002F6B4                 cmp     eax, ebx

___:1002F6B6                 jz      short loc_1002F6D8

___:1002F6B8                 mov     ecx, [esi+10h]

___:1002F6BB                 mov     dword_100730C4, ecx

___:1002F6C1                 mov     edx, [esi+20h]

___:1002F6C4                 mov     dword_100730C8, edx

___:1002F6CA                 mov     [ebp+var_24], 1

___:1002F6D1                 mov     [esi], ebx

___:1002F6D3                 call    sub_10058CD0


___:1002F6D8 loc_1002F6D8:                           ; CODE XREF: sub_1002F630+55j

___:1002F6D8                                         ; sub_1002F630+6Bj …

___:1002F6D8                 mov     [ebp+var_4], 0FFFFFFFEh

___:1002F6DF                 call    sub_1002F701

___:1002F6E4                 mov     eax, [ebp+var_24]

___:1002F6E7                 mov     ecx, [ebp+var_10]

___:1002F6EA                 mov     large fs:0, ecx

___:1002F6F1                 pop     ecx

___:1002F6F2                 pop     edi

___:1002F6F3                 pop     esi

___:1002F6F4                 pop     ebx

___:1002F6F5                 mov     esp, ebp

___:1002F6F7                 pop     ebp

___:1002F6F8                 retn

___:1002F6F8 sub_1002F630    endp

The file name they have is hardcoded and doesn’t change (even across mimic versions), so it’s obvious what we can do to abuse this fact:
bool IsMimicInjected()
HANDLE MimicIPC = OpenFileMapping(FILE_MAP_READ,FALSE,”0xA0C82E”);
if (!MimicIPC)
return false;
// You could do even more to check here by inspecting the memory
// mapped file but that is unnecessary.
return true;
There you have it. WoWMimic detected yet again. This time though the bar has been raised heavily, as you can no longer hide just by restricing WoW’s security descriptors.
Your move, WoWMimic.