• APC注入


    Windows中的2种类型的APC:
        用户模式  APC执行在用户模式下的线程的上下文中,必须得到线程的允许才能得到执行
    同时用户APC还需要目标进程处在Alertable等待状态才能被成功的调度执行 在内核模式中
    可以执行KeWaitForSingleObject.....,在用户模式下可以调用SleepEx..... 当用户APC
    投递到线程中 调用上面函数 执行条件满足时去执行APC历程 执行完APC历程 继续执行线程
        内核模式  分为普通内核APC和特殊内核APC 当APC投递到线程上 特殊的内核APC不需要
    得到现车允许即可得到执行 普通内核APC需要特定环境才能得到执行 特殊内核APC甚至可以唤醒
    阻塞的线程
    
    APC执行优先级  特殊内核APC > 普通内核APC > 用户APC
    
    每个线程都含有2个APC队列  用户模式APC队列 和 内核模式APC队列
    
    
    APC注入的原理是利用当线程被唤醒时APC中的注册函数会被执行的机制,并以此去执行我们的DLL加载代码,进而完成DLL注入的目的,其具体流程如下:
        1)当EXE里某个线程执行到SleepEx()或者WaitForSingleObjectEx()时,系统就会产生一个软中断。
        2)当线程再次被唤醒时,此线程会首先执行APC队列中的被注册的函数。
        3)利用QueueUserAPC()这个API可以在软中断时向线程的APC队列插入一个函数指针,如果我们插入的是Loadlibrary()执行函数的话,就能达到注入DLL的目的。
    
      //打开远程进程  
        handle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessId);  
        if (handle)  
        {  
            //在远程进程申请空间  
            lpData = VirtualAllocEx(handle,  
                NULL,  
                1024,  
                MEM_COMMIT,  
                PAGE_EXECUTE_READWRITE);  
      
            if (lpData)  
            {  
                //在远程进程申请空间中写入待注入DLL的路径  
                bRet = WriteProcessMemory(handle,  
                    lpData,  
                    (LPVOID)sDllName,  
                    1024,&dwRet);  
            }  
            //关闭句柄  
            CloseHandle(handle);  
    }  
    
    当我们准备好 用于注入DLL的LoadLibrary()函数后,接下来需要使用QueueUserAPC()函数将此函数插入到软中断线程的APC队列中。但是由于 QueueUserAPC()函数的第三个参数是线程ID,因此我们需要根据现有进程ID,并通过遍历对比得到线程ID,具体API如下表所示:
    CreateToolhelp32Snapshot  
    创建线程快照  
    Thread32First  
    得到第一个线程快照  
    Thread32Next  
    循环下一个线程快照  
    
    
    
    THREADENTRY32 te = {0};  
        te.dwSize = sizeof(THREADENTRY32);  
        //得到线程快照  
        HANDLE handleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);  
        if (INVALID_HANDLE_VALUE == handleSnap)  
        {  
            return FALSE;  
        }  
      
        BOOL bStat = FALSE;  
        //得到第一个线程  
        if (Thread32First(handleSnap,&te))  
        {  
            do   
            {  
                //进行进程ID对比  
                if (te.th32OwnerProcessID == dwProcessId)  
                {  
                    //得到线程句柄  
                    HANDLE handleThread = OpenThread(  
                        THREAD_ALL_ACCESS,  
                        FALSE,  
                        te.th32ThreadID);  
      
                    if (handleThread)  
                    {  
                        //向线程插入APC  
                        dwRet = QueueUserAPC(  
                            (PAPCFUNC)LoadLibrary,  
                            handleThread,  
                            (ULONG_PTR)lpData);  
                        if (dwRet > 0)  
                        {  
                            bStat = TRUE;  
                        }  
                        //关闭句柄  
                        CloseHandle(handleThread);  
                    }  
                }  
                //循环下一个线程  
            } while (Thread32Next(handleSnap,&te));  
        }  
    CloseHandle(handleSnap);  
  • 相关阅读:
    Java WebService异构系统通信的原理及特点:SOAP与WSDL
    jenkins下拉框选择构建环境
    vue中的hash与history
    一行代码轻松搞定企微内嵌h5调用原生api不生效问题
    开源绘图工具plantUML入门教程(常用于画时序图等)
    什么是持续集成、持续交付、持续部署(CI/CD)?
    一篇文章了解CI/CD管道全流程
    开源免费的SSH工具推荐:electerm(推荐)、Finalshell
    Oracle数据库设置表空间自动扩展(解决因表空间不足引起的ORA01653: unable to extend table错误)
    测试工作中浏览器F12工具简单使用介绍
  • 原文地址:https://www.cnblogs.com/yifi/p/6527752.html
Copyright © 2020-2023  润新知