spotifykeydumper/SpotifyKeyDumper/Hooks.cpp

603 lines
19 KiB
C++
Raw Normal View History

2020-11-02 06:08:10 +01:00
#include "pch.h"
#include "Utils.h"
#include "Hooks.h"
2020-11-16 04:56:22 +01:00
typedef int (__cdecl* keyToLE_v25)(unsigned int* dest, int* key, int bits);
keyToLE_v25 keyToLE_v25_hook = nullptr;
2020-11-02 06:08:10 +01:00
2020-11-16 04:56:22 +01:00
typedef int (__cdecl* keyToLE_v28)(unsigned int* dest, int* key, int bits, bool isEncoded);
keyToLE_v28 keyToLE_v28_hook = nullptr;
typedef int* (__thiscall* authToken_v45)(void* This, int* a2);
authToken_v45 authToken_v45_hook = nullptr;
2020-11-02 06:08:10 +01:00
typedef int* (__thiscall* openTrack_v45)(void* This, int a2, void* a3, int a4, __int64 position, char a6, void* a7);
openTrack_v45 openTrack_v45_hook = nullptr;
typedef int* (__thiscall* log_v45)(void* This, int a2, int a3, void* a4, const char* classStr, int a6,
DWORD* logThing);
log_v45 log_v45_hook;
typedef void (__thiscall* fileIdWriter_v45)(void* This, int* a2);
fileIdWriter_v45 fileIdWriter_v45_hook = nullptr;
typedef void (__thiscall* signalEmitter_v45)(void* This, int a1, int a2);
signalEmitter_v45 signalEmitter_v45_hook = nullptr;
typedef void (__cdecl* keyDecoder_v47)();
keyDecoder_v47 keyDecoder_v47_hook = nullptr;
typedef int (__thiscall* startUpdate_v47)(char* This, char* newVerChars, char** updateUrlPtr, void* a4, int a5, void* a6,
int a7);
startUpdate_v47 startUpdate_v47_hook = nullptr;
typedef void (__thiscall* uriHandler_v47)(DWORD* This, void* a2, int a3, char a4);
uriHandler_v47 uriHandler_v47_hook = nullptr;
typedef bool (__cdecl* isValidUrl_v25)(int* urlThingArg, int a2);
isValidUrl_v25 isValidUrl_v25_hook = nullptr;
typedef int (__cdecl* getBitrate_v25)(int quality);
getBitrate_v25 getBitrate_v25_hook = nullptr;
2020-12-14 00:12:44 +01:00
typedef int (__cdecl* impDecFunc_v47)(DWORD* keyLE, int intOne, DWORD* iv, int* a4);
impDecFunc_v47 impDecFunc_v47_hook = nullptr;
typedef int (__thiscall* sttngsLkp_v48)(void* This, char* strLookup, size_t len);
sttngsLkp_v48 sttngsLkp_v48_hook = nullptr;
std::string authToken = std::string();
std::string keyStr = std::string();
std::string uriStr = std::string();
2020-12-01 02:35:18 +01:00
std::string fileId = std::string();
int quality = 4;
2020-12-01 02:35:18 +01:00
__int64 newPosition = 0;
bool signalled = false;
int destKeyPtr = 0;
char* keyBuffer_v47;
2020-11-02 06:08:10 +01:00
2020-12-01 02:35:18 +01:00
std::string lastUri = std::string();
void TryDownload()
{
if (signalled && lastUri.compare(uriStr) != 0)
{
signalled = false;
lastUri = uriStr;
std::thread t2(Utils::DownloadSong, std::string(fileId), uriStr, keyStr, authToken, quality);
2020-12-01 02:35:18 +01:00
t2.detach();
}
}
2020-11-02 06:08:10 +01:00
int __cdecl keyToLE_hook_v25(unsigned int* dest, int* key, int bits)
{
if (bits == 128)
{
BYTE keyBuffer[16] = {};
2020-11-02 06:08:10 +01:00
BYTE* keyBufPtr = keyBuffer;
memcpy(keyBufPtr, key, 16);
// Only print out key if it is different
std::string newKeyStr = Utils::HexString(keyBufPtr, 16);
if (newKeyStr.compare(keyStr) != 0)
2020-11-02 06:08:10 +01:00
std::cout << "Key: " << newKeyStr << std::endl << std::endl;
keyStr = newKeyStr;
2020-11-02 06:08:10 +01:00
}
2020-11-16 04:56:22 +01:00
return keyToLE_v25_hook(dest, key, bits);
2020-11-02 06:08:10 +01:00
}
int __cdecl keyToLE_hook_v28(unsigned int* dest, int* key, int bits, bool isEncoded)
2020-11-02 06:08:10 +01:00
{
if (bits == 128)
{
void* decodedKeyPtr = key;
if (isEncoded)
{
// key is encoded with some sort of algorithm; decode it here
unsigned int keyDecoded[4] = {};
2020-11-02 06:08:10 +01:00
unsigned int uVar1;
unsigned int keyPtr;
unsigned int uVar3;
int index;
keyPtr = *key;
index = 15;
uVar3 = key[1];
keyDecoded[0] = key[2];
keyDecoded[1] = key[3];
keyDecoded[2] = key[4];
keyDecoded[3] = key[5];
do
{
uVar1 = keyDecoded[index - 1 & 3];
keyDecoded[index & 3] =
keyDecoded[index & 3] +
(((((uVar1 + index + keyPtr & uVar1 * 16 + uVar3) * 2 + uVar1 * -17) -
index) - uVar3) - keyPtr);
2020-11-16 04:56:22 +01:00
index--;
2020-11-02 06:08:10 +01:00
}
while (index >= 0);
decodedKeyPtr = &keyDecoded;
}
// Copy key bytes to new buffer
char keyBuffer[16] = {};
char* keyBufPtr = keyBuffer;
2020-11-02 06:08:10 +01:00
memcpy(keyBufPtr, decodedKeyPtr, 16);
// Only print out key if it is different
std::string newKey = std::string(keyBufPtr, 16);
if (newKey.compare(keyStr) != 0)
{
std::cout << "Key: " << Utils::HexString(reinterpret_cast<BYTE*>(&newKey[0]), 16) << std::endl << std::endl;
keyStr = newKey;
2020-12-01 02:35:18 +01:00
if (Utils::GetSpotifyVersion() >= 45)
TryDownload();
}
2020-11-02 06:08:10 +01:00
}
2020-11-16 04:56:22 +01:00
return keyToLE_v28_hook(dest, key, bits, isEncoded);
}
int* __fastcall authToken_hook_v45(void* This, void* _EDX, int* a2)
{
char* authToken = (char*) *(DWORD*)((a2) + 2); // 8/4 = 2
//std::cout << "authToken: " << authToken << std::endl << std::endl;
::authToken = std::string(authToken);
return authToken_v45_hook(This, a2);
2020-11-02 06:08:10 +01:00
}
int* __fastcall openTrack_hook_v45(void* This, void* _EDX, int a2, void* a3, int a4, __int64 position, char a6,
void* a7)
{
//std::cout << "openTrack!!!" << std::endl << std::endl;
return openTrack_v45_hook(This, a2, a3, a4, newPosition, a6, a7);
}
int* __fastcall log_hook_v45(void* This, void* _EDX, int a2, int a3, void* a4, const char* classStr, int a6,
DWORD* logThing)
{
if (!Utils::BadPtr(logThing))
{
char* logChars = (char*)(*logThing);
if (!Utils::BadPtr(logChars))
{
std::string logStr = std::string(logChars);
if (logStr.length() > 32 && logStr.compare(8, 9, "track_uri") == 0) // 19 + 13 = 32
{
if (logStr.compare(19, 13, "spotify:track") == 0)
{
//std::cout << "Track URI: " << logStr.substr(19, std::string::npos) << std::endl;
uriStr = logStr.substr(19, std::string::npos);
newPosition = 0;
}
else if (logStr.length() > 34 && logStr.compare(19, 15, "spotify:episode") == 0)
{
//std::cout << "Episode URI: " << logStr.substr(19, std::string::npos) << std::endl;
uriStr = logStr.substr(19, std::string::npos);
newPosition = 0;
}
// TODO: e.g. spotify:ad:000000014990f3ec000000203522e473
//else if (logStr.compare(19, 11, "spotify:ad") == 0) // Possibly this works?
/*else
{
std::cout << "Skipping ad: " << logStr.substr(19, std::string::npos) << std::endl;
newPosition = 29000; // 29 seconds: duration of ad
}*/
}
}
}
return log_v45_hook(This, a2, a3, a4, classStr, a6, logThing);
}
void __fastcall fileIdWriter_hook_v45(void* This, void* _EDX, int* a2)
{
// Program sometimes crashes after ads. Could possibly be due to bad pointers
if (Utils::BadPtr(a2) || Utils::BadPtr(a2 + 16) || Utils::BadPtr((char*)*(DWORD*)(a2 + 16)))
return;
// [[ebp+8]+28]
char* fileId = (char*) *(DWORD*)(a2 + 16); // 0x40 / 4 = 16
2020-12-01 02:35:18 +01:00
::fileId = std::string(fileId);
2020-12-01 02:35:18 +01:00
/*std::cout << "fileId = " << fileId << std::endl;
std::cout << "uriStr = " << uriStr<< std::endl;*/
if (uriStr.length() > 15 && uriStr.compare(0, 15, "spotify:episode") == 0)
TryDownload();
return fileIdWriter_v45_hook(This, a2);
}
int signalEmitterInitCount = 0;
const int signalEmitterRequired = 3;
void __fastcall signalEmitter_hook_v45(void* This, void* _EDX, int a1, int a2)
{
// Required in order to guarentee accurate data needed
if (signalEmitterInitCount < signalEmitterRequired)
signalEmitterInitCount++;
else
{
//std::cout << "signalled = true" << std::endl;
signalled = true;
2020-11-16 04:56:22 +01:00
}
return signalEmitter_v45_hook(This, a1, a2);
2020-11-16 04:56:22 +01:00
}
int __cdecl keyToLE_hook_v47(unsigned int* dest, int* key, int bits, bool isEncoded)
{
// Same hook as previously, except key is not decoded in this function anymore
if (bits == 128 && isEncoded)
destKeyPtr = (int)dest;
return keyToLE_v28_hook(dest, key, bits, isEncoded);
}
void __cdecl KeyBufferToKeyStr()
{
std::string newKey = std::string(keyBuffer_v47, 16);
if (keyStr.compare(newKey) != 0)
{
keyStr = newKey;
std::cout << "Key: " << Utils::HexString(reinterpret_cast<BYTE*>(&newKey[0]), 16) << std::endl;
2020-12-01 02:35:18 +01:00
TryDownload();
}
}
__declspec(naked) void keyDecoder_hook_v47()
{
// The spot where this hooks and runs is very weird. Spotify now handles decoding of the key in an instruction set
// held in the .data section (where disassemblers won't typically explore). Looks intentional. :)
__asm
{
pushfd // Push flags and registers to stack to preserve state before
pushad
mov ebx, esi
sub ebx, 12 // Subtract 12 from esi to compare; esi will match on the last 4 bytes of key
cmp destKeyPtr, ebx // Check if destKeyPtr matches ebx (esi - 12)
jne END // If destKeyPtr and esi - 12 don't match, jump to end
mov eax, offset keyBuffer_v47 // Get address from char pointer keyBuffer_v47
mov edi, [eax]
mov cx, 4 // Iterate 4 times (copy 4 bytes each time)
BSWAP_LOOP: // Loop to swap endianness of each dword
mov eax, [ebx]
bswap eax
mov [edi], eax
add ebx, 4
add edi, 4
dec cx
jnz BSWAP_LOOP
call KeyBufferToKeyStr // Set keyStr to chars from keyBuffer_v47 (and print key)
END:
popad // Pop flags and registers back from the stack to preserve state before
popfd
jmp keyDecoder_v47_hook // Jump to trampoline function to run overwritten instructions and continue
}
}
int __fastcall startUpdate_hook_v47(char* This, void* _EDX, char* newVerChars, char** updateUrlPtr, void* a4, int a5,
void* a6, int a7)
{
*updateUrlPtr[0] = '\x00'; // Breaks the URL to prevent updating
return startUpdate_v47_hook(This, newVerChars, updateUrlPtr, a4, a5, a6, a7);
}
void __fastcall uriHandler_hook_v47(DWORD* This, void* _EDX, void* a2, int a3, char a4)
{
int uriType = *This;
// Check if uri type is an ad (12)
if (uriType == 12)
{
DWORD* adUri = This - 42; // 168 / 4 = 42
char* adUriChars = (char*)*adUri;
for (int index = 0; index < 32; index++)
adUriChars[index] = '0';
//std::cout << "Ad uri: spotify:ad:" << std::string((char*)*adUri, 32) << std::endl;
return;
}
return uriHandler_v47_hook(This, a2, a3, a4);
}
bool __cdecl isValidUrl_hook_v25(int* urlThingArg, int arg_4)
{
unsigned char* source = (unsigned char*)*(void**)*(urlThingArg + 1);
std::u16string u16_str(reinterpret_cast<const char16_t*>(source));
std::string utf8Url = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.to_bytes(u16_str);
//std::cout << "URL: " << utf8Url << std::endl;
if (utf8Url.find("doubleclick") != std::string::npos)
{
//printf("Blocked URL: %s\n", utf8Url.c_str());
return false;
}
else
return isValidUrl_v25_hook(urlThingArg, arg_4);
}
// TODO: Fix downloads on low quality and very high quality to get rid of this
bool hasAlertedQuality = false;
int __cdecl getBitrate_hook_v25(int quality)
{
// Force quality to be normal or high quality (since other modes do not reliably work)
// (no, forcing it to very high on a free account does not work)
/*switch (quality)
{
case 0: // Automatic
quality = 3;
break;
case 1: // Low
quality = 2;
break;
case 4: // Very high
quality = 3;
break;
}*/
std::string qualityStr = "?";
switch (quality)
{
case 0:
qualityStr = "Automatic";
break;
case 1:
qualityStr = "Low";
break;
case 2:
qualityStr = "Normal";
break;
case 3:
qualityStr = "High";
break;
case 4:
qualityStr = "Very High";
break;
2020-12-14 00:12:44 +01:00
case 5:
qualityStr = "700k";
break;
}
if (!hasAlertedQuality && quality != 2 && quality != 3)
{
std::cout << "Warning! You have selected an unsupported quality (" + qualityStr + "); select Normal or High"
" quality in the Spotify settings for proper compatibility." << std::endl;
hasAlertedQuality = true;
}
::quality = quality;
return getBitrate_v25_hook(quality);
}
2020-11-16 04:56:22 +01:00
char* GetKeyFuncAddrV26()
2020-11-02 06:08:10 +01:00
{
BYTE ref_v19 = 0x55;
BYTE* byteAtAddrStr = (BYTE*)0x010800C0;
// Byte at byteAtAddr in 1.1.26-19 is 0x55
if (*byteAtAddrStr == ref_v19)
return (char*)0x010800C0;
else
return (char*)0x0107FEC0;
}
2020-11-16 04:56:22 +01:00
char* GetKeyFuncAddrV27()
2020-11-02 06:08:10 +01:00
{
BYTE ref_v7 = 0x55;
BYTE* byteAtAddrStr = (BYTE*)0x01068F90;
// Byte at byteAtAddr in 1.1.27-7 is 0x55
2020-11-02 06:08:10 +01:00
if (*byteAtAddrStr == ref_v7)
return (char*)0x01068F90;
else
return (char*)0x01068F20;
}
2020-12-14 00:12:44 +01:00
char* srUrlChars;
void __cdecl printSRUrl()
{
std::string testStr = std::string(srUrlChars, 95); // 104
std::cout << "Storage Resolve URL: " << testStr << std::endl;
}
__declspec(naked) void testSMHook()
{
2020-12-14 00:12:44 +01:00
__asm
{
pushfd // Push flags and registers to stack to preserve state before
pushad
mov ebx, [eax]
2020-12-14 00:12:44 +01:00
mov eax, offset srUrlChars // Get address from char pointer testStr
mov edi, [eax]
mov cx, 24 // Iterate 24 times (copy 4 bytes each time = 96 bytes total)
COPY_LOOP:
mov eax, [ebx]
mov [edi], eax
add ebx, 4
add edi, 4
dec cx
jnz COPY_LOOP
call printSRUrl // Set keyStr to chars from keyBuffer_v47 (and print key)
popad // Pop flags and registers back from the stack to preserve state before
popfd
jmp keyDecoder_v47_hook // Jump to trampoline function to run overwritten instructions and continue
}
}
constexpr BYTE IV[] = {0x72, 0xE0, 0x67, 0xFB, 0xDD, 0xCB, 0xCF, 0x77, 0xEB, 0xE8, 0xBC, 0x64, 0x3F, 0x63, 0x0D, 0x93};
int __cdecl impDecFunc_hook_v47(DWORD* keyLE, int intOne, DWORD* iv, int* a4)
{
if (/*intOne == 0xA &&*/ !Utils::BadPtr(iv) && memcmp(IV, iv, 16) == 0)
{
// Swap endianness of key by 4 bytes each (+1 int; 16 total)
unsigned long keyBE[4] = {};
keyBE[0] = _byteswap_ulong(*keyLE);
keyBE[1] = _byteswap_ulong(*(keyLE + 1));
keyBE[2] = _byteswap_ulong(*(keyLE + 2));
keyBE[3] = _byteswap_ulong(*(keyLE + 3));
printf("===============================================================================\n");
std::cout << "Key: " << Utils::HexString((BYTE*) keyBE, 16) << std::endl;
std::cout << "IV: " << Utils::HexString((BYTE*) iv, 16) << std::endl;
printf("===============================================================================\n");
}
return impDecFunc_v47_hook(keyLE, intOne, iv, a4);
}
int __fastcall sttngsLkp_hook_v48(void* This, void* _EDX, char* strLookup, size_t len)
{
char* tmpStr;
if (!Utils::BadPtr(strLookup))
{
tmpStr = strLookup;
// Some strLookup's are double pointers
if (!Utils::BadPtr((char*)*(DWORD*)strLookup))
tmpStr = (char*)*(DWORD*)strLookup;
if (memcmp(tmpStr, "app-developer", 13) == 0)
return 2;
else if (memcmp(tmpStr, "employee", 8) == 0 || memcmp(tmpStr, "ta-environment", 14) == 0
|| memcmp(tmpStr, "desktop-beta-tester", 19) == 0 || memcmp(tmpStr, "PLACEHOLDER", 11) == 0)
return 1;
}
return sttngsLkp_v48_hook(This, strLookup, len);
}
2020-11-02 06:08:10 +01:00
void Hooks::Init()
{
int spotifyVer = Utils::GetSpotifyVersion();
// Method is stripped from Release build if this isn't here :/
std::cout << "Spotify version: 1.1." << Utils::GetSpotifyVersion() << std::endl << std::endl;
2020-11-02 06:08:10 +01:00
switch (spotifyVer)
{
case 25:
2020-11-16 04:56:22 +01:00
keyToLE_v25_hook = (keyToLE_v25)Utils::TrampHook32((char*)0x0106B920, (char*)keyToLE_hook_v25, 6);
2020-11-02 06:08:10 +01:00
break;
case 26:
// Two 1.1.26 versions
2020-11-16 04:56:22 +01:00
keyToLE_v25_hook = (keyToLE_v25)Utils::TrampHook32(GetKeyFuncAddrV26(), (char*)keyToLE_hook_v25, 6);
2020-11-02 06:08:10 +01:00
break;
case 27:
// Two 1.1.27 versions
2020-11-16 04:56:22 +01:00
keyToLE_v25_hook = (keyToLE_v25)Utils::TrampHook32(GetKeyFuncAddrV27(), (char*)keyToLE_hook_v25, 6);
2020-11-02 06:08:10 +01:00
break;
case 28:
2020-11-16 04:56:22 +01:00
keyToLE_v28_hook = (keyToLE_v28)Utils::TrampHook32((char*)0x01074650, (char*)keyToLE_hook_v28, 6);
2020-11-02 06:08:10 +01:00
break;
case 29:
2020-11-16 04:56:22 +01:00
keyToLE_v28_hook = (keyToLE_v28)Utils::TrampHook32((char*)0x010861B0, (char*)keyToLE_hook_v28, 6);
break;
2020-11-02 06:08:10 +01:00
case 30:
2020-11-16 04:56:22 +01:00
keyToLE_v28_hook = (keyToLE_v28)Utils::TrampHook32((char*)0x0108E840, (char*)keyToLE_hook_v28, 6);
2020-11-02 06:08:10 +01:00
break;
case 44:
2020-11-16 04:56:22 +01:00
keyToLE_v28_hook = (keyToLE_v28)Utils::TrampHook32((char*)0x010CABC0, (char*)keyToLE_hook_v28, 6);
2020-11-02 06:08:10 +01:00
break;
case 45:
2020-11-16 04:56:22 +01:00
keyToLE_v28_hook = (keyToLE_v28)Utils::TrampHook32((char*)0x010CF780, (char*)keyToLE_hook_v28, 6);
authToken_v45_hook = (authToken_v45)Utils::TrampHook32((char*)0x00BF75F0, (char*)authToken_hook_v45, 7);
log_v45_hook = (log_v45)Utils::TrampHook32((char*)0x010F2370, (char*)log_hook_v45, 5);
fileIdWriter_v45_hook = (fileIdWriter_v45)Utils::TrampHook32((char*)0x00CBB560, (char*)fileIdWriter_hook_v45,
5);
signalEmitter_v45_hook = (signalEmitter_v45)Utils::TrampHook32((char*)0x00B095A0, (char*)signalEmitter_hook_v45,
2020-12-14 00:12:44 +01:00
5);
getBitrate_v25_hook = (getBitrate_v25)Utils::TrampHook32((char*)0x00E48410, (char*)getBitrate_hook_v25, 6);
2020-12-14 00:12:44 +01:00
startUpdate_v47_hook = (startUpdate_v47)Utils::TrampHook32((char*)0x00A0B250, (char*)startUpdate_hook_v47, 5);
2020-11-16 04:56:22 +01:00
break;
case 46:
keyToLE_v28_hook = (keyToLE_v28)Utils::TrampHook32((char*)0x010C2FB0, (char*)keyToLE_hook_v28, 6);
authToken_v45_hook = (authToken_v45)Utils::TrampHook32((char*)0x00BEC8E0, (char*)authToken_hook_v45, 7);
log_v45_hook = (log_v45)Utils::TrampHook32((char*)0x010E59E0, (char*)log_hook_v45, 5);
fileIdWriter_v45_hook = (fileIdWriter_v45)Utils::TrampHook32((char*)0x00CB00D0, (char*)fileIdWriter_hook_v45,
5);
signalEmitter_v45_hook = (signalEmitter_v45)Utils::TrampHook32((char*)0x00B02270, (char*)signalEmitter_hook_v45,
5);
getBitrate_v25_hook = (getBitrate_v25)Utils::TrampHook32((char*)0x00E3C780, (char*)getBitrate_hook_v25, 6);
2020-12-14 00:12:44 +01:00
startUpdate_v47_hook = (startUpdate_v47)Utils::TrampHook32((char*)0x00A03020, (char*)startUpdate_hook_v47, 5);
2020-11-02 06:08:10 +01:00
break;
case 47:
keyBuffer_v47 = new char[16]; // 128 bits = 16 bytes
keyToLE_v28_hook = (keyToLE_v28)Utils::TrampHook32((char*)0x010C5B00, (char*)keyToLE_hook_v47, 6);
keyDecoder_v47_hook = (keyDecoder_v47)Utils::TrampHook32((char*)0x0153148D, (char*)keyDecoder_hook_v47, 7);
authToken_v45_hook = (authToken_v45)Utils::TrampHook32((char*)0x00BED0F0, (char*)authToken_hook_v45, 7);
log_v45_hook = (log_v45)Utils::TrampHook32((char*)0x010E8750, (char*)log_hook_v45, 5);
fileIdWriter_v45_hook = (fileIdWriter_v45)Utils::TrampHook32((char*)0x00CB0630, (char*)fileIdWriter_hook_v45,
5);
signalEmitter_v45_hook = (signalEmitter_v45)Utils::TrampHook32((char*)0x00AFBB50, (char*)signalEmitter_hook_v45,
5);
getBitrate_v25_hook = (getBitrate_v25)Utils::TrampHook32((char*)0x00E3E460, (char*)getBitrate_hook_v25, 6);
2020-12-14 00:12:44 +01:00
startUpdate_v47_hook = (startUpdate_v47)Utils::TrampHook32((char*)0x009FB530, (char*)startUpdate_hook_v47, 5);
//uriHandler_v47_hook = (uriHandler_v47)Utils::TrampHook32((char*)0x010A39E0, (char*)uriHandler_hook_v47, 5);
//isValidUrl_v25_hook = (isValidUrl_v25)Utils::TrampHook32((char*)0x0105CD80, (char*)isValidUrl_hook_v25, 6);
2020-12-14 00:12:44 +01:00
//impDecFunc_v47_hook = (impDecFunc_v47)Utils::TrampHook32((char*)0x010C52F0, (char*)impDecFunc_hook_v47, 6);
break;
case 48:
printf("Downloading are not currently supported on 1.1.48. Please use 1.1.47.\n");
//keyBuffer_v47 = new char[16]; // 128 bits = 16 bytes
keyToLE_v28_hook = (keyToLE_v28)Utils::TrampHook32((char*)0x010E0200, (char*)keyToLE_hook_v47, 6); // Not called
//keyDecoder_v47_hook = (keyDecoder_v47)Utils::TrampHook32((char*)0x0153148D, (char*)keyDecoder_hook_v47, 7);
authToken_v45_hook = (authToken_v45)Utils::TrampHook32((char*)0x00BF7B50, (char*)authToken_hook_v45, 7);
log_v45_hook = (log_v45)Utils::TrampHook32((char*)0x011030E0, (char*)log_hook_v45, 5);
fileIdWriter_v45_hook = (fileIdWriter_v45)Utils::TrampHook32((char*)0x00CBCA60, (char*)fileIdWriter_hook_v45,
5);
signalEmitter_v45_hook = (signalEmitter_v45)Utils::TrampHook32((char*)0x00B02B70, (char*)signalEmitter_hook_v45,
5);
getBitrate_v25_hook = (getBitrate_v25)Utils::TrampHook32((char*)0x00E54D00, (char*)getBitrate_hook_v25, 6);
startUpdate_v47_hook = (startUpdate_v47)Utils::TrampHook32((char*)0x009FD9E0, (char*)startUpdate_hook_v47, 5);
//isValidUrl_v25_hook = (isValidUrl_v25)Utils::TrampHook32((char*)0x01077370, (char*)isValidUrl_hook_v25, 6);
// Dump song manifest URL
//testChars = new char[104];
//keyDecoder_v47_hook = (keyDecoder_v47)Utils::TrampHook32((char*)0x00EE081A, (char*)testSMHook, 5);
// Not called :(
//impDecFunc_v47_hook = (impDecFunc_v47)Utils::TrampHook32((char*)0x010DF9F0, (char*)impDecFunc_hook_v47, 6);
sttngsLkp_v48_hook = (sttngsLkp_v48)Utils::TrampHook32((char*)0x0056A7E0, (char*)sttngsLkp_hook_v48, 5);
break;
2020-11-02 06:08:10 +01:00
}
}