Archive

Archive for July, 2009

WoWMimic v53

July 16th, 2009

Took a look at the latest build of WoWMimic yesterday. Yet again they claim to have made improvements to their “anti-detection methods”, and yet again I see little to no evidence of that. There really is only one word to describe the current state of WoWMimic and their attempts to fix their anti-warden stuff, and that is “failure”.

They have added another layer of obfuscation since the last build I looked at, but like all their obfuscation attempts their efforts are ultimately futile and it’s a 5 minute job at most to pull away all the crap and find the relevant code. What they did was simply add another level of indirection.

Simple explanation:

They use an INT3 (breakpoint) placed on the return address of the function they wish to hook, then they handle that exception in their vectored exception handler, but rather than go straight to their hook sub like previously, they now go to a block of code which raises a second interrupt. From there they handle that second interrupt and go to the hook sub. In short, all they’ve done is add another layer of indirection which is defeated by simply following flow from the exception address of that layer rather than the first layer. A very basic trick, obviously an amateur attempt.

Their hook on NtQueryVirtualMemory is STILL INSECURE. That’s right, after all this time they still can’t get it right. Sure, they fixed the hole that they got burned by in the last wave, but there are still at least 5 holes that I can see in that hook function alone, and 3 elsewhere. Plus, that’s only with a quick look! With an in-depth check I’m positive more could be uncovered.

Obviously I’m not going to tell them what all the holes are though, that would ruin the fun. But if I have some spare time this week I will write a new WardenMimic build, and we might just play a little game…

If anyone is interested, here is their latest code:

http://cypherjb.privatepaste.com/07090Hlmku

Thanks to Kynox for disassembling some misaligned bytes for me because I didn’t have a VM up and running at the time.

So, in summary:
WoWMimic is going in circles. It’s still just as detectable as it has been since day one. Every time they attempt to ‘fix’ one hole they end up opening up several more. It’s obvious their dev team have no idea what they’re doing. You’re free to waste your money on it, but imo you’re stupid for doing so, because at the end of the day you’re simply playing russian roulette with your accounts, and hey, you don’t need to throw money away to do that, there are plenty of free hacks you can use to get banned.

Update:

Oh, I have some advice for the Mimic team.

Rather than wasting all your time attempting (and failing) to obfuscate your code, why don’t you spend some time on actually implementing your anti-warden properly. Security by obscurity is stupid, because it only takes 5-10 minutes to undo what seems to take you guys days. The people you are up against (Blizzard) are not like you, they’re not amateurs. The Warden guy may be lazy, but he’s not stupid, so the only person’s time you’re wasting is your own.

Author: Cypherjb Categories: Games, Programming, Reversing, Windows Tags:

N-Dimensional Vector Template Class

July 8th, 2009

Hey, whipping together some of the math classes for one of my projects and just ‘finished’ an N-dimensional vector class. Only tested lightly. Should be fully portable, but that has not been tested.

Still needs some extra features (cross product, linear interpolation, reflection, etc), and documentation. If and when I finish that I’ll post an update.

You’re free to use this for whatever. All I ask is that if you find any bugs you please report them. (Oh, acknowledging that Kynox’s sister is a nympho is a big plus too.)

EDIT:

Updated version. Now much more const-safe (whoops!), several minor things fixed, a couple of new features added, portability tested some more (compiles under MSVC and Comeau C++), implemented the suggested generic constructors in case they’re of use to someone.

// Preprocessor header guard to stop multiple includes

#ifndef HADES__VECN_H

#define HADES__VECN_H

// C++ Standard Library

#include <cmath>

#include <cassert>

#include <stdexcept>

#include <algorithm>

#include <functional>

#include <numeric>

#include <vector>

#include <iterator>

// Hades namespace

namespace Hades

