挂起一个进程

5 篇文章 0 订阅
1 篇文章 0 订阅

文章文字解说转载自“珠穆朗玛”:http://sluttery.blog.163.com/blog/static/20277252005813749336/


源代码来自“开源中国”的sincoder:http://www.oschina.net/code/snippet_196111_14193


声明:两位作者本人不认识,与之相关的技术本人很陌生,只是见到以后可能用到就摘录下来,所以有疑问去问他们两位吧




老倪今天突然问道怎样才能挂起一个进程。线程很好办,因为系统提供了 SuspendThread() API 可以直接调用。要是在两天以前,老倪还真问住我了;不过幸好是今天,老汉已经知道了答案。忘了是昨天还是前天,在用十六进制方式查看大名鼎鼎的 Process Explorer 的时候,无意之中看到了一个原来没见过的 API 名字:NtSuspendProcess(),望文知义,连弱智都应该能看出来这个函数的作用。与之相对应的还有 NtResumeProcess()。他们的原型为:
 
NTSTATUS NtSuspendProcess(HANDLE hProcess);
NTSTATUS NtResumeProcess(HANDLE hProcess);
 
从 NTDLL.DLL 中找到地址就可以直接用了。另外关于查询一个进程当前是不是处于被挂起状态我还不知道,估计跑不了 NtQueryInformationProcess()。



源代码:

潦草阅读了源代码,竟然发现两个人所说所做的异曲同工(如果两位作者是同一个人那我就无语了……)

//代码用于挂起进程,来自http://www.oschina.net/code/snippet_196111_14193
#include <windows.h>
#include <wchar.h>

