vc++实现Ring3全局HOOK

/***********************************************************************/
/*
实现全局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;
}
posted on 2010-05-30 21:59  carekee  阅读(1058)  评论(0编辑  收藏  举报