{

// N-Dimensional Vector

template <class ElemT, unsigned int Num>

class VecN

{

public:

// ElemT used to store elements

typedef std::vector<ElemT> DataT;

// Element placeholders. For convenience only.

enum Elems

{

XElem,

YElem,

ZElem

};

// Default constructor.

// All dimensions default initialized.

VecN() : m_Size(Num), m_Data(Num) {}

// Vec1 constructor

VecN(ElemT X) : m_Size(Num), m_Data(Num)

{

assert(m_Size == 1);

m_Data[XElem] = X;

}

// Vec2 constructor

VecN(ElemT X, ElemT Y) : m_Size(Num), m_Data(Num)

{

assert(m_Size == 2);

m_Data[XElem] = X; m_Data[YElem] = Y;

}

// Vec3 constructor

VecN(ElemT X, ElemT Y, ElemT Z) : m_Size(Num), m_Data(Num)

{

assert(m_Size == 3);

m_Data[XElem] = X; m_Data[YElem] = Y; m_Data[ZElem] = Z;

}

// Vec4 constructor

VecN(ElemT X, ElemT Y, ElemT Z, ElemT N) : m_Size(Num), m_Data(Num)

{

assert(m_Size == 4);

m_Data[XElem] = X; m_Data[YElem] = Y; m_Data[ZElem] = Z; m_Data[3] = N;

}

// Get reference to vector element

// Implemented by calling const version of function and const_cast’ing

// the returned reference. Safe in this scenario. For more information

// see [Myers].

ElemT& operator[] (unsigned int Index)

{

assert(Index < Num);

return const_cast<ElemT&>(static_cast<const VecN<ElemT, Num>& >(*this).

operator[](Index));

}

// Get const reference to vector element

const ElemT& operator[] (unsigned int Index) const

{

assert(Index < Num);

return m_Data[Index];

}

// Get negated vector

VecN<ElemT, Num> operator- () const

{

VecN<ElemT, Num> Result;

std::transform(m_Data.begin(), m_Data.end(), Result.m_Data.begin(),

std::negate<ElemT>());

return Result;

}

// Vector subtraction

VecN<ElemT, Num> operator- (const VecN<ElemT, Num>& Rhs) const

{

VecN<ElemT, Num> Result;

std::transform(m_Data.begin(), m_Data.end(), Rhs.m_Data.begin(),

Result.m_Data.begin(), std::minus<ElemT>());

return Result;

}

// Vector subtraction

VecN<ElemT, Num> operator-= (const VecN<ElemT, Num>& Rhs)

{

std::transform(m_Data.begin(), m_Data.end(), Rhs.m_Data.begin(),

m_Data.begin(), std::minus<ElemT>());

return *this;

}

// Vector addition

VecN<ElemT, Num> operator+ (const VecN<ElemT, Num>& Rhs) const

{

VecN<ElemT, Num> Result;

std::transform(m_Data.begin(), m_Data.end(), Rhs.m_Data.begin(),

Result.m_Data.begin(), std::plus<ElemT>());

return Result;

}

// Vector addition

VecN<ElemT, Num> operator+= (const VecN<ElemT, Num>& Rhs)

{

std::transform(m_Data.begin(), m_Data.end(), Rhs.m_Data.begin(),

m_Data.begin(), std::plus<ElemT>());

return *this;

}

// Vector multiplication (scales elements)

VecN<ElemT, Num> operator* (ElemT Rhs) const

{

VecN<ElemT, Num> Result;

std::transform(m_Data.begin(), m_Data.end(), Result.m_Data.begin(),

std::bind2nd(std::multiplies<ElemT>(), Rhs));

return Result;

}

// Vector multiplication (scales elements)

// Mixed mode version

friend inline VecN<ElemT, Num> operator* (ElemT Rhs,

const VecN<ElemT, Num>& v)

{

VecN<ElemT, Num> Result;

std::transform(v.m_Data.begin(), v.m_Data.end(), Result.m_Data.begin(),

std::bind2nd(std::multiplies<ElemT>(), Rhs));

return Result;

}

// Vector multiplication (scalar/dot product)

ElemT operator* (const VecN<ElemT, Num>& Rhs) const

{

DataT Result(Num);

std::transform(m_Data.begin(), m_Data.end(), Rhs.m_Data.begin(),

Result.begin(), std::multiplies<ElemT>());

return std::accumulate(Result.begin(), Result.end(),

static_cast<ElemT>(0));

}

// Vector multiplication (scales elements)

VecN<ElemT, Num> operator*= (const VecN<ElemT, Num>& Rhs)

{

std::transform(m_Data.begin(), m_Data.end(), Rhs.m_Data.begin(),

m_Data.begin(), std::multiplies<ElemT>());

return *this;

}

// Vector division (scalar/dot division)

ElemT operator/ (const VecN<ElemT, Num>& Rhs) const

{

DataT Result(Num);

std::transform(m_Data.begin(), m_Data.end(), Rhs.m_Data.begin(),

Result.begin(), std::divides<ElemT>());

return std::accumulate(Result.begin(), Result.end(),

static_cast<ElemT>(0));

}

// Vector division (scalar/dot division)

VecN<ElemT, Num> operator/= (const VecN<ElemT, Num>& Rhs)

{

std::transform(m_Data.begin(), m_Data.end(), Rhs.m_Data.begin(),

m_Data.begin(), std::divides<ElemT>());

return *this;

}

// Equality test

bool operator == (const VecN<ElemT, Num>& Rhs) const

{

return std::equal(m_Data.begin(), m_Data.end(), Rhs.m_Data.begin());

}

// Inequality check

bool operator != (const VecN<ElemT, Num>& Rhs) const

{

return !std::equal(m_Data.begin(), m_Data.end(), Rhs.m_Data.begin());

}

// Output stream overload

// Prints in format:

// E1 E2 … EN

friend inline std::ostream& operator << (std::ostream& Lhs,

const VecN<ElemT, Num>& Rhs)

{

std::copy(Rhs.m_Data.begin(), Rhs.m_Data.end(),

std::ostream_iterator<ElemT>(Lhs, ” “));

return Lhs;

}

// Gets the squared length of a vector

friend inline ElemT LengthSquared(const VecN<ElemT, Num>& v)

{

VecN<ElemT, Num> Temp;

std::transform(v.m_Data.begin(), v.m_Data.end(), v.m_Data.begin(),

Temp.m_Data.begin(), std::multiplies<ElemT>());

return std::accumulate(Temp.m_Data.begin(), Temp.m_Data.end(),

static_cast<ElemT>(0));

}

// Gets the length of a vector

friend inline ElemT Length(const VecN<ElemT, Num>& v)

{

return static_cast<ElemT>(sqrt(static_cast<long double>(

LengthSquared(v))));

}

// Normalizes a vector

friend inline ElemT Normalize(VecN<ElemT, Num>& v)

{

ElemT Len = Length(v);

if (Len != static_cast<ElemT>(0))

{

std::transform(v.m_Data.begin(), v.m_Data.end(), v.m_Data.begin(),

std::bind2nd(std::divides<ElemT>(), Len));

}

return Len;

}

// Tests if a vector is normalized

friend inline bool IsNormalized(const VecN<ElemT, Num>& v,

ElemT Eps = static_cast<ElemT>(1.0001f))

{

return static_cast<ElemT>(fabs(static_cast<long double>(

LengthSquared(v) - static_cast<ElemT>(1))))

<= static_cast<ElemT>(Eps);

}

// Cross product

friend inline VecN<ElemT, 3> Cross(const VecN<ElemT, 3>& v1,

const VecN<ElemT, 3>& v2)

{

return VecN<ElemT, 3>(

(v1[YElem] * v2[ZElem]) - (v1[ZElem] * v2[YElem]),

(v1[ZElem] * v2[XElem]) - (v1[XElem] * v2[ZElem]),

(v1[XElem] * v2[YElem]) - (v1[YElem] * v2[XElem])

);

}

// Reflection

friend inline VecN<ElemT, Num> Reflect(const VecN<ElemT, Num>& v,

const VecN<ElemT, Num>& Normal)

{

return v - (static_cast<ElemT>(2.0) * ((v * Normal) * Normal));

}

private:

// Size of vector

unsigned int m_Size;

// Vector elements

std::vector<ElemT> m_Data;

};

// Ease of use typedefs

typedef VecN<int, 2> Vec2i;

typedef VecN<float, 2> Vec2f;

typedef VecN<double, 2> Vec2d;

typedef VecN<int, 3> Vec3i;

typedef VecN<float, 3> Vec3f;

typedef VecN<double, 3> Vec3d;

}

