Jump to content

Warden


Recommended Posts

  • Replies 125
  • Created
  • Last Reply

Top Posters In This Topic

I don't have time to work on this shit, nore do I care that much, I mainly worked on it cuz I saw a lot of people bitchen that they had cheaters ont here forums. Anyways, here you code, the code is ugly as shit but hey

#ifndef MODULE_H
#define MODULE_H

#pragma comment (lib, "zdll.lib") 
#define ZLIB_DLL
#include <zlib.h>
#include "types.h"
#include "stdint.h"
#include "string.h"
#include <windows.h>
#include <stdio.h>
#include "dynamic_callbacks.h"

typedef struct{
 uint32_t maped_size; /*00*/
 uint32_t unknown1;   /*04*/
 uint32_t ref_table;  /*08*/
 uint32_t ref_count;  /*0C*/
 uint32_t init_addr;  /*10*/
 uint32_t unknown3;   /*14*/
 uint32_t unknown4;   /*18*/
 uint32_t lib_table;  /*1C*/
 uint32_t lib_count;  /*20*/
 uint32_t unknown5;   /*24*/
}module_header, *pmodule_header;

typedef struct{
 uint32_t name_address;
 uint32_t function_table;
}library_referance, *plibrary_referance;

typedef struct{
 uint32_t rc4_init;
 uint32_t unload_module;
 uint32_t handle_packet;
}module_exports;

typedef struct{
 uint32_t send_packet;
 uint32_t check_module;
 uint32_t load_module;
 uint32_t mem_alloc;
 uint32_t mem_free;
 uint32_t set_rc4;
 uint32_t get_rc4;
}module_callbacks;

typedef struct{
 module_callbacks *c;
}module_callbacksp;

typedef struct{
 module_exports    *exports;
 uint32_t           unknown1[5];
 module_callbacksp *callbacks;
 uint32_t           unknown2;
 uint8_t            out_key[0x102];
 uint8_t            in_key[0x102];
}module_init_return, *pmodule_init_return;

typedef uint32_t (__fastcall *module_init_t)         (uint32_t callbacks);
typedef uint32_t (__fastcall *module_init_ran_data)  (uint32_t *init_data, uint32_t _set_zero_, uint8_t *data, uint32_t size);
typedef uint8_t* (__fastcall *module_handle_packet_t)(uint32_t *init_data, uint32_t _set_zero_, uint8_t *packet_data, uint32_t length, uint32_t *byte_handled);

uint32_t __stdcall module_get_prep_size(uint8_t *data);
uint32_t __stdcall module_prep(uint8_t *source);
uint32_t __stdcall module_init(uint32_t module, uint32_t callbacks);
void     __stdcall module_init_rc4(uint8_t *init_data, uint8_t *data, uint32_t data_length);
uint32_t __stdcall module_get_init_address(uint32_t module);
uint32_t __stdcall module_handle_packet(uint8_t *init_data, uint8_t *data, uint32_t length);

#endif

#pragma once
#include "module.h"

#define module_get_int32(a, b) \\
   (*(uint32_t*)(a + (uint32_t)b))

#define module_get_aint32(a, b) \\
   (*(uint32_t*)(&a[b]))

#define module_get_int16(a, b) \\
   (*(uint16_t*)&a[(uint32_t)b])

#define module_swap_int16(a) \\
   (((a & 0xFF00) >> 8) | ((a & 0xFF) << 8))

#define module_set_int32(a, b, c)\\
   (*(uint32_t*)(a + b) = c)


int __stdcall module_prep(uint8_t *source){
   uint32_t src_location;
   uint32_t dest_location;
   uint16_t length = 0;
   uint8_t bskip = 0;
   uint16_t *refs;
   uint32_t x = 0;
   uint32_t y = 0;
   library_referance *libs;
   uint8_t *lib;
   HMODULE handle;
   uint32_t function;
   uint32_t func;
   //uint8_t *msgbuff;
   uint32_t dest;
   uint32_t max_size;
   module_header *header = (pmodule_header)source;

   max_size = module_get_prep_size(source);
   dest = memalloc(max_size);
   memset((uint8_t*)dest, 0, max_size);

   //msgbuff = safe_malloc(500);
   //sprintf_s(msgbuff, 500, "Warden Base: 0x%08X\\n", (uint32_t)dest); write_to_file(msgbuff);

   memcpy((uint8_t*)dest, source, sizeof(module_header));

   src_location = sizeof(module_header) + (header->unknown5 * 12);
   dest_location = module_get_aint32(source, 40);

   //write_to_file("Copying code blocks to module\\n");

   while(dest_location < header->maped_size){
       length = module_get_int16(source, src_location);
       src_location += 2;
       if(!bskip){
           memcpy((uint8_t*)(dest + dest_location), source + src_location, length);
           src_location += length;
       }
       bskip = !bskip;
       dest_location += length;
   } 

   refs = (uint16_t*)(dest + header->ref_table);
   dest_location = 0;

   //sprintf_s(msgbuff, 500, "Adjusting %d references to global variables...\\n", (int)header->ref_count); write_to_file(msgbuff);

   for(x = 0; x < header->ref_count; x++){
       dest_location += module_swap_int16(refs[x]);
       module_set_int32(dest, dest_location, (module_get_int32(dest, dest_location) % max_size) + dest);
   }

   //write_to_file("Updating API library referances...\\n");

   libs = (plibrary_referance)(dest + header->lib_table);
   for(x = 0; x < header->lib_count; x++){
       lib = (uint8_t*)(dest + libs[x].name_address);
       handle = LoadLibrary(lib);

       function = libs[x].function_table;
       while(module_get_int32(dest, function) != 0){
           func = module_get_int32(dest, function);
           if((func & 0x7FFFFFFF) > max_size){
               //sprintf_s(msgbuff, 500, "Attempted to read API from offset pass end of module: 0x%08X\\n", func); write_to_file(msgbuff);
               break;
           }
           if(func & 0x80000000){
               y = (uint32_t)GetProcAddress(handle, (LPCSTR)(func & 0x7FFFFFFF));
           }else{
               y = (uint32_t)GetProcAddress(handle, (uint8_t*)(dest + func));
           }
           module_set_int32(dest, function, y);
           function += 4;
       }
   }
   return dest;
}
int __stdcall module_get_init_address(uint32_t module){
   uint32_t x = module_get_int32(module, 0x10);
   return module_get_int32(module, x);
}

int __stdcall module_init(uint32_t address,  uint32_t callbacks){
   module_init_t init = (module_init_t)address;
   return init(callbacks);
}

void __stdcall module_init_rc4(uint8_t *init_data, uint8_t *data, uint32_t data_length){
   module_init_return* init = (module_init_return*)init_data;
   module_init_ran_data rc4_init = (module_init_ran_data)init->exports->rc4_init;
   rc4_init((uint32_t*)init_data, (uint32_t)0, data, data_length);
}


uint32_t __stdcall module_handle_packet(uint8_t *init_data, uint8_t *data, uint32_t length){
   uint32_t handled = -1;
   module_init_return *init = (module_init_return*)init_data;
   module_handle_packet_t handle = (module_handle_packet_t)init->exports->handle_packet;
   handle((uint32_t*)init_data, (uint32_t)0, data, length, &handled);
   return handled;
}

int __stdcall module_get_prep_size(uint8_t *data){return ((pmodule_header)data)->maped_size; }

#ifndef MEDIV_RANDOM_H
#define MEDIV_RANDOM_H

#include <windows.h>
#include "types.h"
#include "stdint.h"
#include "sha1.h"

typedef struct mediv_random_context{
 uint32_t index;
 uint8_t  data[0x14];
 uint8_t  source1[0x14];
 uint8_t  source2[0x14];
}mediv_random_context;

void __stdcall mediv_random_init(mediv_random_context *ctx, uint8_t *seed, uint32_t length);
void __stdcall mediv_random_get_bytes(mediv_random_context *ctx, uint8_t *buffer, uint32_t length);

#endif

#include "mediv_random.h"

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);
}

/*
*  sha1.h
*
*  Description:
*      This is the header file for code which implements the Secure
*      Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
*      April 17, 1995.
*
*      Many of the variable names in this code, especially the
*      single character names, were used because those were the names
*      used in the publication.
*
*      Please read the file sha1.c for more information.
*
*  Notes:
*      I took this file from BNCSUtil's source, Why? Lazyness. I have modified it a bit but most of its from him. <3
*/

#ifndef _SHA1_H_
#define _SHA1_H_

#include "types.h"
#include "stdint.h"

#ifndef _SHA_enum_
#define _SHA_enum_
enum{
   shaSuccess = 0,
   shaNull,            /* Null pointer parameter */
   shaInputTooLong,    /* input data too long */
   shaStateError       /* called Input after Result */
};
#endif

#define sha1_hash_size 20

typedef enum{
 SHA1,
 xSHA1,
 lSHA1,
 wSHA1,
 MAX = 0xffffffff
}SHA1_t;
/*
*  This structure will hold context information for the SHA-1
*  hashing operation
*/

typedef struct sha1_context{
 uint32_t      intermediate_hash[sha1_hash_size / 4]; /* Message Digest                   */
 uint32_t      length_low;                            /* Message length in bits           */
 uint32_t      length_high;                           /* Message length in bits           */
 int_least16_t message_block_index;                   /* Index into message block array   */
 uint8_t       message_block[64];                     /* 512-bit message blocks           */
 uint8_t       computed;                              /* Is the digest computed?          */
 uint8_t       corrupted;                             /* Is the message digest corrupted? */
 SHA1_t        version;                               /* What version of SHA1 is this?    */
} sha1_context;

/* Function Prototypes */

int __stdcall sha1_reset(sha1_context *);
int __stdcall sha1_input(sha1_context *, const uint8_t *, uint32_t);
int __stdcall sha1_digest(sha1_context *, uint8_t *);
uint32_t __stdcall sha1_checksum(uint8_t *data, uint32_t length, uint32_t version);

#endif

/*
*  sha1.c
*
*  Description:
*    This file implements the Secure Hashing Algorithm 1 as
*    defined in FIPS PUB 180-1 published April 17, 1995.
*
*    The SHA-1, produces a 160-bit message digest for a given
*    data stream.  It should take about 2**n steps to find a
*    message with the same digest as a given message and
*    2**(n/2) to find any two messages with the same digest,
*    when n is the digest size in bits.  Therefore, this
*    algorithm can serve as a means of providing a
*    "fingerprint" for a message.
*
*  Portability Issues:
*    SHA-1 is defined in terms of 32-bit "words".  This code
*    uses <stdint.h> (included via "sha1.h" to define 32 and 8
*    bit unsigned integer types.  If your C compiler does not
*    support 32 bit unsigned integers, this code is not
*    appropriate.
*
*  Caveats:
*    SHA-1 is designed to work with messages less than 2^64 bits
*    long.  Although SHA-1 allows a message digest to be generated
*    for messages of any number of bits less than 2^64, this
*    implementation only works with messages with a length that is
*    a multiple of the size of an 8-bit character.
*
*  Notes:
*    I took this file from BNCSUtil's source, Why? Lazyness. I have modified it a bit but most of its from him. <3
*/

#include "sha1.h"

#define SHA1RoL(bits, word) \\
   (((word) << (bits)) | ((word) >> (32-(bits))))

#define xSHA1RoL(word, bits) \\
   (((word) << (bits)) | ((word) >> (32-(bits))))

#define SHA1batoi(ba, i) \\
 ((ba[i] << 24) | (ba[i+1] << 16) | (ba[i+2] << 8) | ba[i+3])

#define xSHA1batoi(ba, i) \\
 ((ba[i+3] << 24) | (ba[i+2] << 16) | (ba[i+1] << 8) | ba[i])

#define SHA1itoba(a, ba, i) \\
 (ba[i] = (uint8_t)(a >> 24)); (ba[i+1] = (uint8_t)(a >> 16)); (ba[i+2] = (uint8_t)(a >> 8)); (ba[i+3] = (uint8_t)a);

#define xSHA1itoba(a, ba, i) \\
 (ba[i+3] = (uint8_t)(a >> 24)); (ba[i+2] = (uint8_t)(a >> 16)); (ba[i+1] = (uint8_t)(a >> 8)); (ba[i] = (uint8_t)a);

/* Local Function Prototyptes */
void sha1_pad_message(sha1_context *);
void sha1_process_message_block(sha1_context *);

