Archive

Posts Tagged ‘winapi’

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.