#endif // HADES__VECN_H

Hey, whipping together some of the math classes for one of my projects and just ‘finished’ an N-dimensional vector class. Only tested lightly.
Should be fully portable, but that has not been tested.
Still needs some extra features (cross product, linear interpolation, reflection, etc), and documentation. If and when I finish that I’ll post an update.
You’re free to use this for whatever. All I ask is that if you find any bugs you please report them.
Author: Cypherjb Categories: Programming Tags: , , , , ,

Status update and some code

July 6th, 2009

Been quiet the last week because I’ve just moved house. Got everything sorted and up and running now though so I should be able to get some stuff done. I still plan to take a look at some of the bots on the market currently, but have just been so busy lately, and with Mimic already being half-way into their grave I didn’t really think it was urgent to push them in all the way, I think they can take care of that themselves.

Anyway, I figured I may as well post something of use so here’s a C++ logging class I posted on GD that may be of use to people*:

* I’ll post a version with some of the outlined problems fixed Soon. Just gotta get back into the swing of things, moving always shakes me up for a few days.

This is a C++ logging class designed to be both generic and portable. Currently needs fixes in order to be truly portable but I havn’t had time to reinstall G++ or Intel to test, I’ve outlined the minor issues though. If you want to fix the issues it’s a 10 minute job at most, I’m just lazy.

