• Welcome to Valhalla Legends Archive.
 

Rudimentary Warden information

Started by iago, February 28, 2008, 05:07 PM

Previous topic - Next topic
|

bulletproof tiger

It's a little silly to argue whether or not these games use some sort of anti-hack mechanism to stop emulation of the client, also. None of us know for a fact, because if any of us worked at Blizzard we probably wouldn't be sitting here discussing this in the "how to emulate warden" thread.

I'm not at all familiar with how Warden works, but from what Herzog has told us, it sounds like the process sort of goes like this:

1. recv warden 'module' data during logon procedure
2. pointer to warden 'module' data is probably given to some method that makes use of this data
.. is this something that has been researched, and documented? (code snippets, psuedocode, whatever)
3. warden module is used to generate some data that is then forwarded to bnet

is this the general process? if so, is this repeated throughout the duration spent online?

brew

Quote from: chyea on November 16, 2008, 11:40 PM
1. recv warden 'module' data during logon procedure
Yea, well, more like right after.

Quote
2. pointer to warden 'module' data is probably given to some method that makes use of this data
.. is this something that has been researched, and documented? (code snippets, psuedocode, whatever)
huh? :p a pointer to the warden module is the first member of a warden class

Quote
3. warden module is used to generate some data that is then forwarded to bnet
Yes

Quote
is this the general process? if so, is this repeated throughout the duration spent online?
The same module requested after logon is used throughout the connection.
<3 Zorm
Quote[01:08:05 AM] <@Zorm> haha, me get pussy? don't kid yourself quik
Scio te esse, sed quid sumne? :P

bulletproof tiger

What does the module require to function properly? What's stopping a client emulator from downloading the module and using it?

Barabajagal

Data in memory... The module reads application memory where it expects starcraft to be loaded. See the last page or the page before for brew's explanation of why it's not feasible to emulate starcraft in memory.

Mystical

Quote from: brew on November 16, 2008, 10:16 PM
There's a giant dick heading for your mouth.
You say, "Oh man i'm gonna have to suck this thing!" and brace for impact,
however at the last minute it changes trajectory and stabs you in the eye.
You now have this giant penis inside of your eyesocket, impailing your skull.
It pulls out, and rams back in, over and over and over.
You end up dying a slow, painful death.

I don't think we needed to hear about your personal life. :P

bulletproof tiger

Quote from: Andy on November 18, 2008, 03:30 PM
Data in memory... The module reads application memory where it expects starcraft to be loaded. See the last page or the page before for brew's explanation of why it's not feasible to emulate starcraft in memory.

What data, specifically? Is it known how this data is derived? Can this data be produced without needing the client to be loaded? Is this data just to make sure that the client hasn't been modified? If so, is it always static, like lockdown did?

bulletproof tiger

Well? Is this where the extent of the public knowledge ends?

Hdx

Yes, pretty much, If we knew exactly what the module was doing we would have no problem emulating it.
But, the problem is, the modules can change, that's the nature of warden. So the only 100% way to make it happy is to have the entire memory space of sc mapped out with the correct data.

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

Barabajagal

Couldn't we do it with a BIN file like lockdown?

Hdx

Quote from: Andy on November 19, 2008, 01:12 PMCouldn't we do it with a BIN file like lockdown?
Why yes we could, the files we would need are: Starcraft.exe Storm.dll and Battle.snp Map those out, trick warden into not checking where its being called from, and then away you go.

Proud host of the JBLS server www.JBLS.org.
JBLS.org Status:
JBLS/BNLS Server Status

Barabajagal

Well... we already have all those files for hashing... I still think you should be able to load data into a "virtual" memory system somehow. Just copy all the data and allocate enough space for where the data would normally be loaded in memory, and woosh?

bulletproof tiger

Quote from: Hdx on November 19, 2008, 12:17 PM
So the only 100% way to make it happy is to have the entire memory space of sc mapped out with the correct data.

Well, yea, but that's only because nobody seems to have gone through and analyzed what these warden modules actually do. It sounds as if it'd be wise to write up something to perhaps detect certain algorithms in these modules, and eventually add functionality for evaluating these 'on the fly' algorithms with the appropriate data substituted in. In every scenario the data that these algorithms are dependent on should be static. If they were portions of data that could change it wouldn't really be an appropriate thing to base a challenge on - unless of course it's some crazy thing that I just don't understand. :P

I recall seeing one of these warden modules, and I don't think they were too large. I remember them being fairly small. So I'm guessing it's just a single equation, or two, like Herzog mentioned.

In regards to basically writing an asm to whatever code converter... well... that'd take some research.

brew

