Jump to content

Warden


Recommended Posts

  • 39 years later...
  • Replies 125
  • Created
  • Last Reply

Top Posters In This Topic

Has anybody done any research on Warden in WoW?

I know for a fact that the modules they use are the same EXACT ones that are used on other clients. [sC, WC3. and D2] A simple look inside Warden's cache files will tell you this.

I have successfully written a replacement for Mediv that will load unsigned Warden modules, [tested on SC] I have written a DLL to Module converter.

I know how the modules are encrypted, verified, Loaded and executed. I know almost all of the functionality of the current modules that are on live servers [257 if you want to know, 128 variations of a basic test module Read bytes from Y and return them, 128 Extended modules, Which have support for generating new psudo-random rc4 keys, and funnily enough, Mediv]

Rather then digging around in Wow's game files myself, because it takes 3 hours to decompile -.-, Does anybody know:

1) Where the seed for the rc4 keys are snagged from?

2) Where the original Mediv module is located?

SC was easy, simply add in a file to it's BNCache named Mediv.mod and it would load it instead of the real one, Stupid order of loads. At the vary least I'd like to understand where it gets it's seed from. Though I haven't really ever done any WoW related dev so I'm asking before I shove my face in ASM :(

Link to comment
Share on other sites

On WoW, the modules are actually downloaded on log-in from the game server, so they are not stored locally. Could you send me a PM with more information on what you found? You may not be able to talk about it on here.
There is an initial module, Mediv.mod that is locally stored, it is the 1st module that is loaded, and then it handles the transfer/loading of other modules. This is how it works in BNet clients and I'm sure this is how it works in WoW as like I said they use the same EXACT modules.
It's initialized with the sessionkey, I did some research some months ago:

https://sharesource.org/hg/sniffitzt/file/af5505e0931c/src/sniffitzt/WardenHandler.java

Thank you, I did some preliminary work and it looks like you are 100% correct:

int main(){
 uint8_t *k = (uint8_t *)"\\x19\\x21\\x94\\xea\\xcb\\xa4\\x69\\xb6\\xa2\\x48\\x6a\\xc5\\x95\\x1b\\x2e\\x33\\xc3\\x3e\\xbc\\xca\\x31\\x92\\xdc\\xb3\\xc4\\xfe\\x27\\x20\\xdb\\xf8\\x22\\x35\\x80\\x92\\x93\\xc3\\x9f\\xa0\\xcd\\x5e";
 uint8_t *d = (uint8_t *)"\\x8D\\x7D\\x29\\xED\\x78\\x8F\\xE3\\x87\\xBE\\x85\\x98\\x59\\x69\\x93\\x7E\\xB0\\x69\\x23\\x84\\x35\\xE8\\x73\\xC3\\x46\\x02\\x7C\\xD4\\x5C\\xC8\\xCE\\x04\\xD9\\xBE\\x56\\x93\\xB1\\x22";

 /* u.u so much memory to alloc! */
 mediv_random_context *rnd = (mediv_random_context *)safe_malloc(sizeof(mediv_random_context));
 uint8_t *td       = (uint8_t *)safe_malloc(38);
 uint8_t *out_seed = (uint8_t *)safe_malloc(0x10);
 uint8_t *in_seed  = (uint8_t *)safe_malloc(0x10);
 uint8_t *out_key  = (uint8_t *)safe_malloc(0x102);
 uint8_t *in_key   = (uint8_t *)safe_malloc(0x102);
 uint8_t *md5      = (uint8_t *)safe_malloc(0x10);
 uint8_t *key      = (uint8_t *)safe_malloc(0x10);
 uint32_t x = 0;
 uint8_t opcode;
 uint32_t length;
 buffer_t *buf;

 memcpy(td, d, 38);

 mediv_random_init(rnd, k, 40);
 mediv_random_get_bytes(rnd, out_seed, 0x10);
 mediv_random_get_bytes(rnd, in_seed,  0x10);

 rc4_init(out_key, out_seed, 0x10);
 rc4_init(in_key,  in_seed,  0x10);

 rc4_crypt(in_key, td, 38);
 buf = buffer_create_with_data(BO_LITTLE_ENDIAN, td, 38);

 printf("Decrypted Data:\\n");
 buffer_print(buf);


 /* Format for Opcode 0x00:
  *Request:
  *   (Byte[16]) MD5 Hash of Module
  *   (Byte[16]) Module Decryption Seed
  *   (DWORD) Module Length
  *Response:
  *  (Byte) Status
  *    0 - Do not have module, Request Transfer
  *    1 - Have Module and Loaded properly
  */
 opcode = buffer_read_next_int8(buf);
 buffer_read_next_bytes(buf, md5, 0x10);
 buffer_read_next_bytes(buf, key, 0x10);
 length = buffer_read_next_int32(buf);

 printf("\\nOut Seed: "); for(x = 0; x < 0x10; x++) printf("%02X ", out_seed[x]);
 printf("\\nIn Seed:  "); for(x = 0; x < 0x10; x++) printf("%02X ", in_seed[x]);
 printf("\\nOpcode:   0x%02X", opcode);
 printf("\\nMD5:      "); for(x = 0; x < 0x10; x++) printf("%02X ", md5[x]);
 printf("\\nRC4 Seed: "); for(x = 0; x < 0x10; x++) printf("%02X ", key[x]);
 printf("\\nLength:   %d\\n", length);
 return 0;
}

