zoukankan      html  css  js  c++  java
  • 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

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

  • 相关阅读:
    [一个经典的多线程同步问题]解决方案二:Event事件
    [进程与线程]进程、线程的生活
    从C++strStr到字符串匹配算法
    Dubbo 服务集群容错配置
    TCP三次握手
    zookeeper 学习 客户端Acl操作笔记
    ubuntu下的“用vim打开中文乱码,用cat打开正常显示”的解决方法
    JDK1.7 Update14 HotSpot虚拟机GC收集器
    账户信息不存在的问题
    win10 64 使用 visual studio 2017 搭建汇编开发环境
  • 原文地址:https://www.cnblogs.com/kedebug/p/2791754.html
Copyright © 2011-2022 走看看