您的位置:首页 > 其它

PsSetCreateProcessNotifyRoutine进程黑名单

2016-04-29 16:11 253 查看
通过PsSetCreateProcessNotifyRoutine可以设置一个进程回调

当有进程被创建的时候

回调用这个通知

我写了一段代码

通过检测进程对应的文件的版本信息来拒绝进程运行

360以前就这么干的

主要是怎么通过进程ID获取进程的全路径

还有怎么在驱动里面访问程序的资源

#ifndef _SHIELDER_H

#define _SHIELDER_H

#ifdef __cplusplus

extern "C"

{

#endif

#include <ntddk.h>

#ifdef __cplusplus

}

#endif

typedef struct _LDR_RESOURCE_INFO

{

ULONG Type;

ULONG Name;

ULONG Language;

} LDR_RESOURCE_INFO, *PLDR_RESOURCE_INFO;

#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))

#define RESOURCE_TYPE_LEVEL 0

#define RESOURCE_NAME_LEVEL 1

#define RESOURCE_LANGUAGE_LEVEL 2

#define RESOURCE_DATA_LEVEL 3

typedef int BOOL;

typedef ULONG DWORD;

typedef DWORD* PDWORD;

typedef USHORT WORD;

typedef struct _VersionInfo

{

WORD wLength;

WORD wValueLength;

WORD wType;

WCHAR szKey[1];

} VersionInfo, *PVersionInfo;

typedef struct _LangAndCodePage

{

WORD wLanguage;

WORD wCodePage;

} LangAndCodePage, *PLangAndCodePage;

typedef struct _PROCESS_IMAGE_INFORMATION

{

PVOID pEntryPoint;

PVOID unk;

ULONG_PTR stackReserve;

ULONG_PTR stackCommit;

USHORT subsystem;

USHORT unk2;

ULONG osVersion;

ULONG imageVersion;

USHORT dllCharacteristics;

USHORT fileHeaderCharacteristics;

USHORT machine;

USHORT unk3;

PVOID unk4;

PVOID unk5;

ULONG checksum;

} PROCESS_IMAGE_INFORMATION, *PPROCESS_IMAGE_INFORMATION;

//NTSTATUS ZwTerminateProcess(ULONG pProcessHandle,int ExitStatus);

EXTERN_C

NTSTATUS ZwCreateJobObject(

OUT PHANDLE JobHandle,

IN ACCESS_MASK DesiredAccess,

IN POBJECT_ATTRIBUTES ObjectAttributes);

EXTERN_C

NTSTATUS ZwAssignProcessToJobObject(

HANDLE JobHandle,

HANDLE ProcessHandle

);

EXTERN_C

NTSTATUS ZwTerminateJobObject(

HANDLE JobHandle,

NTSTATUS ExitStatus

);

EXTERN_C

NTSTATUS WINAPI ZwQueryInformationProcess(

IN HANDLE ProcessHandle,

IN PROCESSINFOCLASS ProcessInformationClass,

OUT PVOID ProcessInformation,

IN ULONG ProcessInformationLength,

OUT PULONG ReturnLength

);

EXTERN_C

NTSYSAPI

NTSTATUS

NTAPI

ZwCreateSection(

OUT PHANDLE SectionHandle,

IN ACCESS_MASK DesiredAccess,

IN POBJECT_ATTRIBUTES ObjectAttributes,

IN PLARGE_INTEGER MaximumSize,

IN ULONG SectionPageProtection,

IN ULONG AllocationAttributes,

IN HANDLE FileHandle

);

EXTERN_C

NTSTATUS

LdrAccessResource(

IN PVOID pBaseAddress,

IN PIMAGE_RESOURCE_DATA_ENTRY pResourceDataEntry,

OUT PVOID* ppResource,

OUT PULONG puSize

);

EXTERN_C

NTSTATUS

LdrFindResource_U(

IN PVOID pBaseAddress,

IN PLDR_RESOURCE_INFO pResourceInfo,

IN ULONG uLevel,

OUT PIMAGE_RESOURCE_DATA_ENTRY* ppResourceDataEntry

);

