#include "stdafx.h"
#include <stdio.h>
#include<windows.h>
#include <tchar.h>
#include <ImageHlp.h>
#include <tlhelp32.h>

#define dllname "user32.dll" //change this only

#pragma comment (lib,"ImageHlp")

typedef int  (WINAPI *MYMESSAGE)(HWND , LPCTSTR ,LPCTSTR ,UINT);
typedef void (WINAPI *MyGetLocalTime)(LPSYSTEMTIME);
typedef SHORT(WINAPI *MyGetKeyState)(int);
typedef BOOL (WINAPI *MyGetKeyboardState)(LPBYTE);

void ReplaceIATEntryInAllMods(PCSTR pszModuleName, PROC pfnCurrent, PROC pfnNew);
void ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller);


int		WINAPI HookMessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
void	WINAPI HookGetLocalTime(LPSYSTEMTIME lpSystemTime);
SHORT	WINAPI HookGetKeyState(int lpKeyState);
BOOL	WINAPI HookGetKeyboardState(LPBYTE lpKeyState);
FARPROC WINAPI HookGetProcAddress(HMODULE hMod, PCSTR pszProcName);

/*********************************/
/* DLL Main Function             */
/*********************************/

BOOL APIENTRY DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    
    if(ul_reason_for_call==DLL_PROCESS_ATTACH)
    {
		// pfnOrig is the address of the function in the module that you want to search for and replace it by your function
		PROC pfnOrig = GetProcAddress(GetModuleHandle(dllname),"GetKeyState");

		HMODULE hmodCaller = GetModuleHandle(NULL);

		ReplaceIATEntryInAllMods(dllname, pfnOrig,(PROC)HookGetKeyState);

	}

    return TRUE;
}

void ReplaceIATEntryInAllMods(PCSTR pszModuleName, PROC pfnCurrent, PROC pfnNew)
{
	MEMORY_BASIC_INFORMATION mbi;
	if(VirtualQuery(ReplaceIATEntryInAllMods, &mbi, sizeof(mbi)) == 0)
		return;
	HMODULE hModThisMod = (HMODULE) mbi.AllocationBase;

	HANDLE hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, GetCurrentProcessId());
	if(hModuleSnap == INVALID_HANDLE_VALUE)
		return;

	MODULEENTRY32 me;
	me.dwSize = sizeof(me);
	BOOL bModuleResult = Module32First(hModuleSnap, &me);

	char szBuf[256];

	while(bModuleResult) {
		wsprintf(szBuf, "%s %x", me.szModule, me.modBaseAddr);
		//MessageBox(NULL,szBuf,"message",MB_OK);
		if(me.hModule != hModThisMod)
			ReplaceIATEntryInOneMod(pszModuleName, pfnCurrent, pfnNew, me.hModule);
		
		bModuleResult = Module32Next(hModuleSnap, &me);
	}
	CloseHandle(hModuleSnap);
}


void ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller) {

   ULONG ulSize;
   
   // locate the hmodCaller module's import section by calling ImageDirectoryEntryToData, passing it 
   // IMAGE_DIRECTORY_ENTRY_IMPORT
   PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)
	   ImageDirectoryEntryToData(hmodCaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);

   if (pImportDesc == NULL)
      return;  

   // look in the module's import section for the DLL that contains the imported function that we want to change.
   // first find the module
   // then find the address of the function you want to hook
   for (; pImportDesc->Name; pImportDesc++) 
   {
      PSTR pszModName = (PSTR) ((PBYTE) hmodCaller + pImportDesc->Name);
      if (lstrcmpiA(pszModName, pszCalleeModName) == 0)
	  {
         break;
	  }
   }

   if (pImportDesc->Name == 0)
   {
		
        return; 
   }

   //char buffer[256];

   PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA) ((PBYTE) hmodCaller + pImportDesc->FirstThunk);


   /* **************************************** */
   
   for (; pThunk->u1.Function; pThunk++) 
   {
      PROC* ppfn = (PROC*) &pThunk->u1.Function;
	  
	  //wsprintf(buffer,"%x %x",pfnCurrent, *ppfn);
      //MessageBox(NULL,buffer,"Message",MB_OK);

      BOOL fFound = (*ppfn == pfnCurrent);

	  if (fFound) 
	  {
		  MEMORY_BASIC_INFORMATION mbi;

		  //MessageBox(NULL,"function found","Message",MB_OK);
			
		  ::VirtualQuery(ppfn, &mbi, sizeof(MEMORY_BASIC_INFORMATION));

		  // In order to provide writable access to this part of the 
		  // memory we need to change the memory protection

		  if (FALSE == ::VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_READWRITE,&mbi.Protect))
		  	return;

		  *ppfn = *pfnNew;


			// Restore the protection back
    		DWORD dwOldProtect;

			::VirtualProtect(mbi.BaseAddress,mbi.RegionSize,mbi.Protect,&dwOldProtect);
			
			break;
      }
   }

}