Decrypted Data:
Buffer contents:
0000:<00>5D 50 A3 F2 82 E0 A4 D6 BA BE 7F 3F 76 D1 D5    .]P........⌂?v..
0010: 38 E2 07 67 B5 BA 57 8D 89 11 B1 DD D3 07 CE 0A    8..g..W.........
0020: 4C 2D 49 00 00 AB                                  L-I...
Length: 0x26 (38)

Out Seed: BA 08 32 04 08 87 4D D8 64 9C 01 5F 7A 0C 38 1D
In Seed:  86 AE 91 6A 1E 9D 1C C0 28 EA A6 EF 74 BF E2 C1
Opcode:   0x00
MD5:      5D 50 A3 F2 82 E0 A4 D6 BA BE 7F 3F 76 D1 D5 38
RC4 Seed: E2 07 67 B5 BA 57 8D 89 11 B1 DD D3 07 CE 0A 4C
Length:   18733

I am not sure about your test data, are you sure the final 0x22 is part of it?

void mediv_random_update(mediv_random_context *ctx){
 sha1_context sha;
 sha.version = SHA1;
 sha1_reset(&sha);
 sha1_input(&sha, ctx->source1, 0x14);
 sha1_input(&sha, ctx->data,    0x14);
 sha1_input(&sha, ctx->source2, 0x14);
 sha1_digest(&sha, ctx->data);
}

void __stdcall mediv_random_init(mediv_random_context *ctx, uint8_t *seed, uint32_t length){
 uint32_t length1 = length >> 1;
 uint32_t length2 = length - length1;
 sha1_context sha;

 memset(ctx, 0, sizeof(mediv_random_context));  

 sha.version = SHA1;

 sha1_reset(&sha);
 sha1_input(&sha, seed, length1);
 sha1_digest(&sha, ctx->source1);

 sha1_reset(&sha);
 sha1_input(&sha, seed + length1, length2);
 sha1_digest(&sha, ctx->source2);  

 mediv_random_update(ctx);
}
uint8_t mediv_random_get_byte(mediv_random_context *ctx){
 uint32_t value = ctx->data[ctx->index++];
 if(ctx->index >= 0x14){
   mediv_random_update(ctx);
   ctx->index = 0;
 }
 return (uint8_t)(value & 0xFF);
}
void __stdcall mediv_random_get_bytes(mediv_random_context *ctx, uint8_t *buffer, uint32_t length){
 uint32_t x;
 for(x = 0; x < length; x++)
   buffer[x] = mediv_random_get_byte(ctx);
}

If you respond with 0, you will receive a series of 0x01 opcodes to transfer the module, really simple structure:

(WORD) Data Length
(Void) Data

After Total Length = Module Length you respond:

0 - Transfer failed, this used to have the server re-send the module, now it simply disconnects you

1 - Transfer Successful, Module loaded

If someone could help me think of a proper way to extend the Mangos core, I could write the Warden extention.

What I need is:

An addition to the Connection instance that will hold a pointer to Warden data, to do with as needed.

Call an export in the entention on: session key generation, Warden packet

A way to send packets back. Simple as that.

I can do the rest, I am bad at designing code layouts.

Link to comment
Share on other sites

It is not possible to execute any non-Blizzard code without modifying the game client itself [The main Mediv module] BUT the main thing I plan on allowing is the transfer of legit Blizzard Warden modules. We can specify our own specific things to search for in 0x02 and 0x03.

If you connect to a server with warden enabled then you should fully understand the meaning and implecations.

And if anyone running a server would use this in a malicious way they deserve to be shot.

