/** * I hacked the javascript file named comm.js, which received from tencent * server, and find that f**k tencent has changed encryption algorithm * for password in webqq3 . The new algorithm is below(descripted with javascript): * var M=C.p.value; // M is the qq password * var I=hexchar2bin(md5(M)); // Make a md5 digest * var H=md5(I+pt.uin); // Make md5 with I and uin(see below) * var G=md5(H+C.verifycode.value.toUpperCase()); * * @param pwd User's password * @param vc Verify Code. e.g. "!M6C" * @param uin A string like "\x00\x00\x00\x00\x54\xb3\x3c\x53", NB: it * must contain 8 hexadecimal number, in this example, it equaled * to "0x0,0x0,0x0,0x0,0x54,0xb3,0x3c,0x53" * * @return Encoded password on success, else NULL on failed */ static char *lwqq_enc_pwd(const char *pwd, const char *vc, const char *uin) { int i; int uin_byte_length; char buf[128] = {0}; unsigned char sig[32]; char _uin[9] = {0}; if (!pwd || !vc || !uin) { lwqq_log(LOG_ERROR, "Null parameterment\n"); return NULL; } /* Calculate the length of uin (it must be 8?) */ uin_byte_length = strlen(uin) / 4; /** * Ok, parse uin from string format. * "\x00\x00\x00\x00\x54\xb3\x3c\x53" -> {0,0,0,0,54,b3,3c,53} */ for (i = 0; i < uin_byte_length ; i++) { char u[5] = {0}; char tmp; strncpy(u, uin + i * 4 + 2, 2); errno = 0; tmp = strtol(u, NULL, 16); if (errno) { return NULL; } _uin[i] = tmp; } /* Equal to "var I=hexchar2bin(md5(M));" */ md5_buffer(pwd,strlen(pwd),sig); memcpy(buf,sig,sizeof(sig)); /* Equal to "var H=md5(I+pt.uin);" */ memcpy(buf + 16, _uin, uin_byte_length); md5_buffer(buf, 16 + uin_byte_length, sig); md5_sig_to_string(sig,buf,sizeof(buf)); /* Equal to var G=md5(H+C.verifycode.value.toUpperCase()); */ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s", vc); upcase_string(buf, strlen(buf)); md5_buffer(buf, strlen(buf), sig); md5_sig_to_string(sig,buf,sizeof(buf)); upcase_string(buf, strlen(buf)); /* OK, seems like every is OK */ return s_strdup(buf); }
static void run_tests(void) { unsigned char sig[MD5_SIZE], sig2[MD5_SIZE]; char str[33]; str_sig_t *test_p; /* run our tests */ for (test_p = tests; test_p->ss_string != NULL; test_p++) { /* calculate the sig for our test string */ md5_buffer(test_p->ss_string, strlen(test_p->ss_string), sig); /* convert from the sig to a string rep */ md5_sig_to_string(sig, str, sizeof(str)); if (strcmp(str, test_p->ss_sig) == 0) { (void)printf("Sig for '%s' matches '%s'\n", test_p->ss_string, test_p->ss_sig); } else { (void)printf("ERROR: Sig for '%s' is '%s' not '%s'\n", test_p->ss_string, test_p->ss_sig, str); } /* convert from the string back into a MD5 signature */ md5_sig_from_string(sig2, str); if (memcmp(sig, sig2, MD5_SIZE) == 0) { (void)printf(" String conversion also matches\n"); } else { (void)printf(" ERROR: String conversion for '%s' failed\n", test_p->ss_sig); } } }
/* * Read in from stdin and run MD5 on the input */ static void read_file(const char *filename) { unsigned char sig[MD5_SIZE]; char buffer[4096]; md5_t md5; int ret; FILE *stream; if (strcmp(filename, "-") == 0) { stream = stdin; } else { stream = fopen(filename, "r"); if (stream == NULL) { perror(filename); exit(1); } } md5_init(&md5); /* iterate over file */ while (1) { /* read in from our file */ ret = fread(buffer, sizeof(char), sizeof(buffer), stream); if (ret <= 0) break; /* process our buffer buffer */ md5_process(&md5, buffer, ret); } md5_finish(&md5, sig); if (stream != stdin) { (void)fclose(stream); } (void)printf("%25s '", "Resulting signature:"); print_sig(sig); (void)printf("'\n"); /* convert to string to print */ md5_sig_to_string(sig, buffer, sizeof(buffer)); (void)printf("%25s '%s'\n", "Results of md5_to_string:", buffer); /* now we convert it from string back into the sig */ md5_sig_from_string(sig, buffer); (void)printf("%25s '", "After md5_from_string:"); print_sig(sig); (void)printf("'\n"); }
static int __hms_parse_read_body( int fd, hms_msg *msg, int body_len ) { char *buffer = NULL, *p = NULL; int read_in = 0, erred = HMS_FALSE; char computed_checksum[33], *given_checksum = NULL; buffer = malloc( body_len + 1 ); if(buffer == NULL ) { erred = HMS_TRUE; } p = buffer; while( read_in < body_len ) { int sz = read( fd, p, (body_len - read_in) ); if( sz <= 0 ) { erred = HMS_TRUE; break; } else { read_in += sz; p += sz; } } if(erred == HMS_FALSE) { #ifdef HERMES_ENABLE_CHECKSUMS /* Computed checksum */ char hex_checksum[16]; md5_buffer( buffer, body_len, (void *) hex_checksum ); md5_sig_to_string( hex_checksum, computed_checksum, 33); /* Check the checksum if passed */ int ret_chk = 0; ret_chk = hms_msg_get_named_header(msg, HMS_CONTENT_CHECKSUM, &given_checksum); if( ret_chk == 0 && given_checksum != NULL ) { if( strncasecmp( given_checksum, computed_checksum, sizeof(computed_checksum) ) != 0 ) { fprintf(stderr, "[ERROR] Checksums don't match!!\n"); fflush(stderr); fprintf(stderr, "[ERROR] Computed: %s Given: %s\n", computed_checksum, given_checksum ); erred = 1; }// else { fprintf(stderr, "[NOTE] Checksums matched!\n"); } } else { fprintf(stderr, "[NOTE] No checksum provided!\n"); } #endif /* Update the body */ assert(read_in == body_len ); hms_msg_set_body( msg, buffer, body_len ); } if(buffer) { free(buffer); buffer = NULL; } if(given_checksum) { free(given_checksum); given_checksum = NULL; } return (erred == HMS_TRUE) ? -1 : 0; } /* end __hms_parse_read_body() */
bool CCheckPassword::checkPass(const std::string& pass, const std::string& dbpass) { //if(crypted) return Botan::check_bcrypt(pass, dbpass); //else return (pass.compare(dbpass) == 0 ? true : false ); int crypttype = kPlainText; if (dbpass.size() == 60) crypttype = kBcryptedText; else if (dbpass.size() == 32) crypttype = kMD5Text; switch(crypttype) { case kPlainText: { return (pass.compare(dbpass) == 0 ? true : false ); } break; case kMD5Text: { char tmpPass[1024]; char tmpResult[256]; md5_buffer(pass.c_str(), pass.size(), tmpPass); md5_sig_to_string(tmpPass, tmpResult, sizeof(tmpResult)); std::string md5String(tmpResult); std::transform(md5String.begin(), md5String.end(), md5String.begin(), toupper); std::string dbpassUpper(dbpass); std::transform(dbpassUpper.begin(), dbpassUpper.end(), dbpassUpper.begin(), toupper); return (md5String.compare(dbpassUpper) == 0 ? true : false); } break; case kBcryptedText: { return Botan::check_bcrypt(pass, dbpass); } break; default: return false; break; } return false; }
//----------------------------------------------------------------------------- // Purpose: // Input : strIP - // ulPortNum - // Output : Returns TRUE on success, FALSE on failure. //----------------------------------------------------------------------------- void CUISelectServer::ConnectToServer(CTString strIP, ULONG ulPortNum) { if(_pNetwork->m_bSendMessage) return; CUIManager* pUIManager = CUIManager::getSingleton(); // 소켓의 연결을 끊었다가, 다시 연결함. _cmiComm.Reconnect(strIP, ulPortNum); if(_tcpip.Socket == INVALID_SOCKET) { //CPrintF("게임 서버와 연결할 수 없습니다.\n"); pUIManager->CloseMessageBox(MSGCMD_CONNECT_ERROR); CUIMsgBox_Info MsgBoxInfo; MsgBoxInfo.SetMsgBoxInfo( _S( 424, "접속 오류" ), UMBS_OK, UI_SEL_SERVER, MSGCMD_CONNECT_ERROR ); MsgBoxInfo.AddString( _S( 426, "게임 서버와 연결할 수 없습니다." ) ); pUIManager->CreateMessageBox( MsgBoxInfo ); _pNetwork->m_bSendMessage = FALSE; return; } // [091103: selo] 미국에 md5 적용함 #if defined(G_JAPAN)/* || defined(G_USA)*/ // 패스워드 MD5로 암호화 char tmpPass[1024]; char tmpResult[256]; md5_buffer(_pNetwork->m_strUserPW, _pNetwork->m_strUserPW.Length(), tmpPass); md5_sig_to_string(tmpPass, tmpResult, sizeof(tmpResult)); CTString CT_tmpPass = tmpResult; CT_tmpPass.ToUpper(); // MD5로 암호화된 패스워드는 대문자로 전송(서버에서 대문자로 된 패스워드로 처리) _pNetwork->SendLoginMessage(_pNetwork->m_strUserID, CT_tmpPass, pUIManager->GetVersion()); #else _pNetwork->SendLoginMessage(_pNetwork->m_strUserID, _pNetwork->m_strUserPW, pUIManager->GetVersion()); #endif pUIManager->Lock(TRUE); }
char* md5_calc_file_signature(const char *filename) { char buffer[4096]; char* strsig; int ret; FILE *stream; #ifdef HAVE_LIBGCRYPT gcry_md_hd_t md5; gcry_error_t err; unsigned char* sig; #else MD5_CTX md5; unsigned char sig[MD5_DIGEST_LENGTH]; #endif stream = fopen(filename, "r"); if (stream == NULL) { perror(filename); exit(1); } #ifdef HAVE_LIBGCRYPT err = gcry_md_open(&md5, GCRY_MD_MD5, 0); if (err) { fprintf(stderr, "MD5 context creation failure: %s/%s", gcry_strsource (err), gcry_strerror (err)); return NULL; } #else MD5_Init(&md5); #endif /* iterate over file */ while (1) { /* read in from our file */ ret = fread(buffer, sizeof(char), sizeof(buffer), stream); if (ret <= 0) break; /* process our buffer buffer */ #ifdef HAVE_LIBGCRYPT gcry_md_write(md5, buffer, ret); #else MD5_Update(&md5, buffer, ret); #endif } #ifdef HAVE_LIBGCRYPT gcry_md_final(md5); sig = gcry_md_read(md5, GCRY_MD_MD5); if (!sig) { fprintf(stderr, "Unable to calculate MD5 signature for %s", filename); return NULL; } #else MD5_Final(sig, &md5); #endif if (stream != stdin) { (void)fclose(stream); } /* convert to string to print */ strsig = (char*) malloc(16*2+1); if (strsig) { md5_sig_to_string(sig, strsig, 16*2+1); /*(void)printf("%25s '%s'\n", "File key:", strsig);*/ return strsig; } else { return NULL; } }