示例#1
0
/**
 * Calculates the CD-Key hash for use in SID_AUTH_CHECK (0x51)
 * Returns the length of the generated hash; call getHash and pass
 * it a character array that is at least this size.  Returns 0 on failure.
 *
 * Note that clientToken and serverToken will be added to the buffer and
 * hashed as-is, regardless of system endianness.  It is assumed that
 * the program's extraction of the server token does not change its
 * endianness, and since the client token is generated by the client,
 * endianness is not a factor.
 */
size_t CDKeyDecoder::calculateHash(uint32_t clientToken,
    uint32_t serverToken)
{
    struct CDKEYHASH kh;
    SHA1Context sha;
    
    if (!initialized || !keyOK) return 0;
    hashLen = 0;
    
    kh.clientToken = clientToken;
    kh.serverToken = serverToken;
    
    switch (keyType) {
        case KEY_STARCRAFT:
        case KEY_WARCRAFT2:
			kh.product = (uint32_t) LSB4(product);
			kh.value1 = (uint32_t) LSB4(value1);

            kh.value2.s.zero = 0;
            kh.value2.s.v = (uint32_t) LSB4(value2);
            
            keyHash = new char[20];
            calcHashBuf((char*) &kh, 24, keyHash);
            hashLen = 20;

#if DEBUG
			bncsutil_debug_message_a("%s: Hash calculated.", cdkey);
			bncsutil_debug_dump(keyHash, 20);
#endif

            return 20;
        case KEY_WARCRAFT3:
			kh.product = (uint32_t) MSB4(product);
			kh.value1 = (uint32_t) MSB4(value1);
            memcpy(kh.value2.l.v, w3value2, 10);

            if (SHA1Reset(&sha))
                return 0;
            if (SHA1Input(&sha, (const unsigned char*) &kh, 26))
                return 0;
            keyHash = new char[20];
            if (SHA1Result(&sha, (unsigned char*) keyHash)) {
                SHA1Reset(&sha);
                return 0;
            }
            SHA1Reset(&sha);
            hashLen = 20;
			
#if DEBUG
			bncsutil_debug_message_a("%s: Hash calculated.", cdkey);
			bncsutil_debug_dump(keyHash, 20);
#endif

            return 20;
        default:
            return 0;
    }
}
示例#2
0
文件: oldauth.cpp 项目: Shiox/ghostpp
/**
 * Single-hashes the password for account creation and password changes.
 *
 * outBuffer MUST be at least 20 bytes long.
 */
MEXP(void) hashPassword(const char* password, char* outBuffer) {
    calcHashBuf(password, std::strlen(password), outBuffer);

#if DEBUG
	bncsutil_debug_message_a("hashPassword(\"%s\") =", password);
	bncsutil_debug_dump(outBuffer, 20);
#endif
}
示例#3
0
MEXP(long) get_mpq_seed(int mpq_number)
{
	if (((size_t) mpq_number) >= checkrevision_seeds.size()) {
		bncsutil_debug_message_a("error: no known revision check seed for "
			"MPQ#%u", mpq_number);
		return 0;
	}
	
	return checkrevision_seeds[mpq_number];
}
示例#4
0
文件: oldauth.cpp 项目: Shiox/ghostpp
/**
 * Double-hashes the given password using the given
 * server and client tokens.
 *
 * outBuffer MUST be at least 20 bytes long.
 */