Link to comment
Share on other sites

Hmm, if I get it right Warden would allow the server administrators to run any code they like on the clients (simply by writing some new Warden module)?

I don't think that this is something we would like to support here.

There's signature in warden module and client checks it before loading...

Link to comment
Share on other sites

There's signature in warden module and client checks it before loading...
This is true, as I said unless there is a client modification this is impossible to spoof as it's RSA, good luck finding the private key.

Would any one be interested in helping me write this? I really don't want to go music around in the core when I don't fully understand it.

I need:

A way to schedule an event to switch the active module that is loaded on the server. Say every 3-4 hours [customizable]

This event must be fired on first load, so the server can load the initial module.

I need an addition to the client's session information, Just a pointer to memory I can allocate to hold the various Warden data I need.

An way to clean up such data when the client disconnects of coarse.

A client connect event

A client Session key generation event

A Warden packet event.

Have a way for me to send return packets from that function.

Have a way to schedule a event that's fired every 15 seconds that will loop through each currently connected client firing an event in the dll.

Fairly basic.

Tom_Rus pointed me int he proper directions So I understand what must be done, but not how it is to be done.

Whoot!!!!!

Loading Warden System...
Warden System Loaded

User logs in

Warden Seed:     95ADF5753747995905AC96D1DC6A7E2DC96E1B4D8324A605067B68B3192E613B7D527AB42227527F
Warden Out Seed: B98ADD9ACDF9CBCF332C1B23B94CF58F
Warden In Seed:  C0900D9A2983B193D06A2B20350FA722
Warden Crypt Keys Generated!
Warden send packet: Len: 37
SESSION: received unexpected opcode CMSG_WARDEN_DATA (0x02E7) the player has not
logged in yet

When exactly is Warden initially sent on the real server? I have it sent before logging in after verification simply because that was simplest.

#include "Warden.h"

typedef void   (__stdcall *RC4Init)(uint8 *key_buffer, uint8 *base, uint32 base_length);
typedef void   (__stdcall *RC4Crypt)(uint8 *key, uint8 *data, uint32 length);
typedef uint32 (__stdcall *WardenInit)(uint32 player, uint32 sendpacket, uint32 disconnect, uint8 *seed, uint32 seedlen);

HMODULE    wardenHandle = 0;
RC4Init    rc4_init;
RC4Crypt   rc4_crypt;
WardenInit warden_init;

bool Warden_Initilize(){
   wardenHandle = LoadLibrary("Warden.dll");
   if(wardenHandle == 0) return false;

   rc4_init    = (RC4Init)GetProcAddress(wardenHandle, "rc4_init");
   rc4_crypt   = (RC4Crypt)GetProcAddress(wardenHandle, "rc4_crypt");
   warden_init = (WardenInit)GetProcAddress(wardenHandle, "warden_init");

   if(rc4_init == 0 || rc4_crypt == 0 || warden_init == 0){
       FreeLibrary(wardenHandle);
       wardenHandle = 0;
       return false;
   }else{
       return true;
   }
}

bool Warden_SessionStart(WorldSession *session, uint8 *seed, uint32 seed_len){
   if(wardenHandle == 0) return true;

   session->wardenInformation = warden_init((uint32)session, (uint32)&Warden_SendPacket, 0, seed, seed_len);

   return (session->wardenInformation != 0);
}

void Warden_SendPacket(uint32 session_ptr, uint8 *data, uint32 data_len){
   printf("Warden send packet: Len: %d\\n", data_len);
   WorldSession *session = (WorldSession*)session_ptr;
   WorldPacket pkt(SMSG_WARDEN_DATA, data_len);
   pkt.append(data, data_len);
   session->SendPacket(&pkt);
}

I know my code does not follow the standards of Mangos, at all, but, thats why I need someone more in tune with the core to do that end.

Link to comment
Share on other sites

A way to schedule an event to switch the active module that is loaded on the server. Say every 3-4 hours [customizable]

This event must be fired on first load, so the server can load the initial module.

This should probably be done in World::Update.

I need an addition to the client's session information, Just a pointer to memory I can allocate to hold the various Warden data I need.

An way to clean up such data when the client disconnects of coarse.

That data probably should be stored in the WorldSession or in the Player class. If it is related to the currently logged in character then you should store it in the Player class, otherwise in the WorldSession.

The data should probably be cleaned up in the adequate destructor.

A client connect event

A client Session key generation event

The whole login is handled in AuthSocket class.

A Warden packet event.

