写了三天左右,思路什么的都很清晰,真正实现的时候就各种问题,蓝屏蓝到麻木了,幸好是虚拟机,半年前就打算看驱动了,因为各种原因耽搁了,现在什么都要重新来,这篇文章就当是开门贴吧。

主要功能:防止任务管理器结束进程

主要原理:HOOK SSDT表中的NtOpenProcess,如果传入的是保护进程的PID,则返回无效句柄。

这个Windows进程保护器的主要界面如下:

Windows内核学习之进程保护器(防止任务管理器结束进程)-编程知识网

利用此程序实现的禁止任务管理器中结束进程的效果图:

Windows内核学习之进程保护器(防止任务管理器结束进程)-编程知识网

实现过程总结

应用程序层:

//为listcontrol添加右键菜单
#ifndef GET_X_LPARAM
#define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam))
#endif
#ifndef GET_Y_LPARAM
#define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam))
#endif
case WM_CONTEXTMENU:
{
UINT xPos;
UINT yPos;
HWND hwndContext;
hwndContext = (HWND)wParam;
HWND hWndlist= GetDlgItem(hDlg, IDC_PROCESS_LIST);
xPos = GET_X_LPARAM(lParam);
yPos = GET_Y_LPARAM(lParam);
// 来自 hWndlist 的消息
if(hwndContext == hWndlist)
{
// 非右键点击
if (xPos == -1 || yPos == -1)
{
break;
}
HMENU hMenu=LoadMenu(hIns,MAKEINTRESOURCE(IDR_MENU1));
HMENU hMenuTrackPopup=GetSubMenu(hMenu,0);
TrackPopupMenu(hMenuTrackPopup,TPM_LEFTALIGN | TPM_RIGHTBUTTON,xPos,yPos, 0, hDlg, NULL);
DestroyMenu(hMenu);
}
// 做你自己的事
break;
}
TrackPopupMenu倒数第二个参数,要为当前对话框的句柄,否则无法响应菜单ID。
//初始化listcontrol

VOID ListIni(HWND hDlg)
{
HWND hWndlist;
LVCOLUMN ColInfo1 = {0};
LVCOLUMN ColInfo2 = {0};
LVCOLUMN ColInfo3 = {0};
LVCOLUMN ColInfo4 = {0};
LVCOLUMN ColInfo5 = {0};
hWndlist= GetDlgItem(hDlg, IDC_PROCESS_LIST);
SendMessage(hWndlist, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_GRIDLINES);
ColInfo1.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_FMT;
ColInfo1.iSubItem = 0;
ColInfo1.fmt = LVCFMT_CENTER;
ColInfo1.cx = 100;
ColInfo1.pszText = "进程名";
ColInfo1.cchTextMax = 50;
ColInfo2.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_FMT;
ColInfo2.iSubItem = 0;
ColInfo2.fmt = LVCFMT_CENTER;
ColInfo2.cx = 50;
ColInfo2.pszText = "PID";
ColInfo2.cchTextMax = 50;
ColInfo3.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_FMT;
ColInfo3.iSubItem = 0;
ColInfo3.fmt = LVCFMT_CENTER;
ColInfo3.cx = 80;
ColInfo3.pszText = "EPROCESS";
ColInfo3.cchTextMax = 50;
ColInfo4.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_FMT;
ColInfo4.iSubItem = 0;
ColInfo4.fmt = LVCFMT_CENTER;
ColInfo4.cx = 210;
ColInfo4.pszText = "路径";
ColInfo2.cchTextMax = 50;
ColInfo5.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_FMT;
ColInfo5.iSubItem = 0;
ColInfo5.fmt = LVCFMT_CENTER;
ColInfo5.cx = 50;
ColInfo5.pszText = "状态";
ColInfo5.cchTextMax = 50;
::SendMessage(hWndlist, LVM_INSERTCOLUMN, WPARAM(0), LPARAM(&ColInfo1));
::SendMessage(hWndlist, LVM_INSERTCOLUMN, WPARAM(1), LPARAM(&ColInfo2));
::SendMessage(hWndlist, LVM_INSERTCOLUMN, WPARAM(2), LPARAM(&ColInfo3));
::SendMessage(hWndlist, LVM_INSERTCOLUMN, WPARAM(3), LPARAM(&ColInfo4));
::SendMessage(hWndlist, LVM_INSERTCOLUMN, WPARAM(4), LPARAM(&ColInfo5));
}
//与驱动间的通信
传入要保护的进程PID数组
bRet = DeviceIoControl(hDevice, IOCTL_PROTECTPROCESS_CONTROL, ProPid, sizeof(ULONG)*100,
NULL,0,&dwOutput, NULL);
//从驱动中获取当前进程列表
bRet = DeviceIoControl(hDevice, IOCTL_GETPROCESS_CONTROL,&de, sizeof(ULONG),ProcessList,
sizeof(_ProcessList)*100,&dwOutput, NULL);
驱动层:
#pragma PAGEDCODE
struct _ProcessList
{
UCHAR ProcessName[30]; //进程名
ULONG PID;//PID
ULONG Eprocess;//Eprocess
ULONG ProCount;
}ProcessList[100];
#pragma PAGEDCODE
ULONG ProPid[100];

