怎么实现防止被其他进程杀掉

进程防杀的实现

在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()上面,实现了进程防杀。喜悦之余,将这心得体会拿出来与大家分享。


windowsNT下的通过截获OpenProcess函数来禁止终止本进程的VC代码如下:

StickyApp32.cpp文件
#include <windows.h>
#include "HookAPI.h"

typedef HANDLE (__stdcall *OPENPROCESS_PROC)(DWORD, BOOL, DWORD);

OPENPROCESS_PROC pOpenProcess = NULL;

HANDLE __stdcall OpenProcess_Handler(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
{
HANDLE RetValue = NULL;
HWND hWnd;
DWORD ProcessId;

hWnd = FindWindow("ThunderRT5Form", "StickyApp32";

GetWindowThreadProcessId(hWnd, &ProcessId);

if (dwProcessId != ProcessId)
RetValue = pOpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);

return RetValue;
}


__declspec(dllexport) LRESULT CALLBACK HookFunction(int code, WPARAM wParam, LPARAM lParam)
{
if (pOpenProcess == NULL)
pOpenProcess = (OPENPROCESS_PROC)HookAPIFunction(GetModuleHandle(NULL), "KERNEL32.DLL", "OpenProcess", (PROC)OpenProcess_Handler);

return false;
}


BOOL WINAPI DllMain(HANDLE hInst, ULONG dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:

DisableThreadLibraryCalls(hInst);

break;
}

return true;
}


HOOKAPI.cpp文件
// ----------
// HOOKAPI - Matt Pietrek 1995
// ----------

#include <windows.h>
#include "HookAPI.h"

// Macro for adding pointers/DWORDs together without C arithmetic interfering

#define MakePtr(cast, ptr, addValue) (cast)((DWORD)(ptr)+(DWORD)(addValue))

PROC HookAPIFunction(HMODULE hFromModule,
PSTR pszFunctionModule,
PSTR pszFunctionName,
PROC pfnNewProc)
{
PROC pfnOriginalProc;
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
PIMAGE_THUNK_DATA pThunk;

DWORD dwProtectionFlags;
DWORD dwScratch;

// Verify that a valid pfn was passed

if (IsBadCodePtr(pfnNewProc)) return 0;

// First, verify the the module and function names passed to use are valid

pfnOriginalProc = GetProcAddress(GetModuleHandle(pszFunctionModule), pszFunctionName);

if (!pfnOriginalProc) return 0;

pDosHeader = (PIMAGE_DOS_HEADER)hFromModule;

// Tests to make sure we're looking at a module image (the 'MZ' header)

if (IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER))) return 0;

if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) return 0;

// The MZ header has a pointer to the PE header

pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDosHeader, pDosHeader->e_lfanew);

// More tests to make sure we're looking at a "PE" image

if (IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS))) return 0;

if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) return 0;

// We know have a valid pointer to the module's PE header.
// Now go get a pointer to its imports section

pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, pDosHeader,
pNTHeader->OptionalHeader.
DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].
VirtualAddress);

// Bail out if the RVA of the imports section is 0 (it doesn't exist)

if (pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeader) return 0;

// Iterate through the array of imported module descriptors, looking
// for the module whose name matches the pszFunctionModule parameter

while (pImportDesc->Name)
{
PSTR pszModName = MakePtr(PSTR, pDosHeader, pImportDesc->Name);

if (stricmp(pszModName, pszFunctionModule) == 0) break;

// Advance to next imported module descriptor

pImportDesc++;
}

// Bail out if we didn't find the import module descriptor for the
// specified module. pImportDesc->Name will be non-zero if we found it.

if (pImportDesc->Name == 0) return 0;

// Get a pointer to the found module's import address table (IAT)

pThunk = MakePtr(PIMAGE_THUNK_DATA, pDosHeader, pImportDesc->FirstThunk);

// Blast through the table of import addresses, looking for the one
// that matches the address we got back from GetProcAddress above.

while (pThunk->u1.Function)
{
if (pThunk->u1.Function == (PDWORD)pfnOriginalProc)
{
dwProtectionFlags = PAGE_READWRITE;

VirtualProtect(&pThunk->u1.Function, 4096, dwProtectionFlags, &dwScratch);

// We found it! Overwrite the original address with the
// address of the interception function. Return the original
// address to the caller so that they can chain on to it.

pThunk->u1.Function = (PDWORD)pfnNewProc;

return pfnOriginalProc;
}

// Advance to next imported function address

pThunk++;
}

// Function not found

return 0;
}


Hookapi.h文件

#ifndef HOOKAPI_H
#define HOOKAPI_H

PROC HookAPIFunction(HMODULE hFromModule,
PSTR pszFunctionModule,
PSTR pszFunctionName,
PROC pfnNewProc);

#endif


  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
09年初刚到现在这家公司,头让做一个进程防杀的功能,为了保护我们的软件的服务程序,类似360或瑞星这样的安全产品都有进程防杀的功能。研究了一个多月,总结网上的各种防杀方法并参考其代码,特此将各种实现方法归纳为以下6种,并将其对应源码奉上。 源码全部经过自己修改调试,部分为原创,在vs2005下调试通过,在各种windows操作系统下测试过 1. ring3提升线程为系统线程 原理:windows在强制结束进程的时候会先结束掉所有的线程,把程序的线程改成系统线程,就可以达到防杀的目的 优点:ring3实现进程防杀,无驱动无hook,原理及代码都较为简单,能防止任务管理器杀掉进程 缺点:只能下xp下有效(与xp打的补丁也有关,有的xp系统会失败)防杀能力有限,例如不能防住IceSword等工具 该方法是参考了csdn一位朋友的做法,原文地址为 http://blog.csdn.net/KeSummer/archive/2008/05/18/2455379.aspx 2.hookApi之NtQuerySystemInformation 原理:hook NtQuerySystemInformation 来隐藏进程 优点:ring3实现进程隐藏,无驱动,能在任务管理器里隐藏进程 缺点:只能在nt2000下隐藏进程,通用性较差 3.detours库实现进程防杀 原理:和2类似,hook OpenProcess 来防杀进程 优点:防杀能力和通用性都较强,在nt2000,xp,2003均可防杀 缺点:hookApi是用detours库来实现的,2008下防杀失败,不能防住某些进程工具 4.hook任务管理器结束进程事件 原理:挂钩任务管理器窗口,利用CBT钩子拦截结束进程消息 优点:通用性较强,任意的windows平台均可防止任务管理器杀进程 缺点:只能针对windows任务管理起到防杀作用 5.双进程保护 原理:主进程和守护进程互相监控,发现对方不在就启动对方。为了避免父子进程关系,主进程启动临时进程,临时进程启动守护进程 优点:通用性较强,保护能力较强,可保护windows服务程序。hook防杀需要主程序和桌面交互的,而服务程序是不和桌面交互的 缺点:非真正的防杀,只是杀了又启,手段有点不入流 6.驱动级进程保护 原理:驱动级的ZwQuerySystemInformation hook,来隐藏或防杀进程 优点:防杀能力较强,在IceSword 1.2.2版本下测试通过 缺点:加载有驱动,程序实现较为复杂,驱动级hook被360等杀毒工具检测为木马 yipihaoma qq:49489047

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值