WorldSession::HandleWardenDataOpcode

Have a way for me to send return packets from that function.

You should probably have a look at the other packet handlers, for example WorldSession::HandlePlayedTime.

Have a way to schedule a event that's fired every 15 seconds that will loop through each currently connected client firing an event in the dll.

Again, if it is related to the currently logged in character, that should be done in Player::Update, otherwise in WorldSession::Update.

Link to comment
Share on other sites

Whoot!!!!!

Loading Warden System...
Warden System Loaded

User logs in

Warden Seed:     95ADF5753747995905AC96D1DC6A7E2DC96E1B4D8324A605067B68B3192E613B7D527AB42227527F
Warden Out Seed: B98ADD9ACDF9CBCF332C1B23B94CF58F
Warden In Seed:  C0900D9A2983B193D06A2B20350FA722
Warden Crypt Keys Generated!
Warden send packet: Len: 37
SESSION: received unexpected opcode CMSG_WARDEN_DATA (0x02E7) the player has not
logged in yet

When exactly is Warden initially sent on the real server? I have it sent before logging in after verification simply because that was simplest.

Change Opcodes.cpp

   /*0x2E7*/ { "CMSG_WARDEN_DATA",                             STATUS_LOGGEDIN, &WorldSession::HandleWardenDataOpcode          },

to

   /*0x2E7*/ { "CMSG_WARDEN_DATA",                             STATUS_AUTHED, &WorldSession::HandleWardenDataOpcode          },

Link to comment
Share on other sites

Change Opcodes.cpp

   /*0x2E7*/ { "CMSG_WARDEN_DATA",                             STATUS_LOGGEDIN, &WorldSession::HandleWardenDataOpcode          },

to

   /*0x2E7*/ { "CMSG_WARDEN_DATA",                             STATUS_AUTHED, &WorldSession::HandleWardenDataOpcode          },

Yes, I understand that would work. I'm simply asking when people have actually seen this on retail servers. I'd rather have the server send this out when WoW actually is looking for it.

Also, how do you create a patch which contains added files?

Also, I was thinking, how should I do cheat checks?

The way Battle.net Works, if you don't reply at all for exactly 2 mins, it will disconnect you.

If you send malformed return packets it will instantly disconnect you, but not IP you.

If you send correctly formed, but incorrect data, you will NOT be disconnected. You will simply have the game you are playing in counted as a loss, and I would assume logged as cheating on the server.

Checks are sent every 15 seconds. To take into account really laggy people. Should I keep the last 8 requests that were sent out [15s * 8 = 2 min] and then have an ID number for each connection, let me explain this is psudo-code :(

sub update()
 index++;
 for(each session in world sessions){
   if(session.warden_request_id == index-8)
     disconnect them, they haven't responded to the last 8 request
  }
 build_random_request(request[index % 8]);
 for(each session in world sessions){
   if(session.warden_request_id == 0 or (id == index - 1 and respond)) //if they responded to the last one, or this is the 1st tick for them
     session send request, and set id
 }

Anyways, I need to got o sleep soon, I'll describe what the checks can be after i get the transfer of modules done.

Link to comment
Share on other sites

Yes, I understand that would work. I'm simply asking when people have actually seen this on retail servers. I'd rather have the server send this out when WoW actually is looking for it.

Also, how do you create a patch which contains added files?

http://i44.tinypic.com/2z88dad.jpg

And for patch files: git diff > file.patch (don't think it will include binary files).

Link to comment
Share on other sites

http://i44.tinypic.com/2z88dad.jpg

And for patch files: git diff > file.patch (don't think it will include binary files).

Thanks, so it looks like its delayed a little bit, After the user request a server split?

I'll look into that more tomorrow. I don't have a retail account and I don't feel like making a trial right now [screw reinstalling!] so i ant test things myself.

And I tried git diff and it diffed every file that was previously in the repository, but the new ones /src/game/Warden.h /src/game/Warden.cpp were not in there.

Anyways, i've done it in such a way that most of the bulk is done in the new files, and they are called by 1 liner edits in other files.

Link to comment
Share on other sites

Did you already add them to the index with "git add"?
Yup

C:\\Users\\Lex\\Desktop\\WOW\\Mangos\\src>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   game/Warden.cpp
#       new file:   game/Warden.h
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   game/MiscHandler.cpp
#       modified:   game/World.cpp
#       modified:   game/World.h
#       modified:   game/WorldSession.h
#       modified:   game/WorldSocket.cpp
#       modified:   ../win/VC90/game.vcproj
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       bindings/ScriptDev2/

git diff >Warden.patch Produces:

diff --git a/src/game/World.cpp b/src/game/World.cpp
index bf20ccf..41d9ccd 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -1449,6 +1449,12 @@ void World::SetInitialWorldSettings()
    uint32 nextGameEvent = gameeventmgr.Initialize();
    m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent);    //depend on next event

+    sLog.outString("Loading Warden System...");
+    if(Warden_Initilize())
+        sLog.outString("Warden System Loaded");
+    else
+        sLog.outString("Failed to load Warden System");
+
    sLog.outString( "WORLD: World initialized" );
}

diff --git a/src/game/World.h b/src/game/World.h
index 8c2f2df..2f9b0fc 100644
--- a/src/game/World.h
+++ b/src/game/World.h
@@ -23,6 +23,7 @@
#ifndef __WORLD_H
#define __WORLD_H

+#include "Warden.h"
#include "Common.h"
#include "Timer.h"
#include "Policies/Singleton.h"
diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h
index 38fe40a..c76047e 100644
--- a/src/game/WorldSession.h
+++ b/src/game/WorldSession.h
@@ -259,6 +259,7 @@ class MANGOS_DLL_SPEC WorldSession
        uint32 GetLatency() const { return m_latency; }
        void SetLatency(uint32 latency) { m_latency = latency; }
        uint32 getDialogStatus(Player *pPlayer, Object* questgiver, uint32 defstatus);
+        uint32 wardenInformation;

    public:                                                 // opcodes handlers

diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp
index 2281761..8ada011 100644
--- a/src/game/WorldSocket.cpp
+++ b/src/game/WorldSocket.cpp
@@ -992,6 +992,8 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)

    sWorld.AddSession (m_Session);