#define DWordAlign( base, ptr ) \

( (PUCHAR)(base) + ((((PUCHAR)(ptr) - (PUCHAR)(base)) + 3) & ~3) )

#define GetVersionInfoValue( ver ) \

DWordAlign( (ver), (ver)->szKey + wcslen((ver)->szKey) + 1 )

#define GetVersionInfoChildren( ver ) \

(PVersionInfo)( GetVersionInfoValue( ver ) + \

( ( (ver)->wValueLength * \

((ver)->wType? 2 : 1) + 3 ) & ~3 ) )

#define GetVersionInfoNext( ver ) \

(PVersionInfo)( (PUCHAR)ver + (((ver)->wLength + 3) & ~3) )

PVersionInfo

VersionInfoFindChild(

IN PVersionInfo pInfo,

IN LPWSTR lpKey,

IN DWORD dwKeyLength

)

{

PVersionInfo pChild = GetVersionInfoChildren( pInfo );

while( (DWORD) pChild < (DWORD) pInfo + pInfo->wLength )

{

if( ( 0 == _wcsnicmp(pChild->szKey, lpKey, dwKeyLength) ) &&

( 0 == pChild->szKey[dwKeyLength] ) )

{

return pChild;

}

pChild = GetVersionInfoNext( pChild );

}

return NULL;

}

BOOL

VersionInfoQueryValue(

IN PVersionInfo pInfo,

IN LPWSTR lpSubBlock,

OUT PVOID* ppBuffer,

OUT PDWORD pdwLength

)

{

BOOL bStatus = TRUE;

while( *lpSubBlock )

{

LPWSTR lpNextSlash = NULL;

for( lpNextSlash = lpSubBlock; *lpNextSlash; lpNextSlash ++ )

{

if( L'\\' == *lpNextSlash )

{

break;

}

}

if( lpNextSlash == lpSubBlock )

{

lpSubBlock ++;

continue;

}

pInfo = VersionInfoFindChild( pInfo, lpSubBlock, lpNextSlash - lpSubBlock );

if( NULL == pInfo )

{

bStatus = FALSE;

break;

}

lpSubBlock = lpNextSlash;

}

if( NULL != pInfo )

{

*ppBuffer = GetVersionInfoValue( pInfo );

}

if( NULL != pdwLength )

{

*pdwLength = bStatus ? pInfo->wValueLength : 0;

}

return bStatus;

}

BOOL

GetInternalNameFromVersionInfo(

IN PVersionInfo pVersion,

IN DWORD dwLangCount,

IN LPWSTR lpNameType,

OUT LPWSTR lpNameBuffer

)

{

PVOID pTrans = NULL;

DWORD dwTransSize = 0;

BOOL bStatus = FALSE;

bStatus = VersionInfoQueryValue( pVersion,

L"\\VarFileInfo\\Translation",

&pTrans,

&dwTransSize );

if( !bStatus )

{

return FALSE;

}

for( DWORD dwIndex = 0; dwIndex < dwLangCount; dwIndex ++ )

{

WCHAR szSubBlock[100] = { 0 };

WCHAR szLanguage[5] = { 0 };

WCHAR szCodePage[5] = { 0 };

PLangAndCodePage pLangAndCodePage = NULL;

pLangAndCodePage = (PLangAndCodePage) pTrans + dwIndex;

wcscpy( szSubBlock, L"\\StringFileInfo\\" );

swprintf( szLanguage,L"%04x", pLangAndCodePage->wLanguage );

swprintf( szCodePage,L"%04x", pLangAndCodePage->wCodePage );

wcscat( szSubBlock, szLanguage );

wcscat( szSubBlock, szCodePage );

wcscat( szSubBlock, lpNameType );//版本类型

PVOID pName = NULL;

DWORD dwNameSize = 0;

bStatus = VersionInfoQueryValue( pVersion,

szSubBlock,

&pName,

&dwNameSize );

if( bStatus )

{

if( NULL != lpNameBuffer )

{

//获取到了 在这里

memcpy( lpNameBuffer, pName, dwNameSize * sizeof(WCHAR) );

}

break;

}

}

return bStatus;

}

