// Hooks_search.cpp : Defines the entry point for the console application.
//
#include <windows.h>
#include <stdio.h>
#include <string>
#include <Tlhelp32.h>
#include <vector>
#include <Psapi.h>
#include <fstream>
#include "PE_class.h"


#pragma comment (lib,"psapi.lib");

HANDLE hProc;
DWORD pid;
DWORD MainImageBase;//Main module ImageBase 

char* LoadMod(DWORD IB)
{
char ProcName[260];
GetModuleFileNameEx(hProc,(HMODULE)IB,ProcName,260);
std::ifstream f(ProcName,std::ios::binary);
char* buf;
f.seekg(0,std::ios::end);
int size=f.tellg();
f.seekg(0,std::ios::beg);
buf=(char*)malloc(size);
memset(buf,0,size);
int i=0;
char ch;
while(i<size)
{
f.get(ch);
buf[i]=ch;
i++;
}
f.close();
return buf;
}


void str_tolower(char* str)
{
int i=0;
int size=strlen(str);

while(i<size)
{
str[i]=tolower(str[i]);
i++;
}
}

DWORD FindModule(char* mod_name)
{
MODULEENTRY32 mod32;
std::string x;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
mod32.dwSize = sizeof(MODULEENTRY32);
str_tolower(mod_name);
Module32First(hSnapshot, &mod32);
        do
        {
		str_tolower(mod32.szExePath);
		x=mod32.szExePath;
		
		if(x.find(mod_name)!=0xFFFFFFFF)
		{
			return (DWORD)mod32.modBaseAddr;
		}
				
		}
        while(Module32Next(hSnapshot, &mod32));
        CloseHandle(hSnapshot);
		return 0;
}

DWORD FindHookModule(DWORD Address)
{
MODULEENTRY32 mod32;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
//module list
mod32.dwSize = sizeof(MODULEENTRY32);

    Module32First(hSnapshot, &mod32);
	     do
        {
		if(Address>=(DWORD)mod32.modBaseAddr && Address<=(DWORD)(mod32.modBaseAddr+mod32.modBaseSize))
		{
return (DWORD)mod32.modBaseAddr;
		}
			
		}
        while(Module32Next(hSnapshot, &mod32));
        CloseHandle(hSnapshot);
		return 0;
}


void IAT(PE_file* PE)
{
HINSTANCE hInstance =(HINSTANCE)PE->buf;
PIMAGE_DOS_HEADER pdosheader = (PIMAGE_DOS_HEADER)hInstance;
PIMAGE_NT_HEADERS pntheaders = (PIMAGE_NT_HEADERS)((DWORD)hInstance + pdosheader->e_lfanew);
PIMAGE_SECTION_HEADER psectionheader = (PIMAGE_SECTION_HEADER)(pntheaders + 1);
PIMAGE_IMPORT_DESCRIPTOR pimportdescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hInstance + PE->RVA_to_RAW(pntheaders->OptionalHeader.DataDirectory[1].VirtualAddress));
PIMAGE_THUNK_DATA pthunkdatain, pthunkdataout;
PIMAGE_IMPORT_BY_NAME pimportbyname;
DWORD dw;
PCHAR ptr;
DWORD IB;
char* buf;
DWORD ImgSize;
PIMAGE_OPTIONAL_HEADER32 opt;
DWORD address;
DWORD IAT_adr;
DWORD read;