当时看的是Windows驱动开发详解,把变量换到分页内存中,害我蓝屏了30多次。

//获取进程列表
VOID EnumProcessList()
{
ULONG EProcess , FirstEProcess ;
ULONG dwCount = 0 ;
PLIST_ENTRY ActiveProcessLinks;
ULONG dwPidOffset =0x84;
ULONG dwPNameOffset = 0x174;
ULONG dwPLinkOffset = 0x88;
ULONG dwProcessId;
PUCHAR pImageFileName;
FirstEProcess = EProcess = ( ULONG ) PsGetCurrentProcess() ;

while ( EProcess != 0 )
{
dwProcessId = * ( (PULONG) ( EProcess + dwPidOffset ) ) ;
pImageFileName = ( PUCHAR ) ( EProcess + dwPNameOffset ) ;
if ( ( LONG ) dwProcessId >= 0 )
{
//DbgPrint( "[Pid=%8d] EProcess=0x%08x %s\n" ,dwProcessId , EProcess , pImageFileName ) ;
strcpy((char*)ProcessList[dwCount].ProcessName,(char*)pImageFileName);
ProcessList[dwCount].PID=dwProcessId;
ProcessList[dwCount].Eprocess=EProcess;
ProcessList[dwCount].ProCount=0;
dwCount ++ ;
}
ActiveProcessLinks = ( PLIST_ENTRY ) ( EProcess + dwPLinkOffset ) ;
EProcess = ( ULONG ) ActiveProcessLinks->Flink - dwPLinkOffset ;
if ( EProcess == FirstEProcess )
{
break ;
}
}
DbgPrint ( "ProcessNum = %d\n", dwCount ) ;
ULONG i=0;
ProcessList[0].ProCount=dwCount;
DbgPrint ( "ProcessNum = %d\n", ProcessList[0].ProCount ) ;
for (i=0;iMajorFunction)
{
case IRP_MJ_CREATE:
DbgPrint("IRP_MJ_CREATE被调用\n");
break;
case IRP_MJ_CLOSE:
DbgPrint("IRP_MJ_CLOSE被调用\n");
break;
case IRP_MJ_DEVICE_CONTROL:
DbgPrint("IRP_MJ_DEVICE_CONTROL被调用\n");
IoControlCode=IrpStack->Parameters.DeviceIoControl.IoControlCode;
switch(IoControlCode)
{
case IOCTL_PROTECTPROCESS_CONTROL:
inSize=IrpStack->Parameters.DeviceIoControl.InputBufferLength;
outSize=IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
inBuf=(long*)pIrp->AssociatedIrp.SystemBuffer;
RtlCopyMemory(ProPid,inBuf,sizeof(ULONG)*100);
break;
case IOCTL_GETPROCESS_CONTROL:
PVOID pInputBuffer, pOutputBuffer;
ULONG outputLength, inputLength;
DbgPrint("COMM_BufferedIo\r\n");
outputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
inputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
pInputBuffer = pIrp->AssociatedIrp.SystemBuffer;
pOutputBuffer = pIrp->AssociatedIrp.SystemBuffer;
DbgPrint("COMM_BufferedIo UserModeMessage = '%s'", pInputBuffer);
for (int i=0;iIoStatus.Information = outputLength;
break;
default:
break;
}
break;
default:
DbgPrint("未知请求包被调用\n");
break;
}
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
KdPrint(("Leave HelloDDKDispatchRoutine\n"));
return status;
}