/************************************************************************/

/* 根据映像基址获取版本资源

参数1:基址

参数2:版本类型

参数3:获取到的buffer

*/

/************************************************************************/

BOOL

GetModuleInternalName(

IN PVOID pBaseAddress,

IN LPWSTR lpNameType,

OUT LPWSTR lpNameBuffer

)

{

BOOL bStatus = FALSE;

LDR_RESOURCE_INFO resInfo = { 0 };

resInfo.Type = (ULONG) MAKEINTRESOURCEW( 16 ) ;//16为版本的资源类型

resInfo.Name = (ULONG) MAKEINTRESOURCEW( 1 );// 1为版本的资源名称

resInfo.Language = 0;//语言

PIMAGE_RESOURCE_DATA_ENTRY pResourceDataEntry = NULL;

PVOID pData = NULL;

ULONG uSize = 0;

do

{

NTSTATUS status = STATUS_SUCCESS;

//查找资源

status = LdrFindResource_U( pBaseAddress,

&resInfo,

RESOURCE_DATA_LEVEL,

&pResourceDataEntry );

if( STATUS_SUCCESS != status )

{

break;

}

//访问资源

status = LdrAccessResource( pBaseAddress,

pResourceDataEntry,

&pData,

&uSize );

if( STATUS_SUCCESS != status )

{

break;

}

//解析资源

bStatus = GetInternalNameFromVersionInfo( (PVersionInfo) pData,

uSize / sizeof(VersionInfo),

lpNameType,

lpNameBuffer);

} while( FALSE );

return bStatus;

}

/************************************************************************/

/* 获取指定的文件的版本信息

参数1:文件路径

参数2:版本信息类型

参数3:获取到的信息 传出

*/

/************************************************************************/

#define SEC_IMAGE 0x1000000

BOOL

shielder_get_version_info_by_path_name(

IN PUNICODE_STRING PathName,

IN LPWSTR lpNameType,

OUT LPWSTR lpBuffer

)

{

NTSTATUS status = STATUS_SUCCESS;

HANDLE hFile = NULL;

HANDLE hSection = NULL;

PVOID ViewBase = NULL;

BOOL bStatus = FALSE;

do

{

//UNICODE_STRING usName;

//RtlInitUnicodeString( &usName, lpPathName );

OBJECT_ATTRIBUTES oa = { 0 };

InitializeObjectAttributes( &oa,

PathName,

OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,

0,

);

IO_STATUS_BLOCK isb = { 0 };

//打开文件

status = ZwOpenFile(&hFile, FILE_EXECUTE, &oa, &isb, FILE_SHARE_READ, FILE_NON_DIRECTORY_FILE);

if( STATUS_SUCCESS != status )

{

break;

}

oa.ObjectName = NULL;

//创建Section

status = ZwCreateSection( &hSection,

SECTION_ALL_ACCESS,

&oa,

0,

PAGE_EXECUTE,

SEC_IMAGE,

hFile );

if( STATUS_SUCCESS != status )

{

break;

}

SIZE_T ViewSize = 0;

//把内核文件映射到内存

status = ZwMapViewOfSection(hSection,

NtCurrentProcess(),

&ViewBase,

NULL,

0,

NULL,

&ViewSize,

ViewShare,

0,

PAGE_READONLY);

if ( !ViewBase )

break;

//获取版本信息

bStatus = GetModuleInternalName( ViewBase, lpNameType,lpBuffer );

} while( FALSE );

if( NULL != ViewBase )

{

ZwUnmapViewOfSection( NtCurrentProcess(), ViewBase );

}

if( NULL != hSection )

{

ZwClose( hSection );

}

if( NULL != hFile )

{

ZwClose( hFile );

}

return bStatus;

}

/************************************************************************/