int WINAPI HookMessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType)
{

MessageBox(NULL,"This is a Hook test","Yousof Hook Test",uType); 

//To call the origional Message; comment it until return to hide the origional message 
HMODULE hmod = LoadLibrary("user32.dll");

MYMESSAGE Orig_MessageBox = (MYMESSAGE) GetProcAddress(hmod,"MessageBoxW"); 

int nResult = Orig_MessageBox(hWnd,lpText,lpCaption,uType);

PCSTR pszResult = "(Unknown)";
     
   switch (nResult) {
     
	  case IDOK:       pszResult = "Ok";        MessageBox(NULL,"You have pressed OK","OK",MB_OK);			break;
      case IDCANCEL:   pszResult = "Cancel";    MessageBox(NULL,"You have pressed CANCEL","CANCEL",MB_OK);	break;
      case IDABORT:    pszResult = "Abort";     MessageBox(NULL,"You have pressed ABORT","ABORT",MB_OK);	break;
      case IDRETRY:    pszResult = "Retry";     MessageBox(NULL,"You have pressed RETRY","RETRY",MB_OK);	break;
      case IDIGNORE:   pszResult = "Ignore";    MessageBox(NULL,"You have pressed IGNORE","IGNORE",MB_OK);	break;
      case IDYES:      pszResult = "Yes";       MessageBox(NULL,"You have pressed YES","YES",MB_OK);		break;
      case IDNO:       pszResult = "No";        MessageBox(NULL,"You have pressed NO","NO",MB_OK);			break;
     
   }

return nResult;
}


SHORT WINAPI HookGetKeyState(int lpKeyState)
{

// Get the pathname of the process displaying the message box
char szProcessPathname[MAX_PATH];
GetModuleFileNameA(NULL, szProcessPathname, MAX_PATH);

MessageBox(NULL,szProcessPathname,"Hooked Function (GetKeyState) is used by:",MB_OK);

HMODULE hmod = LoadLibrary("user32.dll");
MyGetKeyState key = (MyGetKeyState) GetProcAddress(hmod,"GetKeyState");

int keystate = key(lpKeyState);

switch(keystate)
{
	case 0: MessageBox(NULL,"NO CTRL and NO SHIFT","Message",MB_OK);	break;
	case 1: MessageBox(NULL,"CTRL but NO SHIFT","Message",MB_OK);		break;
	case 2: MessageBox(NULL,"NO CTRL but SHIFT","Message",MB_OK);		break;
	case 3: MessageBox(NULL,"CTRL and SHIFT","Message",MB_OK);			break;
}
	
	
	return keystate;
}


void WINAPI HookGetLocalTime(LPSYSTEMTIME lpSystemTime)
{

	SYSTEMTIME systime;
	char str[256];

	GetLocalTime(&systime);

	wsprintf(str, "Date-> %d\\%d\\%d \n Time-> %d:%d", systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute);
	MessageBox(NULL,str,"Message",MB_OK);

	HMODULE hmod = LoadLibrary("kernel32.dll");
	MyGetLocalTime time = (MyGetLocalTime) GetProcAddress(hmod,"GetLocalTime");


	time(lpSystemTime);
}


BOOL WINAPI HookGetKeyboardState(LPBYTE lpKeyState)
{

	MessageBox(NULL,"We are hooking GetKeyboardState","message",MB_OK);
	BYTE keystate[256];
    BOOL r = GetKeyboardState(keystate);
    if (!r)
		return FALSE;
    if (keystate[VK_SHIFT] & 0x80)
		return TRUE;

    HMODULE hmod = LoadLibrary("user32.dll");
	MyGetKeyboardState keyboardstate = (MyGetKeyboardState) GetProcAddress(hmod,"GetKeyboardState");

	BOOL x = keyboardstate(lpKeyState);
	
	
	return x;

}

FARPROC WINAPI HookGetProcAddress(HMODULE hMod, PCSTR pszProcName)
{
	MessageBox(NULL,"GetProcAddress","Message",MB_OK);
	typedef FARPROC (WINAPI *MyGetProcAddress)(HMODULE, PCSTR);

	HMODULE hmod = LoadLibrary("kernel32.dll");

	MyGetProcAddress pfn = (MyGetProcAddress) GetProcAddress(hmod,"GetProcAddress");

	FARPROC ret = pfn(hMod, pszProcName);

	return ret;

}