/*
*  SHA1Reset
*
*  Description:
*    This function will initialize the SHA1Context in preparation
*    for computing a new SHA1 message digest.
*
*  Parameters:
*    context: [in/out]
*      The context to reset.
*
*  Returns:
*    sha Error Code.
*
*/
int __stdcall sha1_reset(sha1_context *ctx){
 uint8_t x;
 if (!ctx)
   return shaNull;

 ctx->length_low           = 0;
 ctx->length_high          = 0;
 ctx->message_block_index  = 0;

 ctx->intermediate_hash[0] = 0x67452301;
 ctx->intermediate_hash[1] = 0xEFCDAB89;
 ctx->intermediate_hash[2] = 0x98BADCFE;
 ctx->intermediate_hash[3] = 0x10325476;
 ctx->intermediate_hash[4] = 0xC3D2E1F0;

 for(x = 0; x < 64; x++){
   ctx->message_block[x] = 0;
 }
 ctx->computed  = 0;
 ctx->corrupted = 0;

 return shaSuccess;
}

/*
*  SHA1Result
*
*  Description:
*    This function will return the 160-bit message digest into the
*    Message_Digest array  provided by the caller.
*    NOTE: The first octet of hash is stored in the 0th element,
*      the last octet of hash in the 19th element.
*
*  Parameters:
*    context: [in/out]
*      The context to use to calculate the SHA-1 hash.
*    Message_Digest: [out]
*      Where the digest is returned.
*
*  Returns:
*    sha Error Code.
*
*/
int __stdcall sha1_digest(sha1_context *ctx, uint8_t *digest){
 int i;

 if (!ctx || !digest)
   return shaNull;

 if (ctx->corrupted)
   return ctx->corrupted;

 if (!ctx->computed){
   sha1_pad_message(ctx);

   ctx->length_low  = 0;
   ctx->length_high = 0;
   ctx->computed    = 1;
 }

 if(ctx->version != SHA1){
   for(i = 0; i < 5; i++){
     xSHA1itoba(ctx->intermediate_hash[i], digest, i * 4);
   }
 }else{
   for(i = 0; i < 5; i++){
     SHA1itoba(ctx->intermediate_hash[i], digest, i * 4);
   }
 }

 return shaSuccess;
}
/*
*  SHA1Input
*
*  Description:
*    This function accepts an array of octets as the next portion
*    of the message.
*
*  Parameters:
*    context: [in/out]
*      The SHA context to update
*    message_array: [in]
*      An array of characters representing the next portion of
*      the message.
*    length: [in]
*      The length of the message in message_array
*
*  Returns:
*    sha Error Code.
*
*/
int __stdcall sha1_input(sha1_context *ctx, const uint8_t *data, uint32_t length){
 uint32_t x;
 if(!length)
   return shaSuccess;

 if(!ctx || !data)
     return shaNull;

 if(ctx->computed){
   ctx->corrupted = shaStateError;
   return shaStateError;
 }

 for(x = 0; x < length; x++){
   ctx->message_block[ctx->message_block_index++] = (data[x] & 0xFF);
   ctx->length_low += 8;

   if (ctx->length_low == 0){
     ctx->length_high++;
     if(ctx->length_high == 0){
       ctx->corrupted = shaInputTooLong;
       return shaInputTooLong;
     }
   }

   if (ctx->message_block_index == 64)
     sha1_process_message_block(ctx);
 }

 return shaSuccess;
}

/*
* SHA1Math
*
* Description:
*   This is simply so I can have a clean way of 
* doing the Process in one loop insted of 4.
*/
uint32_t sha1_math(uint16_t t, uint32_t B, uint32_t C, uint32_t D){
 if(t < 20)      return ((B & C) | ((~B) & D));
 else if(t < 40) return (B ^ C ^ D);
 else if(t < 60) return ((B & C) | (B & D) | (C & D));
 else            return (B ^ C ^ D);
}
/*
*  SHA1ProcessMessageBlock
*
*  Description:
*    This function will process the next 512 bits of the message
*    stored in the Message_Block array.
*
*  Parameters:
*    None.
*
*  Returns:
*    Nothing.
*
*  Comments:
*    Many of the variable names in this code, especially the
*    single character names, were used because those were the
*    names used in the publication.
*
*
*/


