/* * Skype Login * * Based on: * FakeSkype : Skype reverse engineering proof-of-concept client * Ouanilo MEDEGAN (c) 2006 http://www.oklabs.net * pyskype : Skype login Python script by uunicorn * * Written by: leecher@dose.0wnz.at (c) 2015 * * Module: Credentials handling, reads/writes old Skype credentials format * */ #include "common.h" #include "objects.h" #include "random.h" #include "crc.h" #include "credentials.h" #ifdef _WIN32 #define CRC_SIZE sizeof(short) #else #define CRC_SIZE 0 #endif Memory_U Credentials_Write(Skype_Inst *pInst) { Memory_U creds; uchar *Browser; uint Crc; creds.MsZ = sizeof(pInst->LoginD.LoginHash) + MODULUS_SZ + pInst->LoginD.SignedCredentials.MsZ + CRC_SIZE; if (!(Browser = creds.Memory = malloc(creds.MsZ))) { creds.MsZ = 0; return creds; } memcpy(Browser, pInst->LoginD.LoginHash, sizeof(pInst->LoginD.LoginHash)); Browser+=sizeof(pInst->LoginD.LoginHash); BN_bn2bin(pInst->LoginD.RSAKeys->d, Browser); Browser+=MODULUS_SZ; memcpy(Browser, pInst->LoginD.SignedCredentials.Memory, pInst->LoginD.SignedCredentials.MsZ); Browser+=pInst->LoginD.SignedCredentials.MsZ; #ifdef _WIN32 Crc = crc32(creds.Memory, Browser-creds.Memory, -1); *Browser++ = *((uchar *)(&Crc) + 0); *Browser++ = *((uchar *)(&Crc) + 1); #endif return creds; } /* 0 - OK -1 - Invalid size of credentials blob -2 - Invalid CRC -3 - Out of memory -4 - Unable to parse Signed credentials -5 - RSA public key not found */ int Credentials_Read(Skype_Inst *pInst, Memory_U creds, SResponse *LoginDatas) { uchar *Browser; uint Crc, Idx; RSA *Keys; if (creds.MsZ < sizeof(pInst->LoginD.LoginHash) + MODULUS_SZ + 16 + CRC_SIZE) return -1; #ifdef _WIN32 Crc = crc32(creds.Memory, creds.MsZ-2, -1); if (*((uchar *)(&Crc) + 0) != *((uchar*)creds.Memory+creds.MsZ-2) || *((uchar *)(&Crc) + 1) != *((uchar*)creds.Memory+creds.MsZ-1)) { pInst->pfLog(pInst->pLogStream, "Credentials: Bad CRC!"); return -2; } #endif Browser = creds.Memory; memcpy (pInst->LoginD.LoginHash, Browser, sizeof(pInst->LoginD.LoginHash)); Browser+=sizeof(pInst->LoginD.LoginHash); Keys=RSA_new(); BN_hex2bn(&(Keys->e), "010001"); Keys->d = BN_bin2bn(Browser, MODULUS_SZ, NULL); Browser+=MODULUS_SZ; if (pInst->LoginD.SignedCredentials.Memory) free(pInst->LoginD.SignedCredentials.Memory); pInst->LoginD.SignedCredentials.MsZ = creds.MsZ - CRC_SIZE - (Browser-creds.Memory); if (!(pInst->LoginD.SignedCredentials.Memory = malloc(pInst->LoginD.SignedCredentials.MsZ))) { pInst->LoginD.SignedCredentials.MsZ = 0; RSA_free(Keys); return -3; } memcpy(pInst->LoginD.SignedCredentials.Memory, Browser, pInst->LoginD.SignedCredentials.MsZ); // Now credentials are read, but we need to finish LoginD.RSAKeys by unpacking Signed Credentials if (Credentials_Parse(pInst, pInst->LoginD.SignedCredentials, LoginDatas)<0) { RSA_free(Keys); return -4; } for (Idx = 0; Idx < LoginDatas->NbObj; Idx++) { if (LoginDatas->Objs[Idx].Id == OBJ_ID_LDMODULUS) { Keys->n = BN_bin2bn(LoginDatas->Objs[Idx].Value.Memory.Memory, LoginDatas->Objs[Idx].Value.Memory.MsZ, NULL); if (pInst->LoginD.RSAKeys) RSA_free(pInst->LoginD.RSAKeys); pInst->LoginD.RSAKeys = Keys; return 0; } } RSA_free(Keys); return -5; } int Credentials_Parse(Skype_Inst *pInst, Memory_U Pcred, SResponse *LoginDatas) { uchar *PostProcessed, *Browser; char *Key; uint KeyIdx, PPsZ; RSA *SkypeRSA; Memory_U creds = Pcred; if (!(creds.Memory = malloc(creds.MsZ))) return -2; KeyIdx = htonl(*(uint *)Pcred.Memory); Pcred.Memory += sizeof(uint); Pcred.MsZ -= sizeof(uint); SkypeRSA = RSA_new(); Key = KeySelect(KeyIdx); BN_hex2bn(&(SkypeRSA->n), Key); BN_hex2bn(&(SkypeRSA->e), "010001"); PPsZ = RSA_public_decrypt(Pcred.MsZ, Pcred.Memory, creds.Memory, SkypeRSA, RSA_NO_PADDING); RSA_free(SkypeRSA); if (PPsZ == -1) { pInst->pfLog(pInst->pLogStream, "Credentials decryption failed..\n"); free(creds.Memory); return -1; } PostProcessed = FinalizeLoginDatas(pInst, creds.Memory, &PPsZ, NULL, 0); if (PostProcessed == NULL) { pInst->pfLog(pInst->pLogStream, "Bad Datas Finalization..\n"); free (creds.Memory); return -1; } LoginDatas->Objs = NULL; LoginDatas->NbObj = 0; Browser = PostProcessed; ManageObjects(&Browser, PPsZ, LoginDatas); free(PostProcessed); free(creds.Memory); return 0; }