Archive

Posts Tagged ‘api’

Hades Lua Support

June 24th, 2009

Just finished adding the very first revision of LUA support to Hades. Currently it’s just a proof of concept, as all it does is load a LUA script which calls a custom function I’ve registered to print the arguments passed to the function to the console. Getting that first bit done and working though is the biggest hurdle, so with that finished I can now move on to writing proper code for it and exposing my whole API.

Both x86 (WoW) and x64 (HL2) builds are tested and working.

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

WoWMimic v49

June 5th, 2009

WoWMimic v49 is out, a very quick bugfix release.

Nothing has changed in terms of anti-detection (so WardenMimic still works), but amusingly, they introduced a bug into their (recently removed) GetCursorPos and SetCursorPos hook subs for VEH.

They have removed a line from both that compares an internal flag to 1/0. What’s amusing about it is, they left in a conditional jump that relied on that line. That conditional jump will now fire based off the line above (a SUB instruction, which like CMP sets the ZF), and the jump will never be taken. Why is this amusing? Because its proof that the devs wrote the code using inline assemby. I was moderately sure of this before (due to the use of PUSHAD, POPAD, etc), but now we have confirmation. Not only is it totally unneeded to do all that crap in inline ASM, but it also explains that they did in fact implement the obfuscation code manually (mentioned in a previous post), obviously thinking it posed some kind of barrier.

Sorry guys, but it probably took me less time to undo it than it took you to figure it out and write it. REALLY obvious job. The call/pop trick is one of the oldest in the book, literally. C’mon. Raise the bar and give us something fun and challenging to play with. (Yeah I know, I’m asking for the world from these guys)

P.S. Still can’t figure out how to stop detection by WardenMimic?

Preventing Recursion in API Hooks

May 26th, 2009

I’m sure many have ran across the same issue I did recently, and that is that when doing API hooking of low-level functions (e.g. the NT API) code that is inserted into the hook function (e.g. logging code) will end up calling the same function and cause a stack overflow.

Greyman had a good idea which I’ve used, and put together an example for. Credits to Greyman for the idea.

Basically, you use TLS to hold a flag so that the offending code (the code causing the infinite recursion)  is only executed once per call. The following code should work under all major Windows compilers, but is using a nonstandard compiler extension so may not work cross-platform (which is not a concern for a low level project anyway). Using LdrGetProcedureAddress as an example because using any of the standard output functions will cause the recursive call (printf, std::cout, etc):

NTSTATUS NTAPI APIHook::LdrGetProcedureAddress_Hook( IN HMODULE ModuleHandle,

IN PANSI_STRING FunctionName OPTIONAL, IN WORD Ordinal OPTIONAL,

OUT PVOID *FunctionAddress )

{

// Use TLS to prevent recursive function calls when logging

static __declspec(thread) bool Logging = false;

// Get the true address of the function

NTSTATUS RetVal =

((tLdrGetProcedureAddress)(PROC)(sm_LdrGetProcedureAddress))

(ModuleHandle,FunctionName,Ordinal,FunctionAddress);

// Don’t call function recursively when logging

if (Logging)

return RetVal;

// Start logging wrapper

Logging = true;

// Function pointer

PVOID pFunc = (FunctionAddress ? *FunctionAddress : 0);

// Log API call

if (Config::Get()->ShouldLogFunctions())

{

try

{

// Guard against structured exceptions

SehGuard Guard;

// Create string from c-style string

// Note: Will thrown an access violation if c-style string isn’t a

// valid pointer

std::string FunctionNameTemp(FunctionName->Buffer);

// If we get to this point the string is valid so log it.

DBGPRNT(boost::str(boost::format(”LdrGetProcedureAddress: Module”

” = %p, Name = %s. Return = %p.\n”) %ModuleHandle

%FunctionNameTemp %pFunc).c_str());

}

catch (const SehException& /*e*/)

{

// If we get here the string is invalid so we assume it’s an

// ordinal and log it as such

DBGPRNT(boost::str(boost::format(”LdrGetProcedureAddress: Module”

” = %p,  Ordinal = %u. Return = %p.\n”) %ModuleHandle %Ordinal

%pFunc).c_str());

}

}

// End logging wrapper

Logging = false;

// Check we got a valid pointer back

if (!FunctionAddress)

return RetVal;

// Dereference pointer and get actual function pointer

FARPROC pfn = (FARPROC)(*FunctionAddress);

// Is it one of the functions that we want hooked?

APIHook* p = sm_pHead;

for (; (pfn != NULL) && (p != NULL); p = p->m_pNext)

{

if (pfn == p->m_pOrig)

{

// The address to return matches an address we want to hook

// Return the hook function address instead

pfn = p->m_pHook;

break;

}

}

return RetVal;

}

