看流星社区

 找回密码
 注册账号
查看: 2000|回复: 0

使用QueueUserAPC线程注入(二)

[复制链接]

该用户从未签到

发表于 2013-5-2 09:08:52 | 显示全部楼层 |阅读模式
代码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完成端口没有这个限制。
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-5-14 09:12

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表