PsSetCreateProcessNotifyRoutine进程黑名单

通过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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值