TerminateProcess HOOK

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TerminateProcess HOOK相关的知识,希望对你有一定的参考价值。

我想实现以下功能:
用任务管理器关闭a.exe这个进程的时候,系统并不关闭,只是将a.exe最小化。这个可以通过Hook API TerminateProcess来实现,是否各位大大能给出代码呢
最好是用VC来实现,谢谢两位朋友的答案,但是这两位朋友并没有达到我所需要的要求

如何保证自己的程序不被关闭?

就算是一些进程软件也不可以关闭
samba 我听过有人采用程序互相监控的方法来达到目的。
但这样就会占用系统资源。一个不加什么控件的纯窗体都要3占用MB内存,
如果加上我本来的那个程序,岂不是要占去十几MB内存,这对于我那个小程序来讲不不可忍受的。
请问有什么比较好的方法可以解决?有这方面的控件吗?先谢过大家了!

---------------------------------------------------------------

在WINDOWS操作系统下,当我们无法结束或者不知道怎样结束一个程序的时候,或者是懒得去找“退出”按钮的时候,通常会按“CTRL+ALT+DEL”呼出任务管理器,找到想结束的程序,点一下“结束任务”就了事了,呵呵,虽然有点粗鲁,但大多数情况下都很有效,不是吗?

设想一下,如果有这么一种软件,它所要做的工作就是对某个使用者在某台电脑上的活动作一定的限制,而又不能被使用者通过“结束任务”这种方式轻易地解除限制,那该怎么做?无非有这么三种方法:1.屏蔽“CTRL+ALT+DEL”这个热键的组合;2.让程序不出现在任务管理器的列表之中;3.让任务管理器无法杀掉这个任务。对于第一种方法,这样未免也太残酷了,用惯了“结束任务”这种方法的人会很不习惯的;对于第二种方法,在WINDOWS 9X下可以很轻易地使用注册服务进程的方法实现,但是对于WINDOWS NT架构的操作系统没有这个方法了,进程很难藏身,虽然仍然可以实现隐藏,但实现机制较为复杂;对于第三种方法,实现起来比较简单,我的作品:IPGate 网址过滤器 就是采用的这种方式防杀的,接下来我就来介绍这种方法。

任务管理器的“结束任务”实际上就是强制终止进程,它所使用的杀手锏是一个叫做TerminateProcess()的Win32 API函数,我们来看看它的定义:

BOOL TerminateProcess(
HANDLE hProcess; // 将被结束进程的句柄
UINT uExitCode; // 指定进程的退出码
);

看到这里,是不是觉得不必往下看都知道接下来要做什么:Hook TerminateProcess()函数,每次TerminateProcess()被调用的时候先判断企图结束的进程是否是我的进程,如果是的话就简单地返回一个错误码就可以了。真的是这么简单吗?先提出一个问题,如何根据hProcess判断它是否是我的进程的句柄?答案是:在我的进程当中先获得我的进程的句柄,然后通过进程间通讯机制传递给钩子函数,与hProcess进行比较不就行了?错!因为句柄是一个进程相关的值,不同进程中得到的我的进程的句柄的值在进程间进行比较是无意义的。

怎么办?我们来考察一下我的hProcess它是如何得到的。一个进程只有它的进程ID是独一无二的,操作系统通过进程ID来标识一个进程,当某个程序要对这个进程进行访问的话,它首先得用OpenProcess这个函数并传入要访问的进程ID来获得进程的句柄,来看看它的参数:

HANDLE OpenProcess(
DWORD dwDesiredAccess, // 希望获得的访问权限
BOOL bInheritHandle, // 指明是否希望所获得的句柄可以继承
DWORD dwProcessId // 要访问的进程ID
);

