#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tlhelp32.h> 
#include <wchar.h>


#pragma pack(1) // very important !

#define MsgBox(msg,title) MessageBox(NULL,msg,title,MB_OK);

HANDLE hRemoteThread,hRemoteProcess;
PWSTR pszLibFileRemote=NULL; 


BOOL WINAPI InjectLibInAllW(char *pszLibFile);
BOOL WINAPI InjectLibW(DWORD dwProcessId, char *pszLibFile);

BOOL WINAPI EjectLibFromAllW(char *pszLibFile);
BOOL WINAPI EjectLibW(DWORD dwProcessId, char *pszLibFile);


/* ********************************************************************* */

BOOL WINAPI EjectLibFromAllW(char *pszLibFile)
{
	HANDLE hSnapshot;
	BOOL fOk=FALSE;
	BOOL bRet;
	PROCESSENTRY32 pe32 = {0};
	char exe[MAX_PATH];
	char buffer[MAX_PATH];
	
	__try
	{
		 /*Create a snapshot for processes */
		hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
		
		if(hSnapshot==INVALID_HANDLE_VALUE)
			__leave;
		
		pe32.dwSize = sizeof(PROCESSENTRY32); 

		 /* Loop to get all PID's and eject from each */
		if(Process32First(hSnapshot,&pe32) )
			do
			{
				wsprintf(exe,"%s",pe32.szExeFile);
				//MsgBox(exe,"FileName and ProcessID",MB_OK);
				if(!strcmp(exe,"notepad.exe"))
				{
					bRet=EjectLibW(pe32.th32ProcessID,pszLibFile); /* Inject in each process*/
					if(bRet)
					{
						wsprintf(buffer,"%s %d OK\n",pe32.szExeFile, pe32.th32ProcessID);
						//MsgBox(buffer,"Message");
					}
					else
					{
						wsprintf(buffer,"%s %d Failed; error: %d \n",pe32.szExeFile, pe32.th32ProcessID, GetLastError());
						//MsgBox(buffer,"Message");
					}
				}
				
			}while(Process32Next(hSnapshot,&pe32));
		fOk=TRUE;
	}
	__finally{
		if(hSnapshot != NULL)
			CloseHandle(hSnapshot);
	}
	return fOk;
}



BOOL WINAPI EjectLibW(DWORD dwProcessId, char *pszLibFile)
{
   BOOL fOk = FALSE; ///Assume that the function fails
   HANDLE hthSnapshot = NULL;
   HANDLE hProcess = NULL, hThread = NULL;
   MODULEENTRY32 me = {0};	
   BOOL fFound,fMoreMods;
   PTHREAD_START_ROUTINE pfnThreadRtn;
   DWORD ThreadId = 0;

   __try {
      
	  //Grab a new snapshot of the process
      
	  hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
      
	  if (hthSnapshot == NULL)  __leave;
	  

      ///Get the HMODULE of the desired library
      me.dwSize  =  sizeof(me);
      fFound = FALSE;
      fMoreMods = Module32First(hthSnapshot, &me);
	  char buffer[MAX_PATH];

	  while(fMoreMods) {
		 wsprintf(buffer,"%s",me.szModule);
		 //MsgBox(buffer,"Message");
         fFound = (lstrcmpi(me.szModule, pszLibFile) == 0) || (lstrcmpi(me.szExePath, pszLibFile) == 0);
		 printf("found is %d in %s\n",fFound, me.szModule);
         if (fFound) 
		 {
			 wsprintf(buffer,"%s found in %s",pszLibFile, me.szExePath);
			 MsgBox(buffer,"Module Found");
			 break;
		 }
		 fMoreMods = Module32Next(hthSnapshot, &me);
      }
      
	  if (!fFound)
	  {
		  wsprintf(buffer,"%s not found",pszLibFile);
		  MsgBox(buffer,"Module Not Found");
		  __leave;
	  }
	  

      //Get a handle for the target process.
      hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
		  //OpenProcess(PROCESS_CREATE_THREAD| PROCESS_VM_OPERATION,  //For CreateRemoteThread FALSE, dwProcessId);
      
	  if (hProcess == NULL)
	  {
		  MsgBox("Open process failed","Message");
		  __leave;
	  }


      //Get the real address of FreeLibrary in Kernel32.dll
      
	  pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")), "FreeLibrary");
      
	  if (pfnThreadRtn == NULL)
	  {
		  MsgBox("GetProcAddress of FreeLibrary Failed","Message");
		  __leave;
	  }
	  
	  //Create a remote thread that calls FreeLibrary(DLLPathname)

      hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, me.modBaseAddr, 0, &ThreadId);
      //me.modBaseAddr
	  if (hThread == NULL)
	  {
		  MsgBox("CreateRemoteThread Failed to Unload DLL","Message");
		  __leave;
	  }


      //Wait for the remote thread to terminate
      WaitForSingleObject(hThread, INFINITE);

      fOk = TRUE; //Everything executed successfully
   }
   __finally { //Now we can clean everything up

	  if (hThread     != NULL) 
         CloseHandle(hThread);

      if (hthSnapshot != NULL) 
         CloseHandle(hthSnapshot);

      if (hProcess    != NULL) 
         CloseHandle(hProcess);
   }

   return(fOk);
}


/* ********************************************************************* */

