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

/*

实现全局hook模块基本完工,测试通过,没有发现异常。

         计划1:在hook前首先检验该程序是否已被hook

   计划2:添加枚举进程并hook功能

   计划3:在备份api时,只备份目标api函数,避免备份整个dll浪费空间

   计划4:给my_EventProcess_Thread加上垃圾回收机制

*/

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

#include <stdio.h>

#include <windows.h>

#include <winbase.h>

#include <malloc.h>

#include <stdio.h>

#include <Psapi.h>

#include <Tlhelp32.h>

#pragma comment(lib,"psapi")

#include <winbase.h>

#include <wchar.h>

#include <process.h>

#define WRITEBASE (12)

typedef struct

{

 HMODULE  hModule;//句柄

 LPVOID  lpNewBaseOfDll;//备份dll句柄

 MODULEINFO modinfo;//MODULEINFO结构

}DLLINFO, *PDLLINFO;

typedef struct

{

 HANDLE EventFar;

 HANDLE ObjectProcessHandle;

 DWORD WriteAddress;

}EventInfo,*PEventInfo;

void UpToDebug();//调整令牌提升至debug权限

BOOL InitDll(char *pszDll, PDLLINFO pDllInfo,HANDLE prochandle);

int HookNamedApi(PDLLINFO pDllInfo, char *ApiName, DWORD HookProc,HANDLE ObjectProcessHandle);

int HookProcess(HANDLE ObjectProcessHandle);

void FarStartUp(int Num);

void EditHookProc();

void __stdcall my_EventProcess_Thread(HANDLE EventFar);

DWORD __stdcall Hook_NtResumeThread(HANDLE ThreadHandle,PULONG PreviousSuspendCount OPTIONAL);

BYTE HookCode[]={0xb8,0x0,0x0,0x0,0x0,0xFF,0xE0};

void UpToDebug()//调整令牌提升至debug权限

{

 HANDLE token;

 OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&token);

 TOKEN_PRIVILEGES tp;

 tp.PrivilegeCount =1;

 LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid);

 tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;

 AdjustTokenPrivileges(token,0,&tp,sizeof(tp),0,0);

}

void main(int argc, char **argv)

{

 UpToDebug();//提升至debug权限

 HANDLE ObjectProcessHandle=OpenProcess(PROCESS_ALL_ACCESS,1,atoi(argv[1]));//打开目标进程

 HookProcess(ObjectProcessHandle);

 int wait=0;

 scanf("%d",wait);

    return;

}

int HookProcess(HANDLE ObjectProcessHandle)

{

 DLLINFO Object_dll;

 if(!InitDll("ntdll.dll",&Object_dll,ObjectProcessHandle)) return 0;//备份目标dll

 HookNamedApi(&Object_dll, "NtResumeThread", (DWORD)Hook_NtResumeThread,ObjectProcessHandle);//hook函数

 //hook_api(&user32_dll, "NtQuerySystemInformation", (DWORD)hook_NtQuerySystemInformation, &new_temp,ObjectProcessHandle);//hook函数

 //hook_api(&user32_dll, "NtQueryDirectoryFile", (DWORD)hook_NtQueryDirectoryFile, &new_temp,ObjectProcessHandle);//hook函数

 //hook_api(&user32_dll, "FindFirstFileA", (DWORD)hook_FindFirstFileA, &new_FindFirstFileA,ObjectProcessHandle);//hook函数

 //hook_api(&user32_dll, "FindNextFileA", (DWORD)hook_FindNextFileA, &new_FindFirstFileA,ObjectProcessHandle);

    return 0;

}

BOOL InitDll(char *pszDll, PDLLINFO pDllInfo,HANDLE prochandle)

{

 pDllInfo->hModule = GetModuleHandle(pszDll);//得到目标dll句柄,因为是本地信息,所以要保证本程序加载此dll

 if(!pDllInfo->hModule)

 {

  printf("pDllInfo->hModule is null! in InitDll");

  return 0;

 }

 if(!GetModuleInformation(GetCurrentProcess(), pDllInfo->hModule, &pDllInfo->modinfo, sizeof(MODULEINFO)))//得到目标dll信息

 {

  printf("Error:GetModuleInformation in InitDll");

  return 0;

 }

 pDllInfo->lpNewBaseOfDll = VirtualAllocEx(prochandle,0,pDllInfo->modinfo.SizeOfImage,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);//申请空间并赋予相应权限(执行,读写)

 if(!pDllInfo->lpNewBaseOfDll)

 {

  printf("Error:VirtualAllocEx in InitDll");//错误处理

  return 0;

 }

 BYTE * buffer=(BYTE *)malloc(pDllInfo->modinfo.SizeOfImage);//分配缓冲,容纳目标dll

 ReadProcessMemory(prochandle,pDllInfo->modinfo.lpBaseOfDll,buffer,pDllInfo->modinfo.SizeOfImage,0);//读出,远程dll内容

 WriteProcessMemory(prochandle,pDllInfo->lpNewBaseOfDll,buffer,pDllInfo->modinfo.SizeOfImage,0);//写入备份dll

 return 1;

}