脉络渐渐显现:在调用TerminateProcess()之前,必先调用OpenProcess(),而OpenProcess()的参数表中的dwProcessId是在系统范围内唯一确定的。得出结论:要Hook的函数不是TerminateProcess()而是OpenProcess(),在每次调用OpenProcess()的时候,我们先检查dwProcessId是否为我的进程的ID(利用进程间通讯机制),如果是的话就简单地返回一个错误码就可以了,任务管理器拿不到我的进程的句柄,它如何结束我的进程呢?

至此,疑团全部揭开了。由Hook TerminateProcess()到Hook OpenProcess()的这个过程,体现了一个逆向思维的思想。其实我当初钻进了TerminateProcess()的死胡同里半天出也不来,但最终还是蹦出了灵感的火花,注意力转移到了OpenProcess()上面,实现了进程防杀。喜悦之余,将这心得体会拿出来与大家分享。

---------------------------------------------------------------

要不我给你把我的可执行文件的源代码和动态连接库发给你好了
动态连接库你自己可以换掉
就是要注入的那个
,注入到的目标程序你自己设置

---------------------------------------------------------------

呵呵,我成功实现了:)
通过setwindowshookex建立CBT的Hook,Hook DLL中加载API重定向,就可以达到全局有效的APIHOOK效果了,还要对MapFile操作,以便统一全局的参数

下载地址:http://free.dvs168.net/lysoft/projects/API Hook.rar

by Liu Yang http://lysoft.7u7.net
---------------------------------------------------------------

上面的例子,很厉害的,不只是任务管理器,连别的第三方软件都奈何不得!

禁止 CTRL+ALT+DELETE under XP and Win2000, 2003的方法,不过容易破解

另外,XP下Gina方法是不行的,我提供的Demo就没问题了。至于那个DLL是怎么写的,就不便公开了。调用接口就在代码中,呵呵,花了我3天功夫才搞好。有点累了,休息了。

procedure DisableTaskMgr(bTF: Boolean);
var
reg: TRegistry;
begin
reg := TRegistry.Create;
reg.RootKey := HKEY_CURRENT_USER;

reg.OpenKey('Software', True);
reg.OpenKey('Microsoft', True);
reg.OpenKey('Windows', True);
reg.OpenKey('CurrentVersion', True);
reg.OpenKey('Policies', True);
reg.OpenKey('System', True);

if bTF = True then
begin
reg.WriteString('DisableTaskMgr', '1');
end
else if bTF = False then
begin
reg.DeleteValue('DisableTaskMgr');
end;
reg.CloseKey;
end;

// Example Call:
procedure TForm1.Button1Click(Sender: TObject);
begin
DisableTaskMgr(True);
end;
---------------------------------------------------------------

type //定义一个入口结构
PImage_Import_Entry = ^Image_Import_Entry;
Image_Import_Entry = record
Characteristics: DWORD; //"code"or"data"or"bss"
TimeDateStamp: DWORD;
MajorVersion: Word;
MinorVersion: Word;
Name: DWORD; //所属动态库或程序的名称
LookupTable: DWORD;
end;

type //定义一个跳转的结构
TImportCode = packed record
JumpInstruction: Word; //定义跳转指令jmp
AddressOfPointerToFunction: ^Pointer; //定义要跳转到的函数
end;
PImportCode = ^TImportCode;
implementation
//返回当前函数地址
function LocateFunctionAddress(Code: Pointer): Pointer;
var
func: PImportCode;
begin
Result := Code;
if Code = nil then exit;
try
func := code;
if (func.JumpInstruction = $25FF) then
begin
Result := func.AddressOfPointerToFunction^;
end;
except
Result := nil;
end;
end;
//改变函数的指向
function RepointFunction(OldFunc, NewFunc: Pointer): Integer;
var
IsDone: TList;
//将指定实例中的引入函数定位为新函数
function RepointAddrInModule(hModule: THandle; OldFunc, NewFunc: Pointer): Integer;
var
Dos: PImageDosHeader;//dos head
NT: PImageNTHeaders; //nt head
ImportDesc: PImage_Import_Entry; //函数入口地址
RVA: DWORD;
Func: ^Pointer;
DLL: string;
f: Pointer;
written: DWORD;
begin
Result := 0;
Dos := Pointer(hModule);//实例句柄
if IsDone.IndexOf(Dos) >= 0 then exit; //是否已经替换过此实例句柄
IsDone.Add(Dos); //添加实例句柄
OldFunc := LocateFunctionAddress(OldFunc);