MEXP(void) doubleHashPassword(const char* password, uint32_t clientToken,
uint32_t serverToken, char* outBuffer) {
    char intermediate[28];
    uint32_t* lp;

    calcHashBuf(password, std::strlen(password), intermediate + 8);
    lp = (uint32_t*) &intermediate;
    lp[0] = clientToken;
    lp[1] = serverToken;
    calcHashBuf(intermediate, 28, outBuffer);
	
#if DEBUG
	bncsutil_debug_message_a("doubleHashPassword(\"%s\", 0x%08X, 0x%08X) =",
		password, clientToken, serverToken);
	bncsutil_debug_dump(outBuffer, 20);
#endif
}
示例#5
0
int CDKeyDecoder::processStarCraftKey() {
    int accum, pos, i;
    char temp;
    int hashKey = 0x13AC9741;
	char cdkey[14];

	std::strcpy(cdkey, this->cdkey);
    
    // Verification
    accum = 3;
    for (i = 0; i < (int) (keyLen - 1); i++) {
        accum += ((tolower(cdkey[i]) - '0') ^ (accum * 2));
    }
    
	if ((accum % 10) != (cdkey[12] - '0')) {
		bncsutil_debug_message_a("error: %s is not a valid StarCraft key", cdkey);
        return 0;
	}
    
    // Shuffling
    pos = 0x0B;
    for (i = 0xC2; i >= 7; i -= 0x11) {
        temp = cdkey[pos];
        cdkey[pos] = cdkey[i % 0x0C];
        cdkey[i % 0x0C] = temp;
        pos--;
    }
    
    // Final Value
    for (i = (int) (keyLen - 2); i >= 0; i--) {
        temp = toupper(cdkey[i]);
        cdkey[i] = temp;
        if (temp <= '7') {
            cdkey[i] ^= (char) (hashKey & 7);
            hashKey >>= 3;
        } else if (temp < 'A') {
示例#6
0
MEXP(int) getExeInfo(const char* file_name, char* exe_info,
					 size_t exe_info_size, uint32_t* version, int platform)
{
	const char* base = (char*) 0;
	unsigned long file_size;
	FILE* f = (FILE*) 0;
	int ret;
#ifdef MOS_WINDOWS
	HANDLE hFile;
	FILETIME ft;
	SYSTEMTIME st;
	LPBYTE buf;
	VS_FIXEDFILEINFO* ffi;
	DWORD infoSize, bytesRead;
#else
	cm_pe_t pe;
	cm_pe_resdir_t* root;
	cm_pe_resdir_t* dir;
	cm_pe_version_t ffi;
	size_t i;
	struct stat st;
	struct tm* time;
#endif
	
	if (!file_name || !exe_info || !exe_info_size || !version)
		return 0;

	base = basename(file_name);

	switch (platform) {
		case BNCSUTIL_PLATFORM_X86:
#ifdef MOS_WINDOWS				
			infoSize = GetFileVersionInfoSize(file_name, &bytesRead);
			if (infoSize == 0)
				return 0;
			buf = (LPBYTE) VirtualAlloc(NULL, infoSize, MEM_COMMIT,
										PAGE_READWRITE);
			if (buf == NULL)
				return 0;
			if (GetFileVersionInfo(file_name, NULL, infoSize, buf) == FALSE)
				return 0;
			if (!VerQueryValue(buf, "\\", (LPVOID*) &ffi, (PUINT) &infoSize))
				return 0;
			
			*version =
				((HIWORD(ffi->dwProductVersionMS) & 0xFF) << 24) |
				((LOWORD(ffi->dwProductVersionMS) & 0xFF) << 16) |
				((HIWORD(ffi->dwProductVersionLS) & 0xFF) << 8) | 
				(LOWORD(ffi->dwProductVersionLS) & 0xFF);
#if DEBUG
			bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)",
				base, (HIWORD(ffi->dwProductVersionMS) & 0xFF),
				(LOWORD(ffi->dwProductVersionMS) & 0xFF),
				(HIWORD(ffi->dwProductVersionLS) & 0xFF),
				(LOWORD(ffi->dwProductVersionLS) & 0xFF),
				*version);
#endif
			VirtualFree(buf, 0lu, MEM_RELEASE);
#else
			pe = cm_pe_load(file_name);
			if (!pe)
				return 0;
			root = cm_pe_load_resources(pe);
			if (!root) {
				cm_pe_unload(pe);
				return 0;
			}
				
			for (i = 0; i < root->subdir_count; i++) {
				dir = (root->subdirs + i);
				if (dir->name == 16) {
					if (!cm_pe_fixed_version(pe, dir->subdirs->resources,
											 &ffi))
					{
						cm_pe_unload_resources(root);
						cm_pe_unload(pe);
						return 0;
					}
					break;
				}
			}
			*version =
				((HIWORD(ffi.dwProductVersionMS) & 0xFF) << 24) |
				((LOWORD(ffi.dwProductVersionMS) & 0xFF) << 16) |
				((HIWORD(ffi.dwProductVersionLS) & 0xFF) << 8) | 
				(LOWORD(ffi.dwProductVersionLS) & 0xFF);
#if DEBUG
			bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)",
				base, (HIWORD(ffi.dwProductVersionMS) & 0xFF),
				(LOWORD(ffi.dwProductVersionMS) & 0xFF),
				(HIWORD(ffi.dwProductVersionLS) & 0xFF),
				(LOWORD(ffi.dwProductVersionLS) & 0xFF),
				*version);
#endif
			
			cm_pe_unload_resources(root);
			cm_pe_unload(pe);
#endif
			break;
		case BNCSUTIL_PLATFORM_MAC:
		case BNCSUTIL_PLATFORM_OSX:
			f = fopen(file_name, "r");
			if (!f)
				return 0;
			if (fseek(f, -4, SEEK_END) != 0) {
				fclose(f);
				return 0;
			}
			if (fread(version, 4, 1, f) != 1) {
				fclose(f);
				return 0;
			}
#ifdef MOS_WINDOWS
			fclose(f);
#endif
	}
	