The idea is that you can redirect the standard output streams to a file using a generic class template (so when new character types are added like the ones in C++0x it will be much easier to add support).

This should work across operating systems (Linux, Mac, etc).. Anything with Boost support (which is all major OS’s) SHOULD work, but is untested. Obviously you’ll need to remove the MSVC specific pragmas.

Notes:
* Boost dependency. This will not work without Boost. No I will not help you install Boost, it’s not hard, just read the documentation. If you can’t get it working you probably shouldn’t be using C++.
* Minor modifications needed for it to be truly portable. (See below)
* Relative log file path is hardcoded to “../Logs/Hades-%s.log”. Simply change that to a relative path from your module.
* Compiler is assumed to be MSVC. I am using VS 2008 Team Edition with code analysis enabled. If you get an error about warning “6328″ not being valid simply remove the pragma line with that in it.
* If you are using a compiler other than MSVC you’ll want to remove the ‘pragma warning’ stuff, I’ll fix that later.
* Makes heavy use of templates. Unless you know what you’re doing its probably best to just leave all the typedefs and template stuff alone.

Usage:
Makes use of templates and the standard output streams.
For example:
// Logging objects
Logger<char>::Stream m_AnsiStream;
Logger<wchar_t>::Stream m_WideStream;
// Initialize logger
m_AnsiStream.open(Logger<char>());
std::cout.rdbuf(m_AnsiStream.rdbuf());
m_WideStream.open(Logger<wchar_t>());
std::wcout.rdbuf(m_WideStream.rdbuf());

Now, whenever you use cout or wcout like so:
std::cout << “Look ma, I’m using the standard output stream!” << std::endl;
std::wcout << L”Wide output too!”"<< std::endl;

The output will be redirected to your file rather than to the screen or wherever the standard output was aimed at previously.

Obviously your Logger objects need to remain valid whilst ever your program is running unless you manually reset the standard output stream buffers. This means that you should store them as static objects somewhere. If you store them as a local object then they will be destructed when they move out of scope and you’ll get an access violation.

An alternative to the above is to just heap-allocate the object. Its destructor will never be called but this is probably not a problem. The reason this may be better is that you avoid race conditions implicit in the order of destruction of static objects. Obviously do NOT use a smart pointer because at that point it WILL be deleted and you’re back where you started.

Misc:
You are free to use this for whatever, as long as you agree that Kynox’s sister is a nympho.

Code:

// Preprocessor header guard to stop multiple includes

#ifndef HADES__LOGGER_H

#define HADES__LOGGER_H

// C++ Standard Library

#include <iostream>

#include <string>

#include <vector>

#include <fstream>

// Boost C++ Libraries

#pragma warning(push, 1)

#pragma warning(disable: 6328)

#pragma warning(disable: 4996)

#pragma warning(disable: 4702)

#include <boost/iostreams/categories.hpp>

#include <boost/iostreams/stream.hpp>

#include <boost/date_time/posix_time/posix_time.hpp>

#include <boost/format.hpp>

#include <boost/filesystem.hpp>

#pragma warning(pop)

// Logging class

template <typename _charT>

class Logger