/* 获取进程全路径

参数1: 进程ID

参数2: 传出的UNICODE_STRING 进程全路径

*/

/************************************************************************/

NTSTATUS shielder_get_process_fullpath(IN HANDLE ProcessID, OUT PUNICODE_STRING FullPath)

{

NTSTATUS status = STATUS_UNSUCCESSFUL;

//首先获取进程句柄

HANDLE hProcess = NULL;

OBJECT_ATTRIBUTES oa;

CLIENT_ID client_id;

client_id.UniqueProcess = ProcessID;

client_id.UniqueThread = 0;

InitializeObjectAttributes(&oa, NULL, NULL, NULL, NULL);

status = ZwOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &oa, &client_id);

if (!NT_SUCCESS(status))

return status;

//获取所需要的缓冲区大小

PVOID pBuffer = NULL;

ULONG uRetLen = 0;

status = ZwQueryInformationProcess(hProcess,

ProcessImageFileName,

NULL,

0,

&uRetLen);

if ( !NT_SUCCESS(status) && status == STATUS_INFO_LENGTH_MISMATCH )

{

pBuffer = (PWCH)kmalloc(uRetLen);

if (pBuffer != NULL )

{

RtlZeroMemory(pBuffer, uRetLen);

//获取进程全路径

status = ZwQueryInformationProcess(hProcess,

ProcessImageFileName,

pBuffer,

uRetLen,

&uRetLen);

if ( NT_SUCCESS(status) )

{

//获取UNICODE_STRING

PUNICODE_STRING pustrProcName = (PUNICODE_STRING)pBuffer;//获取到的进程全路径

FullPath->MaximumLength = pustrProcName->MaximumLength;

FullPath->Buffer = (PWCH)kmalloc(pustrProcName->MaximumLength);

if ( FullPath->Buffer != NULL )

{

RtlZeroMemory(FullPath->Buffer, FullPath->MaximumLength);

RtlCopyUnicodeString(FullPath, pustrProcName);

}

}

}

//释放内存

if ( pBuffer != NULL )

{

kfree(pBuffer);

pBuffer = NULL;

}

}

//擦屁股

ZwClose(hProcess);

return status;

}

/************************************************************************/

/* OpenProcess自己实现的

参数1:进程ID

参数2:传出进程句柄

参数2:访问权限

*/

/************************************************************************/

#pragma PAGEDCODE

NTSTATUS MyOpenProcess(HANDLE PID, PHANDLE pHandle,ACCESS_MASK DesiredAccess)

{

NTSTATUS status=0;

PEPROCESS EProcess = NULL;

HANDLE handle = NULL;

UNICODE_STRING y;

PULONG PsProcessType;

status = PsLookupProcessByProcessId(PID, &EProcess);

if (NT_SUCCESS(status))

{

handle = 0;

RtlInitUnicodeString(&y, L"PsProcessType");

PsProcessType =(PULONG) MmGetSystemRoutineAddress(&y);

if (PsProcessType)

{

status = ObOpenObjectByPointer(EProcess, 0, 0, DesiredAccess, (POBJECT_TYPE)*PsProcessType, UserMode, &handle);

if (NT_SUCCESS(status))

{

*pHandle = handle;

}

}

ObfDereferenceObject(EProcess);

}

return status;

}

/************************************************************************/

/* TerminateProcess自己实现的

*/

/************************************************************************/

void MyTerminateProcess(HANDLE hProcess)

{

OBJECT_ATTRIBUTES objOa;

NTSTATUS st;

HANDLE hJob;

//////////////////////////////

RtlZeroMemory(&objOa,sizeof(OBJECT_ATTRIBUTES));

///////////////////////////////////////

objOa.Length = sizeof (OBJECT_ATTRIBUTES);

st = ZwCreateJobObject(&hJob, 0, &objOa);

if (NT_SUCCESS (st))

{

ZwAssignProcessToJobObject(hJob, (HANDLE)hProcess);

ZwTerminateJobObject((HANDLE)hJob,0);

ZwClose (hJob);

ZwClose ((HANDLE)hProcess);

}

}

