/* * 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: Object management functions * */ #include "common.h" #include "objects.h" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #include #endif void WriteValue(uchar **BufferAddr, uint Value) { uint a; for (a = Value; a > 0x7F; a >>= 7, (*BufferAddr)++) **BufferAddr = (uchar)a | 0x80; **BufferAddr = (uchar) a; (*BufferAddr)++; } void ReadValue(uchar **BufferAddr, uint *Value) { uint a=0; uchar c; for (*Value=0, c=**BufferAddr; a==0 || (c & 0x80); a+=7, (*BufferAddr)++) *Value|=((c=**BufferAddr) & 0x7F) << a; } void WriteObject(uchar **Buffer, ObjectDesc Object) { int IdxDown, IdxUp; Object.ObjListInfos.Id = -1; Object.ObjListInfos.Rank = 0; WriteValue(Buffer, Object.Family); WriteValue(Buffer, Object.Id); switch(Object.Family) { case OBJ_FAMILY_NBR: WriteValue(Buffer, Object.Value.Nbr); break; case OBJ_FAMILY_TABLE: IdxUp = 0; IdxDown = sizeof(Object.Value.Table) - 1; while (IdxDown >= 0) (*Buffer)[IdxDown--] = Object.Value.Table[IdxUp++]; *Buffer += sizeof(Object.Value.Table); break; case OBJ_FAMILY_NETADDR: *(unsigned int *)(*Buffer) = inet_addr(Object.Value.Addr.ip); *Buffer += 4; *(unsigned short *)(*Buffer) = htons((u_short)Object.Value.Addr.port); *Buffer += 2; break; case OBJ_FAMILY_BLOB: WriteValue(Buffer, Object.Value.Memory.MsZ); memcpy(*Buffer, Object.Value.Memory.Memory, Object.Value.Memory.MsZ); *Buffer += Object.Value.Memory.MsZ; break; case OBJ_FAMILY_STRING: memcpy(*Buffer, Object.Value.Memory.Memory, Object.Value.Memory.MsZ); *Buffer += Object.Value.Memory.MsZ; *(*Buffer) = 0x00; *Buffer += 1; break; case OBJ_FAMILY_INTLIST: { uint *IntList; IdxUp = 0; IntList = (uint *)Object.Value.Memory.Memory; WriteValue(Buffer, Object.Value.Memory.MsZ); while (IdxUp < Object.Value.Memory.MsZ) { WriteValue(Buffer, IntList[IdxUp]); IdxUp++; } break; } default: DBGPRINT("WriteObject : Unmanaged Object Family\n"); break; } } int DecodeRawObjects(uchar **Buffer, uint Size, SResponse *Response, ObjectDesc **Objs, int Suffix) { int NbObjs, lIdx, IdxUp, IdxDown; uint Family, Id; uchar *Str, *Mark; struct in_addr IP; ObjectDesc *Object; static int Idx = 0; static int Level = 0; static int CurObjListId = -1; static uint CurObjListRank = 0; uint LocalObjListRank; LocalObjListRank = CurObjListRank; NbObjs = Family = Id = lIdx = 0; Mark = *Buffer; ReadValue(Buffer, &NbObjs); Level += 1; if (Level == 1) Idx += Suffix; while (lIdx < NbObjs) { Family = **Buffer; *Buffer += 1; ReadValue(Buffer, &Id); *Objs = (ObjectDesc *)realloc(*Objs, sizeof(ObjectDesc) * (Idx + 1)); Object = &((*Objs)[Idx]); Object->Family = Family; Object->Id = Id; Object->ObjListInfos.Id = CurObjListId; Object->ObjListInfos.Rank = LocalObjListRank; switch (Family) { case OBJ_FAMILY_NBR: ReadValue(Buffer, &(Object->Value.Nbr)); break; case OBJ_FAMILY_TABLE: IdxUp = 0; IdxDown = sizeof(Object->Value.Table) - 1; while (IdxDown >= 0) Object->Value.Table[IdxUp++] = (*Buffer)[IdxDown--]; *Buffer += sizeof(Object->Value.Table); break; case OBJ_FAMILY_NETADDR: #ifdef _WIN32 IP.S_un.S_addr = *(unsigned int *)*Buffer; #else IP.s_addr = *(unsigned int *)*Buffer; #endif memset(Object->Value.Addr.ip, 0, MAX_IP_LEN + 1); strncpy(Object->Value.Addr.ip, inet_ntoa(IP), MAX_IP_LEN + 1); *Buffer += 4; Object->Value.Addr.port = htons(*(unsigned short *)(*Buffer)); *Buffer += 2; break; case OBJ_FAMILY_BLOB: ReadValue(Buffer, &(Object->Value.Memory.MsZ)); Object->Value.Memory.Memory = (uchar *)malloc(Object->Value.Memory.MsZ); memcpy(Object->Value.Memory.Memory, *Buffer, Object->Value.Memory.MsZ); *Buffer += Object->Value.Memory.MsZ; break; case OBJ_FAMILY_STRING: Str = *Buffer; Object->Value.Memory.MsZ = 1; while (*Str++ != 0) Object->Value.Memory.MsZ += 1; Object->Value.Memory.Memory = (uchar *)malloc(Object->Value.Memory.MsZ); memcpy(Object->Value.Memory.Memory, *Buffer, Object->Value.Memory.MsZ); *Buffer += Object->Value.Memory.MsZ; break; case OBJ_FAMILY_INTLIST: ReadValue(Buffer, &(Object->Value.Memory.MsZ)); Object->Value.Memory.Memory = (uchar *)malloc(Object->Value.Memory.MsZ * sizeof(uint)); for (IdxUp = 0; IdxUp < Object->Value.Memory.MsZ; IdxUp++) ReadValue(Buffer, (uint*)(Object->Value.Memory.Memory + (IdxUp * sizeof(uint)))); break; case OBJ_FAMILY_OBJLIST: { uint OldNbObj; int OldCurObjListId; OldCurObjListId = CurObjListId; CurObjListId = (int)Id; CurObjListRank += 1; OldNbObj = Response->NbObj; ManageObjects(Buffer, Size - (*Buffer - Mark), Response); CurObjListId = OldCurObjListId; //Suffix += Response->NbObj - OldNbObj; NbObjs -= 1; //Idx += (Response->NbObj - OldNbObj); goto ContinueDecode; break; } default : break; } Idx += 1; lIdx += 1; ContinueDecode: continue ; } Level -= 1; if (Level == 0) { Idx = 0; CurObjListId = -1; CurObjListRank = 0; } return (NbObjs); } int ManageObjects(uchar **Buffer, uint Size, SResponse *Response) { uchar Mode; Mode = **Buffer; *Buffer += 1; switch (Mode) { case RAW_PARAMS: Response->NbObj += DecodeRawObjects(Buffer, Size - 1, Response, &(Response->Objs), Response->NbObj); return 0; case EXT_PARAMS: // Not supported as not needed by plain login //Response->NbObj += DecodeExtObjects(Buffer, Size - 1, Response, &(Response->Objs), Response->NbObj); break; default: break; } return -1; } void FreeResponse(SResponse *Response) { uint Idx; for (Idx=0; IdxNbObj; Idx++) { switch (Response->Objs[Idx].Family) { case OBJ_FAMILY_BLOB: case OBJ_FAMILY_STRING: case OBJ_FAMILY_INTLIST: if (Response->Objs[Idx].Value.Memory.Memory) free (Response->Objs[Idx].Value.Memory.Memory); break; } } free (Response->Objs); memset(Response, 0, sizeof(SResponse)); }