Archive

Posts Tagged ‘fail’

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 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)

Finding WoWMimic

May 7th, 2009

Hey, called this little snippet “WardenMimic” because it’s just mimicing what warden would have to do to detect the fail bot known as WoWMimic. Very simple example, but afaik similar to how Glider was detected (i.e. via window names and contents). A more sophisticated attack would use hashing of the remote processes memory, but that’s totally unnecessary because  WoWMimic don’t bother to obfuscate or hide anything.

Keep in mind, this was written in literally 5 minutes, a much more solid and reliable method would not be much extra work (maybe just another 5?). The code is designed to be in a DLL that is loaded by (or injected into) WoW.exe so that it is in the same context and has the same privilege level as Warden would. I made sure to load WoW via WoWMimic to ensure anything they would be doing against Warden would happen against me also, though they let you attach on the fly so I don’t think security is one of their major concerns.

Please note that I don’t have a WoWMimic sub so I just downloaded it off their site and am amusing nothing special happens if you actually run the bot that activates any window hiding or obfuscation. Let me know if this is the case and I’ll get a sub and release a new finder.

// Windows API
#include <Windows.h>
#include <io.h>
#include <fcntl.h>
#include <tchar.h>

// C++ Standard Library
#include <iostream>
#include <cstdio>
#include <vector>

// StealthLib
#include “Conditional.h”
#include “Cloaker.h”
#include “Injector.h”

// Holds windows from EnumWindows
std::vector<HWND> Windows;

// Top level window enumeration callback
BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM /*lParam*/)
{
Windows.push_back(hwnd);
return TRUE;
}

// Child level window enumeration callback
BOOL CALLBACK MyEnumChildWindowsProc(HWND hwnd, LPARAM /*lParam*/)
{
std::vector<TCHAR> Buffer(MAX_PATH);
if (GetWindowText(hwnd,&Buffer[0],MAX_PATH) &&
std::tstring(&Buffer[0]) == TEXT(”http://www.mimicusa.com”))
std::cout << “Found WoWMimic URL label!” << std::endl;
Buffer.clear();
Buffer.resize(MAX_PATH);
if (GetWindowText(hwnd,&Buffer[0],MAX_PATH) &&
std::tstring(&Buffer[0]) == TEXT(”Us Ver 3.0.0.42″))
std::cout << “Found WoWMimic version label!” << std::endl;
return TRUE;
}

// DLL entry point
BOOL WINAPI DllMain(HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID /*lpvReserved*/)
{
// Stop unreferenced param warning when __STEALTH is undefined
UNREFERENCED_PARAMETER(hinstDLL);

#ifdef __CONSOLE
// Whether to free the process’s console upon detach
static bool NeedFree = false;
#endif

// Reason for calling DllMain
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
{
#ifdef __CONSOLE
// Set up debug console
NeedFree = (AllocConsole() ? true : false);
FILE* fpOld = NULL;
freopen_s( &fpOld, “CONOUT$”, “w”, stdout );
#endif

EnumWindows(MyEnumWindowsProc,NULL);
for each (HWND Current in Windows)
{
EnumChildWindows(Current,MyEnumChildWindowsProc,NULL);
}

#ifdef __STEALTH
// Cloaker
Cloaker::Get()->AddModule(hinstDLL,true);
#endif

break;
}
case DLL_PROCESS_DETACH:
{
#ifdef __CONSOLE
// Don’t free the console if it already existed upon injection
if (NeedFree)
FreeConsole();
#endif

break;
}
}

// Success
return TRUE;
}

Sorry for the messy code. The base was taken from one of my other projects because I was too lazy to whip up the skeleton by hand. Then I just slapped in the detection stuff. There’s lots of unnecessary crap there, but you get the point.

Obviously if WoW was started as guest you could defeat remote hashing attacks or those similar, but guess what… That’s how they detected Glider! They checked whether the given access token was restricted (i.e. started with reduced privileges).

Protip: Don’t use WoWMimic. Not only is it an awful bot, its a 30 second job (literally) to write a detection routine.

How-To: Waste 10 minutes of your life

April 26th, 2009

Just had an epic fail moment I wanted to share, the type of moment where a realisation hits you like a fucking train and you just wanna kick yourself for not thinking of it.

I was working on an API hooking library (address-table based hooking) and I hook GetProcAddress mainly because I want to log indirect API calls, and partly because EAT hooking isn’t working 100% yet (due to design details which are beyond the scope of this post). I wanted to drop the hook to a lower level so I hooked LdrGetProcedureAddress because that’s the routine that GetProcAddress calls to do the actual work. I then looked at the implementation of LdrGetProcedureAddress and saw that it in turn called LdrGetProcedureAddresEx. Great, I thought, I’ll hook that. Only the hook didn’t ever get called.

Because I had previously always used code hooking I assumed that something funny was going on and that I must have screwed something up. After 10 minutes of rewriting large chunks of code to add debugging information I realised something. It’s an IAT hook, the LdrGetProcedureAddress hook works because GetProcAddress imports that function from NTDLL. LdrGetProcedureAddress however calls LdrGetProcedureAddressEx directly and NTDLL doesn’t import anything because it doesn’t have to, it’s the top of the usermode food chain (so to speak).

Obviously the only way to hook that function is with an EAT hook, so I guess now I HAVE to get that working.

*grumble*