在QQ对应号码目录下user.db文件从800h起20字节为与密码相关数据,其中后16个字节和Hash后摘要有关.这20个字节后4个字节是QQ号码。 QA^FP8!j
QA^FP8!j
下列是一些常用的Hash算法(从微软加密头文件中提取出来的) QA^FP8!j
QA^FP8!j
#define CALG_MD2 1 MD2算法 QA^FP8!j
QA^FP8!j
#define CALG_MD4 2 MD4算法 QA^FP8!j
QA^FP8!j
#define CALG_MD5 3 MD5算法 QA^FP8!j
QA^FP8!j
#define CALG_SHA 4 SHA算法 QA^FP8!j
QA^FP8!j
#define CALG_SHA1 4 SHA1算法 QA^FP8!j
QA^FP8!j
#define CALG_MAC 5 MAC算法 QA^FP8!j
QA^FP8!j
#define ALG_SID_RIPEMD 6 RIPEMD算法 QA^FP8!j
QA^FP8!j
#define ALG_SID_RIPEMD160 7 RIPEMD160算法 QA^FP8!j
QA^FP8!j
#define ALG_SID_SSL3SHAMD5 8 SSL3SHAMD5算法 QA^FP8!j
QA^FP8!j
#define CALG_HMAC 9 HMAC算法 QA^FP8!j
QA^FP8!j
QA^FP8!j
而MD5算法中需要使用下面几个初始值 QA^FP8!j
QA^FP8!j
context->state[0] = 0x67452301; QA^FP8!j
QA^FP8!j
context->state[1] = 0xefcdab89; QA^FP8!j
QA^FP8!j
context->state[2] = 0x98badcfe; QA^FP8!j
QA^FP8!j
context->state[3] = 0x10325476; QA^FP8!j
QA^FP8!j
呵呵,在QQ中一搜索,果然几个特征值赫然在目。但是显然QQ使用了上述20个字节中的前四个字节对MD5密文又做了处理,我跟了两天还是没有头绪(头晕脑胀)。但是我发现把这四个字节改成00 00 00 00,然后登陆输入正确密码,仍然会提示密码不一致是否到服务器验证,选择是,然后验证成功后,这20个字节的后16个字节恰好就是密码的MD5密文。有兴趣的高手可以继续看看奥(其中密码比较函数地址为:004A7E0C) QA^FP8!j
QA^FP8!j
例: QA^FP8!j
QA^FP8!j
1B D5 01 00 5D D7 87 19 0D 92 6D E2 0A 56 E9 19 63 0F 5A E1 DF CA 20 05 QA^FP8!j
QA^FP8!j
DF CA 20 05即是我的QQ号。不过可不要暴力破解我的奥:) QA^FP8!j
QA^FP8!j
1B D5 01 00 5D D7 87 19 0D 92 6D E2 0A 56 E9 19 63 0F 5A E1就是和口令相关的数据 QA^FP8!j
QA^FP8!j
如果把1B D5 01 00改为00 00 00 00,然后按上述步骤登陆后,5D D7 87 19 0D 92 6D E2 0A 56 E9 19 63 0F 5A E1即变为口令的MD5密文。 QA^FP8!j
QA^FP8!j
QA^FP8!j
算法源代码如下: QA^FP8!j
QA^FP8!j
头文件: QA^FP8!j
QA^FP8!j
QA^FP8!j
// Decrypt.h: interface for the CDecrypt class. QA^FP8!j
QA^FP8!j
// QA^FP8!j
QA^FP8!j
////////////////////////////////////////////////////////////////////// QA^FP8!j
QA^FP8!j
#define AFX_DECRYPT_H__916D97B8_C120_4435_BE23_2CF35B8763A2__INCLUDED_ QA^FP8!j
QA^FP8!j
QA^FP8!j
#if _MSC_VER > 1000 QA^FP8!j
QA^FP8!j
#pragma once QA^FP8!j
QA^FP8!j
#endif // _MSC_VER > 1000 QA^FP8!j
QA^FP8!j
QA^FP8!j
#define _WIN32_WINNT 0x0400 QA^FP8!j
QA^FP8!j
#include <afxpriv.h> QA^FP8!j
QA^FP8!j
#include <Wincrypt.h> QA^FP8!j
QA^FP8!j
QA^FP8!j
class CDecrypt QA^FP8!j
QA^FP8!j
{ QA^FP8!j
QA^FP8!j
public: QA^FP8!j
QA^FP8!j
BOOL EncryptMessage(const TCHAR *Message,TCHAR *pHashData,int *pHashLen,int Algorithm); QA^FP8!j
QA^FP8!j
CDecrypt(); QA^FP8!j
QA^FP8!j
virtual ~CDecrypt(); QA^FP8!j
QA^FP8!j
QA^FP8!j
}; QA^FP8!j
QA^FP8!j
QA^FP8!j
#endif // !defined(AFX_DECRYPT_H__916D97B8_C120_4435_BE23_2CF35B8763A2__INCLUDED_) QA^FP8!j
QA^FP8!j
QA^FP8!j
CPP文件: QA^FP8!j
QA^FP8!j
// Decrypt.cpp: implementation of the CDecrypt class. QA^FP8!j
QA^FP8!j
// QA^FP8!j
QA^FP8!j
////////////////////////////////////////////////////////////////////// QA^FP8!j
QA^FP8!j
QA^FP8!j
#include stdafx.h QA^FP8!j
QA^FP8!j
#include Decrypt.h QA^FP8!j
QA^FP8!j
QA^FP8!j
#ifdef _DEBUG QA^FP8!j
QA^FP8!j
#undef THIS_FILE QA^FP8!j
QA^FP8!j
static char THIS_FILE[]=__FILE__; QA^FP8!j
QA^FP8!j
#define new DEBUG_NEW QA^FP8!j
QA^FP8!j
#endif QA^FP8!j
QA^FP8!j
QA^FP8!j
////////////////////////////////////////////////////////////////////// QA^FP8!j
QA^FP8!j
// Construction/Destruction QA^FP8!j
QA^FP8!j
////////////////////////////////////////////////////////////////////// QA^FP8!j
QA^FP8!j
QA^FP8!j
CDecrypt::CDecrypt() QA^FP8!j
QA^FP8!j
{ QA^FP8!j
QA^FP8!j
QA^FP8!j
} QA^FP8!j
QA^FP8!j
QA^FP8!j
CDecrypt::~CDecrypt() QA^FP8!j
QA^FP8!j
{ QA^FP8!j
QA^FP8!j
QA^FP8!j
} QA^FP8!j
QA^FP8!j
QA^FP8!j
BOOL CDecrypt::EncryptMessage(const TCHAR *Message,TCHAR *pHashData,int *pHashLen,int Algorithm) QA^FP8!j
QA^FP8!j
{ QA^FP8!j
QA^FP8!j
BOOL bResult = TRUE; QA^FP8!j
QA^FP8!j
QA^FP8!j
HCRYPTPROV hProv = NULL; QA^FP8!j
QA^FP8!j
HCRYPTKEY hKey = NULL; QA^FP8!j
QA^FP8!j
HCRYPTKEY hXchgKey = NULL; QA^FP8!j
QA^FP8!j
HCRYPTHASH hHash = NULL; QA^FP8!j
QA^FP8!j
DWORD dwLength; QA^FP8!j
QA^FP8!j
// Get handle to user default provider. QA^FP8!j
QA^FP8!j
if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) QA^FP8!j
QA^FP8!j
{ QA^FP8!j
QA^FP8!j
// Create hash object. QA^FP8!j
QA^FP8!j
if (CryptCreateHash(hProv, Algorithm, 0, 0, &hHash)) QA^FP8!j
QA^FP8!j
{ QA^FP8!j
QA^FP8!j
// Hash password string. QA^FP8!j
QA^FP8!j
dwLength = sizeof(TCHAR)*_tcslen(Message); QA^FP8!j
QA^FP8!j
if (CryptHashData(hHash, (BYTE *)Message, dwLength, 0)) QA^FP8!j
QA^FP8!j
{ QA^FP8!j
QA^FP8!j
CryptGetHashParam(hHash,2,(BYTE*)pHashData,(DWORD*)pHashLen,0); QA^FP8!j
QA^FP8!j
} QA^FP8!j
QA^FP8!j
else QA^FP8!j
QA^FP8!j
{ QA^FP8!j
QA^FP8!j
// Error during CryptHashData! QA^FP8!j
QA^FP8!j
bResult = FALSE; QA^FP8!j
QA^FP8!j
} QA^FP8!j
QA^FP8!j
CryptDestroyHash(hHash); // Destroy session key. QA^FP8!j
QA^FP8!j
} QA^FP8!j
QA^FP8!j
else QA^FP8!j
QA^FP8!j
{ QA^FP8!j
QA^FP8!j
// Error during CryptCreateHash! QA^FP8!j
QA^FP8!j
bResult = FALSE; QA^FP8!j
QA^FP8!j
} QA^FP8!j
QA^FP8!j
CryptReleaseContext(hProv, 0); QA^FP8!j
QA^FP8!j
} QA^FP8!j
QA^FP8!j
QA^FP8!j
return bResult; QA^FP8!j
QA^FP8!j
} QA^FP8!j
QA^FP8!j
QA^FP8!j
QA^FP8!j
使用: QA^FP8!j
QA^FP8!j
TCHAR Hash[255]; QA^FP8!j
QA^FP8!j
int Len=-1; QA^FP8!j
QA^FP8!j
CString Message=Your Message; QA^FP8!j
QA^FP8!j
m_decrypt.EncryptMessage((LPCSTR)(Message),Hash,&Len,CALG_MD5); QA^FP8!j
QA^FP8!j
Hash中存放的就是MD5密文。你可以使用上述算法 QA^FP8!j
QA^FP8!j
#define CALG_MD2 1 MD2算法 QA^FP8!j
QA^FP8!j
#define CALG_MD4 2 MD4算法 QA^FP8!j
QA^FP8!j
#define CALG_MD5 3 MD5算法 QA^FP8!j
QA^FP8!j
#define CALG_SHA 4 SHA算法 QA^FP8!j
QA^FP8!j
来替换CALG_MD5参数.