• 使用QueueUserAPC线程注入,


    代码1
    #define _WIN32_WINNT 0x0400
    #define WIN32_LEAN_AND_MEAN   // 从 Windows 头中排除极少使用的资料

    #include 
    <iostream>
    #include 
    <windows.h>
    #include 
    <Winbase.h>
    using namespace std;


    DWORD  WINAPI WorkThread(LPVOID pParam)
    {
        HANDLE Event 
    = (HANDLE)pParam;
        
    for(;;)
        {
            DWORD dwRet 
    = WaitForSingleObjectEx(Event, INFINITE, TRUE);
            
    if(dwRet == WAIT_OBJECT_0)
                
    break;
            
    else 
                
    if(dwRet == WAIT_IO_COMPLETION)
                    printf(
    "WAIT_IO_COMPLETION\n");
                
                
    return 0;
        }
    }


    VOID  WINAPI APCProc(LPVOID dwParam)
    {
        printf(
    "%s", (PVOID)dwParam);
    }

    void TestAPC(BOOL bFast)
    {
        
        HANDLE QuitEvent 
    = CreateEvent(NULL, FALSE, FALSE, NULL);
        HANDLE hThread 
    = CreateThread(NULL,
            
    0,
            WorkThread,
            (LPVOID)QuitEvent,
            
    0,
            NULL);
        
        
        Sleep(
    100); // Wait for WorkThread initialized.
        
        
        
    for(int i=5; i>0; i--)
        {    
            QueueUserAPC((PAPCFUNC)APCProc, hThread, (DWORD)(PVOID)
    "APC here\n");
            
    if(!bFast)
                Sleep(
    1000);
        }
        
        
        SetEvent(QuitEvent);
        
        WaitForSingleObject(hThread, INFINITE);
        
        CloseHandle(hThread);    
    }

    int main()
    {
        TestAPC(
    true);
        
    return 0;
    }
    代码2
    #define _WIN32_WINNT 0x0400
    #define WIN32_LEAN_AND_MEAN   // 从 Windows 头中排除极少使用的资料

    #include 
    <windows.h>
    #include 
    <Tlhelp32.h>
    #include 
    <stdio.h>
    #include 
    <stdlib.h>

    typedef HANDLE (CALLBACK 
    *OPENTHREAD) (DWORD dwFlag, BOOL bUnknow, DWORD dwThreadId); 
    typedef   unsigned   
    long      ULONG_PTR; 


    typedef 
    struct _TIDLIST 
    {
        DWORD dwTid ;
        _TIDLIST 
    *pNext ;
    }TIDLIST;

    DWORD EnumThread(HANDLE hProcess, TIDLIST 
    *pThreadIdList)
    {
        TIDLIST 
    *pCurrentTid = pThreadIdList ;
        HANDLE hThread;
        
    const char szInjectModName[] = "c:\\sysnap.dll" ;
        DWORD dwLen 
    = strlen(szInjectModName) ;
        HMODULE hDll 
    = GetModuleHandle("Kernel32.dll"); 
        
        PVOID param 
    = VirtualAllocEx(hProcess, \
            NULL, dwLen, MEM_COMMIT 
    | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE) ;
        
        
    if (param != NULL)
        {
            DWORD dwRet ;
            
    if (WriteProcessMemory(hProcess, param, (LPVOID)szInjectModName, dwLen, &dwRet))
            {
                
                
    while (pCurrentTid)
                {
                    OPENTHREAD lpfnOpenThread 
    = (OPENTHREAD)::GetProcAddress(hDll, "OpenThread"); 
                    hThread 
    = lpfnOpenThread(THREAD_ALL_ACCESS,FALSE,pCurrentTid->dwTid);
                    
    if (hThread != NULL)
                    {
                        
    //
                        
    // 注入DLL到指定进程
                        
    //
                        QueueUserAPC((PAPCFUNC)LoadLibraryA, hThread, (ULONG_PTR)param) ;
                    }
                    
                    printf(
    "TID:%d\n", pCurrentTid->dwTid) ;
                    pCurrentTid 
    = pCurrentTid->pNext ;
                }
            }
        }
        
    return 0 ;
    }

    DWORD GetProcID(
    const char *szProcessName)
    {
        PROCESSENTRY32 pe32 
    = {0} ;
        pe32.dwSize 
    = sizeof(PROCESSENTRY32);
        
        HANDLE hSnapshot 
    = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) ;
        
        
    if (hSnapshot == INVALID_HANDLE_VALUE)
        {
            
    return 0xFFFFFFFF ;
        }
        
        
    if (!Process32First(hSnapshot, &pe32))
        {
            
    return 0xFFFFFFFF ;
        }
        
        
    do 
        {
            
    if (!_strnicmp(szProcessName, pe32.szExeFile, strlen(szProcessName)))
            {
                printf(
    "%s的PID是:%d\n", pe32.szExeFile, pe32.th32ProcessID);
                
    return pe32.th32ProcessID ;
            }
        } 
    while(Process32Next(hSnapshot, &pe32));
        
        
    return 0xFFFFFFFF ;
        
    }

    TIDLIST
    * InsertTid(TIDLIST *pdwTidListHead, DWORD dwTid)
    {
        TIDLIST 
    *pCurrent = NULL ;
        TIDLIST 
    *pNewMember = NULL ;
        
        
    if (pdwTidListHead == NULL)
        {
            
    return NULL ;
        }
        pCurrent 
    = pdwTidListHead ;
        
        
    while (pCurrent != NULL)
        {
            
            
    if (pCurrent->pNext == NULL)
            {
                
    //
                
    // 定位到链表最后一个元素
                
    //
                pNewMember = (TIDLIST *)malloc(sizeof(TIDLIST)) ;
                
                
    if (pNewMember != NULL)
                {
                    pNewMember
    ->dwTid = dwTid ;
                    pNewMember
    ->pNext = NULL ;
                    pCurrent
    ->pNext = pNewMember ;
                    
    return pNewMember ;
                }
                
    else
                {
                    
    return NULL ;
                }
            }
            pCurrent 
    = pCurrent->pNext ;
        }
        
        
    return NULL ;
    }

    int EnumThreadID(DWORD dwPID, TIDLIST *pdwTidList)
    {
        
    int i = 0 ;
        
        THREADENTRY32 te32 
    = {0} ;
        te32.dwSize
    = sizeof(THREADENTRY32) ;
        
        HANDLE hSnapshot 
    = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,dwPID) ;
        
        
    if(hSnapshot != INVALID_HANDLE_VALUE)
        {
            
    if(Thread32First(hSnapshot,&te32)) 
            {
                
    do
                {
                    
    if(te32.th32OwnerProcessID==dwPID) 
                    {
                        
    if (pdwTidList->dwTid == 0)
                        {
                            pdwTidList
    ->dwTid = te32.th32ThreadID ;
                        }
                        
    else
                        {
                            
    if (NULL == InsertTid(pdwTidList, te32.th32ThreadID))
                            {
                                printf(
    "插入失败!\n") ;
                                
    return 0 ;
                            }
                        }
                        
                    } 
                }
    while(Thread32Next(hSnapshot,&te32));
            }
        }
        
    return 1 ;
    }

    void RemoveTid(TIDLIST *pdwTidListHead)
    {
        TIDLIST 
    *pCurrent = NULL ;
        TIDLIST 
    *pNext = NULL ;
        
        
        
    if (pdwTidListHead == NULL)
        {
            
    return;
        }
        pCurrent 
    = pdwTidListHead ;
        
        
    while (pCurrent != NULL)
        {
            
            pNext 
    = pCurrent->pNext;
            free(pCurrent);
            pCurrent 
    = pNext;
        }
        
    }
    int main(int argc, char* argv[])
    {
        TIDLIST 
    *pTidHead = (TIDLIST *)malloc(sizeof(TIDLIST)) ;
        
        
    if (pTidHead == NULL)
        {
            
    return 1 ;
        }

        RtlZeroMemory(pTidHead, 
    sizeof(TIDLIST)) ;
        
        DWORD dwPID 
    = 0 ;
        
        
    if ((dwPID = GetProcID("explorer.exe")) == 0xFFFFFFFF)
        {
            printf(
    "进程ID获取失败!\n") ;
            
    return 1 ;
        }
        
        
    //
        
    // 枚举线程ID
        
    //
        EnumThreadID(dwPID, pTidHead) ;
        
        HANDLE hProcess 
    = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID) ;
        
        
    if (hProcess == NULL)
        {
            
    return 1 ;
        }
        EnumThread(hProcess, pTidHead) ;
        
        CloseHandle(hProcess);
        
        RemoveTid(pTidHead);
        
        
    return 0;
    }


    Alertable IO(告警IO)提供了更有效的异步通知形式。ReadFileEx / WriteFileEx在发出IO请求的同时,提供一个回调函数(APC过程),当IO请求完成后,一旦线程进入可告警状态,回调函数将会执行。
       以下五个函数能够使线程进入告警状态:
       SleepEx
       WaitForSingleObjectEx
       WaitForMultipleObjectsEx
       SignalObjectAndWait
       MsgWaitForMultipleObjectsEx
       线程进入告警状态时,内核将会检查线程的APC队列,如果队列中有APC,将会按FIFO方式依次执行。如果队列为空,线程将会挂起等待事件对象。以后的某个时刻,一旦APC进入队列,线程将会被唤醒执行APC,同时等待函数返回WAIT_IO_COMPLETION。
       QueueUserAPC可以用来人为投递APC,只要目标线程处于告警状态时,APC就能够得到执行。
       使用告警IO的主要缺点是发出IO请求的线程也必须是处理结果的线程,如果一个线程退出时还有未完成的IO请求,那么应用程序将永远丢失IO完成通知。然而以后我们将会看到IO完成端口没有这个限制。
      
  • 相关阅读:
    Sql2008 全文索引 简明教程
    sql server 全文检索 使用
    数据库分词查询的优缺点以及英文和中文各自的分词方法(一)
    win10中打开SQL Server配置管理器方法
    Asp.net 中高亮显示搜索关键字简单方法
    EntityFramework优缺点
    LoadXml载入Xhtml文件速度很慢
    c#无限循环线程如何正确退出
    线程的等待方法:join
    C#如何优雅的结束一个线程
  • 原文地址:https://www.cnblogs.com/chengxin1982/p/1652398.html
Copyright © 2020-2023  润新知