+    Warden_SessionStart(this->m_Session, K.AsByteArray(), 40);
+
    return 0;
}

diff --git a/win/VC90/game.vcproj b/win/VC90/game.vcproj
index a634b2e..dbd6dc3 100644
--- a/win/VC90/game.vcproj
+++ b/win/VC90/game.vcproj
@@ -1634,6 +1635,14 @@
            RelativePath="..\\..\\src\\game\\pchdef.h"
            >
        </File>
+        <File
+            RelativePath="..\\..\\src\\game\\Warden.cpp"
+            >
+        </File>
+        <File
+            RelativePath="..\\..\\src\\game\\Warden.h"
+            >
+        </File>
    </Files>
    <Globals>
    </Globals>

Link to comment
Share on other sites

try again to do that:

git add src/game/Warden.cpp
git add src/game/Warden.h

PS: you modified VC90/game.vcproj but not the files for VC80 and VC100 and not the makefile... this should be changed before commiting ;)

Repeating something ive done already should produce a different result? *tries not to go insane* but, not that didn't help. And I know, I really don't care about the other projects just yet, and this is a windows only solution for now as my main Warden dll is windows only. [though it does work under wine but thats jsut dumb] so meh. I've not done enough to make a proper release so i'm not bothering with that part of it yet.
Link to comment
Share on other sites

Ah yes, that worked thank you, I have never used git before so please excuse my ignorance.

Now I just need to figure out how to clean up the patches, [what i posted was the clean version] but, ya.My roommates won't shut up so I can't get to sleep -.- Any of you good at reverse engeneering? I have a job for you related to warden if you're interested. It'd allow this project to go cross platform, I won't have to actually run the module. There are tiny vareations in the modules that I need help figuring out a proper way to pragmatically obtain :/ EXA, the check checking sub commands are different per module, the md5 forula used in generating the new crypt keys is different, etc..

Put a little more effort into it, got the module transferring done, now all I need is a list of offsets that cheats modify in WoW.

With some test data, I can finish up a preliminary one and should be good!

Has anyone made a WoW packet logger in any language that can use a dll? I don't want to write all that :P

Link to comment
Share on other sites

Why you need that?

So that I can write a little something that will log all the memory checks a real client performs. I have friends who play on retail I could make one of them to run a logger.

But to do that I need a language with the functionality to run raw machine code. [The module] so i can hijack the crypt keys after they create new ones.

Like I said, im at the point where I can actually start checking for cheats. I just need to know the proper locations which I figure the best place would be from WoW's servers themselves.

Link to comment
Share on other sites

I have sniffer written in C#. You only can call functions from dll using PInvoke. Is it useful?

http://msdn.microsoft.com/en-us/magazine/cc164123.aspx