#ifdef MOS_WINDOWS
	hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
					   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
		return 0;
	file_size = GetFileSize(hFile, NULL);
	if (!GetFileTime(hFile, &ft, NULL, NULL)) {
		CloseHandle(hFile);
		return 0;
	}
	
	if (!FileTimeToSystemTime(&ft, &st)) {
		CloseHandle(hFile);
		return 0;
	}
	CloseHandle(hFile);
	
	ret = snprintf(exe_info, exe_info_size,
				   "%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, st.wMonth,
				   st.wDay, (st.wYear % 100), st.wHour, st.wMinute, st.wSecond,
				   file_size);

#else
	if (!f)
		f = fopen(file_name, "r");
	if (!f)
		return 0;
	if (fseek(f, 0, SEEK_END) == -1) {
		fclose(f);
		return 0;
	}
	file_size = ftell(f);
	fclose(f);
	
	if (stat(file_name, &st) != 0)
		return 0;
	
	time = gmtime(&st.st_mtime);
	if (!time)
		return 0;
	
	switch (platform) {
		case BNCSUTIL_PLATFORM_MAC:
		case BNCSUTIL_PLATFORM_OSX:
			if (time->tm_year >= 100) // y2k
				time->tm_year -= 100;
			break;
	}
	
	ret = (int) snprintf(exe_info, exe_info_size,
						"%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, 
						(time->tm_mon+1), time->tm_mday, time->tm_year,
						time->tm_hour, time->tm_min, time->tm_sec, file_size);
#endif

#if DEBUG
	bncsutil_debug_message(exe_info);
#endif

	return ret;
}
示例#7
0
MEXP(int) checkRevision(const char* formula, const char* files[], int numFiles,
	int mpqNumber, unsigned long* checksum)
{
	long values[4], ovd[4], ovs1[4], ovs2[4];
	char ops[4];
	const char* token;
	int curFormula = 0;
	file_t f;
	uint8_t* file_buffer;
	uint32_t* dwBuf;
	uint32_t* current;
	size_t seed_count;
	
#if DEBUG
	int i;
	bncsutil_debug_message_a("checkRevision(\"%s\", {", formula);
	for (i = 0; i < numFiles; i++) {
		bncsutil_debug_message_a("\t\"%s\",", files[i]);
	}
	bncsutil_debug_message_a("}, %d, %d, %p);", numFiles, mpqNumber, checksum);
#endif
	
	if (!formula || !files || numFiles == 0 || mpqNumber <= 0 || !checksum) {
		bncsutil_debug_message("error: checkRevision() parameter sanity check "
			"failed");
		return 0;
	}
	
	seed_count = checkrevision_seeds.size();
	if (seed_count == 0) {
		initialize_checkrevision_seeds();
		seed_count = checkrevision_seeds.size();
	}
	
	if (seed_count <= (size_t) mpqNumber) {
		bncsutil_debug_message_a("error: no revision check seed value defined "
			"for MPQ number %d", mpqNumber);
		return 0;
	}
	
	token = formula;
	while (token && *token) {
		if (*(token + 1) == '=') {
			int variable = BUCR_GETNUM(*token);
			if (variable < 0 || variable > 3) {
				bncsutil_debug_message_a("error: Unknown revision check formula"
					" variable %c", *token);
				return 0;
			}
			
			token += 2; // skip over equals sign
			if (BUCR_ISNUM(*token)) {
				values[variable] = atol(token);
			} else {
				if (curFormula > 3) {
					// more than 4 operations?  bloody hell.
					bncsutil_debug_message("error: Revision check formula"
						" contains more than 4 operations; unsupported.");
					return 0;
				}
				ovd[curFormula] = variable;
				ovs1[curFormula] = BUCR_GETNUM(*token);
				ops[curFormula] = *(token + 1);
				ovs2[curFormula] = BUCR_GETNUM(*(token + 2));
				curFormula++;
			}
		}
		
		for (; *token != 0; token++) {
			if (*token == ' ') {
				token++;
				break;
			}
		}
	}
	
	// Actual hashing (yay!)
	// "hash A by the hashcode"
	values[0] ^= checkrevision_seeds[mpqNumber];
	
	for (int i = 0; i < numFiles; i++) {
		size_t file_len, remainder, rounded_size, buffer_size;
		
		f = file_open(files[i], FILE_READ);
		if (!f) {
			bncsutil_debug_message_a("error: Failed to open file %s",
				files[i]);
			return 0;
		}
		
		file_len = file_size(f);
		remainder = file_len % 1024;
		rounded_size = file_len - remainder;
		
		file_buffer = (uint8_t*) file_map(f, file_len, 0);
		if (!file_buffer) {
			file_close(f);
			bncsutil_debug_message_a("error: Failed to map file %s into memory",
				files[i]);
			return 0;
		}
		
		if (remainder == 0) {
			// Mapped buffer may be used directly, without padding.
			dwBuf = (uint32_t*) file_buffer;
			buffer_size = file_len;
		} else {
			// Must be padded to nearest KB.
			size_t extra = 1024 - remainder;
			uint8_t pad = (uint8_t) 0xFF;
			uint8_t* pad_dest;
			
			buffer_size = file_len + extra;
			dwBuf = (uint32_t*) malloc(buffer_size);
			if (!dwBuf) {
				bncsutil_debug_message_a("error: Failed to allocate %d bytes "
					"of memory as a temporary buffer", buffer_size);
				file_unmap(f, file_buffer);
				file_close(f);
				return 0;
			}
			
			memcpy(dwBuf, file_buffer, file_len);
			file_unmap(f, file_buffer);
			file_buffer = (uint8_t*) 0;
			
			pad_dest = ((uint8_t*) dwBuf) + file_len;
			for (size_t j = file_len; j < buffer_size; j++) {
				*pad_dest++ = pad--;
			}
			
		}

		current = dwBuf;
		for (size_t j = 0; j < buffer_size; j += 4) {
			values[3] = LSB4(*(current++));
			for (int k = 0; k < curFormula; k++) {
				switch (ops[k]) {
					case '+':
						values[ovd[k]] = values[ovs1[k]] + values[ovs2[k]];
						break;
					case '-':
						values[ovd[k]] = values[ovs1[k]] - values[ovs2[k]];
						break;
					case '^':
						values[ovd[k]] = values[ovs1[k]] ^ values[ovs2[k]];
						break;
					case '*':
						// well, you never know
						values[ovd[k]] = values[ovs1[k]] * values[ovs2[k]];
						break;
					case '/':
						// well, you never know
						values[ovd[k]] = values[ovs1[k]] / values[ovs2[k]];
						break;
					default:
						// unrecognized operation
						// shit
						file_unmap(f, dwBuf);
						file_close(f);
						return 0;
				}
			}
		}

		if (file_buffer)
 			file_unmap(f, file_buffer);
		else if (dwBuf && file_buffer == 0)
			free(dwBuf); // padded buffer
		file_close(f);
	}

	*checksum = (unsigned long) LSB4(values[2]);
#if DEBUG
	bncsutil_debug_message_a("\tChecksum = %lu", *checksum);
#endif
	return 1;
}
示例#8
0
/**
 * Creates a new CD-key decoder object, using the specified key.
 * keyLength should be the length of the key, NOT INCLUDING the
 * null-terminator.  Applications should use isKeyValid after using
 * this constructor to check the validity of the provided key.
 */
