Native API -- ScOpenProcess

        好久没写日志了,实在是没有时间啊!写日志也成了浪费时间,无奈啊!

        最近研究了下如何用 Native API 打开指定进程,从而实现根据 PID 来返回进程句柄,从而达到内存填 0 来查杀进程的目的!下面贴出来代码,当然参考了很多大牛的代码:

HANDLE __stdcall ScOpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)

{  

    NTSTATUS    status;

    BOOLEAN     wasEnabled;

    char        *pBuf = NULL;

    DWORD       buflen = 0x10000, needlen = 0;

    DWORD       HandleCnt = 0;

    HANDLE      hRetProcess;



    PSYSTEM_HANDLE_INFORMATION  pSysHandleInfo = NULL;

    OBJECT_ATTRIBUTES           objatr = {sizeof(OBJECT_ATTRIBUTES), 0, NULL, NULL};

    CLIENT_ID                   cid;



    if ( bInheritHandle )

        objatr.Attributes |= OBJ_INHERIT;



    // 提权

    RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &wasEnabled);



    // 尝试正常方式打开

    cid.UniqueProcess = (HANDLE)dwProcessId;

    cid.UniqueThread  = 0;

    status = ZwOpenProcess(&hRetProcess, dwDesiredAccess, &objatr, &cid);

    if (NT_SUCCESS(status) )

        return hRetProcess;



    // 查询句柄信息

    do 

    {

        // 申请查询句柄信息所需要的内存

        ZwAllocateVirtualMemory(

            NtCurrentProcess(), 

            (PVOID *)&pBuf,

            0,

            &buflen,

            MEM_COMMIT,

            PAGE_READWRITE);

        // 查询系统句柄信息

        status = ZwQuerySystemInformation(

            SystemHandleInformation,

            (PVOID)pBuf,

            buflen,

            &needlen);

        if (status == STATUS_SUCCESS)

            break;



        // 若不成功则释放内存

        ZwFreeVirtualMemory(

            NtCurrentProcess(),

            (PVOID *)&pBuf,

            &buflen,

            MEM_RELEASE);



        // 加大申请的内存块, 一直到成功为止

        buflen *= 2;

        pBuf = NULL;

    } while ( TRUE );



    // 返回的缓冲区内容第一个 DWORD 是句柄的个数

    HandleCnt = *(DWORD *)pBuf;



    pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION)( (char *)pBuf + sizeof(DWORD) );

    for (DWORD i = 0; i < HandleCnt; i ++)

    {

        // 只验证类型为 PROCESS 的

        if ( pSysHandleInfo->ObjectTypeNumber == OB_TYPE_PROCESS)

        {

            HANDLE      hOwnerProc;

            HANDLE      hTmpProc;



            cid.UniqueProcess = (HANDLE)pSysHandleInfo->ProcessId;

            cid.UniqueThread  = 0;

            status = ZwOpenProcess(

                &hOwnerProc,

                PROCESS_DUP_HANDLE,

                &objatr,

                &cid);

            if ( NT_SUCCESS(status) )

            {

                // 打开成功,则把句柄复制过来

                status = ZwDuplicateObject(

                    hOwnerProc,

                    (HANDLE)pSysHandleInfo->Handle,

                    NtCurrentProcess(),

                    &hTmpProc,

                    PROCESS_ALL_ACCESS,

                    FALSE,

                    0);

                if ( NT_SUCCESS(status) )

                {

                    PROCESS_BASIC_INFORMATION BasicInfo = {0};



                    status = ZwQueryInformationProcess(

                        hTmpProc,

                        ProcessBasicInformation,

                        &BasicInfo,

                        sizeof(BasicInfo),

                        NULL);

                    if ( NT_SUCCESS(status) )

                    {

                        if (BasicInfo.UniqueProcessId == dwProcessId)

                        {

                            // 按需要的权限把句柄复制过来

                            ZwDuplicateObject(

                                hOwnerProc,

                                (HANDLE)pSysHandleInfo->Handle,

                                NtCurrentProcess(),

                                &hRetProcess,

                                dwDesiredAccess,

                                FALSE,

                                0);

                            ZwClose(hOwnerProc);

                            ZwClose(hTmpProc);

                            break;

                        }

                    }

                    ZwClose(hTmpProc);

                }

                ZwClose(hOwnerProc);

            }

        }

        pSysHandleInfo ++;

    }

    // 释放内存

    if (pBuf)

        ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *)&pBuf, &buflen, MEM_RELEASE);



    return hRetProcess;

}

 

由此可以内存暴力枚举进程的雏形,关键是ZwQueryInformationProcess啊!通过抹掉自己进程在csrss里的句柄可以逃过这种方法。如今R3下的方法已经变得科普了,真正的技术还是在R0啊!打好基础,努力向R0迈进吧!

你可能感兴趣的:(process)