#include "appleauth/iauth.h" #include "tier2/fileformats/plist.h" #include "http/http.h" #include "openssl/srp.h" #include "openssl/sha.h" #include "tier0/rand.h" IHTTPClientManager *g_pHttpClientMgr = NULL; // autogenerated #define APPLE_LOCAL_USER "e2e70285da39596ef06153b9c4e1e5dc8d2f983bc5cd63f5b1e292207060d931" #define APPLE_HTTP_HEADER \ { \ {"X-Apple-I-Client-Time", "2026-1-1T12:00:00"}, \ {"X-Apple-Locale", "en_US"}, \ {"X-Apple-I-TimeZone", "Europe/Kyiv"}, \ {"X-Mme-Client-Info", " "}, \ {"User-Agent", "akd/1.0 CFNetwork/808.1.4"}, \ {"X-Apple-I-MD-LU", APPLE_LOCAL_USER}, \ {"X-Apple-I-MD-M", "0"}, \ {"X-Apple-I-SRL-NO", "0"}, \ {"X-Mme-Device-Id", "0"}, \ {"Content-Type", "text/x-xml-plist"}, \ {"Accept", "*/*"}, \ }; class CAppleAuth: public IAppleAuth { public: virtual void Init() override; virtual void Shutdown() override; virtual EAppleAuthStatus SubmitLoginData( const char *szEmail, const char *szPassword ) override; virtual EAppleAuthStatus Submit2FA( const char *szCode ) override; CUtlString FetchADIPB(); void FetchHeaders( CUtlString szAdiPb ); IHTTPClient *m_pANIClient; IHTTPClient *m_pGrandSlamClient; CUtlString m_szProvisionStart = "/grandslam/MidService/startMachineProvisioning"; CUtlString m_szProvisionFinish = "/grandslam/MidService/finishMachineProvisioning"; IJSONObject *pHeader; CUtlString m_szAppleIMD; CUtlString m_szAppleIMDM; CUtlString m_szAppleIMDRINFO; }; CUtlString CAppleAuth::FetchADIPB() { CUtlString szProvisionExpectedInputRaw = NULL; IJSONObject *pObject = NULL; IJSONObject *pPlistObject = NULL; CUtlString szProvisionExpectedInput = NULL; CUtlString szAdiPb = NULL; m_pANIClient = g_pHttpClientMgr->Connect("ani.sidestore.io", true, NULL); m_pGrandSlamClient = g_pHttpClientMgr->Connect("gsa.apple.com", true, NULL); { HTTPHeaderParam_t params[] = APPLE_HTTP_HEADER; HTTPHeader_t header = { sizeof(params)/sizeof(HTTPHeaderParam_t), params, }; m_pGrandSlamClient->Get("/grandslam/GsService2/lookup", &header); HTTPResponse_t r = m_pGrandSlamClient->GetResponse(); if ( r.m_uCode != 200 ) { g_pHttpClientMgr->Disconnect(m_pANIClient); g_pHttpClientMgr->Disconnect(m_pGrandSlamClient); return NULL; } } if ( !m_pANIClient->WebSocket_Connect("/v3/provisioning_session") ) Plat_FatalErrorFunc("Failed to init AppleAuth websocket\n"); // Getting adipb while ( ( szProvisionExpectedInputRaw = m_pANIClient->WebSocket_RecvText() ) != NULL ) { pObject = JSONManager()->ReadString(szProvisionExpectedInputRaw); szProvisionExpectedInput = pObject->GetValue("result")->GetStringValue(); V_printf("%s\n",szProvisionExpectedInput.GetString()); if ( szProvisionExpectedInput == "GiveIdentifier" ) { m_pANIClient->WebSocket_SendText("{\"identifier\": \"" APPLE_LOCAL_USER "\"}"); continue; } if ( szProvisionExpectedInput == "GiveStartProvisioningData" ) { const char *plist = "\n" "\n" "\n" "\n" "\tHeader\n" "\t\n" "\tRequest\n" "\t\n" "\n" "\n"; HTTPHeaderParam_t params[] = APPLE_HTTP_HEADER; HTTPHeader_t header = { sizeof(params)/sizeof(HTTPHeaderParam_t), params, }; m_pGrandSlamClient->Post(m_szProvisionStart, &header, V_strlen(plist), plist); HTTPResponse_t r = m_pGrandSlamClient->GetResponse(); if ( r.m_uCode != 200 ) { g_pHttpClientMgr->Disconnect(m_pANIClient); g_pHttpClientMgr->Disconnect(m_pGrandSlamClient); return NULL; } IJSONObject *pObject = PropertyListManager()->ReadString(r.m_message); CUtlString spim = pObject->GetValue("Response")->GetObject()->GetValue("spim")->GetStringValue(); m_pANIClient->WebSocket_SendText(CUtlString("{\"spim\": \"%s\"}", spim.GetString())); continue; } if ( szProvisionExpectedInput == "GiveEndProvisioningData" ) { CUtlString cpim = pObject->GetValue("cpim")->GetStringValue(); CUtlString plist = CUtlString( "\n" "\n" "\n" "\n" "\tHeader\n" "\t\n" "\tRequest\n" "\t\n" "\tcpim\n" "\t%s\n" "\t\n" "\n" "\n", cpim.GetString()); HTTPHeaderParam_t params[] = APPLE_HTTP_HEADER; HTTPHeader_t header = { sizeof(params)/sizeof(HTTPHeaderParam_t), params, }; m_pGrandSlamClient->Post(m_szProvisionFinish, &header, V_strlen(plist), plist); HTTPResponse_t r = m_pGrandSlamClient->GetResponse(); if ( r.m_uCode != 200 ) { g_pHttpClientMgr->Disconnect(m_pANIClient); g_pHttpClientMgr->Disconnect(m_pGrandSlamClient); return NULL; } IJSONObject *pObject = PropertyListManager()->ReadString(r.m_message); CUtlString tk = pObject->GetValue("Response")->GetObject()->GetValue("tk")->GetStringValue(); CUtlString ptm = pObject->GetValue("Response")->GetObject()->GetValue("ptm")->GetStringValue(); V_printf("%s\n",CUtlString("{\"tk\": \"%s\", \"ptm\": \"%s\"}", tk.GetString(), ptm.GetString()).GetString()); m_pANIClient->WebSocket_SendText(CUtlString("{\"tk\": \"%s\", \"ptm\": \"%s\"}", tk.GetString(), ptm.GetString())); continue; } if ( szProvisionExpectedInput == "ProvisioningSuccess" ) { szAdiPb = pObject->GetValue("adi_pb")->GetStringValue(); g_pHttpClientMgr->Disconnect(m_pANIClient); break; } if ( szProvisionExpectedInput == "Timeout" ) { break; } g_pHttpClientMgr->Disconnect(m_pANIClient); g_pHttpClientMgr->Disconnect(m_pGrandSlamClient); return NULL; } g_pHttpClientMgr->Disconnect(m_pANIClient); g_pHttpClientMgr->Disconnect(m_pGrandSlamClient); return szAdiPb; } void CAppleAuth::FetchHeaders( CUtlString szAdiPb ) { // Get header HTTPHeaderParam_t params[] = { "Content-Type", "application/json", }; HTTPHeader_t header = { sizeof(params)/sizeof(HTTPHeaderParam_t), params, }; m_pANIClient = g_pHttpClientMgr->Connect("ani.sidestore.io", true, NULL); CUtlString szPostData = CUtlString("{\"identifier\": \"" APPLE_LOCAL_USER "\", \"adi_pb\": \"%s\"}", szAdiPb.GetString()); V_printf("%s\n",szPostData.GetString()); m_pANIClient->Post("/v3/get_headers", &header, V_strlen(szPostData), szPostData); HTTPResponse_t r = m_pANIClient->GetResponse(); V_printf("%i\n",r.m_uCode); if ( r.m_uCode == 200 ) { V_printf("%s\n",r.m_message.GetMemory()); pHeader = JSONManager()->ReadString(r.m_message); m_szAppleIMD = pHeader->GetValue("X-Apple-I-MD")->GetStringValue(); m_szAppleIMDM = pHeader->GetValue("X-Apple-I-MD-M")->GetStringValue(); m_szAppleIMDRINFO = pHeader->GetValue("X-Apple-I-MD-RINFO")->GetStringValue(); JSONManager()->FreeObject(pHeader); } g_pHttpClientMgr->Disconnect(m_pANIClient); } void CAppleAuth::Init() { CreateInterfaceFn fnHttpFactory = Sys_GetFactory("funnyhttp"); g_pHttpClientMgr = (IHTTPClientManager*)fnHttpFactory(HTTP_CLIENT_INTERFACE_VERSION, NULL); CUtlString szAdiPb = FetchADIPB(); FetchHeaders(szAdiPb); } void CAppleAuth::Shutdown() { } EAppleAuthStatus CAppleAuth::SubmitLoginData( const char *szEmail, const char *szPassword ) { const char *pszUser = "your_username"; const char *pszPass = ""; SRP_gN *pstGN = SRP_get_default_gN("2048"); if (!pstGN) return APPLE_AUTH_FAILURE; const BIGNUM *pN = pstGN->N; const BIGNUM *pG = pstGN->g; unsigned char aucSalt[16]; Plat_URandom(sizeof(aucSalt), aucSalt); unsigned char aucHash[SHA256_DIGEST_LENGTH]; SHA256_CTX stCtx; SHA256_Init(&stCtx); SHA256_Update(&stCtx, aucSalt, sizeof(aucSalt)); SHA256_Update(&stCtx, pszUser, strlen(pszUser)); SHA256_Update(&stCtx, ":", 1); SHA256_Update(&stCtx, pszPass, strlen(pszPass)); SHA256_Final(aucHash, &stCtx); BIGNUM *pX = BN_bin2bn(aucHash, SHA256_DIGEST_LENGTH, NULL); BIGNUM *pV = BN_new(); BN_CTX *pstCtx = BN_CTX_new(); if (!BN_mod_exp(pV, pG, pX, pN, pstCtx)) return APPLE_AUTH_FAILURE; BN_free(pX); BIGNUM *pA = BN_new(); BIGNUM *pApriv = BN_new(); if (!BN_rand(pApriv, 256, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) return APPLE_AUTH_FAILURE; if (!BN_mod_exp(pA, pG, pApriv, pN, pstCtx)) return APPLE_AUTH_FAILURE; char *pszA = BN_bn2hex(pA); V_printf("A: %s\n",pszA); CUtlString plist = CUtlString( "\n" "\n" "\n" "\n" "\tHeader\n" "\t\n" "\tRequest\n" "\t\n" "\tA2k\n" "\t%s\n" "\tps\n" "\ts2ks2k_fo\n" "\t%s\n" "\to\n" "\tcomplete\n" "\tcpd\n" "\t\n" "\tbootstrap\n" "\t\n" "\tcapp\n" "\tAppStore\n" "\tckgen\n" "\t\n" "\tdc\n" "\t#d4c5b3\n" "\tdec\n" "\t#e1e4e3\n" "\tloc\n" "\ten_US\n" "\tpbe\n" "\t\n" "\tprtn\n" "\tME349\n" "\tsvct\n" "\tiTunes\n" "\tX-Apple-I-MD\n" "\t%s\n" "\tX-Apple-I-MD-M\n" "\t%s\n" "\tX-Apple-I-MD-RINFO\n" "\t%s\n" "\t\n" "\t\n" "\n" "\n", pszA, szEmail, m_szAppleIMD.GetString(), m_szAppleIMDM.GetString(), m_szAppleIMDRINFO.GetString()); m_pGrandSlamClient = g_pHttpClientMgr->Connect("gsa.apple.com", true, NULL); HTTPHeaderParam_t params[] = { {"Content-Type", "text/x-xml-plist"}, {"Accept", "*/*"}, }; HTTPHeader_t header = { sizeof(params)/sizeof(HTTPHeaderParam_t), params, }; V_printf("%s\n",plist.GetString()); m_pGrandSlamClient->Post("/grandslam/GsService2", &header, plist.GetLenght(), plist); HTTPResponse_t stResponse = m_pGrandSlamClient->GetResponse(); V_printf("%i\n", stResponse.m_uCode); if (stResponse.m_uCode == 200) { V_printf("%s\n",stResponse.m_message.GetMemory()); } g_pHttpClientMgr->Disconnect(m_pGrandSlamClient); OPENSSL_free(pszA); BN_free(pApriv); BN_free(pA); BN_free(pV); BN_CTX_free(pstCtx); return APPLE_AUTH_SUCCESS; } EAppleAuthStatus CAppleAuth::Submit2FA( const char *szCode ) { } static CAppleAuth s_appleAuth; EXPOSE_INTERFACE_GLOBALVAR(CAppleAuth, IAppleAuth, APPLE_AUTH_INTERFACE_VERSION, s_appleAuth);