BOOL WINAPI InjectLibInAllW(char *pszLibFile)
{
	HANDLE hSnapshot;
	BOOL fOk=FALSE;
	BOOL bRet;
	PROCESSENTRY32 pe32 = {0};
	char buffer[MAX_PATH];
	char exe[MAX_PATH];
	
	__try
	{
		 /*Create a snapshot for processes */
		hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
		
		if(hSnapshot==INVALID_HANDLE_VALUE)
			__leave;
		
		pe32.dwSize = sizeof(PROCESSENTRY32); 

		 /* Loop to get all PID's and inject in each */
		if(Process32First(hSnapshot,&pe32) )
			do
			{
				wsprintf(exe,"%s",pe32.szExeFile);
				//MsgBox(exe,"FileName and ProcessID");
				if(!strcmp(exe,"notepad.exe"))
				{
					bRet=InjectLibW(pe32.th32ProcessID,pszLibFile); /* Inject in each process*/
					if(bRet)
					{
						wsprintf(buffer,"%s %d OK\n",pe32.szExeFile, pe32.th32ProcessID);
						//MsgBox(buffer,"Message");
					}
					else
					{
						wsprintf(buffer,"%s %d Failed; error: %d \n",pe32.szExeFile, pe32.th32ProcessID, GetLastError());
						//MsgBox(buffer,"Message");
					}
				}
			}while(Process32Next(hSnapshot,&pe32));

		fOk=TRUE;
	}
	__finally{
		if(hSnapshot != NULL)
			CloseHandle(hSnapshot);
	}
	return fOk;
}


BOOL WINAPI InjectLibW(DWORD dwProcessId, char *pszLibFile) 
{
   BOOL fOk = FALSE; /*Assume that the function fails*/
   HANDLE hProcess = NULL, hThread = NULL;
   PWSTR pszLibFileRemote = NULL;
   PTHREAD_START_ROUTINE pfnThreadRtn;
   //int cch,cb;
   int cb;
   DWORD ThreadId=0;

	char buffer[256];
	wsprintf(buffer,"we are injecting: %s %d",pszLibFile,dwProcessId);
	//MsgBox(buffer,"Message");

   __try {
	
	   /*Get a handle for the target process.*/
	   hProcess = OpenProcess(
         PROCESS_CREATE_THREAD     |   /*For CreateRemoteThread*/
         PROCESS_VM_OPERATION      |   /*For VirtualAllocEx/VirtualFreeEx*/
         PROCESS_VM_WRITE,             /*For WriteProcessMemory*/
         FALSE, dwProcessId);

	  if (hProcess == NULL) __leave;

      /*Calculate the number of bytes needed for the DLL's pathname*/
	  cb = (1+strlen(pszLibFile))*sizeof(char); /* calculates the dll length */


      /*Allocate space in the remote process for the pathname*/
	  pszLibFileRemote = (LPWSTR) VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
      if (pszLibFileRemote == NULL) __leave;


      /*Copy the DLL's pathname to the remote process's address space*/
	  if (!WriteProcessMemory(hProcess, pszLibFileRemote, (PVOID) pszLibFile, cb, NULL)) __leave;


      /*Get the real address of LoadLibraryW in Kernel32.dll*/
	  pfnThreadRtn = (PTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle("Kernel32.dll"), 
	  #ifdef UNICODE
		"LoadLibraryW");
	  #else
		"LoadLibraryA");
	  #endif

      
	  if (pfnThreadRtn == NULL) __leave;


      /*Create a remote thread that calls LoadLibraryW(DLLPathname)*/
	  hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, pszLibFileRemote, 0, &ThreadId);

	  if (hThread == NULL) __leave;


      /*Wait for the remote thread to terminate*/
	  WaitForSingleObject(hThread, INFINITE);

      fOk = TRUE; /*Everything executed successfully*/
   }
   __finally { /*Now, we can clean everthing up*/

      /*Free the remote memory that contained the DLL's pathname*/
      if (pszLibFileRemote != NULL) 
         VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);

      if (hThread  != NULL) 
         CloseHandle(hThread);

      if (hProcess != NULL) 
         CloseHandle(hProcess);
   }

   return(fOk);
}

/* ********************************************************************* */

// to change the process privilages
BOOL SetPrivilege() 
{ 
    TOKEN_PRIVILEGES tkp;
    HANDLE hToken;
    if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken)) 
        return FALSE;
    LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tkp.Privileges[0].Luid); 
    tkp.PrivilegeCount=1;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0);  
    return TRUE;
}
 
/* ********************************************************************* */



int main()
{
    //char pszlibfilename[MAX_PATH];
	char pszlibfilename[MAX_PATH];

	/*Get the current directory of the DLL */
    
	GetCurrentDirectory(MAX_PATH,pszlibfilename);  
    
	if (pszlibfilename[strlen(pszlibfilename)-1 ]!='\\')
	{
        strcat(pszlibfilename,"\\InjectionDLL.dll");
		MsgBox(pszlibfilename,"DLL name");
    }
	else
	{
        strcat(pszlibfilename,"InjectionDLL.dll");
		MsgBox(pszlibfilename,"DLL name");
	}

    
	/* Apply the privilege */
    if (!SetPrivilege())
    {
        printf("Error in SetPrivilege(): %d\n ",GetLastError());
		return 1;
    }

	char x;
	BOOL Inject, Eject;
	printf("For Injection DLL enter: 'i' or 'I'\n");
	printf("For Ejection DLL enter: 'e' or 'E'\n");
	scanf("%c",&x);
	
	/* Do the Injection and Ejection */

	switch(x)
	{
	case 'i':
	case 'I':

		Inject = InjectLibInAllW(pszlibfilename);

		if(Inject) 
		{
			MsgBox("Injection is Successful","Message");
		}
		else
		{
			MsgBox("Injection Failed","Message");
		}

	break;

	case 'e':
	case 'E':

		Eject = EjectLibFromAllW(pszlibfilename);
		
		if(Eject)
		{
			MsgBox("Ejection DLL successfully done","Ejection");
		}
		else
		{
			MsgBox("Ejection DLL failed!","Ejection");
		}
	break;
	}

return 0;
}