void sha1_process_message_block(sha1_context *ctx){
 uint16_t t;             /* Loop counter        */
 uint32_t temp;          /* Temporary word value*/
 uint32_t W[80];         /* Word sequence       */
 uint32_t A, B, C, D, E; /* Word buffers        */
 const uint32_t K[] = {0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6};

 if(ctx->version == xSHA1){
   for(t = 0; t < 16; t++)  W[t] = xSHA1batoi(ctx->message_block, t * 4);
   for(t = 16; t < 80; t++) W[t] = xSHA1RoL(1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
 }else if(ctx->version == lSHA1){
   for(t = 0; t < 16; t++)  W[t] = xSHA1batoi(ctx->message_block, t * 4);
   for(t = 16; t < 80; t++) W[t] = SHA1RoL(1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
 }else{
   for(t = 0; t < 16; t++)  W[t] = SHA1batoi(ctx->message_block, t * 4);
   for(t = 16; t < 80; t++) W[t] = SHA1RoL(1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
 }

 A = ctx->intermediate_hash[0];
 B = ctx->intermediate_hash[1];
 C = ctx->intermediate_hash[2];
 D = ctx->intermediate_hash[3];
 E = ctx->intermediate_hash[4];

 for(t = 0; t < 80; t++){
   temp = SHA1RoL(5,A) + sha1_math(t, B, C, D) + E + W[t] + K[t / 20];
   E = D;
   D = C;
   C = SHA1RoL(30,B);
   B = A;
   A = temp;
 }

 ctx->intermediate_hash[0] += A;
 ctx->intermediate_hash[1] += B;
 ctx->intermediate_hash[2] += C;
 ctx->intermediate_hash[3] += D;
 ctx->intermediate_hash[4] += E;

 ctx->message_block_index = 0;
}


/*
*  SHA1PadMessage
*
*  Description:
*    According to the standard, the message must be padded to an even
*    512 bits.  The first padding bit must be a '1'.  The last 64
*    bits represent the length of the original message.  All bits in
*    between should be 0.  This function will pad the message
*    according to those rules by filling the Message_Block array
*    accordingly.  It will also call the ProcessMessageBlock function
*    provided appropriately.  When it returns, it can be assumed that
*    the message digest has been computed.
*
*  Parameters:
*    context: [in/out]
*      The context to pad
*    ProcessMessageBlock: [in]
*      The appropriate SHA*ProcessMessageBlock function
*  Returns:
*    Nothing.
*
*/

void sha1_pad_message(sha1_context *ctx){
 if(ctx->version == xSHA1){
   while(ctx->message_block_index < 64)
     ctx->message_block[ctx->message_block_index++] = 0;
 }else{
   if (ctx->message_block_index > 55){
     ctx->message_block[ctx->message_block_index++] = 0x80;

     while(ctx->message_block_index < 64)
       ctx->message_block[ctx->message_block_index++] = 0;

     sha1_process_message_block(ctx);
   }else{
     ctx->message_block[ctx->message_block_index++] = 0x80;
   }

   while(ctx->message_block_index < 56)
     ctx->message_block[ctx->message_block_index++] = 0;

   if(ctx->version == lSHA1){
     xSHA1itoba(ctx->length_high, ctx->message_block, 60);
     xSHA1itoba(ctx->length_low,  ctx->message_block, 56);
   }else{
     SHA1itoba(ctx->length_high, ctx->message_block, 56);
     SHA1itoba(ctx->length_low,  ctx->message_block, 60);
   }
 }
 sha1_process_message_block(ctx);
}



uint32_t __stdcall sha1_checksum(uint8_t *data, uint32_t length, uint32_t version){
 uint8_t digest[20];
 sha1_context ctx;
 ctx.version = version;
 sha1_reset(&ctx);
 sha1_input(&ctx, data, length);
 sha1_digest(&ctx, digest);

 return *((uint32_t*)&digest[0]) ^ *((uint32_t*)&digest[4]) ^ 
    *((uint32_t*)&digest[8]) ^ *((uint32_t*)&digest[12]) ^ *((uint32_t*)&digest[16]);
}

Link to comment
Share on other sites

#pragma once
#include "types.h"
#include "stdint.h"
#include "string.h"
#include <windows.h>
#include <stdio.h>
#include "module.h"
#include "dynamic_callbacks.h"
#include "mediv_random.h"
#include "rc4.h"
#include "md5.h"
#include "buffer.h"
#include "config.h"

#define WARDEN_SEND (0x00)
#define WARDEN_RECV (0x01)
#define WARDEN_BNCS (0x02)

#define SID_AUTH_INFO  (0x50)
#define SID_AUTH_CHECK (0x51)
#define SID_WARDEN     (0x5E)

#define MODULE_INFORMATION (0x00)
#define MODULE_TRANSFER    (0x01)
#define CHEAT_CHECKS       (0x02)
#define NEW_CRYPT_KEYS     (0x05)


typedef enum{
   WARDEN_SUCCESS = 0,             //All Went Well, Don't handle the packet Internally
   WARDEN_TRANSFER_FAILED,         //If the module transfer failed
   WARDEN_UNKNOWN_PROTOCOL,        //Not used, will be when adding support for MCP/UDP
   WARDEN_UNKNOWN_SUBID,           //Unknown Sub-ID [Not 0x00, 0x01, 0x02, or 0x05]
   WARDEN_RAW_FAILURE,             //The module was not able to handle the packet itself
   WARDEN_PACKET_FAILURE,          //Something went HORRIBLY wrong in warden_packet, should NEVER happen.
   WARDEN_INIT_FAILURE,            //Calling Init() in the module failed
   WARDEN_LOAD_FILE_FAILURE,       //Could not load module from file [Not to bad, prolly just dosen't exist]
   WARDEN_LOAD_MD5_FAILURE,        //Failed MD5 checksum when loading module [Either Bad tranfer or HD file corrupt]
   WARDEN_LOAD_INVALID_SIGNATURE,  //Module failed RSA verification
   WARDEN_LOAD_DECOMPRESS_FAILURE, //Module failed to decompress properly
   WARDEN_LOAD_PREP_FAILURE,       //Module prepare failed, Usually if module is corrupt
   WARDEN_CHECK_UNKNOWN_COMMAND,   //Unknown sub-command in CHEAT_CHECKS
   WARDEN_CHECK_TO_MANY_LIBS,      //There were more then 4 libraries in a single 0x02 packet [this is eww yes, but I'll figure out a beter way later]
   WARDEN_MEM_UNKNOWN_PRODUCT, 
   WARDEN_MEM_UNKNOWN_SEGMENT,     //Could not read segment from ini file
   WARDEN_INVALID_INSTANCE,        //If the instance passed to any api is invalid (0)
   WARDEN_MAX = 0xffffffff
};

typedef struct{
 uint32_t send_packet;
 uint32_t check_module;
 uint32_t load_module;
 uint32_t mem_alloc;
 uint32_t mem_free;
 uint32_t set_rc4;
 uint32_t get_rc4;
}callbacks_t;
typedef struct{
 callbacks_t *c;
}callbacksp_t;

typedef struct{
   callbacksp_t *callbacks;
   uint32_t     product;
   uint8_t      *seed;
   uint32_t     seed_len;
   uint8_t      *in_key;
   uint8_t      *out_key;
   uint8_t      *module_md5;
   uint8_t      *module_seed;
   uint32_t     module;
   uint32_t     module_size;
   uint32_t     module_position;
   uint32_t     init_data;
   uint8_t      PAGE_CHECK_A;
   uint8_t      MEM_CHECK;
   uint8_t      XOR_CODE;
   uint32_t     session;
   uint32_t     disconnect;
   uint32_t     sendpacket;
   uint8_t      last_opcode;
}warden_instance;
typedef struct module_info module_info_t;
struct module_info{
   uint8_t  md5[0x10];
   uint8_t  key[0x10];
   uint8_t  xor;
   uint8_t  mem_check;
   uint8_t  pag_check;
   uint8_t *data;
   uint32_t size;
   module_info_t *next;
};

typedef struct{
 module_info_t *modules;
}world_instance;

void warden_init_rc4keys(warden_instance *ctx);
void warden_send_packet(warden_instance *ctx, const uint8_t *data, uint16_t size);
void warden_save_file(warden_instance *ctx, uint32_t file_step);
uint32_t warden_load_module(warden_instance *ctx);
uint32_t warden_mem_check(warden_instance *ctx, buffer_t *buffer, buffer_t *out_buffer, uint8_t *lib);
uint32_t warden_page_check(warden_instance *ctx, buffer_t *buffer, buffer_t *out_buffer);

uint32_t warden_module_information(warden_instance *ctx, buffer_t *buffer);
uint32_t warden_module_transfer(warden_instance *ctx, buffer_t *buffer);
uint32_t warden_cheat_check(warden_instance *ctx, buffer_t *buffer);

uint32_t __stdcall warden_init(uint32_t world, uint32_t session, uint32_t sendpacket, uint32_t disconnect, uint8_t *seed, uint32_t seedlen);
uint32_t __stdcall warden_data(uint32_t main_instance, uint32_t instance, uint32_t length, const uint8_t *data);
uint32_t __stdcall warden_cleanup(uint32_t instance);


uint32_t __stdcall warden_send_module_information(uint32_t instance);
uint32_t warden_recv_module_information(world_instance *world, warden_instance *ctx, buffer_t *in);

void warden_send_module_transfer(warden_instance *ctx);
uint32_t warden_recv_module_transfer(world_instance *world, warden_instance *ctx, buffer_t *in);\\

void warden_send_cheat_check(world_instance *world, warden_instance *ctx);

typedef void (*MangosSendPacket)(uint32_t session_ptr, uint8_t *data, uint32_t data_len);

#include "warden.h"
uint8_t *to_hex(uint8_t *data, uint32_t size, BOOLEAN spaces){
   uint8_t *buff = safe_malloc(size * (spaces == TRUE ? 3 : 2));
   uint32_t x = 0;

   for(x = 0; x < size; x++){
       if(spaces == TRUE)
           sprintf_s((uint8_t*)(buff + (3 * x)), 4, "%02X ", data[x]);
       else
           sprintf_s((uint8_t*)(buff + (2 * x)), 4, "%02X", data[x]);
   }
   return buff;
}
uint8_t *load_file(uint8_t *path, uint32_t *size_buf){
   FILE *fp;
   uint32_t result;
   uint8_t *data;
   uint32_t size;
   fopen_s(&fp, path, "rb");
   if(fp != NULL){
       fseek(fp, 0, SEEK_END);
       size = ftell(fp);
       rewind(fp);
       data = (uint8_t*)safe_malloc(size);
       result = fread(data, 1, size, fp);
       fclose(fp);
       if(result != size){
           free(data);
           if(size_buf != NULL) *size_buf = 0;
           return NULL;
       }else{
           if(size_buf != NULL) *size_buf = size;
           return data;
       }
   }
   if(size_buf != NULL) *size_buf = 0;
   return NULL;
}

uint32_t __stdcall warden_first_run(){
   world_instance *ctx = safe_malloc(sizeof(world_instance));
   uint8_t *path = (uint8_t*)safe_malloc(0x30);
   uint8_t *hex;
   uint8_t *tmp = "\\xF8\\xA4\\xCB\\x47\\xA7\\x0A\\xBD\\xC0\\xB0\\x03\\xEE\\x4C\\x0C\\xC6\\x44\\xCE";
   ctx->modules = safe_malloc(sizeof(module_info_t));
   memcpy(&ctx->modules->md5[0], tmp, 0x10);
   ctx->modules->xor = 0xB1;
   ctx->modules->mem_check = 0x1B;
   ctx->modules->pag_check = 0x87;

   hex = to_hex(ctx->modules->md5, 0x10, FALSE);
   sprintf_s(path, 0x30, "./warden/%s.bin", hex);
   ctx->modules->data = load_file(path, &ctx->modules->size);
   printf("Size: %d\\n", ctx->modules->size );

   sprintf_s(path, 0x30, "./warden/%s.key", hex);
   tmp = load_file(path, 0);
   if(tmp != NULL)
       memcpy(&ctx->modules->key[0], tmp, 0x10);
   return (uint32_t)ctx;
}

uint32_t __stdcall warden_init(uint32_t world, uint32_t session, uint32_t sendpacket, uint32_t disconnect, uint8_t *seed, uint32_t seedlen){
   world_instance *ctx = (world_instance*)world;
   warden_instance *instance = safe_malloc(sizeof(warden_instance));
   uint32_t code_segment     = memalloc(0x1c0);
   memset(instance, 0, sizeof(warden_instance));
   instance->callbacks       = safe_malloc(sizeof(callbacksp_t));
   instance->callbacks->c    = safe_malloc(sizeof(callbacks_t));
   instance->session         = session;
   instance->sendpacket      = sendpacket;
   instance->disconnect      = disconnect;
   instance->seed            = safe_malloc(seedlen);
   instance->seed_len        = seedlen;
   instance->module          = memalloc(ctx->modules->size);
   instance->module_size     = ctx->modules->size;
   instance->module_md5      = safe_malloc(0x10);
   instance->module_seed     = safe_malloc(0x10);
   instance->MEM_CHECK       = ctx->modules->mem_check;
   instance->PAGE_CHECK_A    = ctx->modules->pag_check;
   instance->XOR_CODE        = ctx->modules->xor;
   memcpy((uint8_t*)instance->module, ctx->modules->data, ctx->modules->size);
   memcpy(instance->module_md5, &ctx->modules->md5[0], 0x10);
   memcpy(instance->module_seed, &ctx->modules->key[0], 0x10);
   memcpy(instance->seed, seed, seedlen);
   warden_init_rc4keys(instance);


   instance->callbacks->c->send_packet  = get_callback_packet(code_segment + 0x000, (uint32_t)instance);
   instance->callbacks->c->check_module = get_callback_check (code_segment + 0x040, (uint32_t)instance);
   instance->callbacks->c->load_module  = get_callback_load  (code_segment + 0x080, (uint32_t)instance);
   instance->callbacks->c->mem_alloc    = get_callback_malloc(code_segment + 0x0C0, (uint32_t)instance);
   instance->callbacks->c->mem_free     = get_callback_mfree (code_segment + 0x100, (uint32_t)instance);
   instance->callbacks->c->set_rc4      = get_callback_setrc4(code_segment + 0x140, (uint32_t)instance);
   instance->callbacks->c->get_rc4      = get_callback_getrc4(code_segment + 0x180, (uint32_t)instance);

   warden_send_module_information((uint32_t)instance);
   return (uint32_t)instance;
}

uint32_t __stdcall warden_send_module_information(uint32_t instance){
   /**********************************************
    * MEDIV_MODULE_INFORMATION (0x00)            *
    *--------------------------------------------*
    * S->C:                                      *
    *   (Byte[16]) MD5 Hash of Module            *
    *   (Byte[16]) Module Decryption Seed        *
    *   (DWORD) Module Length                    *
    * C->S:                                      *
    *  (Byte) Status                             *
    *    0 - Do not have module, Request Transfer*
    *    1 - Have Module and Loaded properly     *
    **********************************************/

   warden_instance *ctx = (warden_instance*)instance;
   buffer_t *buff = buffer_create(BO_LITTLE_ENDIAN);
   buffer_add_int8(buff, '\\x00');
   buffer_add_bytes(buff, ctx->module_md5, 0x10);
   buffer_add_bytes(buff, ctx->module_seed, 0x10);
   buffer_add_int32(buff, ctx->module_size);
   warden_send_packet(ctx, buff->data, buff->current_length);
   buffer_destroy(buff);
   return 0;
}

uint32_t warden_recv_module_information(world_instance *world, warden_instance *ctx, buffer_t *in){
   /**********************************************
    * MEDIV_MODULE_INFORMATION (0x00)            *
    *--------------------------------------------*
    * S->C:                                      *
    *   (Byte[16]) MD5 Hash of Module            *
    *   (Byte[16]) Module Decryption Seed        *
    *   (DWORD) Module Length                    *
    * C->S:                                      *
    *  (Byte) Status                             *
    *    0 - Do not have module, Request Transfer*
    *    1 - Have Module and Loaded properly     *
    **********************************************/
   if(buffer_read_next_int8(in) == 1){
       printf("They already have the module\\n");
       warden_send_cheat_check(world, ctx);
   }else{
       printf("They need the module!\\n");
       warden_send_module_transfer(ctx);
   }
   return WARDEN_SUCCESS;
}

uint32_t __stdcall warden_data(uint32_t winstance, uint32_t instance, uint32_t length, const uint8_t *raw_data){
   warden_instance *ctx = (warden_instance*)instance;
   world_instance *world = (world_instance*)winstance;
   buffer_t *buf = buffer_create(BO_LITTLE_ENDIAN);
   uint8_t *data = (uint8_t*)safe_malloc(length);
   uint32_t result = WARDEN_SUCCESS;
   memcpy(data, raw_data, length);
   rc4_crypt(ctx->in_key, data, length);
   buffer_add_bytes(buf, data, (uint16_t)length);

   if(ctx->last_opcode == MODULE_INFORMATION){
       result = warden_recv_module_information(world, ctx, buf);
   }else if(ctx->last_opcode == MODULE_TRANSFER){
       result = warden_recv_module_transfer(world, ctx, buf);
   }else{
       switch(buffer_read_next_int8(buf)){
           default:
               printf("Unknown Warden Packet:\\n");
               buffer_print(buf);
       }
   }

   buffer_destroy(buf);
   free(data);
   return result;
}

void warden_send_module_transfer(warden_instance *ctx){
   /**********************************
    * MEDIV_MODULE_TRANSFER (0x01)   *
    *--------------------------------*
    * S->C:                          *
    *  (Word) Payload Length         *
    *  (Void)  Payload               *
    *                                *
    * C->S: (When tranfer finishes)  *
    *  (Byte) Status                 *
    *     - 0: Something went wrong  *
    *     - 1: Module loaded         * 
    **********************************/
   uint32_t x = 0;
   buffer_t *buf = NULL;
   uint16_t size;
   printf("Sending module to client\\n");
   for(x = 0; x < ctx->module_size; x += 0x100){
       size = (uint16_t)(ctx->module_size - x < 0x100 ? ctx->module_size - x : 0x100);
       buf = buffer_create(BO_LITTLE_ENDIAN);
       buffer_add_int8(buf, MODULE_TRANSFER);
       buffer_add_int16(buf, size);
       buffer_add_bytes(buf, (uint8_t*)((uint32_t)ctx->module + x), size);
       warden_send_packet(ctx, buf->data, buf->current_length);
       buffer_destroy(buf);
   }
   printf("Module transfer complete\\n");
}

uint32_t warden_recv_module_transfer(world_instance *world, warden_instance *ctx, buffer_t *in){
   /**********************************
    * MEDIV_MODULE_TRANSFER (0x01)   *
    *--------------------------------*
    * C->S: (When tranfer finishes)  *
    *  (Byte) Status                 *
    *     - 0: Something went wrong  *
    *     - 1: Module loaded         * 
    **********************************/

   if(buffer_read_next_int8(in) == 1){
       printf("Module transfer successful!\\n");
       return WARDEN_SUCCESS;
   }else{
       printf("Module transfer failed!\\n");
       return WARDEN_TRANSFER_FAILED;
   }
}

uint32_t __stdcall warden_cleanup(uint32_t instance){
   warden_instance *ctx = (warden_instance*)instance;

   if(ctx == NULL) return WARDEN_INVALID_INSTANCE;
   if(ctx->in_key      != NULL) free(ctx->in_key);
   if(ctx->out_key     != NULL) free(ctx->out_key);
   if(ctx->seed        != NULL) free(ctx->seed);
   if(ctx->module      != 0   ) memfree(ctx->module, ctx->module_size);
   if(ctx->module_md5  != NULL) free(ctx->module_md5);
   if(ctx->module_seed != NULL) free(ctx->module_seed);
   if(ctx->callbacks){
       memfree(ctx->callbacks->c->send_packet, 0x1000);
       free(ctx->callbacks);
   }
   free(ctx);
   return WARDEN_SUCCESS;
}

void warden_init_rc4keys(warden_instance *ctx){
   mediv_random_context *rnd = safe_malloc(sizeof(mediv_random_context));
   uint8_t *out_seed = safe_malloc(0x10);
   uint8_t *in_seed  = safe_malloc(0x10);
   ctx->out_key = safe_malloc(0x102);
   ctx->in_key  = safe_malloc(0x102);

   mediv_random_init(rnd, ctx->seed, ctx->seed_len);
   mediv_random_get_bytes(rnd, in_seed, 0x10);
   mediv_random_get_bytes(rnd, out_seed,  0x10);

   rc4_init(ctx->out_key, out_seed, 0x10);
   rc4_init(ctx->in_key,  in_seed,  0x10);

   printf("\\n");
   printf("Warden Seed:     %s\\n", to_hex(ctx->seed, ctx->seed_len, FALSE));
   printf("Warden Out Seed: %s\\n", to_hex(out_seed, 0x10, FALSE));
   printf("Warden In Seed:  %s\\n", to_hex(in_seed, 0x10, FALSE));
   printf("Warden Crypt Keys Generated!\\n");
}

uint8_t *to_string(uint8_t *data){
   uint32_t length;
   uint8_t *buff;
   uint32_t x = 0;

   if(data == NULL) 
       return NULL;

   length = strlen(data) / 2;
   buff   = safe_malloc(length);

   for(x = 0; x < length; x++){
       sscanf_s(data, "%02x", &buff[x], 1);
       data += 2;
   }
   return buff;
}

void warden_send_packet(warden_instance *ctx, const uint8_t *data, uint16_t size){
   uint8_t *pdata = safe_malloc(size);
   memcpy(pdata, data, size);
   ctx->last_opcode = data[0];

   rc4_crypt(ctx->out_key, pdata, (uint32_t)size);
   ((MangosSendPacket)ctx->sendpacket)(ctx->session, pdata, size);
   free(pdata);
}

uint32_t warden_load_module(warden_instance *ctx){
   uint32_t size;
   uint32_t temp_module;

   if(md5_verify_data((uint8_t*)ctx->module, ctx->module_size, ctx->module_md5) == 1){
       rc4_crypt_data((uint8_t*)ctx->module, ctx->module_size, ctx->module_seed, 0x10);

       if((*(uint32_t*)(ctx->module + ctx->module_size - 0x104)) == 'SIGN'){
           size        = *(uint32_t*)(ctx->module);
           temp_module = memalloc(size);
           if(uncompress((uint8_t*)temp_module, &size, (uint8_t*)(ctx->module + 4), ctx->module_size - 0x108) == 0){
               memfree(ctx->module, ctx->module_size);
               ctx->module      = temp_module;
               ctx->module_size = size;

               size = module_get_prep_size((uint8_t*)ctx->module);
               temp_module = module_prep((uint8_t*)ctx->module);
               if(temp_module != 0){
                   memfree(ctx->module, ctx->module_size);
                   ctx->module      = temp_module;
                   ctx->module_size = size;
                   return WARDEN_SUCCESS;
               }else{
                   return WARDEN_LOAD_PREP_FAILURE;
               }
           }else{
               return WARDEN_LOAD_DECOMPRESS_FAILURE;
           }
       }else{
           return WARDEN_LOAD_INVALID_SIGNATURE;
       }
   }else{
       return WARDEN_LOAD_MD5_FAILURE;
   }
}

void warden_send_cheat_check(world_instance *world, warden_instance *ctx){
   /**************************************
    * CHEAT_CHECKS (0x02)                *
    *------------------------------------*
    * S->C:                              *
    *  (PString[]) Libraries             *
    *  (Byte)      Check Type            *
    *    -PageCheckA                     *
    *     (DWORD)    Seed                *
    *     (Byte[20]) SHA1                *
    *     (DWORD)    Address             *
    *     (Byte)     Length              *
    *    -MemCheck                       *
    *     (Byte)  Library                *
    *     (DWORD) Address                *
    *     (Byte)  Length                 *
    *  (Byte) XOr Code                   *
    *                                    *
    * C-S:                               *
    *  (Word)  Length of Payload         *
    *  (DWORD) Checksum of Payload       *
    *  -PageCheckA                       *
    *    (Byte) Found                    *
    *      - 0: Hash Was Not found       *
    *      - 1: Hash Was Found           *
    *  -MemCheck                         *
    *    (Byte) Status                   *
    *      - 1: Could not read segment   *
    *      - 0: Segment to follow        *
    *    If Status = 0                   *
    *      (Void) Memory                 *
    **************************************/
   buffer_t *buf = buffer_create(BO_LITTLE_ENDIAN);
   buffer_add_int8(buf, CHEAT_CHECKS);
   buffer_add_int8(buf, 0);
   buffer_add_int8(buf, ctx->MEM_CHECK ^ ctx->XOR_CODE);
   buffer_add_int8(buf, 0);
   buffer_add_int32(buf, 0x00420541);
   buffer_add_int8(buf, 0x0a);
   buffer_add_int8(buf, ctx->XOR_CODE);
   warden_send_packet(ctx, buf->data, buf->current_length);
   buffer_destroy(buf);
}

#ifndef RC4_H
#define RC4_H

#include "stdint.h"

void __stdcall rc4_init(uint8_t *key_buffer, uint8_t *base, uint32_t base_length);
void __stdcall rc4_crypt(uint8_t *key, uint8_t *data, uint32_t length);
void __stdcall rc4_crypt_data(uint8_t *data, uint32_t data_length, uint8_t *base, uint32_t base_length);

#endif

#ifndef RC4_C
#define RC4_C

#include "rc4.h"

void SWAP(uint8_t *a, uint8_t *b){
 uint8_t t;
 t = *a;
 *a = *b;
 *b = t;
}

void __stdcall rc4_init(uint8_t *key_buffer, uint8_t *base, uint32_t base_length){
 uint8_t val = 0;
 uint32_t position = 0;
 uint32_t i;

 for(i = 0; i < 0x100; i++)
   key_buffer[i] = (uint8_t)i;

 key_buffer[0x100] = 0;
 key_buffer[0x101] = 0;

 for(i = 1; i <= 0x40; i++){
   val += key_buffer[(i * 4) - 4] + base[position++ % base_length];
   SWAP(&key_buffer[(i * 4) - 4], &key_buffer[val & 0x0FF]);

   val += key_buffer[(i * 4) - 3] + base[position++ % base_length];
   SWAP(&key_buffer[(i * 4) - 3], &key_buffer[val & 0x0FF]);

   val += key_buffer[(i * 4) - 2] + base[position++ % base_length];
   SWAP(&key_buffer[(i * 4) - 2], &key_buffer[val & 0x0FF]);

   val += key_buffer[(i * 4) - 1] + base[position++ % base_length];
   SWAP(&key_buffer[(i * 4) - 1], &key_buffer[val & 0x0FF]);
 }
}

void __stdcall rc4_crypt(uint8_t *key, uint8_t *data, uint32_t length){
 uint32_t i;
 for(i = 0; i < length; i++){
   key[0x100]++;
   key[0x101] += key[key[0x100]];
   SWAP(&key[key[0x101]], &key[key[0x100]]);
   data[i] ^= key[(key[key[0x101]] + key[key[0x100]]) & 0x0FF];
 }
}

void __stdcall rc4_crypt_data(uint8_t *data, uint32_t data_length, uint8_t *base, uint32_t base_length){
 uint8_t key[0x102];
   rc4_init(key, base, base_length);
   rc4_crypt(key, data, data_length);
}

#endif

Link to comment
Share on other sites

#ifndef MD5_H
#define MD5_H

//This code is based on [url]http://people.csail.mit.edu/rivest/Md5.c[/url] 
//Bet heavily edited by me to the point where it isnt recognisable.

#include "stdint.h"
#include "math.h"

#ifndef _MD5_enum_
#define _MD5_enum_
enum{
   md5_success = 0,
   md5_null,            /* Null pointer parameter */
   md5_input_too_long,  /* input data too long, >= 0x10000000000000000*/
   md5_state_error      /* called Input after Digest */
};
#endif
#define md5_hash_size 16

typedef struct md5_context{
 uint32_t      intermediate_hash[md5_hash_size / 4]; /* Message Digest                   */
 uint32_t      length_low;                           /* Message length in bits           */
 uint32_t      length_high;                          /* Message length in bits           */
 int_least16_t message_block_index;                  /* Index into message block array   */
 uint8_t       message_block[64];                    /* 512-bit message blocks           */
 uint8_t       computed;                             /* Is the digest computed?          */
 uint8_t       corrupted;                            /* Is the message digest corrupted? */
} md5_context;

int __stdcall md5_reset(md5_context *);
int __stdcall md5_input(md5_context *, const uint8_t *, uint32_t);
int __stdcall md5_digest(md5_context *, uint8_t *);
int __stdcall md5_verify_data(uint8_t *, uint32_t, const uint8_t *);

#endif

#include "md5.h"

void md5_process_message_block(md5_context *);

#define md5_batoi(ba, i) \\
 ((ba[i+3] << 24) | (ba[i+2] << 16) | (ba[i+1] << 8) | ba[i])

#define md5_rol(word, bits) \\
   (((word) << (bits)) | ((word) >> (32-(bits))))


#define md5_itoba(a, ba, i) \\
 (ba[i+3] = (uint8_t)(a >> 24)); (ba[i+2] = (uint8_t)(a >> 16)); (ba[i+1] = (uint8_t)(a >> 8)); (ba[i] = (uint8_t)a);

uint32_t md5_math(uint16_t t, uint32_t B, uint32_t C, uint32_t D){
 if(t < 16)      return (D ^ (B & (C ^ D)));
 else if(t < 32) return (C ^ (D & (B ^ C)));
 else if(t < 48) return (B ^ C ^ D);
 else            return (C ^ (B | ~D));
}
uint16_t md5_index(uint16_t t){
 if(t < 16)      return t;
 else if(t < 32) return (5 * t + 1) % 16;
 else if(t < 48) return (3 * t + 5) % 16;
 else            return (7 * t)     % 16;
}
uint16_t md5_shift(uint16_t t){
 if(t < 16)      return (((t % 4) + 1) * 5 + 2);
 else if(t < 32) return (t % 4 == 0 ? 5 : (t % 4 == 1 ?  9 : (t % 4 == 2 ? 14 : 20)));
 else if(t < 48) return (t % 4 == 0 ? 4 : (t % 4 == 1 ? 11 : (t % 4 == 2 ? 16 : 23)));
 else            return (t % 4 == 0 ? 6 : (t % 4 == 1 ? 10 : (t % 4 == 2 ? 15 : 21)));
}

int __stdcall md5_reset(md5_context *ctx){
 uint8_t x = 0;

 if(!ctx)
   return md5_null;

 ctx->length_low  = 0;
 ctx->length_high = 0;
 ctx->computed    = 0;
 ctx->corrupted   = 0;
 ctx->message_block_index = 0;

 for(x = 0; x < 64; x++)
   ctx->message_block[x] = 0;

 ctx->intermediate_hash[0] = 0x67452301;
 ctx->intermediate_hash[1] = 0xEFCDAB89;
 ctx->intermediate_hash[2] = 0x98BADCFE;
 ctx->intermediate_hash[3] = 0x10325476;

 return md5_success;
}
int __stdcall md5_input(md5_context *ctx, const uint8_t *data, uint32_t length){
 uint32_t x;
 if(!length)
   return md5_success;

 if(!ctx || !data)
   return md5_null;

 if(ctx->computed){
   ctx->corrupted = md5_state_error;
   return md5_state_error;
 }

 for(x = 0; x < length; x++){
   ctx->message_block[ctx->message_block_index++] = (data[x] & 0xFF);
   ctx->length_low += 8;

   if (ctx->length_low == 0){
     ctx->length_high++;
     if(ctx->length_high == 0){
       ctx->corrupted = md5_input_too_long;
       return md5_input_too_long;
     }
   }

   if(ctx->message_block_index == 64)
     md5_process_message_block(ctx);
 }
 return md5_success;
}
int __stdcall md5_digest(md5_context *ctx, uint8_t *digest){
 int i;

 if (!ctx || !digest)
   return md5_null;

 if (ctx->corrupted)
   return ctx->corrupted;

 if (!ctx->computed){
   if (ctx->message_block_index > 55){
     ctx->message_block[ctx->message_block_index++] = 0x80;

     while(ctx->message_block_index < 64)
       ctx->message_block[ctx->message_block_index++] = 0;

     md5_process_message_block(ctx);
   }else{
     ctx->message_block[ctx->message_block_index++] = 0x80;
   }

   while(ctx->message_block_index < 56)
     ctx->message_block[ctx->message_block_index++] = 0;

   md5_itoba(ctx->length_high, ctx->message_block, 60);
   md5_itoba(ctx->length_low,  ctx->message_block, 56);

   md5_process_message_block(ctx);

   ctx->length_low  = 0;
   ctx->length_high = 0;
   ctx->computed    = 1;
 }

 for(i = 0; i < 4; i++){
   md5_itoba(ctx->intermediate_hash[i], digest, i * 4);
 }

 return md5_success;
}

void md5_process_message_block(md5_context *ctx){
 uint16_t t;          
 uint32_t temp;       
 uint32_t W[16];      
 uint32_t A, B, C, D; 
 const uint32_t K[] = { /* K = floor(abs(sin(x+1) & (2 pow 32))) */
   0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 
   0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 
   0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 
   0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 
   0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 
   0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 
   0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 
   0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
 };

 for(t = 0; t < 16; t++)
   W[t] = md5_batoi(ctx->message_block, t * 4);

 A = ctx->intermediate_hash[0];
 B = ctx->intermediate_hash[1];
 C = ctx->intermediate_hash[2];
 D = ctx->intermediate_hash[3];

 for(t = 0; t < 64; t++){
   temp = B + md5_rol((A + md5_math(t, B, C, D) + W[md5_index(t)] + K[t]), md5_shift(t));
   A = D; 
   D = C; 
   C = B; 
   B = temp;
 }

 ctx->intermediate_hash[0] += A;
 ctx->intermediate_hash[1] += B;
 ctx->intermediate_hash[2] += C;
 ctx->intermediate_hash[3] += D;

 ctx->message_block_index = 0;
}

int __stdcall md5_verify_data(uint8_t *data, uint32_t length, const uint8_t *correct_md5){
   md5_context ctx;
   uint8_t digest[16];
   uint32_t x;
   md5_reset(&ctx);
   md5_input(&ctx, data, length);
   md5_digest(&ctx, digest);

   if(!correct_md5)
       return 0;

   for(x = 0; x < 16; x++){
       if(digest[x] != correct_md5[x])
           return 0;
   }

   return 1;
}

#ifndef DYNAMIC_CALLBACKS_H
#define DYNAMIC_CALLBACKS_H
#include <stdio.h>
#include "types.h"
#include "stdint.h"
#include "string.h"
#include "warden.h"
#include "types.h"

uint32_t __stdcall memalloc(uint32_t size);
void     __stdcall memfree(uint32_t address, uint32_t size);

void     __stdcall module_packet(uint32_t instance, uint32_t packet, uint32_t size);
uint32_t __stdcall module_check (uint32_t instance, uint32_t module, uint32_t rc4_key);
uint32_t __stdcall module_load  (uint32_t instance, uint32_t rc4_key, uint32_t module, uint32_t size);
uint32_t __stdcall module_malloc(uint32_t instance, uint32_t size);
void     __stdcall module_mfree (uint32_t instance, uint32_t address);
uint32_t __stdcall module_setrc4(uint32_t instance, uint32_t ptr_keys, uint32_t size);
uint32_t __stdcall module_getrc4(uint32_t instance, uint32_t ptr_keys, uint32_t *size);

uint32_t get_callback_packet(uint32_t new_function, uint32_t instance);
uint32_t get_callback_check (uint32_t new_function, uint32_t instance);
uint32_t get_callback_load  (uint32_t new_function, uint32_t instance);
uint32_t get_callback_malloc(uint32_t new_function, uint32_t instance);
uint32_t get_callback_mfree (uint32_t new_function, uint32_t instance);
uint32_t get_callback_setrc4(uint32_t new_function, uint32_t instance);
uint32_t get_callback_getrc4(uint32_t new_function, uint32_t instance);
#endif

#ifndef DYNAMIC_CALLBACKS_C
#define DYNAMIC_CALLBACKS_C
#include "dynamic_callbacks.h"


uint32_t __stdcall memalloc(uint32_t size){
   LPVOID x = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
   VirtualLock(x, size);
   return (uint32_t)x;
}
void __stdcall memfree(uint32_t address, uint32_t size){
   VirtualUnlock((uint8_t*)address, size);
   VirtualFree((uint8_t*)address, 0, MEM_RELEASE);
}

void __stdcall module_packet(uint32_t instance, uint32_t packet, uint32_t size){
   /*warden_instance *ctx = (warden_instance*)instance;
   size += 4;
   send(ctx->socket_handle, "\\xff\\x5e", 2, 0);
   send(ctx->socket_handle, (uint8_t*)&size, 2, 0);
   send(ctx->socket_handle, (uint8_t*)packet, size - 4, 0);*/
}

uint32_t __stdcall module_check(uint32_t instance, uint32_t module, uint32_t rc4_key) { return 1; }
uint32_t __stdcall module_load(uint32_t instance, uint32_t rc4_key, uint32_t module, uint32_t size){ return 1; }
uint32_t __stdcall module_malloc(uint32_t instance, uint32_t size)                    { return (uint32_t)safe_malloc(size); }
void __stdcall module_mfree(uint32_t instance, uint32_t address)                      { free((uint8_t*)address); }
uint32_t __stdcall module_setrc4(uint32_t instance, uint32_t ptr_keys, uint32_t size) { return 1; }
uint32_t __stdcall module_getrc4(uint32_t instance, uint32_t ptr_keys, uint32_t *size){ return 1; }

uint32_t get_callback_packet(uint32_t new_function, uint32_t instance){
   uint32_t function_address = (uint32_t)module_packet;
   uint32_t function_call    = new_function + 22;
   memcpy((uint8_t*)new_function, "\\xFF\\x74\\x24\\x08\\xFF\\x74\\x24\\x08\\x68\\x0B\\xAD\\xC0\\xDE\\xFF\\x15\\x0B\\xAD\\xC0\\xDE\\xC2\\x08\\x00\\x00\\x00\\x00\\x00", 26);
   memcpy((uint8_t*)(new_function+9),  &instance, 4);
   memcpy((uint8_t*)(new_function+15), &function_call, 4);
   memcpy((uint8_t*)(new_function+22), &function_address, 4);
   return new_function;
}

uint32_t get_callback_check(uint32_t new_function, uint32_t instance){
   uint32_t function_address = (uint32_t)module_check;
   uint32_t function_call    = new_function + 22;
   memcpy((uint8_t*)new_function, "\\xFF\\x74\\x24\\x08\\xFF\\x74\\x24\\x08\\x68\\x0B\\xAD\\xC0\\xDE\\xFF\\x15\\x0B\\xAD\\xC0\\xDE\\xC2\\x08\\x00\\x00\\x00\\x00\\x00", 26);
   memcpy((uint8_t*)(new_function+9),  &instance, 4);
   memcpy((uint8_t*)(new_function+15), &function_call, 4);
   memcpy((uint8_t*)(new_function+22), &function_address, 4);
   return new_function;
}

uint32_t get_callback_load(uint32_t new_function, uint32_t instance){
   uint32_t function_address = (uint32_t)module_load;
   uint32_t function_call    = new_function + 26;
   memcpy((uint8_t*)new_function, "\\xFF\\x74\\x24\\x0C\\xFF\\x74\\x24\\x0C\\xFF\\x74\\x24\\x0C\\x68\\x0B\\xAD\\xC0\\xDE\\xFF\\x15\\x0B\\xAD\\xC0\\xDE\\xC2\\x0C\\x00\\x00\\x00\\x00\\x00", 30);
   memcpy((uint8_t*)(new_function+13), &instance, 4);
   memcpy((uint8_t*)(new_function+19), &function_call, 4);
   memcpy((uint8_t*)(new_function+26), &function_address, 4);
   return new_function;
}

uint32_t get_callback_malloc(uint32_t new_function, uint32_t instance){
   uint32_t function_address = (uint32_t)module_malloc;
   uint32_t function_call    = new_function + 18;
   memcpy((uint8_t*)new_function, "\\xFF\\x74\\x24\\x04\\x68\\x0B\\xAD\\xC0\\xDE\\xFF\\x15\\x0B\\xAD\\xC0\\xDE\\xC2\\x04\\x00\\x00\\x00\\x00\\x00", 22);
   memcpy((uint8_t*)(new_function+5),  &instance, 4);
   memcpy((uint8_t*)(new_function+11), &function_call, 4);
   memcpy((uint8_t*)(new_function+18), &function_address, 4);
   return new_function;
}

uint32_t get_callback_mfree(uint32_t new_function, uint32_t instance){
   uint32_t function_address = (uint32_t)module_mfree;
   uint32_t function_call    = new_function + 18;
   memcpy((uint8_t*)new_function, "\\xFF\\x74\\x24\\x04\\x68\\x0B\\xAD\\xC0\\xDE\\xFF\\x15\\x0B\\xAD\\xC0\\xDE\\xC2\\x04\\x00\\x00\\x00\\x00\\x00", 22);
   memcpy((uint8_t*)(new_function+5),  &instance, 4);
   memcpy((uint8_t*)(new_function+11), &function_call, 4);
   memcpy((uint8_t*)(new_function+18), &function_address, 4);
   return new_function;
}

uint32_t get_callback_setrc4(uint32_t new_function, uint32_t instance){
   uint32_t function_address = (uint32_t)module_setrc4;
   uint32_t function_call    = new_function + 22;
   memcpy((uint8_t*)new_function, "\\xFF\\x74\\x24\\x08\\xFF\\x74\\x24\\x08\\x68\\x0B\\xAD\\xC0\\xDE\\xFF\\x15\\x0B\\xAD\\xC0\\xDE\\xC2\\x08\\x00\\x00\\x00\\x00\\x00", 26);
   memcpy((uint8_t*)(new_function+9),  &instance, 4);
   memcpy((uint8_t*)(new_function+15), &function_call, 4);
   memcpy((uint8_t*)(new_function+22), &function_address, 4);
   return new_function;
}

uint32_t get_callback_getrc4(uint32_t new_function, uint32_t instance){
   uint32_t function_address = (uint32_t)module_getrc4;
   uint32_t function_call    = new_function + 22;
   memcpy((uint8_t*)new_function, "\\xFF\\x74\\x24\\x08\\xFF\\x74\\x24\\x08\\x68\\x0B\\xAD\\xC0\\xDE\\xFF\\x15\\x0B\\xAD\\xC0\\xDE\\xC2\\x08\\x00\\x00\\x00\\x00\\x00", 26);
   memcpy((uint8_t*)(new_function+9),  &instance, 4);
   memcpy((uint8_t*)(new_function+15), &function_call, 4);
   memcpy((uint8_t*)(new_function+22), &function_address, 4);
   return new_function;
}

#endif

#pragma once

#include <windows.h>
#include <stdio.h>
#include "types.h"


uint8_t *read_ini(const uint8_t *file, uint8_t *header, uint8_t *key, uint8_t *defa);

#include "config.h"

uint8_t *read_ini(const uint8_t *file, uint8_t *header, uint8_t *key, uint8_t *defa){
   uint8_t *path = safe_malloc(0x100);
   uint8_t *buff = safe_malloc(0x100);
   uint32_t ret;
   GetCurrentDirectory(0x100, path);
   sprintf_s(path, 0x100, "%s\\\\%s", path, file);
   ret = GetPrivateProfileStringA(header, key, defa, buff, 0x100, path);
   return (ret == 0 ? defa : buff);
}

#ifndef __PACKET_BUFFER_H__
#define __PACKET_BUFFER_H__

#pragma comment (lib, "Ws2_32.lib") 
#include <windows.h>
#include "types.h"

typedef enum
{
   BO_HOST,
   BO_NETWORK,
   BO_LITTLE_ENDIAN,
   BO_BIG_ENDIAN
} BYTE_ORDER_t;

/* This struct shouldn't be accessed directly */
typedef struct 
{
   /* Byte order to use */
   BYTE_ORDER_t byte_order;

   /* The current position in the string, used when reading it. */
   uint16_t position;

   /* The maximum length of the buffer that "buffer" is pointing to.  When 
    * space in this runs out, it's expanded  */
   uint16_t max_length;

   /* The current length of the buffer. */
   uint16_t current_length;

   /* The current buffer.  Will always point to a string of length max_length */
   uint8_t *data;

   /* Set to FALSE when the packet is destroyed, to make sure I don't accidentally
    * re-use it (again) */
   BOOLEAN valid;

} buffer_t;

/* Create a new packet buffer */
buffer_t *buffer_create(BYTE_ORDER_t byte_order);

/* Create a new packet buffer, with data. */
buffer_t *buffer_create_with_data(BYTE_ORDER_t byte_order, const void *data, const uint16_t length);

/* Destroy the buffer and free resources.  If this isn't used, memory will leak. */
void buffer_destroy(buffer_t *buffer);

/* Get the length of the buffer. */
uint16_t buffer_get_length(buffer_t *buffer);

/* Get the current location in the buffer. */
uint16_t buffer_get_current_offset(buffer_t *buffer);

/* Return the contents of the buffer in a newly allocated string. Fill in the length, if a pointer
* is given. Note that this allocates memory that has to be freed! */
uint8_t *buffer_create_string(buffer_t *buffer, uint16_t *length);
/* Does the same thing as above, but also frees up the buffer (good for a function return). */
uint8_t *buffer_create_string_and_destroy(buffer_t *buffer, uint16_t *length);

/* Add data to the end of the buffer */
buffer_t *buffer_add_int8(buffer_t *buffer,      const uint8_t data);
buffer_t *buffer_add_int16(buffer_t *buffer,     const uint16_t data);
buffer_t *buffer_add_int32(buffer_t *buffer,     const uint32_t data);
buffer_t *buffer_add_ntstring(buffer_t *buffer,  const char *data);
/* Note: UNICODE support is a hack -- it prints every second character as a NULL, but is otherwise ASCII. */
buffer_t *buffer_add_unicode(buffer_t *buffer,   const char *data);
buffer_t *buffer_add_bytes(buffer_t *buffer,     const void *data, const uint16_t length);
buffer_t *buffer_add_buffer(buffer_t *buffer,    const buffer_t *source);

/* Read the next data from the buffer.  The first read will be at the beginning.
* An assertion will fail and the program will end if read off
* the end of the buffer; it's probably a good idea to verify that enough data can be removed
* before actually attempting to remove it; otherwise, a DoS condition can occur */
uint8_t   buffer_read_next_int8(buffer_t *buffer);
uint16_t  buffer_read_next_int16(buffer_t *buffer);
uint32_t  buffer_read_next_int32(buffer_t *buffer);
char     *buffer_read_next_ntstring(buffer_t *buffer, char *data_ret, uint16_t max_length);
char     *buffer_read_next_unicode(buffer_t *buffer, char *data_ret, uint16_t max_length);
void     *buffer_read_next_bytes(buffer_t *buffer, void *data, uint16_t length);

/* Read the next data, without incrementing the current pointer. */
uint8_t   buffer_peek_next_int8(buffer_t *buffer);
uint16_t  buffer_peek_next_int16(buffer_t *buffer);
uint32_t  buffer_peek_next_int32(buffer_t *buffer);
char     *buffer_peek_next_ntstring(buffer_t *buffer, char *data_ret, uint16_t max_length);
char     *buffer_peek_next_unicode(buffer_t *buffer, char *data_ret, uint16_t max_length);
void     *buffer_peek_next_bytes(buffer_t *buffer, void *data, uint16_t length);

/* Read data at the specified location in the buffer (counting the first byte as 0). */
uint8_t   buffer_read_int8_at(buffer_t *buffer, uint16_t offset);
uint16_t  buffer_read_int16_at(buffer_t *buffer, uint16_t offset);
uint32_t  buffer_read_int32_at(buffer_t *buffer, uint16_t offset);
char     *buffer_read_ntstring_at(buffer_t *buffer, uint16_t offset, char *data_ret, uint16_t max_length);
char     *buffer_read_unicode_at(buffer_t *buffer, uint16_t offset, char *data_ret, uint16_t max_length);
void     *buffer_read_bytes_at(buffer_t *buffer, uint16_t offset, void *data, uint16_t length);

/* These boolean functions check if there are enough bytes left in the buffer to remove
* specified data.  These should always be used on the server side to verify valid
* packets */
BOOLEAN buffer_can_read_int8(buffer_t *buffer);
BOOLEAN buffer_can_read_int16(buffer_t *buffer);
BOOLEAN buffer_can_read_int32(buffer_t *buffer);
BOOLEAN buffer_can_read_ntstring(buffer_t *buffer);
BOOLEAN buffer_can_read_unicode(buffer_t *buffer);
BOOLEAN buffer_can_read_bytes(buffer_t *buffer, uint16_t length);

/* These functions check if there are enough bytes in the buffer at the specified location. */
BOOLEAN buffer_can_read_int8_at(buffer_t *buffer, uint16_t offset);
BOOLEAN buffer_can_read_int16_at(buffer_t *buffer, uint16_t offset);
BOOLEAN buffer_can_read_int32_at(buffer_t *buffer, uint16_t offset);
BOOLEAN buffer_can_read_ntstring_at(buffer_t *buffer, uint16_t offset, uint16_t max_length);
BOOLEAN buffer_can_read_unicode_at(buffer_t *buffer, uint16_t offset, uint16_t max_length);
BOOLEAN buffer_can_read_bytes_at(buffer_t *buffer, uint16_t offset, uint16_t length);

/* Print out the buffer in a nice format */
void buffer_print(buffer_t *buffer);
void buffer_print_pad(buffer_t *buffer, uint8_t *padding);

/* Returns a pointer to the actual buffer (I don't recommend using this). */
uint8_t *buffer_get(buffer_t *buffer, uint16_t *length);

#endif

Link to comment
Share on other sites

/* buffer.c
* By Ron
* Created August, 2008
*
* This module provides an easy way to marshall data coming/going. 
*/

#include <stdio.h>
#include <stdlib.h>
#include "stdint.h"
#include <string.h>
#include "buffer.h"
#include "types.h"

/* The initial max length of the string */
#define STARTING_LENGTH 1

static uint16_t host_to_network_16(uint16_t data)
{
   return htons(data);
}
static uint16_t host_to_host_16(uint16_t data)
{
   return data;
}
static uint16_t host_to_little_endian_16(uint16_t data)
{
   uint16_t network = host_to_network_16(data);

   return ((network >> 8) & 0x00FF) | 
           ((network << 8) & 0xFF00);
}
static uint16_t host_to_big_endian_16(uint16_t data)
{
   return host_to_network_16(data);
}

static uint32_t host_to_network_32(uint32_t data)
{
   return htonl(data);
}
static uint32_t host_to_host_32(uint32_t data)
{
   return data;
}
static uint32_t host_to_little_endian_32(uint32_t data)
{
   uint32_t network = host_to_network_32(data);

   return ((network << 24)  & 0xFF000000) | 
           ((network << 8)  & 0x00FF0000) | 
           ((network >> 8)  & 0x0000FF00) | 
           ((network >> 24) & 0x000000FF);
}
static uint32_t host_to_big_endian_32(uint32_t data)
{
   return host_to_network_32(data);
}


static uint16_t network_to_host_16(uint16_t data)
{
   return htons(data);
}
/*static uint16_t host_to_host_16(uint16_t data)
{
   return data;
} */
static uint16_t little_endian_to_host_16(uint16_t data)
{
   uint16_t network = network_to_host_16(data);

   return ((network >> 8) & 0x00FF) | 
           ((network << 8) & 0xFF00);
}
static uint16_t big_endian_to_host_16(uint16_t data)
{
   return network_to_host_16(data);
}

static uint32_t network_to_host_32(uint32_t data)
{
   return htonl(data);
}
/*static uint32_t host_to_host_32(uint32_t data)
{
   return data;
} */
static uint32_t little_endian_to_host_32(uint32_t data)
{
   uint32_t network = network_to_host_32(data);

   return ((network << 24)  & 0xFF000000) | 
           ((network << 8)  & 0x00FF0000) | 
           ((network >> 8)  & 0x0000FF00) | 
           ((network >> 24) & 0x000000FF);
}
static uint32_t big_endian_to_host_32(uint32_t data)
{
   return network_to_host_32(data);
}



/* Create a new packet buffer */
buffer_t *buffer_create(BYTE_ORDER_t byte_order)
{
   buffer_t *new_buffer = safe_malloc(sizeof(buffer_t));

   new_buffer->byte_order     = byte_order;
   new_buffer->valid          = TRUE;
   new_buffer->position       = 0;
   new_buffer->max_length     = STARTING_LENGTH;
   new_buffer->current_length = 0;
   new_buffer->data           = safe_malloc(STARTING_LENGTH * sizeof(char));

   return new_buffer;
}

/* Create a new packet buffer, with data.  The data shouldn't include the packet header, 
* it will be added.  The length is the length of the data, without the header. */
buffer_t *buffer_create_with_data(BYTE_ORDER_t byte_order, const void *data, const uint16_t length)
{
   buffer_t *new_buffer = buffer_create(byte_order);
   if(!new_buffer)
       DIE_MEM();

   buffer_add_bytes(new_buffer, data, length);

   return new_buffer;
}

/* Destroy the buffer and free resources.  If this isn't used, memory will leak. */
void buffer_destroy(buffer_t *buffer)
{
   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");
   buffer->valid = FALSE;

   memset(buffer->data, 0, buffer->max_length);
   free(buffer->data);

   memset(buffer, 0, sizeof(buffer_t));
   free(buffer);
}

uint16_t buffer_get_length(buffer_t *buffer)
{
   return buffer->current_length;
}

uint16_t buffer_get_current_offset(buffer_t *buffer)
{
   return buffer->position;
}

/* Add data to the end of the buffer */
buffer_t *buffer_add_int8(buffer_t *buffer, const uint8_t data)
{
   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");

   buffer_add_bytes(buffer, &data, 1);

   return buffer;
}

uint8_t *buffer_create_string(buffer_t *buffer, uint16_t *length)
{
   uint8_t *ret;

   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");

   ret = safe_malloc(buffer_get_length(buffer));
   memcpy(ret, buffer->data, buffer_get_length(buffer));

   if(length)
       *length = buffer_get_length(buffer);

   return ret;
}

uint8_t *buffer_create_string_and_destroy(buffer_t *buffer, uint16_t *length)
{
   uint8_t *ret = buffer_create_string(buffer, length);

   buffer_destroy(buffer);

   return ret;
}

buffer_t *buffer_add_int16(buffer_t *buffer, const uint16_t data)
{
   uint16_t converted;

   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");

   switch(buffer->byte_order)
   {
       case BO_NETWORK:       converted = host_to_network_16(data);       break;
       case BO_HOST:          converted = host_to_host_16(data);          break;
       case BO_LITTLE_ENDIAN: converted = host_to_little_endian_16(data); break;
       case BO_BIG_ENDIAN:    converted = host_to_big_endian_16(data);    break;
   }

   buffer_add_bytes(buffer, &converted, 2);

   return buffer;
}

buffer_t *buffer_add_int32(buffer_t *buffer, const uint32_t data)
{
   uint32_t converted;

   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");

   switch(buffer->byte_order)
   {
       case BO_NETWORK:       converted = host_to_network_32(data);       break;
       case BO_HOST:          converted = host_to_host_32(data);          break;
       case BO_LITTLE_ENDIAN: converted = host_to_little_endian_32(data); break;
       case BO_BIG_ENDIAN:    converted = host_to_big_endian_32(data);    break;
   }

   buffer_add_bytes(buffer, &converted, 4);

   return buffer;
}

buffer_t *buffer_add_ntstring(buffer_t *buffer, const char *data)
{
   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");

   buffer_add_bytes(buffer, data, strlen(data) + 1);

   return buffer;
}

buffer_t *buffer_add_unicode(buffer_t *buffer, const char *data)
{
   size_t i;
   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");

   for(i = 0; i < (strlen(data) + 1); i++)
       buffer_add_int16(buffer, data[i]);

   return buffer;
}

buffer_t *buffer_add_bytes(buffer_t *buffer, const void *data, const uint16_t length)
{
   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");

   if(buffer->current_length + length < buffer->current_length)
       DIE("Overflow.");

   /* Resize the buffer, if necessary. */
   if(buffer->current_length + length > buffer->max_length)
   {
       do
       {
           /* Check for overflow. */
           if(buffer->max_length << 1 < buffer->max_length)
               DIE("Overflow.");
           /* Double the length. */
           buffer->max_length = buffer->max_length << 1;
       }
       while(buffer->current_length + length > buffer->max_length);

       buffer->data = safe_realloc(buffer->data, buffer->max_length);
   }

   memcpy(buffer->data + buffer->current_length, data, length);

   buffer->current_length += length;

   return buffer;
}

buffer_t *buffer_add_buffer(buffer_t *buffer, const buffer_t *source)
{
   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");
   if(!source->valid)
       DIE("Program attempted to use deleted buffer.");

   buffer_add_bytes(buffer, source->data, source->current_length);

   return buffer;
}


uint8_t buffer_read_next_int8(buffer_t *buffer)
{
   uint8_t ret = buffer_read_int8_at(buffer, buffer->position);
   buffer->position += 1;
   return ret;
}
uint16_t buffer_read_next_int16(buffer_t *buffer)
{
   uint16_t ret = buffer_read_int16_at(buffer, buffer->position);
   buffer->position += 2;
   return ret;
}
uint32_t buffer_read_next_int32(buffer_t *buffer)
{
   uint32_t ret = buffer_read_int32_at(buffer, buffer->position);
   buffer->position += 4;
   return ret;
}
char *buffer_read_next_ntstring(buffer_t *buffer, char *data_ret, uint16_t max_length)
{
   buffer_read_ntstring_at(buffer, buffer->position, data_ret, max_length);
   buffer->position += strlen(data_ret) + 1;

   return data_ret;
}
char *buffer_read_next_unicode(buffer_t *buffer, char *data_ret, uint16_t max_length)
{
   buffer_read_unicode_at(buffer, buffer->position, data_ret, max_length);
   buffer->position += (strlen(data_ret) + 1) * 2;

   return data_ret;
}
void *buffer_read_next_bytes(buffer_t *buffer, void *data, uint16_t length)
{
   buffer_read_bytes_at(buffer, buffer->position, data, length);
   buffer->position += length;

   return data; 
}

uint8_t buffer_peek_next_int8(buffer_t *buffer)
{
   return buffer_read_int8_at(buffer, buffer->position);
}
uint16_t buffer_peek_next_int16(buffer_t *buffer)
{
   return buffer_read_int16_at(buffer, buffer->position);
}
uint32_t buffer_peek_next_int32(buffer_t *buffer)
{
   return buffer_read_int32_at(buffer, buffer->position);
}
char *buffer_peek_next_ntstring(buffer_t *buffer, char *data_ret, uint16_t max_length)
{
   return buffer_read_ntstring_at(buffer, buffer->position, data_ret, max_length);
}
char *buffer_peek_next_unicode(buffer_t *buffer, char *data_ret, uint16_t max_length)
{
   return buffer_read_unicode_at(buffer, buffer->position, data_ret, max_length);
}
void *buffer_peek_next_bytes(buffer_t *buffer, void *data, uint16_t length)
{
   return buffer_read_bytes_at(buffer, buffer->position, data, length);
}



uint8_t buffer_read_int8_at(buffer_t *buffer, uint16_t offset)
{
   uint8_t ret;

   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");

   buffer_read_bytes_at(buffer, offset, &ret, 1);

   return ret;
}

uint16_t buffer_read_int16_at(buffer_t *buffer, uint16_t offset)
{
   uint16_t ret;

   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");

   buffer_read_bytes_at(buffer, offset, &ret, 2);

   switch(buffer->byte_order)
   {
       case BO_NETWORK:       ret = network_to_host_16(ret);       break;
       case BO_HOST:          ret = host_to_host_16(ret);          break;
       case BO_LITTLE_ENDIAN: ret = little_endian_to_host_16(ret); break;
       case BO_BIG_ENDIAN:    ret = big_endian_to_host_16(ret);    break;
   }

   return ret;
}

uint32_t buffer_read_int32_at(buffer_t *buffer, uint16_t offset)
{
   uint32_t ret;

   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");

   buffer_read_bytes_at(buffer, offset, &ret, 4);

   switch(buffer->byte_order)
   {
       case BO_NETWORK:       ret = network_to_host_32(ret);       break;
       case BO_HOST:          ret = host_to_host_32(ret);          break;
       case BO_LITTLE_ENDIAN: ret = little_endian_to_host_32(ret); break;
       case BO_BIG_ENDIAN:    ret = big_endian_to_host_32(ret);    break;
   }

   return ret;
}

char *buffer_read_ntstring_at(buffer_t *buffer, uint16_t offset, char *data_ret, uint16_t max_length)
{
   uint16_t i = 0;
   uint8_t ch;

   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");
   if(!buffer_can_read_ntstring_at(buffer, offset, max_length))
       DIE("Program read off the end of the buffer.");

   do
   {
       ch = buffer->data[offset + i];
       data_ret[i] = ch;
       i++;
   }
   while(ch && i < max_length);

   data_ret[i - 1] = 0;

   return data_ret;
}

char *buffer_read_unicode_at(buffer_t *buffer, uint16_t offset, char *data_ret, uint16_t max_length)
{
   uint16_t i = 0;
   uint8_t  ch;

   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");
   if(!buffer_can_read_ntstring_at(buffer, offset, max_length))
       DIE("Program read off the end of the buffer.");

   do
   {
       ch = (uint8_t)buffer_read_int16_at(buffer, offset + (i * 2));
       data_ret[i] = ch;
       i++;
   }
   while(ch && i < max_length);

   data_ret[i - 1] = 0;

   return data_ret;
}

void *buffer_read_bytes_at(buffer_t *buffer, uint16_t offset, void *data, uint16_t length)
{
   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");
   if(!buffer_can_read_bytes_at(buffer, offset, length))
       DIE("Program read off the end of the buffer.");

   memcpy(data, buffer->data + offset, length);

   return data;
}

/* These boolean functions check if there's enough bytes left in the buffer to remove
* specified data.  These should always be used on the server side to verify valid
* packets */
BOOLEAN buffer_can_read_int8(buffer_t *buffer)
{
   return buffer_can_read_bytes(buffer, 1);
}
BOOLEAN buffer_can_read_int16(buffer_t *buffer)
{
   return buffer_can_read_bytes(buffer, 2);
}
BOOLEAN buffer_can_read_int32(buffer_t *buffer)
{
   return buffer_can_read_bytes(buffer, 4);
}
BOOLEAN buffer_can_read_ntstring(buffer_t *buffer)
{
   uint16_t i;
   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");

   for(i = buffer->position; i < buffer->current_length; i++)
       if(buffer->data[i] == '\\0')
           return TRUE;

   return FALSE;
}
/* It's important for the logic in this function to closely match the logic in read_unicode_at(), which
* is why I convert it to a uint8_t. */
BOOLEAN buffer_can_read_unicode(buffer_t *buffer)
{
   uint16_t i;
   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");

   for(i = buffer->position; i < buffer->current_length; i++)
       if(((uint8_t)buffer_read_int16_at(buffer, i)) == 0)
           return TRUE;

   return FALSE;
}
BOOLEAN buffer_can_read_bytes(buffer_t *buffer, uint16_t length)
{
   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");
   if(buffer->position + length < buffer->position)
       DIE("Overflow.");

   return buffer_can_read_bytes_at(buffer, buffer->position, length);
}

BOOLEAN buffer_can_read_int8_at(buffer_t *buffer, uint16_t offset)
{
   return buffer_can_read_bytes_at(buffer, offset, 1);
}

BOOLEAN buffer_can_read_int16_at(buffer_t *buffer, uint16_t offset)
{
   return buffer_can_read_bytes_at(buffer, offset, 2);
}

BOOLEAN buffer_can_read_int32_at(buffer_t *buffer, uint16_t offset)
{
   return buffer_can_read_bytes_at(buffer, offset, 4);
}

BOOLEAN buffer_can_read_ntstring_at(buffer_t *buffer, uint16_t offset, uint16_t max_length)
{
   uint16_t i;
   BOOLEAN good = TRUE;
   BOOLEAN done = FALSE;

   for(i = 0; i < max_length - 1 && !done && good; i++)
   {
       if(buffer->data[offset + i] == '\\0')
           done = TRUE;

       if(offset + i + 1 > buffer->current_length)
           good = FALSE;
   }

   return good;
}

BOOLEAN buffer_can_read_unicode_at(buffer_t *buffer, uint16_t offset, uint16_t max_length)
{
   uint16_t i;
   BOOLEAN good = TRUE;
   BOOLEAN done = FALSE;

   for(i = 0; i < max_length - 1 && !done && good; i++)
   {
       if(!buffer_can_read_int16_at(buffer, offset + (i * 2)))
           good = FALSE;
       else if(((uint8_t)buffer_read_int16_at(buffer, offset + (i * 2))) == 0)
           done = TRUE;
   }

   return good;
}

BOOLEAN buffer_can_read_bytes_at(buffer_t *buffer, uint16_t offset, uint16_t length)
{
   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");
   if(offset + length < offset)
       DIE("Overflow");

   return (offset + length - 1) < buffer->current_length;
}


static char get_character_from_byte(uint8_t byte)
{
   if(byte < 0x20 || byte > 0x7F)
       return '.';
   return byte;
}

/* Print out the buffer in a nice format */
void buffer_print(buffer_t *buffer){ buffer_print_pad(buffer, ""); }
void buffer_print_pad(buffer_t *buffer, uint8_t *padding)
{
   uint16_t length = buffer->current_length;
   uint16_t i, j;
   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");

   printf("%sBuffer contents:", padding);
   for(i = 0; i < length; i++)
   {
       if(!(i % 16))
       {
           if(i > 0)
           {
               printf("   ");
               for(j = 16; j > 0; j--)
               {
                   printf("%c", get_character_from_byte(buffer->data[i - j]));
               }
           }
           if(i == buffer->position)
               printf("\\n%s%04X:<", padding, i);
           else
               printf("\\n%s%04X: ", padding, i);
       }

       if(i == buffer->position)
           printf("%02X>", buffer->data[i]);
       else if(i == buffer->position - 1)
           printf("%02X<", buffer->data[i]);
       else
           printf("%02X ", buffer->data[i]);
   }

   for(i = length % 16; i < 17; i++)
       printf("   ");
   for(i = length - (length % 16); i < length; i++)
       printf("%c", get_character_from_byte(buffer->data[i]));

   printf("\\n%sLength: 0x%02X (%d)\\n", padding, length, length);
}

/* Returns a pointer to the actual buffer */
uint8_t *buffer_get(buffer_t *buffer, uint16_t *length)
{
   if(!buffer->valid)
       DIE("Program attempted to use deleted buffer.");
   *length = buffer->current_length;
   return buffer->data;
}

Link to comment
Share on other sites

Most of this is public domain either created by myself or an associate of mine, the MD5 class is a re-write of the sha1 class which is a complete re-write of a sha1 class I took from an associate of mine. But pretty much do with as they will.

None of this information is new, its all publically avalible if you know where to look so ya, have fun. I really really hate edrama.

I am not going to be posting my dll->module converter because i simply can't find it and I don';t care enough to look any further. BUT! if you wish to contact me with any questions on how things work feel free to post them here or PM me. I'll answer them if i have time and if I feel like it, fair enough?

Sorry about the multiple posts, but obviously my posts were to long for single. And I was to damn lazy to paste bin it or something.

Link to comment
Share on other sites

So, what does it do, and how do you use it?

Also, does it work on *nix?

It includes all the functions you need to download, unpack, initialize, run, and respond to warden's modules. You use it by reading ti and taking 5 mins to wrap your head around how it works, it's actually rather simple. And parts work under *nix systems, and other parts (executing the raw machine code in the module) does not.

If anyone is interested in using it, take a moment and read it to learn what it does yourself. If you get stuck or have questions about a particular aspect of what Warden is doing. Feel free to post. But general questions from people who have no interest/use for this is just annoying. (Not to sound mean i'd just don't have the time to explain every aspect in detail when most of the code speaks for itself)

Link to comment
Share on other sites

I'm genuinely interested, it's just too low-level for my "C++ experience" to handle.

Just wondering, let's say I had a module for detecting cheats. Could you give an example of how I would send this module to the client?

EDIT: Done some more research, found a nice tool for extracting modules from WoW's cache (it stores them locally in wowcache.wdb after closing) and even decrypting/converting them into DLLs. Client side anti-cheat for the average server admin is looking pretty promising.

Link to comment
Share on other sites

EDIT: Done some more research, found a nice tool for extracting modules from WoW's cache (it stores them locally in wowcache.wdb after closing) and even decrypting/converting them into DLLs. Client side anti-cheat for the average server admin is looking pretty promising.
Got a link to it?

Anyways,
Mediv_Random: Used to generate the encryption seeds. Feed in the session token, read 16 bytes seed a rc4 with that, thats the client's out key, Do the same for the next 16 bytes and thats the in key.

SHA1: 
Supports various types of the SHA1 algorithm, X-SHA1 used in Bnet password hashing, Normal SHA1 used in Warden, and L-SHA1 used in Checkrevision.
It also has a helper function that will compute the packet checksum for cheat responses (Just the 20 bytes of SHA1(Data) Xored together in 32-bit segments)

MD5: MD5 implementation fully standard


Dynamic_Callbacks:
Will create stub functions for the callbacks needed by the warden module. So that a single instance of the app can have multiple Warden modules running at the same time.

Config:
Simply reading an INI file


Module:
module_get_prep_size: Returns how big the module will be after fully loaded/preped (used to alloc proper memory)
module_prep:
Verifies the Module's integraty by checking if MD5(Module) = Module Name
Decrypts the module using basic RC4
Checks the Module Signature using RSA - Not done, screw writing a BigInt handler in C -.-
Decompresses the module using standard zlib inflate
Copies the decompressed module to the final buffer
Adjusts references to local variables accordingly. 
Inserts the proper dll import information
The module format is a striped down version of the PE format so meh.
module_get_init_address: Gets the physical address of the module's init() function.
module_init: Calls the init() function inside of the module after prep, returning a region of memory to be passed to further calls to the function
module_init_rc4: Call's the module exported init_rc4 function to initialize the encryption keys used when communicating tot eh server.
module_handle_packet: Calls the module internal packet handler to deal with the received, encrypted packet.

RC4: Standard rc4 implementation


Warden:
warden_packet - Deals with the raw incoming packet, decrypts it as needed
warden_module_information - Handles opcode 0x00, module information:
S->C: MEDIV_MODULE_INFORMATION (0x00) 
 (BYTE[16]) MD5 Checksum - MD5 checksum of the modules compressed encrypted data
 (BYTE[16]) Module RC4 Seed - RC4 seed for decryption of the module
 (DWORD)    Module Compressed Length - Size of the packet
C->S:
 (BYTE) Status - 0: The module was either correct or not in the cache request transfer, 1: The module was in the cache and loaded successfully

warden_module_transfer: - Basic file transfer for the module
S->C:  MEDIV_MODULE_TRANSFER (0x01) 
 (Word) Payload Length
 (Void)  Payload

C->S: When Transfer is complete
 (Byte) Status - 0: Something went wrong (md5 didn't match could not decrypt etc..) You will be DCed 1: Module loaded successfully ready for requests

warden_cheat_check: - Deals with opcode 0x02, the checking for chatzorz!
I must note this is module specific, the CheckType IDs change per module, also, there is One (1) module floating around where the check is simply CRC332(Data) & SHA1(Data) This is the test module [Mediv] but oddly enough it's still in rotation 

S->C:  CHEAT_CHECKS (0x02) 
 (PString[]) Libraries - Pascal string array of Libraries used in this check (Pascal strings are (Byte) Length (void) data as opposed to Null terminated strings)
 (Byte)      Check Type  - There can be any amount of checks, but the format is the same
     -PageCheckA             - Check the data in the page @ Address of length Length if SHA1(SHA1(Seed) & Data) = SHA1 value
        (DWORD)    Seed      
        (Byte[20]) SHA1       
        (DWORD)    Address 
        (Byte)     Length        
     -MemCheck             - Simple, read Length bytes at Location Address, if Library != then Address is relative to base address of the library in the above array with index Library         
        (Byte)  Library           
        (DWORD) Address    
        (Byte)  Length           
   'There are 3 other checks, which i havn't encountered in the wild so iono what they do
  (Byte) XOr Code         - Used to decdoe the CheckType byte to the actuall checktype ID (CheckType ^= XorCode

C->S:
 (WORD) Payload length
 (DWORD) Payload checksum (SHA1(Payload) Xored together in 32-bit segments)
 (Void) Payload
   -PAGECHECKA
     (Byte) Status - 1: SHA1 value was found, 0: SHA1 value was NOT found
  -MemCheck 
    (Byte) Status - 1: Could not read from that address, 0: Read successful
    If Status = 0 Then
      (Void) Read data

warden_handle_raw
Passes the encrypted packet off onto the module to handle, THOUGH! Being sure to update the module's RC4 keys before, and snagging them after, so to keep continuity

That *should* be the jist of how things work, if you have a specific question and i mean SPECIFIC please feel free to ask.

Link to comment
Share on other sites

Here's that thing I was talking about: http://www.gamethreat.net/forums/old-downloads/38708-warden-explorer.html

Also, you never answered my question about sending a module. :)

I apologize right now for my noobiness, I know it must be frustrating to see someone walk up to the code you've working on for a long time and pick it apart with "OMG WAT DOES THIS DO?!" but I am interested in learning more about this.

Link to comment
Share on other sites

Here's that thing I was talking about: http://www.gamethreat.net/forums/old-downloads/38708-warden-explorer.html

Also, you never answered my question about sending a module. :)

I apologize right now for my noobiness, I know it must be frustrating to see someone walk up to the code you've working on for a long time and pick it apart with "OMG WAT DOES THIS DO?!" but I am interested in learning more about this.

Interesting simply looks like a cach browser that simply only shows modules. Rather lame, except for the convert to dll.. but meh that part isn't difficult, I'll look at it more when I get home.

As for your question.

When WoW's connection starts you use Mediv_Random to create the seeds for the encryption keys (Using the session key), gen the keys using RC4. Send 0x00, if they say they did not have the module, you send it with a spew of 0x01's

Formats of all the packets are in my last post.

I'm not gunna give you actuall code for Mangos itself as I posted that a while ago in my old posts i think. And i dont want to look for/write it again.

Anyways, u.u i wanna go to be but can't, to fucking hot!

Link to comment
Share on other sites

I was thinking it would be useful for extracting modules from official servers for use with your Warden system. Also useful for looking into the modules and how they work.

Oh, and you mentioned Mediv.mod as the base Warden loader, when I'm pretty sure on WoW it's Maiev.mod (as in http://www.wowwiki.com/Maiev :lol:) Just a minor issue but probably nothing important. It may also be a regional thing, I'm not sure.

Link to comment
Share on other sites

I was thinking it would be useful for extracting modules from official servers for use with your Warden system. Also useful for looking into the modules and how they work.

Oh, and you mentioned Mediv.mod as the base Warden loader, when I'm pretty sure on WoW it's Maiev.mod (as in http://www.wowwiki.com/Maiev :lol:) Just a minor issue but probably nothing important. It may also be a regional thing, I'm not sure.

It could also be that I can't spell worth crap :(

Anyways, what i'd suggest is that someone who has time, write a little packet logger program that knowns how to decode Warden's communications, then simply log all of said communications. Once it's easy to see the raw decrypted packets it'll be easy for anyone who understands how to read binary data to understand what warden is doing.

Anybody up for the challenge?

Link to comment
Share on other sites

....
Warden:
warden_packet - Deals with the raw incoming packet, decrypts it as needed
warden_module_information - Handles opcode 0x00, module information:
S->C: MEDIV_MODULE_INFORMATION (0x00) 
 (BYTE[16]) MD5 Checksum - MD5 checksum of the modules compressed encrypted data
 (BYTE[16]) Module RC4 Seed - RC4 seed for decryption of the module
 (DWORD)    Module Compressed Length - Size of the packet
C->S:
 (BYTE) Status - 0: The module was either currupt or not in the cache request transfer, 1: The module was in the cache and loaded successfully

warden_module_transfer: - Basic file transfer for the module
S->C:  MEDIV_MODULE_TRANSFER (0x01) 
 (Word) Payload Length
 (Void)  Payload

C->S: When Transfer is complete
 (Byte) Status - 0: Something went wrong (md5 didn't match could not decrypt etc..) You will be DCed 1: Module loaded successfully ready for requests

warden_cheat_check: - Deals with opcode 0x02, the checking for chatzorz!
I must note this is module specific, the CheckType IDs change per module, also, there is One (1) module floating around where the check is simply CRC332(Data) & SHA1(Data) This is the test module [Mediv] but oddly enough it's still in rotation 

S->C:  CHEAT_CHECKS (0x02) 
 (PString[]) Libraries - Pascal string array of Libraries used in this check (Pascal strings are (Byte) Length (void) data as opposed to Null terminated strings)
 (Byte)      Check Type  - There can be any amount of checks, but the format is the same
     -PageCheckA             - Check the data in the page @ Address of length Length if SHA1(SHA1(Seed) & Data) = SHA1 value
        (DWORD)    Seed      
        (Byte[20]) SHA1       
        (DWORD)    Address 
        (Byte)     Length        
     -MemCheck             - Simple, read Length bytes at Location Address, if Library != 0 then Address is relative to base address of the library in the above array with index Library         
        (Byte)  Library           
        (DWORD) Address    
        (Byte)  Length           
   'There are 3 other checks, which i havn't encountered in the wild so iono what they do
  (Byte) XOr Code         - Used to decdoe the CheckType byte to the actuall checktype ID (CheckType ^= XOr Code)

C->S:
 (WORD) Payload length
 (DWORD) Payload checksum (SHA1(Payload) Xored together in 32-bit segments)
 (Void) Payload
   -PAGECHECKA
     (Byte) Status - 1: SHA1 value was found, 0: SHA1 value was NOT found
  -MemCheck 
    (Byte) Status - 1: Could not read from that address, 0: Read successful
    If Status = 0 Then
      (Void) Read data

warden_handle_raw
Passes the encrypted packet off onto the module to handle, THOUGH! Being sure to update the module's RC4 keys before, and snagging them after, so to keep continuity

....

so reading is good right? Some of the functionality of some packets I do not fully understand, but common I can't hold your hand. And I'm bad with ASM so someones gunna have to get elbow deep and help if you want more documentation then that, But for now, we know how to create modules, we know how to transfer them, we know how to load them, we know how to encrypt/decrypt them, we know how to communicate with them! *Looks for someone open to pass the football to...*

BTWm Just a side note, due to the nature of warden, all this shit could change in a heart beat. EXCEPT the fact that the initial module work like this. But once it'd downloaded/loaded a neww module the formats for each packet can be completely different.

Link to comment
Share on other sites

Sorry to stick my nose in here, but I really do hope you can get this working like Blizzard's if that's what is trying to be done. Especially if it can be worked on and implemented into MaNGOS. The whole cheat-hacking is a really bad flaw and if there could be a real Warden monitoring it, it would be awesome.

Link to comment
Share on other sites

Good job in figuring this all out. not many have.

But by exposing all this, it basically voids warden's ability to actually detect cheats. If you know how all the inner-workings work, then it's much easier to bypass (or emulate ;) - It'll help with the kiddies, but this actually helps cheat-makers even more.

Link to comment
Share on other sites

Good job in figuring this all out. not many have.

But by exposing all this, it basically voids warden's ability to actually detect cheats. If you know how all the inner-workings work, then it's much easier to bypass (or emulate ;) - It'll help with the kiddies, but this actually helps cheat-makers even more.

Considering the fact that a lot of the inner working of Warden have been public all along. And most people who make real cheats can simply look at the code and see whats going on, I don't see anything new here that would drastically reduce the already vulnerable security of Warden.

The things that make warden work, is not HOW it does something its how much, it does something. Basically you got to make something to fucking rediclious that it's a bitch and a half for cheat makers to work around. (having to completely duplicate the entirety of WoW's Memory and screen buffers for example) If you can do something like that, not many people will make cheats.

What I would like to see is it being the norm that Servers can create and run there own modules. Yes you would need severe trust int eh server operators because they will have the ability to run arbitrary code. But, to fucking bad! If a server is ran that distributes malicious modules, then you shouldn't be using the server! I don't know about most of you guys but I'm a rather trusting and trustworthy individual. (I am entrusted with over 50,000 cdkeys that run through my JBLS server every hour) Never once have I logged or used any. It's all a matter of trust.

Considering the fact that you would have to modify your client yourself to not verify the RSA signature, you should be full aware what that would do.

Link to comment
Share on other sites

Considering the fact that a lot of the inner working of Warden have been public all along. And most people who make real cheats can simply look at the code and see whats going on, I don't see anything new here that would drastically reduce the already vulnerable security of Warden.

The things that make warden work, is not HOW it does something its how much, it does something. Basically you got to make something to fucking rediclious that it's a bitch and a half for cheat makers to work around. (having to completely duplicate the entirety of WoW's Memory and screen buffers for example) If you can do something like that, not many people will make cheats.

What I would like to see is it being the norm that Servers can create and run there own modules. Yes you would need severe trust int eh server operators because they will have the ability to run arbitrary code. But, to fucking bad! If a server is ran that distributes malicious modules, then you shouldn't be using the server! I don't know about most of you guys but I'm a rather trusting and trustworthy individual. (I am entrusted with over 50,000 cdkeys that run through my JBLS server every hour) Never once have I logged or used any. It's all a matter of trust.

Considering the fact that you would have to modify your client yourself to not verify the RSA signature, you should be full aware what that would do.

Regarding the 'duplicate the entirety of WoW's memory and screen buffers' is a little thrown out of proportion. It took me a week or so to reverse engineer Warden enough to emulate it on the packet level. Anyone with the time and x86 assembly know-how can achieve the same.

Though, regarding your last comment; running a Blizzard certified module is the only logical and safe route to take if someone were to actually implement this. Nice work though, but finding people whom are willing to constantly maintain an anticheat, free of charge will be one of the tougher tasks.

PS: You still have a few opcodes and scans left to reverse ;)

Link to comment
Share on other sites

Regarding the 'duplicate the entirety of WoW's memory and screen buffers' is a little thrown out of proportion. It took me a week or so to reverse engineer Warden enough to emulate it on the packet level. Anyone with the time and x86 assembly know-how can achieve the same.
Indeed thats as far as we went and then droped it. We run the modules for 0x05, and handle 0x00-0x02 ourselves. IF you were to FULLY run the module letting it handle everything then yes you would need to duplicate the eintirity of wow to be save it grabs the correct values in 0x02.
Though, regarding your last comment; running a Blizzard certified module is the only logical and safe route to take if someone were to actually implement this. Nice work though, but finding people whom are willing to constantly maintain an anticheat, free of charge will be one of the tougher tasks.
hence why i'm shifting it off to you nice fellow <3
PS: You still have a few opcodes and scans left to reverse ;)
I know, and i'm not going to do them! This research was solely done because it started to affect chat bots on Battle.net. Since they do not employ any other scans or opcodes at the channel level, this was all that was needed to keep out chat bots online, so I really don't care about the other stuff. (Though I would like a better pragmatic way to obtain the sub-commands for the scan opcode any tips?) <3

Ugh spoke to soon, Warden was just reactivated on Battle.net with a new sub-command enabled u.u Its in channel so people are bitching at me to fix it -.-

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