int HookNamedApi(PDLLINFO pDllInfo, char *ApiName, DWORD HookProc,HANDLE ObjectProcessHandle)

{

 DWORD      dw, NamedApiAddress,NewFunc;

 MEMORY_BASIC_INFORMATION mbi;

 static EventInfo myEventInfo;

 static Num=0x676e696b;

 NamedApiAddress = (DWORD)GetProcAddress(pDllInfo->hModule, ApiName);//目标api地址,每个进程的api地址都是一样的,只要找本进程的就可以了。

 if(NamedApiAddress == NULL)

 {

  printf("Error:GetProcAddress in hook_api");//错误处理

  return 0;

 }

 if(!VirtualQueryEx(ObjectProcessHandle,(void *)NamedApiAddress,&mbi,sizeof(MEMORY_BASIC_INFORMATION)))//获取api所在内存信息

 {

  printf("Error:VirtualQueryEx in hook_api");

  return 0;

 }

 if(!VirtualProtectEx(ObjectProcessHandle,mbi.BaseAddress,mbi.RegionSize,PAGE_EXECUTE_READWRITE,&dw))//分配写和执行权限

 {

  printf("Error:VirtualProtectEx in hook_api");

  return 0;

 }

 LPVOID WriteAddress=VirtualAllocEx(ObjectProcessHandle,0,1000,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);//分配内存,写入hook函数

 //计算原函数COPY的位置

 NewFunc = NamedApiAddress - (DWORD)pDllInfo->modinfo.lpBaseOfDll + (DWORD)pDllInfo->lpNewBaseOfDll;

 //修改原函数入口处内容


 if(strcmp(ApiName,"NtResumeThread")==0)

 {

  DWORD my_CreateEventA=(DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"CreateEventA");

  HANDLE EventFar;

  __asm

  {

   pushad

   push 00000000h

      push Num

   push 0x676e696b

   push esp

   push 0

   push 0

   push 0

   call my_CreateEventA

   mov EventFar,eax

   pop eax

   pop eax

   pop eax

   popad

  }

  *(PDWORD)((DWORD)FarStartUp+9)=(DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"OpenEventA");

     LPVOID StartUpAddr=VirtualAllocEx(ObjectProcessHandle,0,500,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);//分配内存,写入StartUp函数

  WriteProcessMemory(ObjectProcessHandle,StartUpAddr,(LPVOID)FarStartUp,500,0);

  printf("%x/n",(DWORD)StartUpAddr);

  HANDLE FarThread=CreateRemoteThread(ObjectProcessHandle,0,0, (LPTHREAD_START_ROUTINE)StartUpAddr,(PVOID)Num,0,0);

  WaitForSingleObject(FarThread,-1);

  CloseHandle(FarThread);

  DWORD ReadBuf;

  ReadProcessMemory(ObjectProcessHandle,(LPVOID)((DWORD)StartUpAddr+21),&ReadBuf,4,0);

  VirtualFreeEx(ObjectProcessHandle,StartUpAddr,500,MEM_RELEASE);

  *(PDWORD)(HookProc+WRITEBASE+7)=ReadBuf;

  myEventInfo.EventFar=EventFar;

  myEventInfo.ObjectProcessHandle=ObjectProcessHandle;

  myEventInfo.WriteAddress=(DWORD)WriteAddress;

  CreateThread(0,0,(unsigned long (__stdcall *)(void *))my_EventProcess_Thread,&myEventInfo,0,0);

  Num++;

 }

 *(PDWORD)(HookProc+WRITEBASE)=NewFunc;

 *(PDWORD)(HookProc+WRITEBASE+14)=(DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"GetCurrentProcessId");

 *(PDWORD)(HookProc+WRITEBASE+21)=(DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"SetEvent");

 *(PDWORD)(HookProc+WRITEBASE+28)=(DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"WaitForSingleObject");

 *(PDWORD)(HookProc+WRITEBASE+35)=(DWORD)GetProcAddress(GetModuleHandle("ntdll.dll"),"NtQueryInformationThread");

 *(PDWORD)(HookProc+WRITEBASE+42)=(DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"ResetEvent");

 WriteProcessMemory(ObjectProcessHandle,WriteAddress,(void *)HookProc,1000,0);

 *(PDWORD)(&HookCode[0]+1)=(DWORD)WriteAddress;

 WriteProcessMemory(ObjectProcessHandle,(LPVOID)NamedApiAddress,&HookCode,7,0);

 printf("func:%x/n",WriteAddress);//调试信息

 return 1;

}

