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;
}