typedef struct _UNICODE_STRING {
	USHORT Length;        
	USHORT MaximumLength;
	PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _CLIENT_ID {
    HANDLE UniqueProcess;
    HANDLE UniqueThread;
} CLIENT_ID;
typedef CLIENT_ID *PCLIENT_ID;
typedef LONG KPRIORITY;
typedef enum _KWAIT_REASON {
    Executive,
	FreePage,
	PageIn,
	PoolAllocation,
	DelayExecution,
	Suspended,
	UserRequest,
	WrExecutive,
	WrFreePage,
	WrPageIn,
	WrPoolAllocation,
	WrDelayExecution,
	WrSuspended,
	WrUserRequest,
	WrEventPair,
	WrQueue,
	WrLpcReceive,
	WrLpcReply,
	WrVirtualMemory,
	WrPageOut,
	WrRendezvous,
	WrKeyedEvent,
	WrTerminated,
	WrProcessInSwap,
	WrCpuRateControl,
	WrCalloutStack,
	WrKernel,
	WrResource,
	WrPushLock,
	WrMutex,
	WrQuantumEnd,
	WrDispatchInt,
	WrPreempted,
	WrYieldExecution,
	WrFastMutex,
	WrGuardedMutex,
	WrRundown,
	MaximumWaitReason
} KWAIT_REASON;

typedef struct _VM_COUNTERS {
    SIZE_T PeakVirtualSize;
    SIZE_T VirtualSize;
    ULONG  PageFaultCount;
    SIZE_T PeakWorkingSetSize;
    SIZE_T WorkingSetSize;
    SIZE_T QuotaPeakPagedPoolUsage;
    SIZE_T QuotaPagedPoolUsage;
    SIZE_T QuotaPeakNonPagedPoolUsage;
    SIZE_T QuotaNonPagedPoolUsage;
    SIZE_T PagefileUsage;
    SIZE_T PeakPagefileUsage;
} VM_COUNTERS;
typedef VM_COUNTERS *PVM_COUNTERS;

typedef struct _SYSTEM_THREAD_INFORMATION {
    ULONGLONG KernelTime;
    ULONGLONG UserTime;
    ULONGLONG CreateTime;
    ULONG WaitTime;
    ULONG Reserved1;
    PVOID StartAddress;
    CLIENT_ID ClientId;
    KPRIORITY Priority;
    LONG BasePriority;
    ULONG ContextSwitchCount;
    ULONG State;
    KWAIT_REASON WaitReason;
} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;

typedef struct _SYSTEM_PROCESS_INFORMATION {
    ULONG NextEntryOffset;
    ULONG NumberOfThreads;
    ULONGLONG Reserved[3];
    ULONGLONG CreateTime;
    ULONGLONG UserTime;
    ULONGLONG KernelTime;
    UNICODE_STRING ImageName;
    KPRIORITY BasePriority;
    HANDLE ProcessId;
    HANDLE InheritedFromProcessId;
    ULONG HandleCount;
    ULONG Reserved2[2];
    ULONG PrivatePageCount;  // Garbage
    VM_COUNTERS VirtualMemoryCounters;
    IO_COUNTERS IoCounters;
    SYSTEM_THREAD_INFORMATION Threads[1];
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;


/*----------------------------------------------------
函数说明: 动态加载动库文件
输入参数: pDllName 库文件名称,pProcName导出函数名字
输出参数: 无
返回值   : 返回函数的的地址
----------------------------------------------------*/
VOID *GetDllProc(CHAR * pDllName, CHAR *pProcName)
{
	HMODULE         hMod;
	hMod = LoadLibraryA(pDllName);
	if(hMod == NULL)
		return NULL;
	
	return GetProcAddress(hMod, pProcName);
}

//宏定义函数的指针
typedef LONG (WINAPI *Fun_NtQuerySystemInformation) (int SystemInformationClass,
													 OUT PVOID SystemInformation,
													 IN ULONG SystemInformationLength,
													 OUT ULONG * pReturnLength OPTIONAL);
typedef __success(return >= 0) LONG NTSTATUS;
#define STATUS_INFO_LENGTH_MISMATCH         ((LONG)0xC0000004L)
#define SystemProcessInformation         5


//Jan 4 2005
//Enable specific privilege
//启用特定的权限
BOOL EnableSpecificPrivilege(BOOL bEnable,LPCTSTR Name)
{
	BOOL bResult = FALSE;
	HANDLE hToken;
	TOKEN_PRIVILEGES TokenPrivileges;
	
	if(OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,&hToken) == 0)
	{
		return FALSE;
	}
	
	TokenPrivileges.PrivilegeCount = 1;
	TokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
	bResult = LookupPrivilegeValue(NULL,Name,&TokenPrivileges.Privileges[0].Luid);
	if(!bResult)
	{
		CloseHandle(hToken);
		return FALSE;
	}
	
	bResult = AdjustTokenPrivileges(hToken,FALSE,&TokenPrivileges,sizeof(TOKEN_PRIVILEGES),NULL,NULL);
	if(GetLastError() != ERROR_SUCCESS || !bResult)
	{
		CloseHandle(hToken);
		return FALSE;
	}
	
	CloseHandle(hToken);
	return TRUE;
}

//Jan 4 2005
//Enable all privilege, return num of privileges successfully enabled
//启用所有的特权,特权返回NUM成功启用
DWORD EnableAllPrivilege(BOOL bEnable)
{
	DWORD count=0; 
	///
	count+=EnableSpecificPrivilege(bEnable,SE_ASSIGNPRIMARYTOKEN_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_AUDIT_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_BACKUP_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_CHANGE_NOTIFY_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_CREATE_PAGEFILE_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_CREATE_PERMANENT_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_CREATE_TOKEN_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_DEBUG_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_INC_BASE_PRIORITY_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_INCREASE_QUOTA_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_LOAD_DRIVER_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_LOCK_MEMORY_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_PROF_SINGLE_PROCESS_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_REMOTE_SHUTDOWN_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_RESTORE_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_SECURITY_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_SHUTDOWN_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_SYSTEM_ENVIRONMENT_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_SYSTEM_PROFILE_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_SYSTEMTIME_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_TAKE_OWNERSHIP_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_TCB_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_UNSOLICITED_INPUT_NAME);
	count+=EnableSpecificPrivilege(bEnable,SE_MACHINE_ACCOUNT_NAME);
	
	return count;
}



/*------------------------------------------------------------------
函数说明: 获取系统进程的信息
输入参数: SYSTEM_PROCESS_INFORMATION
输出参数: 无

--------------------------------------------------------------------*/
BOOL GetSysProcInfo(SYSTEM_PROCESS_INFORMATION ** ppSysProcInfo)
{
	Fun_NtQuerySystemInformation     _NtQuerySystemInformation;
	DWORD         dwSize = 1024*1024;
	VOID         * pBuf = NULL;
	LONG         lRetVal;

	_NtQuerySystemInformation = (Fun_NtQuerySystemInformation)GetDllProc("NTDLL.DLL", "NtQuerySystemInformation");
	//这里提到了获取进程挂起信息的NtQuerySystemInformation函数
	if(_NtQuerySystemInformation == NULL)
		return FALSE;

	for(;;)
	{
		if(pBuf)
			free(pBuf);
		pBuf = (VOID *)malloc(dwSize);
		lRetVal = _NtQuerySystemInformation(SystemProcessInformation,
			pBuf, dwSize, NULL);
		if(STATUS_INFO_LENGTH_MISMATCH != lRetVal)
			break;
		dwSize += 1024;
	}
	
	if(lRetVal == 0)
	{
		*ppSysProcInfo = (SYSTEM_PROCESS_INFORMATION *)pBuf;
		return TRUE;
	}
	free(pBuf);
	return FALSE;
}

//通过进程名称挂起进程的主函数
BOOL SuspendProcessByName(wchar_t *pszProcessName)
{         
	VOID (__stdcall *pRtlInitUnicodeString)(PUNICODE_STRING ,PCWSTR);
	LONG (__stdcall *pRtlCompareUnicodeString)(PUNICODE_STRING  ,PUNICODE_STRING  ,BOOLEAN);	
	NTSTATUS (__stdcall *pNtSuspendProcess)(HANDLE);
	BOOL         bRetVal, bFind;
	UNICODE_STRING usProcessName;
	HANDLE		hProcess;
	SYSTEM_PROCESS_INFORMATION     *     pProcInfo, * pCurProcInfo;

	pRtlInitUnicodeString = (void (__stdcall *)(PUNICODE_STRING ,PCWSTR))GetDllProc("ntdll.dll","RtlInitUnicodeString");
	pRtlCompareUnicodeString =(long (__stdcall *)(PUNICODE_STRING  ,PUNICODE_STRING  ,BOOLEAN)) GetDllProc("ntdll.dll","RtlCompareUnicodeString");
	pNtSuspendProcess = (NTSTATUS (__stdcall *)(HANDLE))GetDllProc("ntdll.dll","NtSuspendProcess");
	//这里提到了挂起进程的NtSuspendProcess函数
	//这里的原句是pNtSuspendProcess = GetDllProc("ntdll.dll","NtSuspendProcess");在VS2010中编译出错,显示无法实现类型转换,故改为显示类型转换

	if(pRtlInitUnicodeString == NULL || pRtlCompareUnicodeString == NULL || pNtSuspendProcess == NULL)
	{
		wprintf(L"init function failed ..\n");
		return FALSE;
	}
	pRtlInitUnicodeString(&usProcessName,pszProcessName);
	bRetVal = GetSysProcInfo(&pProcInfo);
	if(bRetVal == FALSE || pProcInfo == NULL)
	{
		wprintf(L"enum process failed...\n");
		return FALSE;
	}
	pCurProcInfo = pProcInfo;
	bFind = FALSE;
	for(;;)
	{
		if(pRtlCompareUnicodeString(&usProcessName,&pCurProcInfo->ImageName,TRUE) == 0)
		{
			bFind = TRUE;
			wprintf(L"%s's pid is %d\n",pszProcessName,pCurProcInfo->ProcessId);
			hProcess = OpenProcess(PROCESS_SUSPEND_RESUME,FALSE,(DWORD)pCurProcInfo->ProcessId);
			if(hProcess == NULL)
			{
				wprintf(L"Open process failed !\n");
				goto failed;
			}
			if(pNtSuspendProcess(hProcess) != 0)
				wprintf(L"suspend process %s failed\n",pszProcessName);
		}
		//wprintf(L"--->%s\n",pCurProcInfo->ImageName.Buffer);
		if(pCurProcInfo->NextEntryOffset == 0)
			break;
		pCurProcInfo = (SYSTEM_PROCESS_INFORMATION *)((BYTE *)pCurProcInfo + pCurProcInfo->NextEntryOffset);
	}
	if(bFind == FALSE)
	{
		wprintf(L"process %s not find !\n",pszProcessName);
failed:
		free(pProcInfo);
		return FALSE;
	}
	free(pProcInfo);
	return TRUE;
}

//main函数
int main()
{
	wprintf(L"\tkilldog.exe By:sincoder \n\tBlog:www.sincoder.com\n");
	EnableAllPrivilege(TRUE);
	if(SuspendProcessByName(L"SafeDogGuardCenter.exe"))//需要挂起的进程名
		wprintf(L"Done!\n");
	return 0;
}

本人注:代码挂起的是SafeDogGuardCenter.exe,即安全狗的进程。新建一个控制台工项目空项目,即将上述代码放入一个新建的cpp中即可运行。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值