{

public:

// Sink information

typedef _charT char_type;

typedef boost::iostreams::sink_tag category;

// STL typedefs

typedef std::basic_ofstream<char_type> tofstream;

typedef std::basic_string<char_type> tstring;

// Boost typedefs

typedef boost::basic_format<char_type> tformat;

struct path_traits;

typedef boost::filesystem::basic_path<tstring, path_traits> tpath;

struct path_traits

{

typedef tstring internal_string_type;

typedef tstring external_string_type;

static external_string_type to_external( const tpath &,

const internal_string_type & src ) { return src; }

static internal_string_type to_internal(

const external_string_type & src ) { return src; }

};

// Stream typedef

typedef boost::iostreams::stream< Logger<_charT> > Stream;

// Constructor

Logger() : m_LogPath(GeneratePath())

{ }

// Generate path to log file.

tstring GeneratePath()

{

// For boost

using namespace boost::posix_time;

using namespace boost::filesystem;

using boost::str;

// For STL

using std::string;

using std::wstring;

// Get local time

ptime Time(second_clock::local_time());

// Convert time to string YYYY-MM-DDTHH:MM:SS

tstring TimeStr(to_iso_extended_string_type<char_type>(Time));

// Reformat time YYYY-MM-DD_HH-MM-SS

TimeStr[10] = ‘_’;

TimeStr[13] = ‘-’;

TimeStr[16] = ‘-’;

// Generate file path relative to initial directory

wstring WideFormat(L”../Logs/Hades-%s.log”);

tstring AnyFormat(WideFormat.begin(), WideFormat.end());

tstring RelPath(str(tformat(AnyFormat) %TimeStr));

// Make full path to log file

tpath Current(initial_path<tpath>());

Current /= RelPath;

// Return path to log file

return Current.string();

}

// Writes n characters from s

std::streamsize write(const char_type* s, std::streamsize n)

{

// For boost

using namespace boost::posix_time;

// Get time

ptime Time(second_clock::local_time());

tstring TimeStr = to_simple_string_type<char_type>(Time);

// Open file

tofstream Out(m_LogPath.c_str(), tofstream::out | tofstream::app );

if(Out.is_open() && Out.good())

{

// Write time as string

Out << ‘[' << TimeStr << "]: “;

// Write data

Out.write(s, n);

}

// Return size

return n;

}

private:

// Path to log file

tstring m_LogPath;

};

#endif // HADES__LOGGER_H

// Preprocessor header guard to stop multiple includes
#ifndef HADES__LOGGER_H
#define HADES__LOGGER_H
// C++ Standard Library
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
// Boost C++ Libraries
#pragma warning(push, 1)
#pragma warning(disable: 6328)
#pragma warning(disable: 4996)
#pragma warning(disable: 4702)
#include <boost/iostreams/categories.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#pragma warning(pop)
// Logging class
template <typename _charT>
class Logger
{
public:
// Sink information
typedef _charT char_type;
typedef boost::iostreams::sink_tag category;
// STL typedefs
typedef std::basic_ofstream<char_type> tofstream;
typedef std::basic_string<char_type> tstring;
// Boost typedefs
typedef boost::basic_format<char_type> tformat;
struct path_traits;
typedef boost::filesystem::basic_path<tstring, path_traits> tpath;
struct path_traits
{
typedef tstring internal_string_type;
typedef tstring external_string_type;
static external_string_type to_external( const tpath &,
const internal_string_type & src ) { return src; }
static internal_string_type to_internal(
const external_string_type & src ) { return src; }
};
// Stream typedef
typedef boost::iostreams::stream< Logger<_charT> > Stream;
// Constructor
Logger() : m_LogPath(GeneratePath())
{ }
// Generate path to log file.
tstring GeneratePath()
{
// For boost
using namespace boost::posix_time;
using namespace boost::filesystem;
using boost::str;
// For STL
using std::string;
using std::wstring;
// Get local time
ptime Time(second_clock::local_time());
// Convert time to string YYYY-MM-DDTHH:MM:SS
tstring TimeStr(to_iso_extended_string_type<char_type>(Time));
// Reformat time YYYY-MM-DD_HH-MM-SS
TimeStr[10] = ‘_’;
TimeStr[13] = ‘-’;
TimeStr[16] = ‘-’;
// Generate file path relative to initial directory
wstring WideFormat(L”../Logs/Hades-%s.log”);
tstring AnyFormat(WideFormat.begin(), WideFormat.end());
tstring RelPath(str(tformat(AnyFormat) %TimeStr));
// Make full path to log file
tpath Current(initial_path<tpath>());
Current /= RelPath;
// Return path to log file
return Current.string();
}
// Writes n characters from s
std::streamsize write(const char_type* s, std::streamsize n)
{
// For boost
using namespace boost::posix_time;
// Get time
ptime Time(second_clock::local_time());
tstring TimeStr = to_simple_string_type<char_type>(Time);
// Open file
tofstream Out(m_LogPath.c_str(), tofstream::out | tofstream::app );
if(Out.is_open() && Out.good())
{
// Write time as string
Out << ‘[' << TimeStr << "]: “;
// Write data
Out.write(s, n);
}
// Return size
return n;
}
private:
// Path to log file
tstring m_LogPath;
};
#endif // HADES__LOGGER_H
Author: Cypherjb Categories: Games, Programming Tags: , , , , , ,