In the above code DBGPRNT is just a macro used to call ‘printf’ if a certain compiler flag is enabled, or omit the code entirely if the flag is disabled. Implemented that way for performance reasons. Irrelevant details aside though, its easy to see how the implementation and how simple it is to use. Obviously thread-safe due to the variable being thread-local so it shouldn’t interfere with anything, I’ve yet to have any problems with it. Tested on both IA-32 and AMD64.

Hardcoded IPC Name Still There

May 21st, 2009

It seems that whilst the WoWMimic folks have ‘kinda’ listened to Kynox, Harko, Myself, etc. they still have selective hearing. Although they’ve started hooking VirtualQueryEx (they still haven’t worked out to hook the NT API it seems) the hardcoded IPC name seems to still be there.

That means that this still works: In-process WoWMimic Detection

On a nicer note though it seems that they have finally realized that they are not immune to Warden. Granted, they learned this the hard way (it seems that either WoW or Warden is detecting it in some shape or form), but at least it finally happened.

More WoWMimic Detection Code

May 15th, 2009

Well, we have found yet another hole in WoWMimic that is criminally easy to abuse. Credits to Kynox and Harko for working on this with me.

This code abuses the fact that the WoWMimic idiots are only hooking VirtualQuery, and none of the lower control paths, so we can easily call VirtualQueryEx to verify that the results we get back are untainted. If we find something that has been modified we know we have a hidden page. Mimic only hides the base page, not the entire module, so at the point I’ve marked “Warden function to do hashing goes here”, you simply need to do standard hashing of  data in the page, something which Warden already does (the reason for the hook in the first place).

void FindHiddenPages()

{

std::cout << “Start!” << std::endl << std::hex;

PVOID p1 = 0, p2 = 0;

MEMORY_BASIC_INFORMATION MyMbi = { 0 };

typedef std::vector< std::pair<PVOID,PVOID> > tAddresses;

tAddresses AddressList;

tAddresses Hidden;

while (VirtualQuery(p1,&MyMbi,sizeof(MyMbi)) == sizeof(MyMbi))

{

if (MyMbi.State == MEM_COMMIT && MyMbi.AllocationBase != p2 &&

MyMbi.AllocationBase == MyMbi.BaseAddress)

{

AddressList.push_back(std::make_pair(MyMbi.AllocationBase,MyMbi.BaseAddress) );

}

p2 = MyMbi.AllocationBase;

p1 = reinterpret_cast<PVOID>(reinterpret_cast<DWORD_PTR>(p1) + MyMbi.RegionSize);

}

p1 = p2 = 0;

while (VirtualQueryEx(GetCurrentProcess(),p1,&MyMbi,sizeof(MyMbi)) == sizeof(MyMbi))

{

if (MyMbi.State == MEM_COMMIT && MyMbi.AllocationBase != p2 &&

MyMbi.AllocationBase == MyMbi.BaseAddress)

{

std::pair<PVOID,PVOID> MyAddresses(MyMbi.AllocationBase,MyMbi.BaseAddress);

const tAddresses::const_iterator iCurrent(std::find(AddressList.begin(),AddressList.end(), MyAddresses));

if (iCurrent == AddressList.end())

Hidden.push_back(MyAddresses);

}

p2 = MyMbi.AllocationBase;

p1 = reinterpret_cast<PVOID>(reinterpret_cast<DWORD_PTR>(p1) + MyMbi.RegionSize);

}

for (tAddresses::const_iterator i = Hidden.begin(); i != Hidden.end(); ++i)

{

std::cout << “Hidden page! Allocation Base: ” << i->first

<< “. Base Address: ” << i->second << “.” << std::endl;

// Warden function to do hashing goes here

}

std::cout << “End!” << std::endl << std::dec;

}

On its own, even without hashing, you still have ground for a kick at the very least because hiding memory pages is something that only malicious software normally does. Once you add hashing though you have a guarantee of no false positives so you can go ahead and ban for it.

Yet again it seems that WoWMimic just doesn’t stand up when it comes to the detection test. Don’t trust their website, this thing is trivial to detect.

Windows 7 RC1 Binaries

April 25th, 2009

As everyone probably already knows, the Windows 7 release candidate was leaked to the interwebs (build 7100). Because I’m an Australian and our technology infrastructure is 5 years behind the rest of the western world I can’t grab the builds straight away due to caps on internet usage and whatnot.

Thanks to maclone though I don’t have to. He was kind enough to rip the binaries I was interested in from the x64 build and send them to me. I figured they might be of use to other people too (there’s quite a few changes you’ll need to be aware of if you’re doing heavy API hooking like I am) so I’ve mirrored them to a public link. All credits to maclone for actually pulling these out for me.

Download

Included is both the x86 and x64 versions of Kernel32.dll, Ntdll.dll, User32.dll, and KernelBase.dll (new in Windows 7 — along with a handful of other Kernel32 sub-binaries which I did not request).

Anyway, this is just a quick post so people can avoid downloading the entire OS unnecessarily if they’re like me and just need a handful of DLLs.

A more interesting post should be incoming today or tomorrow where I’ll be posting usermode rootkit code.