Jump to content

daveh

Members
  • Posts

    38
  • Joined

  • Last visited

    Never
  • Donations

    0.00 GBP 

Everything posted by daveh

  1. Thank you, btw SMSG_AUTH_CHALLENGE is: struct SMSG_AUTH_CHALLENGE // Opcode: 0x8500 { uint32 ClientKey_part3; uint32 ServerKey_part1; uint8 unk; uint32 Seed; uint32 ServerKey_part3; uint32 ServerKey_part2; uint32 ClientKey_part1; uint32 ClientKey_part2; uint32 ServerKey_part4; uint32 ClientKey_part4; }
  2. Hi, I've made a rough patch for tiawps (https://github.com/arrai/tiawps), to decrypt 4.0.x wow sniff data. 4.0.3 CONNECTION_PTR_OFFSET is 0xCB2F8C, session key offset is still 1288. 4.0.1 CONNECTION_PTR_OFFSET is 0xCA5C34, session key offset is still 1288. Update: 2010-11-10: Now handling SMSG_REDIRECT_CLIENT 2010-11-23: Update for 4.0.3 Patch for 4.0.3 (for git master branch) patch for reader 4.0.3: diff --git a/src/reader/reader.bat b/src/reader/reader.bat index 7f8177e..58b125e --- a/src/reader/reader.bat +++ b/src/reader/reader.bat @@ -1,5 +1,6 @@ @echo off -echo "Tiawps sessionkey reader Build 12340 3.3.5" +echo "Tiawps sessionkey reader Build 13287 4.0.3" SET PATH=%~dp0 REM Switch to drive @@ -7,5 +8,7 @@ REM Switch to drive cd %PATH% -tiawps_reader.exe 13081844 1288 +rem CONNECTION_PTR_OFFSET = 0xCB2F8C +tiawps_reader.exe 13315980 1288 PAUSE patch for decrypter 4.0.3: diff --git a/src/decrypter/main.c b/src/decrypter/main.c old mode 100644 new mode 100755 index 8bfe4ff..3f92af0 --- a/src/decrypter/main.c +++ b/src/decrypter/main.c @@ -4,6 +4,8 @@ #include <time.h> #include <ctype.h> #include <sqlite3.h> +#include <openssl/bn.h> +//#include <openssl/rsa.h> #include "pcapreader.h" #include "structs.h" @@ -13,10 +15,14 @@ #define DEBUG 0 // SIZE SIZE CMD CMD -const uint8_t MAGIC_WOW_START[] = {0x00, 0x2A, 0xEC, 0x01}; +//const uint8_t MAGIC_WOW_START[] = {0x00, 0x2A, 0xEC, 0x01}; // 3.3.5 +//const uint8_t MAGIC_WOW_START[] = {0x00, 0x27, 0x00, 0x85}; // 4.0.1 +const uint8_t MAGIC_WOW_START[] = {0x00, 0x27, 0x00, 0x34}; // 4.0.3 static uint8_t SESSIONKEY[sESSION_KEY_LENGTH]; +static int merge_files = 0; + void readSessionkeyFile(const char* file) { FILE *fp = fopen(file, "r"); @@ -385,6 +391,258 @@ void removeInvalidConnections() struct tcp_connection *currentDecryptedConnection; +static BIGNUM *my_BN_bin2bn(const uint8_t *s, int len, BIGNUM *ret) +{ + uint8_t tmp[1024] = {0}; + for (int i = 0; i < len; i++) + tmp[i] = s[len-1-i]; + return BN_bin2bn(tmp, len, ret); +} + +static int my_BN_bn2bin(const BIGNUM *a, unsigned char *to) +{ + uint8_t tmp[1024] = {0}; + int len = BN_bn2bin(a, tmp); + for (int i = 0; i < len; i++) + to[i] = tmp[len-1-i]; + return len; +} + +static int parse_SMSG_REDIRECT_CLIENT(const uint8_t *in, uint8_t *out) +{ + uint8_t b_e[] = { 0x01, 0x00, 0x01, 0x00 }; // public-key exp + uint8_t b_m[] = { // modulus + 0x91, 0xD5, 0x9B, 0xB7, 0xD4, 0xE1, 0x83, 0xA5, 0x22, 0x2B, 0x5F, 0x38, 0xF4, 0xB8, 0x86, 0xFF, + 0x32, 0x84, 0x38, 0x2D, 0x99, 0x38, 0x8F, 0xBA, 0xF3, 0xC9, 0x22, 0x5D, 0x51, 0x73, 0x1E, 0x28, + 0x87, 0x24, 0x8F, 0xB5, 0xC9, 0xB0, 0x7C, 0x95, 0xD0, 0x6B, 0x5B, 0xF4, 0x94, 0xC5, 0x94, 0x9D, + 0xFA, 0x6F, 0x47, 0x3A, 0xA3, 0x86, 0xC0, 0xA8, 0x37, 0xF3, 0x9B, 0xEF, 0x2F, 0xC1, 0xFB, 0xB3, + 0xF4, 0x1C, 0x2B, 0x0E, 0xD3, 0x6D, 0x88, 0xBB, 0x02, 0xE0, 0x4E, 0x63, 0xFA, 0x76, 0xE3, 0x43, + 0xF9, 0x01, 0xFD, 0x23, 0x5E, 0x6A, 0x0B, 0x14, 0xEC, 0x5E, 0x91, 0x34, 0x0D, 0x0B, 0x4F, 0xA3, + 0x5A, 0x46, 0xC5, 0x5E, 0xDC, 0xB5, 0xCD, 0xC1, 0x47, 0x6B, 0x59, 0xCA, 0xFA, 0xA9, 0xBE, 0x24, + 0x9F, 0xF5, 0x05, 0x6B, 0xBB, 0x67, 0x8B, 0xB7, 0xE4, 0x3A, 0x43, 0x00, 0x5C, 0x1C, 0xB7, 0xCA, + 0x98, 0x90, 0x79, 0x77, 0x6D, 0x05, 0x4F, 0x83, 0xCC, 0xAC, 0x06, 0x2E, 0x50, 0x11, 0x87, 0x23, + 0xD8, 0xA6, 0xF7, 0x6F, 0x7A, 0x59, 0x87, 0xA6, 0xDE, 0x5D, 0xD8, 0xEC, 0x44, 0xBE, 0x45, 0x31, + 0x7F, 0x8A, 0xF0, 0x58, 0x89, 0x53, 0x74, 0xDF, 0xCC, 0xAD, 0x01, 0x24, 0xD8, 0x19, 0x65, 0x1C, + 0x25, 0xD3, 0xE1, 0x6B, 0x8B, 0xDA, 0xFE, 0x1D, 0xA4, 0x2C, 0x8B, 0x25, 0xED, 0x7C, 0xFF, 0x6A, + 0xE0, 0x63, 0xD0, 0x52, 0x20, 0x7E, 0x62, 0x49, 0xD2, 0xB3, 0x6B, 0xCC, 0x91, 0x69, 0xA5, 0x08, + 0x8B, 0x69, 0x65, 0xFF, 0xB9, 0xC9, 0x17, 0x02, 0x5D, 0xD8, 0x8E, 0x1A, 0x63, 0xD9, 0x2A, 0x7F, + 0xDB, 0xE3, 0xF8, 0x76, 0x6D, 0xEA, 0x0E, 0x36, 0x98, 0x78, 0x19, 0xC5, 0x87, 0xBA, 0x6C, 0x20, + 0xB6, 0x08, 0x44, 0x04, 0x4C, 0xA8, 0xD5, 0xB6, 0x9D, 0x4D, 0x00, 0x20, 0x40, 0x00, 0x90, 0x04 + }; + + // decrypt data (RSA-decrypt) + BIGNUM r, a, e, m; + BN_init(&r); + BN_init(&a); + BN_init(&e); + BN_init(&m); + my_BN_bin2bn(in, 256, &a); + my_BN_bin2bn(b_e, 4, &e); + my_BN_bin2bn(b_m, 256, &m); + BN_CTX *ctx = BN_CTX_new(); + BN_mod_exp(&r, &a, &e, &m, ctx); //FIXME: use RSA-decrypt + BN_CTX_free(ctx); + + uint8_t d_out[256] = {0}; + int len = my_BN_bn2bin(&r, d_out); + printf("len = %d\\n", len); + if (len < 0) + return len; + + // make data ordered + uint8_t *p = d_out; + memcpy(out+6, p, 1); p++; + memcpy(out+104, p, 1); p++; + memcpy(out+8, p, 1); p++; + memcpy(out+134, p, 2); p+=2; + memcpy(out+124, p, 1); p++; + memcpy(out+140, p, 2); p+=2; + memcpy(out+19, p, 1); p++; + memcpy(out+142, p, 2); p+=2; + memcpy(out+160, p, 2); p+=2; + memcpy(out+52, p, 1); p++; + memcpy(out, p, 1); p++; + memcpy(out+26, p, 1); p++; + memcpy(out+248, p, 1); p++; + memcpy(out+84, p, 1); p++; + memcpy(out+86, p, 1); p++; + memcpy(out+56, p, 1); p++; + memcpy(out+235, p, 1); p++; + memcpy(out+154, p, 2); p+=2; + memcpy(out+68, p, 1); p++; + memcpy(out+48, p, 1); p++; + memcpy(out+13, p, 1); p++; + memcpy(out+81, p, 1); p++; + memcpy(out+252, p, 2); p+=2; + memcpy(out+110, p, 1); p++; + memcpy(out+128, p, 1); p++; + memcpy(out+32, p, 1); p++; + memcpy(out+62, p, 1); p++; + memcpy(out+256, p, 4); p+=4; + memcpy(out+126, p, 1); p++; + memcpy(out+138, p, 2); p+=2; + memcpy(out+123, p, 1); p++; + memcpy(out+121, p, 1); p++; + memcpy(out+82, p, 1); p++; + memcpy(out+200, p, 4); p+=4; + memcpy(out+245, p, 1); p++; + memcpy(out+50, p, 1); p++; + memcpy(out+9, p, 1); p++; + memcpy(out+232, p, 1); p++; + memcpy(out+148, p, 2); p+=2; + memcpy(out+35, p, 1); p++; + memcpy(out+21, p, 1); p++; + memcpy(out+4, p, 1); p++; + memcpy(out+95, p, 1); p++; + memcpy(out+168, p, 4); p+=4; + memcpy(out+37, p, 1); p++; + memcpy(out+97, p, 1); p++; + memcpy(out+71, p, 1); p++; + memcpy(out+25, p, 1); p++; + memcpy(out+130, p, 2); p+=2; + memcpy(out+224, p, 4); p+=4; + memcpy(out+23, p, 1); p++; + memcpy(out+61, p, 1); p++; + memcpy(out+36, p, 1); p++; + memcpy(out+40, p, 1); p++; + memcpy(out+57, p, 1); p++; + memcpy(out+65, p, 1); p++; + memcpy(out+233, p, 1); p++; + memcpy(out+74, p, 1); p++; + memcpy(out+34, p, 1); p++; + memcpy(out+249, p, 1); p++; + memcpy(out+42, p, 1); p++; + memcpy(out+47, p, 1); p++; + memcpy(out+118, p, 1); p++; + memcpy(out+76, p, 1); p++; + memcpy(out+108, p, 1); p++; + memcpy(out+78, p, 1); p++; + memcpy(out+33, p, 1); p++; + memcpy(out+192, p, 4); p+=4; + memcpy(out+156, p, 2); p+=2; + memcpy(out+132, p, 2); p+=2; + memcpy(out+152, p, 2); p+=2; + memcpy(out+45, p, 1); p++; + memcpy(out+67, p, 1); p++; + memcpy(out+180, p, 4); p+=4; + memcpy(out+92, p, 1); p++; + memcpy(out+91, p, 1); p++; + memcpy(out+75, p, 1); p++; + memcpy(out+101, p, 1); p++; + memcpy(out+216, p, 4); p+=4; + memcpy(out+120, p, 1); p++; + memcpy(out+44, p, 1); p++; + memcpy(out+240, p, 1); p++; + memcpy(out+109, p, 1); p++; + memcpy(out+99, p, 1); p++; + memcpy(out+234, p, 1); p++; + memcpy(out+15, p, 1); p++; + memcpy(out+125, p, 1); p++; + memcpy(out+89, p, 1); p++; + memcpy(out+196, p, 4); p+=4; + memcpy(out+251, p, 1); p++; + memcpy(out+66, p, 1); p++; + memcpy(out+31, p, 1); p++; + memcpy(out+93, p, 1); p++; + memcpy(out+29, p, 1); p++; + memcpy(out+239, p, 1); p++; + memcpy(out+64, p, 1); p++; + memcpy(out+87, p, 1); p++; + memcpy(out+73, p, 1); p++; + memcpy(out+238, p, 1); p++; + memcpy(out+55, p, 1); p++; + memcpy(out+70, p, 1); p++; + memcpy(out+150, p, 2); p+=2; + memcpy(out+63, p, 1); p++; + memcpy(out+246, p, 1); p++; + memcpy(out+243, p, 1); p++; + memcpy(out+49, p, 1); p++; + memcpy(out+241, p, 1); p++; + memcpy(out+172, p, 4); p+=4; + memcpy(out+79, p, 1); p++; + memcpy(out+103, p, 1); p++; + memcpy(out+1, p, 1); p++; + memcpy(out+12, p, 1); p++; + memcpy(out+122, p, 1); p++; + memcpy(out+41, p, 1); p++; + memcpy(out+18, p, 1); p++; + memcpy(out+106, p, 1); p++; + memcpy(out+46, p, 1); p++; + memcpy(out+22, p, 1); p++; + memcpy(out+208, p, 4); p+=4; + memcpy(out+102, p, 1); p++; + memcpy(out+30, p, 1); p++; + memcpy(out+54, p, 1); p++; + memcpy(out+247, p, 1); p++; + memcpy(out+77, p, 1); p++; + memcpy(out+228, p, 4); p+=4; + memcpy(out+85, p, 1); p++; + memcpy(out+100, p, 1); p++; + memcpy(out+146, p, 2); p+=2; + memcpy(out+111, p, 1); p++; + memcpy(out+11, p, 1); p++; + memcpy(out+43, p, 1); p++; + memcpy(out+242, p, 1); p++; + memcpy(out+94, p, 1); p++; + memcpy(out+14, p, 1); p++; + memcpy(out+90, p, 1); p++; + memcpy(out+28, p, 1); p++; + memcpy(out+53, p, 1); p++; + memcpy(out+72, p, 1); p++; + memcpy(out+98, p, 1); p++; + memcpy(out+114, p, 1); p++; + memcpy(out+127, p, 1); p++; + memcpy(out+236, p, 1); p++; + memcpy(out+204, p, 4); p+=4; + memcpy(out+59, p, 1); p++; + memcpy(out+212, p, 4); p+=4; + memcpy(out+184, p, 4); p+=4; + memcpy(out+60, p, 1); p++; + memcpy(out+17, p, 1); p++; + memcpy(out+113, p, 1); p++; + memcpy(out+105, p, 1); p++; + memcpy(out+107, p, 1); p++; + memcpy(out+5, p, 1); p++; + memcpy(out+83, p, 1); p++; + memcpy(out+27, p, 1); p++; + memcpy(out+96, p, 1); p++; + memcpy(out+164, p, 4); p+=4; + memcpy(out+24, p, 1); p++; + memcpy(out+158, p, 2); p+=2; + memcpy(out+119, p, 1); p++; + memcpy(out+250, p, 1); p++; + memcpy(out+58, p, 1); p++; + memcpy(out+88, p, 1); p++; + memcpy(out+10, p, 1); p++; + memcpy(out+7, p, 1); p++; + memcpy(out+20, p, 1); p++; + memcpy(out+51, p, 1); p++; + memcpy(out+3, p, 1); p++; + memcpy(out+144, p, 2); p+=2; + memcpy(out+188, p, 4); p+=4; + memcpy(out+16, p, 1); p++; + memcpy(out+136, p, 2); p+=2; + memcpy(out+116, p, 1); p++; + memcpy(out+39, p, 1); p++; + memcpy(out+38, p, 1); p++; + memcpy(out+237, p, 1); p++; + memcpy(out+2, p, 1); p++; + memcpy(out+69, p, 1); p++; + memcpy(out+220, p, 4); p+=4; + memcpy(out+115, p, 1); p++; + memcpy(out+117, p, 1); p++; + memcpy(out+112, p, 1); p++; + memcpy(out+176, p, 4); p+=4; + memcpy(out+80, p, 1); p++; + memcpy(out+244, p, 1); p++; + + // verify data + if (*(uint32_t*)(out+256) != 0x77177AB3) + return -1; + + return len; +} + void decryptCallback(uint8_t s2c, uint64_t time, uint16_t opcode, uint8_t *data, uint32_t data_len, void *db) { insertPacket(s2c, time, opcode, data, data_len, db); @@ -397,16 +655,24 @@ void decryptCallback(uint8_t s2c, uint64_t time, uint16_t opcode, uint8_t *data, switch(opcode) { // forwarding connection - case 1293: + case 0x9000:// 0x8400(4.0.1) //SMSG_REDIRECT_CLIENT //1293: { - const uint32_t expected_size = 4+2+4+20; + const uint32_t expected_size = 1+256+4+8; //4+2+4+20; if(data_len != expected_size) { - printf("WARNING: packet 1293 is %u bytes long, but we expected %u\\n", data_len, expected_size); + printf("WARNING: packet SMSG_REDIRECT_CLIENT is %u bytes long, but we expected %u\\n", data_len, expected_size); return; } - uint32_t fwd_addr = *(data)<<24 | *(data+1)<<16 | *(data+2) << 8 | *(data+3); - uint16_t fwd_port = ntohs(*((uint16_t*)(data+4))); + uint8_t ordered_data[256] = {0}; + if (parse_SMSG_REDIRECT_CLIENT(data+1, ordered_data) < 0) + { + printf("WARNING: decrypt/parse packet SMSG_REDIRECT_CLIENT fail\\n"); + break; + } + //uint32_t fwd_addr = *(data)<<24 | *(data+1)<<16 | *(data+2) << 8 | *(data+3); + //uint16_t fwd_port = ntohs(*((uint16_t*)(data+4))); + uint32_t fwd_addr = ntohl(*((uint32_t*)(ordered_data+164))); + uint16_t fwd_port = ntohs(*((uint16_t*)(ordered_data+252))); // find the connection for(uint32_t i=0; i<connection_count; ++i) { @@ -416,6 +682,7 @@ void decryptCallback(uint8_t s2c, uint64_t time, uint16_t opcode, uint8_t *data, { printf("Set connection forwarding bit on %s:%u\\n", addrToStr(fwd_addr), ntohs(fwd_port)); connection->forwarded = 1; + currentDecryptedConnection->forwarded = 2; return; } } @@ -427,6 +694,7 @@ void decryptCallback(uint8_t s2c, uint64_t time, uint16_t opcode, uint8_t *data, void decrypt() { + sqlite3 *db=NULL; for(uint32_t i=0; i<connection_count; ++i) { struct tcp_connection *connection = connections[i]; @@ -442,8 +710,8 @@ void decrypt() struct tm* timestruct = localtime(&time); strftime (filename, sizeof(filename), format, timestruct); - sqlite3 *db=NULL; - initDatabase(filename, &db); + if(!merge_files || (merge_files && !connection->forwarded)) + initDatabase(filename, &db); struct decryption_state client_state, server_state; uint8_t custom_serverseed[16]; @@ -451,11 +719,11 @@ void decrypt() if(connection->forwarded) { - const uint32_t expected_size = 2+2*4+2*16; + const uint32_t expected_size = 2+4+1+2*16;//2+2*4+2*16; uint8_t* data = connection->to.data.buffer; uint32_t size = data[0]<<8 | data[1]; uint32_t opcode = data[3]<<8 | data[2]; - if(opcode != 492) + if(opcode != 0x3400) // 8500(4.0.1) //SMSG_AUTH_CHALLENGE //492) { printf("WARNING: first packet in stream is not 492 but %u\\n", opcode); continue; @@ -465,12 +733,22 @@ void decrypt() printf("WARNING: packet 492 is %u bytes long, but we expected %u\\n", size, expected_size); continue; } - memcpy(custom_serverseed, data+4+2*4, 16); - memcpy(custom_clientseed, data+4+2*4+16, 16); + //memcpy(custom_serverseed, data+4+2*4, 16); + //memcpy(custom_clientseed, data+4+2*4+16, 16); + memcpy(custom_serverseed+0*4, data+4+3*4, 4); + memcpy(custom_serverseed+1*4, data+4+6*4+1, 4); + memcpy(custom_serverseed+2*4, data+4+8*4+1, 4); + memcpy(custom_serverseed+3*4, data+4+5*4+1, 4); + memcpy(custom_clientseed+0*4, data+4+0*4, 4); + memcpy(custom_clientseed+1*4, data+4+7*4+1, 4); + memcpy(custom_clientseed+2*4, data+4+4*4+1, 4); + memcpy(custom_clientseed+3*4, data+4+1*4, 4); printf("Using custom seeds for forwarded connection\\n"); init_decryption_state_server(&server_state, SESSIONKEY, custom_serverseed); init_decryption_state_client(&client_state, SESSIONKEY, custom_clientseed); + + connection->forwarded = 0; } else { @@ -514,7 +792,8 @@ void decrypt() } update_decryption(nextState, participant->timeinfo.info[ti_counter].epoch_micro, data, datalen, db, decryptCallback); } - freeDatabase(&db); + if(!merge_files || (merge_files && !connection->forwarded)) + freeDatabase(&db); free_decryption_state(&server_state); free_decryption_state(&client_state); @@ -524,20 +803,28 @@ void decrypt() int main(int argc, char *argv[]) { - if(argc != 3) + if(argc < 3) { - printf("Usage: %s $dumpfile.cap $keyfile.txt\\n", argv[0]); + printf("Usage: %s [-m] $dumpfile.cap $keyfile.txt\\n", argv[0]); + printf(" [-m] merge output files\\n"); return 1; } char* pcapFile = argv[1]; char* keyFile = argv[2]; + if (!strcmp(argv[1], "-m")) + { + merge_files = 1; + pcapFile = argv[2]; + keyFile = argv[3]; + } // maybe switched arguments? char* magicKeyfileEnd = "txt"; if(strlen(keyFile) >= 3 && memcmp(keyFile+strlen(keyFile)-3, magicKeyfileEnd, 3)) { - pcapFile = argv[2]; - keyFile = argv[1]; + char *temp = pcapFile; + pcapFile = keyFile; + keyFile = temp; } readSessionkeyFile(keyFile); diff --git a/src/decrypter/sqliteout.c b/src/decrypter/sqliteout.c old mode 100644 new mode 100755 index cc75c05..2fcd4f4 --- a/src/decrypter/sqliteout.c +++ b/src/decrypter/sqliteout.c @@ -47,7 +47,8 @@ void insertClientBuild(uint8_t *data, uint32_t data_len, sqlite3 *db) printf("FATAL: got a packet with opcode = 493 = CMSG_AUTH_SESSION but payload len=%u < 4\\n", data_len); exit(1); } - uint32_t *clientBuild = (uint32_t*)data; + //uint32_t *clientBuild = (uint32_t*)data; + uint16_t *clientBuild = (uint16_t*)(data+2*1); const char* insertFormat = "insert into header values ('clientBuild', %u)"; uint32_t allocSize = strlen(insertFormat)+10 /*uint32*/; @@ -60,6 +61,19 @@ void insertClientBuild(uint8_t *data, uint32_t data_len, sqlite3 *db) sprintf(buffer, insertFormat, *clientBuild); executeSql(db, buffer); free(buffer); + + // make sniffitzt happy + char sql[512]; + sprintf(sql, "insert into header values ('clientLang', '%s')", ""); + executeSql(db, sql); + sprintf(sql, "insert into header values ('accountName', '%s')", (char*)(data+22*1+1*2+1*8+5*4)); + executeSql(db, sql); + sprintf(sql, "insert into header values ('realmName', '%s')", ""); + executeSql(db, sql); + sprintf(sql, "insert into header values ('realmServer', '%s')", ""); + executeSql(db, sql); + sprintf(sql, "insert into header values ('snifferVersion', '%s')", ""); + executeSql(db, sql); } void insertPacket(uint8_t s2c, uint64_t time, uint16_t opcode, uint8_t *data, uint32_t data_len, void* arg) @@ -83,7 +97,7 @@ void insertPacket(uint8_t s2c, uint64_t time, uint16_t opcode, uint8_t *data, ui free(queryBuffer); - if(opcode == 493) + if(opcode == 0x880a) // 0x3000(4.0.1) //CMSG_AUTH_SESSION //493(3.3.5)) insertClientBuild(data, data_len, db); } Patch for 4.0.1 (already in git cata branch) BTW: SMSG_AUTH_CHALLENGE = 0x8500 (4.0.1) { uint32 ClientKey_part3; uint32 ServerKey_part1; uint8 unk; uint32 Seed; uint32 ServerKey_part3; uint32 ServerKey_part2; uint32 ClientKey_part1; uint32 ClientKey_part2; uint32 ServerKey_part4; uint32 ClientKey_part4; } patch for reader 4.0.1: diff --git a/src/reader/reader.bat b/src/reader/reader.bat index 7f8177e..58b125e --- a/src/reader/reader.bat +++ b/src/reader/reader.bat @@ -1,5 +1,6 @@ @echo off -echo "Tiawps sessionkey reader Build 12340 3.3.5" +rem echo "Tiawps sessionkey reader Build 12340 3.3.5" +echo "Tiawps sessionkey reader Build 13205 4.0.1" SET PATH=%~dp0 REM Switch to drive @@ -7,5 +8,7 @@ REM Switch to drive cd %PATH% -tiawps_reader.exe 13081844 1288 +rem tiawps_reader.exe 13081844 1288 +rem CONNECTION_PTR_OFFSET = 0xCA5C34 +tiawps_reader.exe 13261876 1288 PAUSE patch for decrypter 4.0.1: diff --git a/src/decrypter/main.c b/src/decrypter/main.c old mode 100644 new mode 100755 index 228a7bc..b59e0e7 --- a/src/decrypter/main.c +++ b/src/decrypter/main.c @@ -4,6 +4,8 @@ #include <time.h> #include <ctype.h> #include <sqlite3.h> +#include <openssl/bn.h> +//#include <openssl/rsa.h> #include "pcapreader.h" #include "structs.h" @@ -13,10 +15,13 @@ #define DEBUG 0 // SIZE SIZE CMD CMD -const uint8_t MAGIC_WOW_START[] = {0x00, 0x2A, 0xEC, 0x01}; +//const uint8_t MAGIC_WOW_START[] = {0x00, 0x2A, 0xEC, 0x01}; +const uint8_t MAGIC_WOW_START[] = {0x00, 0x27, 0x00, 0x85}; static uint8_t SESSIONKEY[sESSION_KEY_LENGTH]; +static int merge_files = 0; + void readSessionkeyFile(const char* file) { FILE *fp = fopen(file, "r"); @@ -385,6 +390,257 @@ void removeInvalidConnections() struct tcp_connection *currentDecryptedConnection; +static BIGNUM *my_BN_bin2bn(const uint8_t *s, int len, BIGNUM *ret) +{ + uint8_t tmp[1024] = {0}; + for (int i = 0; i < len; i++) + tmp[i] = s[len-1-i]; + return BN_bin2bn(tmp, len, ret); +} + +static int my_BN_bn2bin(const BIGNUM *a, unsigned char *to) +{ + uint8_t tmp[1024] = {0}; + int len = BN_bn2bin(a, tmp); + for (int i = 0; i < len; i++) + to[i] = tmp[len-1-i]; + return len; +} + +static int parse_SMSG_REDIRECT_CLIENT(const uint8_t *in, uint8_t *out) +{ + uint8_t b_e[] = { 0x01, 0x00, 0x01, 0x00 }; // private-key exp + uint8_t b_m[] = { // modulus + 0x91, 0xD5, 0x9B, 0xB7, 0xD4, 0xE1, 0x83, 0xA5, 0x22, 0x2B, 0x5F, 0x38, 0xF4, 0xB8, 0x86, 0xFF, + 0x32, 0x84, 0x38, 0x2D, 0x99, 0x38, 0x8F, 0xBA, 0xF3, 0xC9, 0x22, 0x5D, 0x51, 0x73, 0x1E, 0x28, + 0x87, 0x24, 0x8F, 0xB5, 0xC9, 0xB0, 0x7C, 0x95, 0xD0, 0x6B, 0x5B, 0xF4, 0x94, 0xC5, 0x94, 0x9D, + 0xFA, 0x6F, 0x47, 0x3A, 0xA3, 0x86, 0xC0, 0xA8, 0x37, 0xF3, 0x9B, 0xEF, 0x2F, 0xC1, 0xFB, 0xB3, + 0xF4, 0x1C, 0x2B, 0x0E, 0xD3, 0x6D, 0x88, 0xBB, 0x02, 0xE0, 0x4E, 0x63, 0xFA, 0x76, 0xE3, 0x43, + 0xF9, 0x01, 0xFD, 0x23, 0x5E, 0x6A, 0x0B, 0x14, 0xEC, 0x5E, 0x91, 0x34, 0x0D, 0x0B, 0x4F, 0xA3, + 0x5A, 0x46, 0xC5, 0x5E, 0xDC, 0xB5, 0xCD, 0xC1, 0x47, 0x6B, 0x59, 0xCA, 0xFA, 0xA9, 0xBE, 0x24, + 0x9F, 0xF5, 0x05, 0x6B, 0xBB, 0x67, 0x8B, 0xB7, 0xE4, 0x3A, 0x43, 0x00, 0x5C, 0x1C, 0xB7, 0xCA, + 0x98, 0x90, 0x79, 0x77, 0x6D, 0x05, 0x4F, 0x83, 0xCC, 0xAC, 0x06, 0x2E, 0x50, 0x11, 0x87, 0x23, + 0xD8, 0xA6, 0xF7, 0x6F, 0x7A, 0x59, 0x87, 0xA6, 0xDE, 0x5D, 0xD8, 0xEC, 0x44, 0xBE, 0x45, 0x31, + 0x7F, 0x8A, 0xF0, 0x58, 0x89, 0x53, 0x74, 0xDF, 0xCC, 0xAD, 0x01, 0x24, 0xD8, 0x19, 0x65, 0x1C, + 0x25, 0xD3, 0xE1, 0x6B, 0x8B, 0xDA, 0xFE, 0x1D, 0xA4, 0x2C, 0x8B, 0x25, 0xED, 0x7C, 0xFF, 0x6A, + 0xE0, 0x63, 0xD0, 0x52, 0x20, 0x7E, 0x62, 0x49, 0xD2, 0xB3, 0x6B, 0xCC, 0x91, 0x69, 0xA5, 0x08, + 0x8B, 0x69, 0x65, 0xFF, 0xB9, 0xC9, 0x17, 0x02, 0x5D, 0xD8, 0x8E, 0x1A, 0x63, 0xD9, 0x2A, 0x7F, + 0xDB, 0xE3, 0xF8, 0x76, 0x6D, 0xEA, 0x0E, 0x36, 0x98, 0x78, 0x19, 0xC5, 0x87, 0xBA, 0x6C, 0x20, + 0xB6, 0x08, 0x44, 0x04, 0x4C, 0xA8, 0xD5, 0xB6, 0x9D, 0x4D, 0x00, 0x20, 0x40, 0x00, 0x90, 0x04 + }; + + // decrypt data (RSA-decrypt) + BIGNUM r, a, e, m; + BN_init(&r); + BN_init(&a); + BN_init(&e); + BN_init(&m); + my_BN_bin2bn(in, 256, &a); + my_BN_bin2bn(b_e, 4, &e); + my_BN_bin2bn(b_m, 256, &m); + BN_CTX *ctx = BN_CTX_new(); + BN_mod_exp(&r, &a, &e, &m, ctx); //FIXME: use RSA-decrypt + BN_CTX_free(ctx); + + uint8_t d_out[256] = {0}; + int len = my_BN_bn2bin(&r, d_out); + if (len < 0) + return len; + + // make data ordered + uint8_t *p = d_out; + memcpy(out+89, p, 1); p++; + memcpy(out+94, p, 1); p++; + memcpy(out+151, p, 1); p++; + memcpy(out+159, p, 1); p++; + memcpy(out+155, p, 1); p++; + memcpy(out+118, p, 1); p++; + memcpy(out+46, p, 2); p+=2; + memcpy(out+129, p, 1); p++; + memcpy(out+127, p, 1); p++; + memcpy(out+44, p, 2); p+=2; + memcpy(out+32, p, 2); p+=2; + memcpy(out+157, p, 1); p++; + memcpy(out+164, p, 1); p++; + memcpy(out+134, p, 1); p++; + memcpy(out+124, p, 1); p++; + memcpy(out+83, p, 1); p++; + memcpy(out+122, p, 1); p++; + memcpy(out+96, p, 1); p++; + memcpy(out+71, p, 1); p++; + memcpy(out+50, p, 2); p+=2; + memcpy(out+17, p, 1); p++; + memcpy(out+4, p, 1); p++; + memcpy(out+132, p, 1); p++; + memcpy(out+112, p, 1); p++; + memcpy(out+156, p, 1); p++; + memcpy(out+220, p, 4); p+=4; + memcpy(out+59, p, 1); p++; + memcpy(out+72, p, 1); p++; + memcpy(out+130, p, 1); p++; + memcpy(out+182, p, 1); p++; + memcpy(out+154, p, 1); p++; + memcpy(out+138, p, 1); p++; + memcpy(out+61, p, 1); p++; + memcpy(out+166, p, 1); p++; + memcpy(out+139, p, 1); p++; + memcpy(out+186, p, 1); p++; + memcpy(out+10, p, 1); p++; + memcpy(out+137, p, 1); p++; + memcpy(out+68, p, 1); p++; + memcpy(out+36, p, 2); p+=2; + memcpy(out+115, p, 1); p++; + memcpy(out+87, p, 1); p++; + memcpy(out+175, p, 1); p++; + memcpy(out+172, p, 1); p++; + memcpy(out+252, p, 4); p+=4; + memcpy(out+16, p, 1); p++; + memcpy(out+88, p, 1); p++; + memcpy(out+248, p, 4); p+=4; + memcpy(out+180, p, 1); p++; + memcpy(out+18, p, 1); p++; + memcpy(out+78, p, 1); p++; + memcpy(out+11, p, 1); p++; + memcpy(out+24, p, 2); p+=2; + memcpy(out+162, p, 1); p++; + memcpy(out+204, p, 4); p+=4; + memcpy(out+54, p, 2); p+=2; + memcpy(out+125, p, 1); p++; + memcpy(out+98, p, 1); p++; + memcpy(out+102, p, 1); p++; + memcpy(out+114, p, 1); p++; + memcpy(out+216, p, 4); p+=4; + memcpy(out+20, p, 1); p++; + memcpy(out+136, p, 1); p++; + memcpy(out+116, p, 1); p++; + memcpy(out+185, p, 1); p++; + memcpy(out+224, p, 4); p+=4; + memcpy(out+146, p, 1); p++; + memcpy(out+109, p, 1); p++; + memcpy(out+106, p, 1); p++; + memcpy(out+244, p, 4); p+=4; + memcpy(out+135, p, 1); p++; + memcpy(out+62, p, 1); p++; + memcpy(out+60, p, 1); p++; + memcpy(out+84, p, 1); p++; + memcpy(out+91, p, 1); p++; + memcpy(out+48, p, 2); p+=2; + memcpy(out+144, p, 1); p++; + memcpy(out+108, p, 1); p++; + memcpy(out+63, p, 1); p++; + memcpy(out+121, p, 1); p++; + memcpy(out+145, p, 1); p++; + memcpy(out+19, p, 1); p++; + memcpy(out+13, p, 1); p++; + memcpy(out+12, p, 1); p++; + memcpy(out+52, p, 2); p+=2; + memcpy(out+6, p, 1); p++; + memcpy(out+74, p, 1); p++; + memcpy(out+176, p, 1); p++; + memcpy(out+69, p, 1); p++; + memcpy(out+5, p, 1); p++; + memcpy(out+99, p, 1); p++; + memcpy(out+97, p, 1); p++; + memcpy(out+14, p, 1); p++; + memcpy(out+140, p, 1); p++; + memcpy(out+177, p, 1); p++; + memcpy(out+149, p, 1); p++; + memcpy(out+101, p, 1); p++; + memcpy(out+107, p, 1); p++; + memcpy(out+228, p, 4); p+=4; + memcpy(out+82, p, 1); p++; + memcpy(out+184, p, 1); p++; + memcpy(out+119, p, 1); p++; + memcpy(out+158, p, 1); p++; + memcpy(out+143, p, 1); p++; + memcpy(out+196, p, 4); p+=4; + memcpy(out+86, p, 1); p++; + memcpy(out+38, p, 2); p+=2; + memcpy(out+142, p, 1); p++; + memcpy(out+240, p, 4); p+=4; + memcpy(out+104, p, 1); p++; + memcpy(out+77, p, 1); p++; + memcpy(out+168, p, 1); p++; + memcpy(out+150, p, 1); p++; + memcpy(out+9, p, 1); p++; + memcpy(out+22, p, 1); p++; + memcpy(out+7, p, 1); p++; + memcpy(out+95, p, 1); p++; + memcpy(out+110, p, 1); p++; + memcpy(out+34, p, 2); p+=2; + memcpy(out+161, p, 1); p++; + memcpy(out+117, p, 1); p++; + memcpy(out+141, p, 1); p++; + memcpy(out+111, p, 1); p++; + memcpy(out+212, p, 4); p+=4; + memcpy(out+179, p, 1); p++; + memcpy(out+200, p, 4); p+=4; + memcpy(out+147, p, 1); p++; + memcpy(out+66, p, 1); p++; + memcpy(out+70, p, 1); p++; + memcpy(out+67, p, 1); p++; + memcpy(out+100, p, 1); p++; + memcpy(out+128, p, 1); p++; + memcpy(out+133, p, 1); p++; + memcpy(out+28, p, 2); p+=2; + memcpy(out+15, p, 1); p++; + memcpy(out+188, p, 4); p+=4; + memcpy(out, p, 4); p+=4; + memcpy(out+165, p, 1); p++; + memcpy(out+169, p, 1); p++; + memcpy(out+76, p, 1); p++; + memcpy(out+65, p, 1); p++; + memcpy(out+163, p, 1); p++; + memcpy(out+85, p, 1); p++; + memcpy(out+148, p, 1); p++; + memcpy(out+23, p, 1); p++; + memcpy(out+208, p, 4); p+=4; + memcpy(out+183, p, 1); p++; + memcpy(out+56, p, 2); p+=2; + memcpy(out+73, p, 1); p++; + memcpy(out+21, p, 1); p++; + memcpy(out+120, p, 1); p++; + memcpy(out+152, p, 1); p++; + memcpy(out+113, p, 1); p++; + memcpy(out+232, p, 4); p+=4; + memcpy(out+170, p, 1); p++; + memcpy(out+64, p, 1); p++; + memcpy(out+81, p, 1); p++; + memcpy(out+80, p, 1); p++; + memcpy(out+123, p, 1); p++; + memcpy(out+8, p, 1); p++; + memcpy(out+79, p, 1); p++; + memcpy(out+26, p, 2); p+=2; + memcpy(out+236, p, 4); p+=4; + memcpy(out+92, p, 1); p++; + memcpy(out+30, p, 2); p+=2; + memcpy(out+42, p, 2); p+=2; + memcpy(out+174, p, 1); p++; + memcpy(out+131, p, 1); p++; + memcpy(out+75, p, 1); p++; + memcpy(out+93, p, 1); p++; + memcpy(out+40, p, 2); p+=2; + memcpy(out+167, p, 1); p++; + memcpy(out+171, p, 1); p++; + memcpy(out+173, p, 1); p++; + memcpy(out+160, p, 1); p++; + memcpy(out+105, p, 1); p++; + memcpy(out+178, p, 1); p++; + memcpy(out+103, p, 1); p++; + memcpy(out+192, p, 4); p+=4; + memcpy(out+58, p, 1); p++; + memcpy(out+90, p, 1); p++; + memcpy(out+126, p, 1); p++; + memcpy(out+181, p, 1); p++; + memcpy(out+153, p, 1); p++; + + // verify data + if (*(uint32_t*)out != 0x77177AB3) + return -1; + + return len; +} + void decryptCallback(uint8_t s2c, uint64_t time, uint16_t opcode, uint8_t *data, uint32_t data_len, void *db) { insertPacket(s2c, time, opcode, data, data_len, db); @@ -397,16 +653,24 @@ void decryptCallback(uint8_t s2c, uint64_t time, uint16_t opcode, uint8_t *data, switch(opcode) { // forwarding connection - case 1293: + case 0x8400: //SMSG_REDIRECT_CLIENT //1293: { - const uint32_t expected_size = 4+2+4+20; + const uint32_t expected_size = 4+256+1; //4+2+4+20; if(data_len != expected_size) { printf("WARNING: packet 1293 is %u bytes long, but we expected %u\\n", data_len, expected_size); return; } - uint32_t fwd_addr = *(data)<<24 | *(data+1)<<16 | *(data+2) << 8 | *(data+3); - uint16_t fwd_port = ntohs(*((uint16_t*)(data+4))); + uint8_t ordered_data[256] = {0}; + if (parse_SMSG_REDIRECT_CLIENT(data+4, ordered_data) < 0) + { + printf("WARNING: decrypt/parse packet SMSG_REDIRECT_CLIENT fail\\n"); + break; + } + //uint32_t fwd_addr = *(data)<<24 | *(data+1)<<16 | *(data+2) << 8 | *(data+3); + //uint16_t fwd_port = ntohs(*((uint16_t*)(data+4))); + uint32_t fwd_addr = ntohl(*((uint32_t*)(ordered_data+252))); + uint16_t fwd_port = ntohs(*((uint16_t*)(ordered_data+24))); // find the connection for(uint32_t i=0; i<connection_count; ++i) { @@ -416,6 +680,7 @@ void decryptCallback(uint8_t s2c, uint64_t time, uint16_t opcode, uint8_t *data, { printf("Set connection forwarding bit on %s:%u\\n", addrToStr(fwd_addr), ntohs(fwd_port)); connection->forwarded = 1; + currentDecryptedConnection->forwarded = 2; return; } } @@ -427,6 +692,7 @@ void decryptCallback(uint8_t s2c, uint64_t time, uint16_t opcode, uint8_t *data, void decrypt() { + sqlite3 *db=NULL; for(uint32_t i=0; i<connection_count; ++i) { struct tcp_connection *connection = connections[i]; @@ -442,8 +708,8 @@ void decrypt() struct tm* timestruct = localtime(&time); strftime (filename, sizeof(filename), format, timestruct); - sqlite3 *db=NULL; - initDatabase(filename, &db); + if(!merge_files || (merge_files && !connection->forwarded)) + initDatabase(filename, &db); struct decryption_state client_state, server_state; uint8_t custom_serverseed[16]; @@ -451,11 +717,11 @@ void decrypt() if(connection->forwarded) { - const uint32_t expected_size = 2+2*4+2*16; + const uint32_t expected_size = 2+4+1+2*16;//2+2*4+2*16; uint8_t* data = connection->to.data.buffer; uint32_t size = data[0]<<8 | data[1]; uint32_t opcode = data[3]<<8 | data[2]; - if(opcode != 492) + if(opcode != 0x8500) //SMSG_AUTH_CHALLENGE //492) { printf("WARNING: first packet in stream is not 492 but %u\\n", opcode); continue; @@ -465,12 +731,22 @@ void decrypt() printf("WARNING: packet 492 is %u bytes long, but we expected %u\\n", size, expected_size); continue; } - memcpy(custom_serverseed, data+4+2*4, 16); - memcpy(custom_clientseed, data+4+2*4+16, 16); + //memcpy(custom_serverseed, data+4+2*4, 16); + //memcpy(custom_clientseed, data+4+2*4+16, 16); + memcpy(custom_serverseed+0*4, data+4+1*4, 4); + memcpy(custom_serverseed+1*4, data+4+4*4+1, 4); + memcpy(custom_serverseed+2*4, data+4+3*4+1, 4); + memcpy(custom_serverseed+3*4, data+4+7*4+1, 4); + memcpy(custom_clientseed+0*4, data+4+5*4+1, 4); + memcpy(custom_clientseed+1*4, data+4+6*4+1, 4); + memcpy(custom_clientseed+2*4, data+4+0*4, 4); + memcpy(custom_clientseed+3*4, data+4+8*4+1, 4); printf("Using custom seeds for forwarded connection\\n"); init_decryption_state_server(&server_state, SESSIONKEY, custom_serverseed); init_decryption_state_client(&client_state, SESSIONKEY, custom_clientseed); + + connection->forwarded = 0; } else { @@ -514,7 +790,8 @@ void decrypt() } update_decryption(nextState, participant->timeinfo.info[ti_counter].epoch_micro, data, datalen, db, decryptCallback); } - freeDatabase(&db); + if(!merge_files || (merge_files && !connection->forwarded)) + freeDatabase(&db); free_decryption_state(&server_state); free_decryption_state(&client_state); @@ -524,20 +801,28 @@ void decrypt() int main(int argc, char *argv[]) { - if(argc != 3) + if(argc < 3) { - printf("Usage: %s $dumpfile.cap $keyfile.txt\\n", argv[0]); + printf("Usage: %s [-m] $dumpfile.cap $keyfile.txt\\n", argv[0]); + printf(" [-m] merge output files\\n"); return 1; } char* pcapFile = argv[1]; char* keyFile = argv[2]; + if (!strcmp(argv[1], "-m")) + { + merge_files = 1; + pcapFile = argv[2]; + keyFile = argv[3]; + } // maybe switched arguments? char* magicKeyfileEnd = "txt"; if(strlen(keyFile) >= 3 && memcmp(keyFile+strlen(keyFile)-3, magicKeyfileEnd, 3)) { - pcapFile = argv[2]; - keyFile = argv[1]; + char *temp = pcapFile; + pcapFile = keyFile; + keyFile = temp; } readSessionkeyFile(keyFile); diff --git a/src/decrypter/sqliteout.c b/src/decrypter/sqliteout.c index cc75c05..3a67983 100644 --- a/src/decrypter/sqliteout.c +++ b/src/decrypter/sqliteout.c @@ -60,6 +60,19 @@ void insertClientBuild(uint8_t *data, uint32_t data_len, sqlite3 *db) sprintf(buffer, insertFormat, *clientBuild); executeSql(db, buffer); free(buffer); + + //FIXME make sniffitzt happy + char sql[512]; + sprintf(sql, "insert into header values ('clientLang', '%s')", ""); + executeSql(db, sql); + sprintf(sql, "insert into header values ('accountName', '%s')", (char*)(data+8));//FIXME + executeSql(db, sql); + sprintf(sql, "insert into header values ('realmName', '%s')", ""); + executeSql(db, sql); + sprintf(sql, "insert into header values ('realmServer', '%s')", ""); + executeSql(db, sql); + sprintf(sql, "insert into header values ('snifferVersion', '%s')", ""); + executeSql(db, sql); } void insertPacket(uint8_t s2c, uint64_t time, uint16_t opcode, uint8_t *data, uint32_t data_len, void* arg) @@ -83,7 +96,7 @@ void insertPacket(uint8_t s2c, uint64_t time, uint16_t opcode, uint8_t *data, ui free(queryBuffer); - if(opcode == 493) + if(opcode == 0x3000) //CMSG_AUTH_SESSION //493) insertClientBuild(data, data_len, db); }
  3. Hi, any problem with this patch? It's such a big typo...
  4. * What bug does the patch fix? What features does the patch add? Server crashes on Linux at startup since 9170 * For which repository revision was the patch created? [9174] * Is there a thread in the bug report section or at lighthouse? If yes, please add a link to the thread. no. * Who has been writing this patch? Please include either forum user names or email addresses. daveh Patch: diff --git a/src/game/DBCStores.cpp b/src/game/DBCStores.cpp index ce4d88c..8923d99 100644 --- a/src/game/DBCStores.cpp +++ b/src/game/DBCStores.cpp @@ -186,7 +186,6 @@ static bool ReadDBCBuildFileText(const std::string& dbc_path, char const* locale { char buf[100]; fread(buf,1,100-1,file); - fclose(file); text = &buf[0]; fclose(file);
  5. * What bug does the patch fix? What features does the patch add? Hunter/Warlock summon a hunter/summon pet first, then can't summon a mini pet. * For which repository revision was the patch created? [9162] * Is there a thread in the bug report section or at lighthouse? If yes, please add a link to the thread. No * Who has been writing this patch? Please include either forum user names or email addresses. daveh Patch: diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index b082a09..318c4ee 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -4759,6 +4759,8 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_ALREADY_HAVE_CHARM; } } + + break; } // Not used for summon? case SPELL_EFFECT_SUMMON_PHANTASM:
  6. Just found SMSG_SPELL_START and SMSG_SPELL_GO send unknown spell ID (not in Spell.dbc) in a offi server, while doing quest As the Crow Flies by using item Stormcrow Amulet: 1. When using item Stormcrow Amulet, it casts spell Stormcrow Amulet: 2. After sending spell Stormcrow Amulet, offi server sends some unknown spell IDs: How does this mean?
  7. Confirmed, mostly crash when player has pet and change map.
  8. Thanks. It confused sniffitzt btw...
  9. You sure the cache data is from offi server? And it's clean? I don't see level 0 in my clean WDB cache, they all are -1. And a quick search in wowhead.com show no level 0 quests: http://www.wowhead.com/?quests&filter=minle=0;maxle=0
  10. Didn't see "heal 0, overheal 698" in 3.1.3. 3.1.3 didn't send full overheal log to client, but 3.2.2a does. Sending full overheal log every 5s is really noisily, consider as a new 3.2.x blizz bug. So this problem is clear: mangos doesn't send overheal log to client for SPELL_AURA_OBS_MOD_HEALTH/SPELL_AURA_PERIODIC_HEAL. Anyway, the updated blizzlike patch: diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 2cf57a8..18179ea 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -6499,11 +6571,11 @@ void Aura::PeriodicTick() sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, 0, 0, 0.0f, isCrit); - m_target->SendPeriodicAuraLog(&pInfo); - int32 gain = m_target->ModifyHealth(pdamage); + SpellPeriodicAuraLogInfo pInfo(this, pdamage, pdamage-gain, 0, 0, 0.0f, isCrit); + m_target->SendPeriodicAuraLog(&pInfo); + // add HoTs to amount healed in bgs if( pCaster->GetTypeId() == TYPEID_PLAYER ) if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() )
  11. I see, the last 2 lines mean heal 0 point? And which version? But I don't see these logs in a 3.1.3 offi server, I'll confirm that again. Thank you:)
  12. Just found HIGHGUID_PLAYER is 0x0A00 in an offi server. It happens in all server? Does the HIGHGUID_PLAYER value changed? enum HighGuid { HIGHGUID_ITEM = 0x4000, // blizz 4000 HIGHGUID_CONTAINER = 0x4000, // blizz 4000 [b] HIGHGUID_PLAYER = 0x0000, // blizz 0000[/b] HIGHGUID_GAMEOBJECT = 0xF110, // blizz F110 HIGHGUID_TRANSPORT = 0xF120, // blizz F120 (for GAMEOBJECT_TYPE_TRANSPORT) HIGHGUID_UNIT = 0xF130, // blizz F130 HIGHGUID_PET = 0xF140, // blizz F140 HIGHGUID_VEHICLE = 0xF150, // blizz F550 HIGHGUID_DYNAMICOBJECT = 0xF100, // blizz F100 HIGHGUID_CORPSE = 0xF101, // blizz F100 HIGHGUID_MO_TRANSPORT = 0x1FC0, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT) };
  13. Oh, which spell btw? I'm trying fix the problem got too much noise from spell 28176 http://www.wowhead.com/?spell=28176
  14. This patch doesn't stop the tick, it just does nothing when triggered. My goal is to fix the bug that client still receive aura log when player has max health. How about this alt fix: diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 2cf57a8..a08d0ae 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -6499,11 +6571,14 @@ void Aura::PeriodicTick() sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, 0, 0, 0.0f, isCrit); - m_target->SendPeriodicAuraLog(&pInfo); - int32 gain = m_target->ModifyHealth(pdamage); + if (gain) + { + SpellPeriodicAuraLogInfo pInfo(this, gain, 0, 0, 0, 0.0f, isCrit); + m_target->SendPeriodicAuraLog(&pInfo); + } + // add HoTs to amount healed in bgs if( pCaster->GetTypeId() == TYPEID_PLAYER ) if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() )
  15. Yes, these quests no longer show in gray as low level quests.
  16. What bug does the patch fix? What features does the patch add? When caster has aura SPELL_AURA_PERIODIC_HEAL or SPELL_AURA_OBS_MOD_HEALTH, he's healed again and again even he has reached max health. mangos doesn't send overheal log to client for SPELL_AURA_OBS_MOD_HEALTH/SPELL_AURA_PERIODIC_HEAL. For which repository revision was the patch created? 8713 Is there a thread in the bug report section or at lighthouse? If yes, please add a link to the thread. No. Who has been writing this patch? Please include either forum user names or email addresses. me [color="Silver"]diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 75a166e..73a68d3 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -6512,6 +6584,9 @@ void Aura::PeriodicTick() // This method can modify pdamage bool isCrit = IsCritFromAbilityAura(pCaster, pdamage); + if (pdamage == 0 || (pdamage > 0 && (m_target->GetHealth() >= m_target->GetMaxHealth()))) + return; + sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());[/color] Updated patch: diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 2cf57a8..18179ea 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -6499,11 +6571,11 @@ void Aura::PeriodicTick() sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, 0, 0, 0.0f, isCrit); - m_target->SendPeriodicAuraLog(&pInfo); - int32 gain = m_target->ModifyHealth(pdamage); + SpellPeriodicAuraLogInfo pInfo(this, pdamage, pdamage-gain, 0, 0, 0.0f, isCrit); + m_target->SendPeriodicAuraLog(&pInfo); + // add HoTs to amount healed in bgs if( pCaster->GetTypeId() == TYPEID_PLAYER ) if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() )
  17. What bug does the patch fix? What features does the patch add? Just find quest dynamic level also uses value -1, client also uses -1 to display quest color. This should fix dynamic level quest shows in gray in client quest log window. For which repository revision was the patch created? 8734 Is there a thread in the bug report section or at lighthouse? If yes, please add a link to the thread. No. Who has been writing this patch? Please include either forum user names or email addresses. me PS: Pls clean client cache first, then update DB. code: http://paste2.org/p/483939 diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp index 422ad6f..6ecfe2c 100644 --- a/src/game/GossipDef.cpp +++ b/src/game/GossipDef.cpp @@ -151,7 +172,7 @@ void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID ) data << uint32(questID); data << uint32(qItem.m_qIcon); - data << uint32(pSession->GetPlayer()->GetQuestLevel(pQuest)); + data << int32(pQuest->GetQuestLevel()); std::string Title = pQuest->GetTitle(); int loc_idx = pSession->GetSessionDbLocaleIndex(); @@ -400,7 +421,7 @@ void PlayerMenu::SendQuestGiverQuestList( QEmote eEmote, const std::string& Titl data << uint32(questID); data << uint32(qmi.m_qIcon); - data << uint32(pSession->GetPlayer()->GetQuestLevel(pQuest)); + data << int32(pQuest->GetQuestLevel()); data << title; } pSession->SendPacket( &data ); @@ -547,7 +568,7 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest ) data << uint32(pQuest->GetQuestId()); // quest id data << uint32(pQuest->GetQuestMethod()); // Accepted values: 0, 1 or 2. 0==IsAutoComplete() (skip objectives/details) - data << uint32(pQuest->GetQuestLevel()); // may be 0, static data, in other cases must be used dynamic level: Player::GetQuestLevel + data << int32(pQuest->GetQuestLevel()); // may be 0, -1, static data, in other cases must be used dynamic level: Player::GetQuestOrPlayerLevel data << uint32(pQuest->GetZoneOrSort()); // zone or sort to display in quest log data << uint32(pQuest->GetType()); // quest type diff --git a/src/game/Player.cpp b/src/game/Player.cpp index c8e9ca2..2445d0f 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -5952,7 +5945,7 @@ void Player::RewardReputation(Quest const *pQuest) { if(pQuest->RewRepFaction[i] && pQuest->RewRepValue[i] ) { - int32 rep = CalculateReputationGain(GetQuestLevel(pQuest), pQuest->RewRepValue[i], pQuest->RewRepFaction[i], true); + int32 rep = CalculateReputationGain(GetQuestOrPlayerLevel(pQuest), pQuest->RewRepValue[i], pQuest->RewRepFaction[i], true); FactionEntry const* factionEntry = sFactionStore.LookupEntry(pQuest->RewRepFaction[i]); if(factionEntry) GetReputationMgr().ModifyReputation(factionEntry, rep); diff --git a/src/game/Player.h b/src/game/Player.h index 4c9325d..d571ea9 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1280,7 +1280,7 @@ class MANGOS_DLL_SPEC Player : public Unit /*** QUEST SYSTEM ***/ /*********************************************************/ - uint32 GetQuestLevel( Quest const* pQuest ) const { return pQuest && pQuest->GetQuestLevel() ? pQuest->GetQuestLevel() : getLevel(); } + uint32 GetQuestOrPlayerLevel( Quest const* pQuest ) const { return pQuest && (pQuest->GetQuestLevel()>0) ? pQuest->GetQuestLevel() : getLevel(); } void PrepareQuestMenu( uint64 guid ); void SendPreparedQuest( uint64 guid ); diff --git a/src/game/QuestDef.cpp b/src/game/QuestDef.cpp index 5a53e52..c469537 100644 --- a/src/game/QuestDef.cpp +++ b/src/game/QuestDef.cpp @@ -27,7 +27,7 @@ Quest::Quest(Field * questRecord) ZoneOrSort = questRecord[2].GetInt32(); SkillOrClass = questRecord[3].GetInt32(); MinLevel = questRecord[4].GetUInt32(); - QuestLevel = questRecord[5].GetUInt32(); + QuestLevel = questRecord[5].GetInt32(); Type = questRecord[6].GetUInt32(); RequiredRaces = questRecord[7].GetUInt32(); RequiredSkillValue = questRecord[8].GetUInt32(); @@ -169,7 +169,7 @@ uint32 Quest::XPValue( Player *pPlayer ) const if( RewMoneyMaxLevel > 0 ) { uint32 pLevel = pPlayer->getLevel(); - uint32 qLevel = QuestLevel; + uint32 qLevel = QuestLevel > 0 ? QuestLevel : 0; float fullxp = 0; if (qLevel >= 15) fullxp = RewMoneyMaxLevel / 6.0f; diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h index 546a5dc..54e95a4 100644 --- a/src/game/QuestDef.h +++ b/src/game/QuestDef.h @@ -181,7 +181,7 @@ class Quest int32 GetZoneOrSort() const { return ZoneOrSort; } int32 GetSkillOrClass() const { return SkillOrClass; } uint32 GetMinLevel() const { return MinLevel; } - uint32 GetQuestLevel() const { return QuestLevel; } + int32 GetQuestLevel() const { return QuestLevel; } uint32 GetType() const { return Type; } uint32 GetRequiredRaces() const { return RequiredRaces; } uint32 GetRequiredSkillValue() const { return RequiredSkillValue; } @@ -274,7 +274,7 @@ class Quest int32 ZoneOrSort; int32 SkillOrClass; uint32 MinLevel; - uint32 QuestLevel; + int32 QuestLevel; uint32 Type; uint32 RequiredRaces; uint32 RequiredSkillValue; diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index a93b658..1ecda8a 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -606,7 +606,7 @@ uint32 WorldSession::getDialogStatus(Player *pPlayer, Object* questgiver, uint32 { if ( pQuest->IsAutoComplete() || (pQuest->IsRepeatable() && pPlayer->getQuestStatusMap()[quest_id].m_rewarded)) result2 = DIALOG_STATUS_REWARD_REP; - else if (pPlayer->getLevel() <= pPlayer->GetQuestLevel(pQuest) + sWorld.getConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF) ) + else if (pPlayer->getLevel() <= pPlayer->GetQuestOrPlayerLevel(pQuest) + sWorld.getConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF) ) { if (pQuest->HasFlag(QUEST_FLAGS_DAILY)) result2 = DIALOG_STATUS_AVAILABLE_REP; SQL: ALTER TABLE quest_template CHANGE COLUMN QuestLevel QuestLevel smallint(6) NOT NULL DEFAULT 0;
  18. gitbub.com supports git clone http://....git.
  19. For some reason, I need clone mangos over http, but get errors: Is it gitbub.com's problem?
×
×
  • 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