通过PsSetCreateProcessNotifyRoutine可以设置一个进程回调
当有进程被创建的时候
回调用这个通知
我写了一段代码
通过检测进程对应的文件的版本信息来拒绝进程运行
360以前就这么干的
主要是怎么通过进程ID获取进程的全路径
还有怎么在驱动里面访问程序的资源
#ifndef _SHIELDER_H
#define _SHIELDER_H
#ifdef __cplusplus
extern "C"
{
#endif
#include
#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