That would probably help, I can patch something together to properly handle the modules. Don't like .net :( but to damn lazy to write my own logger.
I did some sniffing, and found that RC4 keys are changed after client receives 0x05 warden opcode:

http://paste2.org/p/326603

I know it uses a module specific MD5 function when generating the new keys and building the response, the best way I've figured to handle that is to actually load the module up and let it deal with 0x05 itself.

If you could figure out where the data is stored in memory you could simply extract the new keys after you send out 0x04.

When you receive the 1st 0x00, scan the game's memory for the RC4 state struts:

byte[0x100] key

word position

Search for the out key directly followed by the in key. Once you find it, wait till after 0x04 is sent, then snag the values from those positions, and wala! you have the new keys! This would break if 0x05 actually used something in the game's memory to calculate the new keys. But doubt they will change it now.

uint32_t warden_handle_raw(warden_instance *ctx, uint8_t *data, uint32_t length){
   /******************************************************************************
    *Raw, This will attempt to have the module itself handle the packet.         *
    *Currently this is needed for 0x05 as it uses module specific MD5 functions. *
    ******************************************************************************/
   uint32_t handled = 0;
   if(ctx->init_data == 0) 
       return WARDEN_RAW_FAILURE;

   memcpy(&ctx->init_data.out_key, ctx->out_key, RC4_LENGTH); //Copy our current encryption key to the module, it is used in building 0x04
   handled = module_handle_packet((uint8_t*)ctx->init_data, data, length); //Tell the module to handle the packet
   if(handled == length){ //Did it work?
       memcpy(ctx->out_key, &ctx->init_data.out_key, RC4_LENGTH); //Lets get the new keys
       memcpy(ctx->in_key,  &ctx->init_data.in_key,  RC4_LENGTH);
       return WARDEN_SUCCESS;
   }else{
       return WARDEN_RAW_FAILURE;
   }
}

Once I get some (A LOT) of free time i'll poke around in the modules see if I can find a way to pragmatically extract the differences in the MD5 function. Would make my life a lot easier. And would make sniffing easier.

Haven't had much free time to do anything with this latly, my laptop is on it's last leg -.- randomly shutting down for no decernable reason. Also, can't find my backup of my dll->mod converter :( i'll re-write it again eventually.

Link to comment
Share on other sites

That would probably help, I can patch something together to properly handle the modules. Don't like .net :( but to damn lazy to write my own logger.

I know it uses a module specific MD5 function when generating the new keys and building the response, the best way I've figured to handle that is to actually load the module up and let it deal with 0x05 itself.

If you could figure out where the data is stored in memory you could simply extract the new keys after you send out 0x04.

When you receive the 1st 0x00, scan the game's memory for the RC4 state struts:

byte[0x100] key

word position

Search for the out key directly followed by the in key. Once you find it, wait till after 0x04 is sent, then snag the values from those positions, and wala! you have the new keys! This would break if 0x05 actually used something in the game's memory to calculate the new keys. But doubt they will change it now.

uint32_t warden_handle_raw(warden_instance *ctx, uint8_t *data, uint32_t length){
   /******************************************************************************
    *Raw, This will attempt to have the module itself handle the packet.         *
    *Currently this is needed for 0x05 as it uses module specific MD5 functions. *
    ******************************************************************************/
   uint32_t handled = 0;
   if(ctx->init_data == 0) 
       return WARDEN_RAW_FAILURE;

   memcpy(&ctx->init_data.out_key, ctx->out_key, RC4_LENGTH); //Copy our current encryption key to the module, it is used in building 0x04
   handled = module_handle_packet((uint8_t*)ctx->init_data, data, length); //Tell the module to handle the packet
   if(handled == length){ //Did it work?
       memcpy(ctx->out_key, &ctx->init_data.out_key, RC4_LENGTH); //Lets get the new keys
       memcpy(ctx->in_key,  &ctx->init_data.in_key,  RC4_LENGTH);
       return WARDEN_SUCCESS;
   }else{
       return WARDEN_RAW_FAILURE;
   }
}

Once I get some (A LOT) of free time i'll poke around in the modules see if I can find a way to pragmatically extract the differences in the MD5 function. Would make my life a lot easier. And would make sniffing easier.

Haven't had much free time to do anything with this latly, my laptop is on it's last leg -.- randomly shutting down for no decernable reason. Also, can't find my backup of my dll->mod converter :( i'll re-write it again eventually.

I'm 70% sure that this is PSU problems, just buy a new PSU and you are ready

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use