void  FarStartUp(int Num){

 int myOpenEvent=0x10020000;

 __asm call GetMyAddr;

 DWORD myEventHandle=0x00220000;

 DWORD FuncAddr;

 __asm

 {

  jmp run

GetMyAddr:

  pop eax

  mov FuncAddr,eax

  push eax

  ret

run:

  push 00000000

  push Num

  push 0x676e696b

  push esp

  push 0

  push EVENT_ALL_ACCESS

  call myOpenEvent

  mov myEventHandle,eax

 }

 *(PDWORD)(FuncAddr+3)=myEventHandle;

    return;

}

void __stdcall my_EventProcess_Thread(PVOID InEventInfo)

{

 EventInfo myEventInfo;

 PEventInfo Info=(PEventInfo)InEventInfo;

 myEventInfo.EventFar=Info->EventFar;

 myEventInfo.ObjectProcessHandle=Info->ObjectProcessHandle;

 myEventInfo.WriteAddress=Info->WriteAddress;

 while(true)

 {

  WaitForSingleObject(myEventInfo.EventFar,-1);

  DWORD ReadBuf=0;

  ReadProcessMemory(myEventInfo.ObjectProcessHandle,(LPVOID)(myEventInfo.WriteAddress+67),&ReadBuf,4,0);

  HANDLE ObjectProcessHandle=OpenProcess(PROCESS_ALL_ACCESS,1,ReadBuf);

  HookProcess(ObjectProcessHandle);

  SetEvent(myEventInfo.EventFar);

  ResetEvent(myEventInfo.EventFar);

 }

 return;

}

DWORD __stdcall Hook_NtResumeThread(

        HANDLE ThreadHandle,

        PULONG PreviousSuspendCount OPTIONAL)

{

 /*int OldNtResumeThread=0x11223344;//原NtQueryDirectoryFile函数

 int EventHandle=0x11002200;

 int my_GetCurrentProcessId=0x00224466;

 int my_SetEnent=0x22447688;

 int my_WaitForSingleObject=0x22556577;

 int my_NtQueryInformationThread=0x99884756;*/

 //int FarRead=0x00220044;

 int OldNtResumeThread;//原NtQueryDirectoryFile函数

 int EventHandle;

 int my_GetCurrentProcessId;

 int my_SetEnent;

 int my_WaitForSingleObject;

 int my_NtQueryInformationThread;

 int my_ResetEvent;

 __asm

 {

  mov OldNtResumeThread,00112244h

  mov EventHandle,00225588h

  mov my_GetCurrentProcessId,22447799h

  mov my_SetEnent,55662244h

  mov my_WaitForSingleObject,55889966h

  mov my_NtQueryInformationThread,77554411h

  mov my_ResetEvent,55661188h

  pushad

 }

 __asm call GetAddr;

 int FarRead;

 __asm mov FarRead,22550011h;


 DWORD myAddr;

 __asm

 {

  jmp start

GetAddr:

     pop eax

  mov myAddr,eax

  push eax

  ret

start:

 }

 DWORD myStatus;//存储返回变量

 BYTE SystemInfo[60];

 int infoaddr=(DWORD)&SystemInfo;

 int CurrentProcess;

 __asm

 {

  push 0

     push 28

  push infoaddr

  push 0

  push ThreadHandle

     call my_NtQueryInformationThread

  mov myStatus,eax

 }

 DWORD id=*(DWORD *)(SystemInfo+8);

 __asm

 {

  call my_GetCurrentProcessId

  mov CurrentProcess,eax

 }

 if(id==(DWORD)CurrentProcess)

 {

     __asm

  {

      push PreviousSuspendCount

      push ThreadHandle

      call OldNtResumeThread

      mov myStatus,eax

   popad

  }

     return myStatus;

 }

 if(myStatus==0)

 {

  *(PDWORD)(myAddr+3)=id;

  __asm

  {

   push EventHandle

   call my_SetEnent

   push -1

   push EventHandle

   call my_WaitForSingleObject

   push EventHandle

   call my_ResetEvent

  }

 }

 __asm

 {

  push PreviousSuspendCount

  push ThreadHandle

  call OldNtResumeThread

  mov myStatus,eax

  popad

 }

return myStatus;

}