CDKeyDecoder::CDKeyDecoder(const char* cdKey, size_t keyLength) {
    unsigned int i;
    
    initialized = 0;
	product = 0;
	value1 = 0;
	value2 = 0;
    keyOK = 0;
    hashLen = 0;
	cdkey = (char*) 0;
	w3value2 = (char*) 0;
	keyHash = (char*) 0;
    
    if (keyLength <= 0) return;
    
    // Initial sanity check
    if (keyLength == 13) {
        // StarCraft key
        for (i = 0; i < keyLength; i++) {
            if (!isdigit(cdKey[i])) return;
        }
        keyType = KEY_STARCRAFT;
#if DEBUG
				bncsutil_debug_message_a(
					"Created CD key decoder with STAR key %s.", cdKey
				);
#endif
    } else {
        // D2/W2/W3 key
        for (i = 0; i < keyLength; i++) {
            if (!isalnum(cdKey[i])) return;
        }
        switch (keyLength) {
            case 16:
                keyType = KEY_WARCRAFT2;
#if DEBUG
				bncsutil_debug_message_a(
					"Created CD key decoder with W2/D2 key %s.", cdKey
				);
#endif
                break;
            case 26:
                keyType = KEY_WARCRAFT3;
#if DEBUG
				bncsutil_debug_message_a(
					"Created CD key decoder with WAR3 key %s.", cdKey
				);
#endif
                break;
            default:
#if DEBUG
				bncsutil_debug_message_a(
					"Created CD key decoder with unrecognized key %s.", cdKey
				);
#endif
                return;
        }
    }
    
    cdkey = new char[keyLength + 1];
    initialized = 1;
    keyLen = keyLength;
    strcpy(cdkey, cdKey);
    
    switch (keyType) {
        case KEY_STARCRAFT:
            keyOK = processStarCraftKey();
#if DEBUG
			bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; "
				"private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2());
#endif
            break;
        case KEY_WARCRAFT2:
            keyOK = processWarCraft2Key();
#if DEBUG
			bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; "
				"private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2());
#endif
            break;
        case KEY_WARCRAFT3:
            keyOK = processWarCraft3Key();
#if DEBUG
			bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; ",
				cdkey, keyOK, getProduct(), getVal1());
#endif
            break;
        default:
            return;
    }
}