#267
It'd be nice to know wtf 9000h is. It's a global variable within the module with some psuedo-random (hell, even xor'd with esp) value that seems to be a centric part of the module. This is where it's generated, in 56f25ca5bd550b384cc4fa457b438012 at least (i've nicknamed it magic):

int __stdcall makevalues_2F01() {
 FILETIME ft;
 LARGE_INTEGER largeint;
 unsigned int result
 ft.dwLowDateTime = 0;
 ft.dwHighDateTime = 0;
 if ((magic != BB40E64E) && (magic & 0xFFFF0000)) {
   result = ~magic;
   v9004 = ~magic;
 } else {
   GetSystemTimeAsFileTime(&ft);
   uint syshash = GetTickCount() ^ (GetCurrentThreadId() ^ (GetCurrentProcessId() ^ ft.dwLowDateTime ^ ft.dwHighDateTime));
   QueryPerformanceCounter(&largeint);
   result = largeint.LowPart ^ largeint.HighPart;
   uint tmp = largeint.LowPart ^ largeint.HighPart ^ syshash;
   if (tmp == 0xBB40E64E) {
     tmp = 0xBB40E64F;
   } else {
     if (!(tmp & 0xFFFF0000)) {
       result = tmp << 16;
       tmp |= tmp << 16;
     }
   }
   magic = tmp;
   v9004 = ~tmp;
 }
 return result;
}


It's boggling to me. The authors of this module have the audacity to expect this, xored with GetTickCount() ffs, to be some exact value?


@chyea:
the modules can actually be quite large. the one i'm working on right now is 32 kb.
<3 Zorm
Quote[01:08:05 AM] <@Zorm> haha, me get pussy? don't kid yourself quik
Scio te esse, sed quid sumne? :P

bulletproof tiger

Quote from: brew on November 19, 2008, 02:33 PM
It'd be nice to know wtf 9000h is. It's a global variable within the module with some psuedo-random (hell, even xor'd with esp) value that seems to be a centric part of the module. This is where it's generated, in 56f25ca5bd550b384cc4fa457b438012 at least (i've nicknamed it magic):

int __stdcall makevalues_2F01() {
  FILETIME ft;
  LARGE_INTEGER largeint;
  unsigned int result
  ft.dwLowDateTime = 0;
  ft.dwHighDateTime = 0;
  if ((magic != BB40E64E) && (magic & 0xFFFF0000)) {
    result = ~magic;
    v9004 = ~magic;
  } else {
    GetSystemTimeAsFileTime(&ft);
    uint syshash = GetTickCount() ^ (GetCurrentThreadId() ^ (GetCurrentProcessId() ^ ft.dwLowDateTime ^ ft.dwHighDateTime));
    QueryPerformanceCounter(&largeint);
    result = largeint.LowPart ^ largeint.HighPart;
    uint tmp = largeint.LowPart ^ largeint.HighPart ^ syshash;
    if (tmp == 0xBB40E64E) {
      tmp = 0xBB40E64F;
    } else {
      if (!(tmp & 0xFFFF0000)) {
        result = tmp << 16;
        tmp |= tmp << 16;
      }
    }
    magic = tmp;
    v9004 = ~tmp;
  }
  return result;
}


It's boggling to me. The authors of this module have the audacity to expect this, xored with GetTickCount() ffs, to be some exact value?

Looks to me like it's not very magic, heh. Looks like it's checking to see if that value is what it expects, and if it's not it reset it to something more appropriate - in this case, a time stamp, or something.

brew

#269
Haha :D I just figured out exactly what it is. Apparently, it's a 'security cookie' thrown in as a defense against buffer overruns.

**EDIT
Oh by the way, for anyone else checking out what the modules do,
here's a listing of battle.snp's 'warden exports'

.rdata:1903DB64 WardenSNPExportTable dd offset WardenSNPSend0x5E ;19031410
.rdata:1903DB64                                         ; DATA XREF: .data:off_19043408
.rdata:1903DB68                 dd offset WardenSNPModuleStart  ;19031E80
.rdata:1903DB6C                 dd offset SaveModuleToBNCache ;19031500
.rdata:1903DB70                 dd offset WardenSNPAllocCrap ;190313B0
.rdata:1903DB74                 dd offset WardenSNPFreeWrapper ;19031390
.rdata:1903DB78                 dd offset WardenSNPDupClass ;19031340
.rdata:1903DB7C                 dd offset WardenSNPMemcpyNFree ;190312D0
<3 Zorm
Quote[01:08:05 AM] <@Zorm> haha, me get pussy? don't kid yourself quik
Scio te esse, sed quid sumne? :P

|