int i=0;
while ( pimportdescriptor->TimeDateStamp != 0 ||pimportdescriptor->Name != 0)
{
	ptr = (PCHAR)((DWORD)hInstance+ PE->RVA_to_RAW((DWORD)pimportdescriptor->Name));
	//lib name
	i=0;
	IB=FindModule(ptr);//function return module imagebase
	buf=LoadMod(IB);//loading module
	PE_file PE2((HMODULE)buf);//module to class
	opt=PE2.GetOptionalHeader();
	ImgSize=opt->SizeOfImage;//size of module
	free(buf);

	//check imports
		pthunkdataout = (PIMAGE_THUNK_DATA)((DWORD)hInstance + PE->RVA_to_RAW((DWORD)pimportdescriptor->FirstThunk));
		if (pimportdescriptor->Characteristics == 0)
		{
			pthunkdatain = pthunkdataout;
		}
		else 
		{
			pthunkdatain = (PIMAGE_THUNK_DATA)((DWORD)hInstance +PE->RVA_to_RAW((DWORD)pimportdescriptor->Characteristics));
		}

		while ( pthunkdatain->u1.AddressOfData != NULL)
		{
			if ((DWORD)pthunkdatain->u1.Ordinal & IMAGE_ORDINAL_FLAG)
			//import by ordinal
			{
				LPSTR x=MAKEINTRESOURCE(LOWORD(pthunkdatain->u1.Ordinal));
				address=MainImageBase+(pimportdescriptor->FirstThunk+(i*4));
				//calculate pointer to function
				ReadProcessMemory(hProc,(LPCVOID)address,&IAT_adr,4,&read);
				//read address of function from process
				if(IAT_adr<IB || IAT_adr>(IB+ImgSize))
				//check
				{
				DWORD HookBase=FindHookModule(IAT_adr);
				char modname[260];
				if(HookBase==0)
				{
				strcpy(modname,"Virtual Memory");
				}
				else
				{
				GetModuleFileNameEx(hProc,(HMODULE)HookBase,modname,260);
				}
printf("Ord: %x(%s) --- Hooked by %s(0x%.8x)\n",x,ptr,modname,IAT_adr);
				}
							
				
			} else {
				
				pimportbyname = (PIMAGE_IMPORT_BY_NAME)(PE->RVA_to_RAW((DWORD)pthunkdatain->u1.AddressOfData) + (DWORD)hInstance);
				address=MainImageBase+(pimportdescriptor->FirstThunk+(i*4));
				ReadProcessMemory(hProc,(LPCVOID)address,&IAT_adr,4,&read);
				if(IAT_adr<IB || IAT_adr>(IB+ImgSize))
				{
				DWORD HookBase=FindHookModule(IAT_adr);
				char modname[260];
				if(HookBase==0)
				{
				strcpy(modname,"Virtual Memory");
				}
				else
				{
				GetModuleFileNameEx(hProc,(HMODULE)HookBase,modname,260);
				}
				printf("%s(%s) --- Hooked by %s(0x%.8x)\n",(char*)pimportbyname->Name,ptr,modname,IAT_adr);
				}
				
			}
			
        i++;
			pthunkdatain++;
			pthunkdataout++;
		}
    
	pimportdescriptor++;  

}
}



void ProcList()
{
PROCESSENTRY32 lppe32;

	
    HANDLE hSnapshot;
   hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    lppe32.dwSize = sizeof(PROCESSENTRY32);
   
    Process32First(hSnapshot, &lppe32);
	     do
        {
		printf("%s\t%d\n",lppe32.szExeFile,lppe32.th32ProcessID);
		}
        while(Process32Next(hSnapshot, &lppe32));
        CloseHandle(hSnapshot);

}


DWORD FindImageBase(DWORD pid,DWORD* IB,DWORD* ImgSize)
{
PROCESSENTRY32 lppe32;
char buf[260];
	memset(buf,0,260);
    HANDLE hSnapshot;
   hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    lppe32.dwSize = sizeof(PROCESSENTRY32);
   
    Process32First(hSnapshot, &lppe32);
	    do
        {
		if(lppe32.th32ProcessID==pid)
		{
		strcpy(buf,lppe32.szExeFile);
		break;
		}
		
		}
        while(Process32Next(hSnapshot, &lppe32));
        CloseHandle(hSnapshot);
if(buf[0]==0)
{
return 0;
}

MODULEENTRY32 mod32;
std::string x;

   hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
   mod32.dwSize = sizeof(MODULEENTRY32);
   
    Module32First(hSnapshot, &mod32);
	     do
        {
		x=mod32.szExePath;
		if(x.find(buf)!=0xFFFFFFFF)
		{
			*IB=(DWORD)mod32.modBaseAddr;
			*ImgSize=mod32.modBaseSize;
		}
		
		
		}
        while(Module32Next(hSnapshot, &mod32));
        CloseHandle(hSnapshot);
return 1;
}

int main(int argc, CHAR* argv[])
{
printf("\n\nIAT Hook detector v. 1.0 by Grzonu\n\n");

if(argc!=2)
{
	printf("usage: %s <pid>\n\n",argv[0]);
	ProcList();
	return 0;
}
pid=atoi(argv[1]);
DWORD IB=0;
DWORD ImgSize=0;
FindImageBase(pid,&IB,&ImgSize);
printf("ImageBase: 0x%.8x\nImageSize: 0x%.8x\n\n",IB,ImgSize);

hProc=OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION,FALSE,pid);
if(hProc==0)
{
printf("can`t open process\n");
return 0;
}
char* buf=LoadMod(IB);
MainImageBase=IB;
PE_file PE((HMODULE)buf);
IAT(&PE);
free(buf);


	return 0;
}

