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迈进吧!

-------------------------------------------------------

kedebug

Department of Computer Science and Engineering,

Shanghai Jiao Tong University

E-mail: kedebug0@gmail.com

GitHub: http://github.com/kedebug

-------------------------------------------------------

原文地址:https://www.cnblogs.com/kedebug/p/2791754.html