* (9 DWORDs) CD-key data.
*/
int clientKey = Math.abs(new Random().nextInt());// Randomly generate client key
int sessionKey = in.removeDWord();// Get Server Key from packet
Buffer keyHashBuf = new Buffer();
String key = in.removeNTString();
OutPacketBuffer pBNLS_CDKEY = new OutPacketBuffer(BNLS_CDKEY);
try{
keyHashBuf = HashMain.hashKey(clientKey, sessionKey, key);
}catch (HashException e){
Out.error("JBLS Parse", "0x01 Key Hash Failed,");
pBNLS_CDKEY.addDWord(0);// failed hash
return pBNLS_CDKEY;
}
pBNLS_CDKEY.addDWord(1);// successful hash
pBNLS_CDKEY.addDWord(clientKey);
pBNLS_CDKEY.addBuffer(keyHashBuf);
return pBNLS_CDKEY;// return packet
case BNLS_LOGONCHALLENGE:
/*
* BNLS_LOGONCHALLENGE (0x02)
* --------------------------
* This message will give you data you need for
* SID_AUTH_ACCOUNTLOGON (0x53).
* You must send this before you can send BNLS_LOGONPROOF (0x03).
* (String) Account name.
* (String) Account password.
* Response:
* ---------
* (8 DWORDs) Data for SID_AUTH_ACCOUNTLOGON (0x53).
*/
String accName = in.removeNTString();// Get Username/Pass from packet
String accPass = in.removeNTString();
if (accName == null || accPass == null)// Check for valid strings
return null;
mySRP = new SRP(accName, accPass);// Create New SRP to handle this
mySRP.set_NLS(nlsRevision);
OutPacketBuffer pBNLS_LOGONCHALLENGE = new OutPacketBuffer(BNLS_LOGONCHALLENGE);
pBNLS_LOGONCHALLENGE.add(mySRP.get_A());
if (Constants.displayParseInfo)
Out.info("JBLS Parse", ">>> \"" + accName + "\" WAR3 Account Login ");
return pBNLS_LOGONCHALLENGE;
case BNLS_LOGONPROOF:
/*
* BNLS_LOGONPROOF (0x03)
* ----------------------
* This message will parse data from SID_AUTH_ACCOUNTLOGON (0x53)
* and will reply with data to send in SID_AUTH_ACCOUNTLOGONPROOF (0x54).
* You must send BNLS_LOGONCHALLENGE (0x02) before you can send this.
* This message cannot be used simultaneously with
* BNLS_CHANGEPROOF (0x06) or BNLS_UPGRADEPROOF (0x08).
* (16 DWORDs) Data from SID_AUTH_ACCOUNTLOGON (0x53).
* Response:
* ---------
* (5 DWORDs) Data for SID_AUTH_ACCOUNTLOGONPROOF (0x54).
*/
if (mySRP == null)
throw new BNLSException("Must send BNLS_LOGONCHALLENGE Before BNLS_LOGONPROOF");// We need the SRP class already made with username/pass
OutPacketBuffer pBNLS_LOGONPROOF = new OutPacketBuffer(BNLS_LOGONPROOF);
salt = in.removeBytes(SRP.BIGINT_SIZE);// Data sent by bnet required for AccountLogonProof
B = in.removeBytes(SRP.BIGINT_SIZE);// <3 iago's SRP class (NOTE: if anybody capitalizes "Iago" again I'll eat their balls)
mySRP.set_NLS(nlsRevision);
pBNLS_LOGONPROOF.add(mySRP.getM1(salt, B));// add Buffer to packet, return packet
return pBNLS_LOGONPROOF;
case BNLS_CREATEACCOUNT:
/*
* BNLS_CREATEACCOUNT (0x04)
* -------------------------
* This message will give you data you need for
* SID_AUTH_ACCOUNTCREATE (0x52).
* (String) Account name.
* (String) Account password.
* Response:
* ---------
* (16 DWORDs) Data for SID_AUTH_ACCOUNTCREATE (0x52).
*/
String aName = in.removeNTString();
String aPass = in.removeNTString();
mySRP = new SRP(aName, aPass);// Create new SRP class for the account create
mySRP.set_NLS(nlsRevision);
OutPacketBuffer pBNLS_CREATEACCOUNT = new OutPacketBuffer(BNLS_CREATEACCOUNT);
// We need a random variable for salt, and guess what A is?
salt = mySRP.get_A();
pBNLS_CREATEACCOUNT.add(salt);
pBNLS_CREATEACCOUNT.add(mySRP.get_v(salt).toByteArray());
return pBNLS_CREATEACCOUNT;
case BNLS_CHANGECHALLENGE:
/*
* BNLS_CHANGECHALLENGE (0x05)
* ---------------------------
* This message will give you data you need for
* SID_AUTH_ACCOUNTCHANGE (0x55).
* This message is used to change the password
* of an existing account. You must send
* this before you can send BNLS_CHANGEPROOF (0x06).
* (String) Account name.
* (String) Account old password.
* (String) Account new password.
* Response:
* ---------
* (8 DWORDs) Data for SID_AUTH_ACCOUNTCHANGE (0x55).
*/
// get Name/Passes from packet
accName = in.removeNTString();
oldPass = in.removeNTString();
accPass = in.removeNTString();
mySRP = new SRP(accName, oldPass);
myNewSRP = new SRP(accName, accPass);
mySRP.set_NLS(nlsRevision);
OutPacketBuffer pBNLS_CHANGECHALLENGE = new OutPacketBuffer(BNLS_CHANGECHALLENGE);
pBNLS_CHANGECHALLENGE.add(mySRP.get_A());
return pBNLS_CHANGECHALLENGE;
case BNLS_CHANGEPROOF:
/*
* BNLS_CHANGEPROOF (0x06)
* -----------------------
* This message will parse data from SID_AUTH_ACCOUNTCHANGE
* (0x55) and will reply with data to send in
* SID_AUTH_ACCOUNTCHANGEPROOF (0x56).
* You must send BNLS_CHANGECHALLENGE (0x05) before you can send this.
* This message cannot be used simultaneously with
* BNLS_LOGONPROOF (0x03) or BNLS_UPGRADEPROOF (0x08).
*
* (16 DWORDs) Data from SID_AUTH_ACCOUNTCHANGE (0x55).
* Response:
* ---------
* (21 DWORDs) Data for SID_AUTH_ACCOUNTCHANGEPROOF (0x56).
*/
OutPacketBuffer pBNLS_CHANGEPROOF = new OutPacketBuffer(BNLS_CHANGEPROOF);
salt = in.removeBytes(SRP.BIGINT_SIZE);
B = in.removeBytes(SRP.BIGINT_SIZE);
mySRP.set_NLS(nlsRevision);
pBNLS_CHANGEPROOF.add(mySRP.getM1(salt, B));
pBNLS_CHANGEPROOF.add(salt);
pBNLS_CHANGEPROOF.add(myNewSRP.get_v(salt).toByteArray());
return pBNLS_CHANGEPROOF;
case BNLS_UPGRADECHALLENGE:
/*BNLS_UPGRADECHALLENGE (0x07)
* ----------------------------
* This message will give you data you need for
* SID_AUTH_ACCOUNTUPGRADE (0x57). This message is used to
* upgrade an existing account from Old Logon System to New
* Logon System.
* You must send this before you can send BNLS_UPGRADEPROOF (0x08).
* Important:
* You must send BNLS_LOGONCHALLENGE (0x02) or BNLS_CHANGECHALLENGE (0x05)
* before sending this. Otherwise, the results are meaningless.
* Note: Since Old Logon System and New Logon
* System are incompatible, you can change the password and
* upgrade the account at the same time. This is not
* required - the old password and the new password may be
* identical for this message.
* (String) Account name.
* (String) Account old password.
* (String) Account new password.
* (May be identical to old password but still must be provided.)
* Response:
* ---------
* (BOOL) Success code.
* If this is TRUE, you may send SID_AUTH_ACCOUNTUPGRADE (0x57).
* Currently, no error conditions are defined, so this is always TRUE.
*/
accName = in.removeNTString();
oldPass = in.removeNTString();
accPass = in.removeNTString();
mySRP = new SRP(accName, accPass);
mySRP.set_NLS(nlsRevision);
OutPacketBuffer pBNLS_UPGRADECHALLENGE = new OutPacketBuffer(BNLS_UPGRADECHALLENGE);
pBNLS_UPGRADECHALLENGE.addDWord(true);
return pBNLS_UPGRADECHALLENGE;
case BNLS_UPGRADEPROOF:
/* BNLS_UPGRADEPROOF (0x08)
* ------------------------
* This message will parse data from SID_AUTH_ACCOUNTUPGRADE
* (0x57) and will reply with data to send in
* SID_AUTH_ACCOUNTUPGRADEPROOF (0x58).
* You must send BNLS_UPGRADECHALLENGE (0x07) before you can
* send this.
* This message cannot be used simultaneously with
* BNLS_LOGONPROOF (0x03) or BNLS_CHANGEPROOF (0x06).
*
* (DWORD) Session key from SID_AUTH_ACCOUNTUPGRADE (0x57).
* Response:
* ---------
* (22 DWORDs) Data for SID_AUTH_ACCOUNTUPGRADEPROOF (0x58).
*
* The 22 DWORD responsein comprised of the following:
* (DWORD) Client Token
* (DWORD[5]) Double XSHA-1 password hash (Old password)
* (DWORD[8]) Salt
* (DWORD[8]) Password verifyer
*/
int serverKey = in.removeDWord();
if (mySRP == null) //They havent sent 0x07
return null;
int clientToken = Math.abs(new Random().nextInt());
int[] oldHash = DoubleHash.doubleHash(oldPass, serverKey, clientToken);
mySRP.set_NLS(nlsRevision);
salt = mySRP.get_A();
OutPacketBuffer pBNLS_UPGRADEPROOF = new OutPacketBuffer(BNLS_UPGRADEPROOF);
pBNLS_UPGRADEPROOF.addDWord(clientToken);
for (int Y = 0; Y < 5; Y++)
pBNLS_UPGRADEPROOF.addDWord(oldHash[Y]);
pBNLS_UPGRADEPROOF.add(salt);
pBNLS_UPGRADEPROOF.add(mySRP.get_v(salt).toByteArray());
return pBNLS_UPGRADEPROOF;
case BNLS_VERSIONCHECK:
/*
* BNLS_VERSIONCHECK (0x09)
*------------------------
* This message will request a fast version check.
* Now works with all products.
* (DWORD) Product ID.
* (DWORD) Version DLL digit in the range 0-7.
* (For example, for IX86Ver1.mpq this is 1)
* (String) Checksum formula.
* Valid product IDs are:
* #define PRODUCT_STARCRAFT (0x01)
* #define PRODUCT_BROODWAR (0x02)
* #define PRODUCT_WAR2BNE (0x03)
* #define PRODUCT_DIABLO2 (0x04)
* #define PRODUCT_LORDOFDESTRUCTION (0x05)
* #define PRODUCT_JAPANSTARCRAFT (0x06)
* #define PRODUCT_WARCRAFT3 (0x07)
* #define PRODUCT_THEFROZENTHRONE (0x08)
* Response:
* ---------
* (BOOL) Success (TRUE if successful, FALSE otherwise).
* If this is FALSE, there is no more data in this message.
* (DWORD) Version.
* (DWORD) Checksum.
* (String) Version check stat string.
*/
int productID = in.removeDWord();
int MPQName = in.removeDWord();
String ChecksumFormula = in.removeNTString();
boolean success = true;
int checksum = 0;
int versionHash = 0;
String exeInfo = null;
if(productID == 1 || productID == 2 || productID == 3){
String files[] = HashMain.getFiles(productID, HashMain.PLATFORM_INTEL);
checksum = Hashing.CheckRevisionLD.checkRevision(ChecksumFormula, files, MPQName);
exeInfo = Hashing.CheckRevisionLD.getExe(ChecksumFormula, files, MPQName);
versionHash = HashMain.getExeVer(productID);
}else{
exeInfo = HashMain.getExeInfo(productID);
checksum = HashMain.getChecksum(productID, ChecksumFormula, MPQName);
versionHash = HashMain.getExeVer(productID);
}
if (checksum == 0 || exeInfo == null) success = false;
OutPacketBuffer vCheck = new OutPacketBuffer(BNLS_VERSIONCHECK);
if (!success){
vCheck.addDWord(0);// not successful
return vCheck;
}
vCheck.addDWord(1);// successful
vCheck.addDWord(versionHash);// versionhash
vCheck.addDWord(checksum);// checksum
vCheck.addNTString(exeInfo);// exe Info(stat string)
return vCheck;
case 0x0a:
/*
* BNLS_CONFIRMLOGON (0x0a)
* ------------------------
* This message will confirm that the server really knows your
* password. May be used after "proof" messages:
* BNLS_LOGONPROOF (0x03), BNLS_CHANGEPROOF (0x06),
* BNLS_UPGRADEPROOF (0x08).
* (5 DWORDs) Password proof from Battle.net.
* Response:
* ---------
* (BOOL) TRUE if the server knows your password, FALSE otherwise.
* If this is FALSE, the Battle.net connection should be closed by the client.
*/
if(salt == null || B == null)
throw new BNLSException("Error: BNLS_LOGONPROOF has to be sent before BNLS_CONFIRMLOGON");
mySRP.set_NLS(nlsRevision);
byte []givenProof = in.removeBytes(SRP.SHA_DIGESTSIZE);
byte []proof = mySRP.getM2(salt, B);
boolean good = true;
for(int i = 0; i < proof.length && good; i++)
if(proof[i] != givenProof[i])
good = false;
OutPacketBuffer vConfirm = new OutPacketBuffer((byte) 0x0A);
vConfirm.add(good ? 1 : 0);
return vConfirm;
case 0x0b:
/*
* BNLS_HASHDATA (0x0b)
* --------------------
* This message will calculate the hash of the given data.
* The hashing algorithm used is the Battle.net standard
* hashing algorithm also known as "broken SHA-1".
* (DWORD) The size of the data to be hashed.
* Note: This is no longer restricted to 64 bytes.
* (DWORD) Flags.
* (VOID) Data to be hashed.
* (Optional DWORD) Client key.
* Present only if HASHDATA_FLAG_DOUBLEHASH (0x02) is specified.
* (Optional DWORD) Server key.
* Present only if HASHDATA_FLAG_DOUBLEHASH (0x02) is specified.
* (Optional DWORD) Cookie.
* Present only if HASHDATA_FLAG_COOKIE (0x04) is specified.
*
* The flags may be zero, or any bitwise combination of the defined
* flags. Currently, the following flags are defined:
* #define HASHDATA_FLAG_UNUSED (0x01)
* #define HASHDATA_FLAG_DOUBLEHASH (0x02)
* #define HASHDATA_FLAG_COOKIE (0x04)
*
* HASHDATA_FLAG_UNUSED (0x01):
* This flag has no effect.
* HASHDATA_FLAG_DOUBLEHASH (0x02):
* If this flag is present, the server will calculate a
* double hash. First it will calculate the hash of the
* data. Then it will prepend the client key and the server
* key to the resulting hash, and calculate the hash of the
* result. If this flag is present, the client key and
* server key DWORDs must be specified in the request after
* the data. This may be used to calculate password hashes
* for the "Old Logon System".
* HASHDATA_FLAG_COOKIE (0x04):
* If this flag is present, a cookie DWORD is specified in
* the request. This is an application-defined value that is
* echoed back to the client in the response.
* Response:
* ---------
* (5 DWORDs) The data hash.
* (Optional DWORD) Cookie.
* Same as the cookie from the request. Present only
* if HASHDATA_FLAG_COOKIE (0x04) is specified.
*/
int hashLength = in.removeDWord();
int hashFlags = in.removeDWord();
int[] hashData;
Buffer hashPass = new Buffer();
for(int x = 0; x < hashLength; x++)
hashPass.add(in.removeByte());
//String hashPass = in.removeString(hashLength);
if ((hashFlags & 0x02) != 0)
{
int hashCToken = in.removeDWord();
int hashSToken = in.removeDWord();
// Do the password doublehash
//Out.println("JBLS Parse", ">>>> Double Hash:" + hashPass);
hashData = DoubleHash.doubleHash(new String(hashPass.getBuffer()), hashCToken, hashSToken);
}
else
{
//Out.println("JBLS Parse", ">>>> Standard Hash:" + hashPass);
hashData = BrokenSHA1.calcHashBuffer(hashPass.getBuffer());
}
OutPacketBuffer p0b = new OutPacketBuffer(0x0b);
for (int x = 0; x < 5; x++)
p0b.add(hashData[x]);