if IsBadReadPtr(Dos, SizeOf(TImageDosHeader)) then exit;

if Dos.e_magic <> IMAGE_DOS_SIGNATURE then exit;//判断是否是合法的dos头

NT := Pointer(Integer(Dos) + dos._lfanew);//得到pe头
//得到输入函数的相关虚地址
RVA := NT^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

if RVA = 0 then exit;
//计算实际第一个输入函数地址
ImportDesc := pointer(integer(Dos) + RVA);
while (ImportDesc^.Name <> 0) do
begin
//得到输入的动态库名称
DLL := PChar(Integer(Dos) + ImportDesc^.Name);
//递归到另一个动态库
RepointAddrInModule(GetModuleHandle(PChar(DLL)), OldFunc, NewFunc);
//计算引入函数在程序中的调入地址
Func := Pointer(Integer(DOS) + ImportDesc.LookupTable);
while Func^ <> nil do
begin
f := LocateFunctionAddress(Func^);
//找寻引入的函数
if f = OldFunc then
begin
//注入新函数地址
WriteProcessMemory(GetCurrentProcess, Func, @NewFunc, 4, written);
if Written > 0 then Inc(Result);
end;
Inc(Func);
end;
Inc(ImportDesc);
end;
end;

begin
IsDone := TList.Create;
try
Result := RepointAddrInModule(GetModuleHandle(nil), OldFunc, NewFunc);
finally
IsDone.Free;
end;
end;
参考技术A 1.用FileMon看看守护进程是哪个。
2.用VB编一段超小的程序:(伪码)
On Error Resume Next
KillIt:
delete("A.exe")
GoTo KillIt
运行之,结束A.exe

C++ hook 问题

检测键盘,有按键就cout<<“按键了”。
应该是怎么个流程??
要不要自己写个DLL?然后用程序加载或注入?
我知道用什么函数,但是返回的句柄老是0。

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
// function declaration.
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam );
int main()


// Retrieve the applications instance
HINSTANCE appInstance = GetModuleHandle(NULL);
// Set a global Windows Hook to capture keystrokes.
SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, appInstance, 0 );
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0)


TranslateMessage(&msg);
DispatchMessage(&msg);


return 0;

LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam )


// Declare our pointer to the KBDLLHOOKSTRUCT
KBDLLHOOKSTRUCT *pKeyBoard = (KBDLLHOOKSTRUCT *)lParam;
switch( wParam )


case WM_KEYUP: // When the key has been pressed and released


switch( pKeyBoard->vkCode ) // Check to see what key has been pushed


case VK_RETURN: // The return/enter key has been pressed
DWORD timestamp = pKeyBoard->time; // This shows our timestamp when the key was pushed.
printf("Enter Key Pressed %u", timestamp ); // Show us when the key has been pushed
break;


default:
return CallNextHookEx( NULL, nCode, wParam, lParam );

return 0;
参考技术A 如果是Hook全局的而不是某个特定的进程则需要将Hook过程编写为一个DLL,以便让任何程序都可以加载它来获取Hook过程函数。至于你说的返回的句柄是0,我记得hook键盘按键的钩子获取到的值是存在wParam里面的。返回值当然不会有结果。

以上是关于TerminateProcess HOOK的主要内容,如果未能解决你的问题,请参考以下文章

TerminateProcess HOOK

ExitProcess,TerminateProcess,CreateToolhelp32Snapshot,Process32First,Process32Next,OpenProcess

进程关闭过程

delphi 提升openprocess权限

Windows Internals 笔记——终止进程

如何安全地杀死 robocopy 进程