/**********************************************************************/

NTSTATUS MyKillProcess(HANDLE Pid)

{

HANDLE hProcess;

NTSTATUS ret= MyOpenProcess(Pid,&hProcess,1);

MyTerminateProcess(hProcess);

return ret;

}

//

// 常常困扰于在从一个Unicode中找到另外一个Unicode中包含的字符串,而且用C库中的wcsstr()的函数经常因为函数不安全儿导致蓝屏,特别花时间自己写了一个查找函数

//

// 说明:该函数忽略大小写,在一个UNICODE Sting中查找子串,如果查找到了就返回第一个子串所在的地址指针,如果没能找到,返回NULL(0)

//

//

//

//

//

//

// 例如: 第一个UNICODE_STRING 中的字符串是 L"asdfasdf"

//

// 第二个UNICODE_STRING 中的字符串是L"fA"

//

// 函数会返回"f"的地址!

//

// 当然,如果找不到就返回NULL

//

WCHAR* findSubUnicodeStrSafe(PUNICODE_STRING pWstr,PUNICODE_STRING pSubStr)

{

int i = 0, j = 0;

WCHAR* pw = pWstr->Buffer;

WCHAR* ps = pSubStr->Buffer;

//WCHAR Cmask = ~(L'a' - L'A');

if (pWstr->Length < pSubStr->Length)

{

return NULL;

}

//

// ((*pw>0x40 && *pw<0x5B)?(*pw+0x20):((*pw>0x60 && *pw<0x7B)?(*pw-0x20):0) == *ps)// (若大写则转小写/若小写则转大写)保证是大小写字符

//

for (i = 0; i < (pWstr->Length - pSubStr->Length)/2 + 1; i ++)

{

if ((*pw == *ps) || ((*pw>0x40 && *pw<0x5B)?(*pw+0x20):((*pw>0x60 && *pw<0x7B)?(*pw-0x20):0) == *ps))//case insensitive

{

for(j = 1; j < pSubStr->Length/2; j ++) //第一个已经比较过了,不用在比较了,所以j从1开始

{

if ((*(pw+j) != *(ps+j)) && ((*(pw+j)>0x40 && *(pw+j)<0x5B)?(*(pw+j)+0x20):((*(pw+j)>0x60 && *(pw+j)<0x7B)?(*(pw+j)-0x20):0) != *(ps+j)))

{

break;

}

}

if (j == pSubStr->Length/2)

{

return pw;

}

}

pw ++;

}

return NULL;

}

/************************************************************************/

/* 进程创建回调

参数1:父进程ID

参数2:进程ID

参数2:是否创建

*/

/************************************************************************/

VOID

shielder_create_process_nofitycation (

IN HANDLE ParentId,

IN HANDLE ProcessId,

IN BOOLEAN Create

)

{

NTSTATUS status;

UNICODE_STRING FullPath;//进程全路径

//只要创建的

if ( Create )

{

//获取进程全路径

status = shielder_get_process_fullpath(ProcessId, &FullPath);

if ( NT_SUCCESS(status) )

{

WCHAR szBuffer[256] = { 0 };//传出参数 版本信息

UNICODE_STRING ustrBlockName;

UNICODE_STRING ustrNameInfo;//获取到的

RtlInitUnicodeString(&ustrBlockName, L"十彩");//黑名单

//获取进程版本信息

//CompanyName 公司名称

//FileDescription 文件描述

//InternalName 内部名称

//ProductName产品名称

shielder_get_version_info_by_path_name(&FullPath, L"\\ProductName", szBuffer);

RtlInitUnicodeString(&ustrNameInfo, szBuffer);

//匹配

if ( NULL != findSubUnicodeStrSafe(&ustrNameInfo, &ustrBlockName) )

{

//匹配到了就杀掉

MyKillProcess(ProcessId);

}

//释放UNICODE

RtlFreeUnicodeString(&FullPath);

}

}

return;

}

#endif
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: