123456811 发表于 2024-3-6 09:12:43

VC++远程线程注入类x86 + x64 (NtCreateThreadEx + LdrLoadDll)



Ring3下的DLL注入工具 x86 x64(NtCreateThreadEx + LdrLoadDll方式实现,可以注入系统进程)

使用NtCreateThreadEx + LdrLoadDll方式实现远程线程注入的特色在于比一般的远程线程注入稳定,可以注入系统进程,服务进程等。

核心源代码如下。
//OD跟踪,发现最后调用的是NtCreateThreadEx,所以这里手动调用
HANDLE Cx64Inject::MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)
{
      HANDLE hThread = NULL;
      FARPROC pFunc = NULL;
      if( IsVistaOrLater())// Vista, 7, Server2008
      {
                pFunc = GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx");
                if( pFunc == NULL )
                {
                        MyOutputDebugStringA("MyCreateRemoteThread() : GetProcAddress("NtCreateThreadEx") 调用失败!错误代码: [%d]", GetLastError());
                        return NULL;
                }
                ((_NtCreateThreadEx64)pFunc)(&hThread,0x1FFFFF,NULL,hProcess,pThreadProc,pRemoteBuf,FALSE,NULL,NULL,NULL,NULL);
                if( hThread == NULL )
                {
                        MyOutputDebugStringA("MyCreateRemoteThread() : NtCreateThreadEx() 调用失败!错误代码: [%d]", GetLastError());
                        return NULL;
                }
      }
      else// 2000, XP, Server2003
      {
                hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL);
                if( hThread == NULL )
                {
                        MyOutputDebugStringA("MyCreateRemoteThread() : CreateRemoteThread() 调用失败!错误代码: [%d]", GetLastError());
                        return NULL;
                }
      }
      if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )
      {
                MyOutputDebugStringA("MyCreateRemoteThread() : WaitForSingleObject() 调用失败!错误代码: [%d]", GetLastError());
                return NULL;
      }
      return hThread;
}


//在目标进程中创建线程并注入dll
BOOL Cx64Inject::InjectDll(DWORD dwProcessId,LPCWSTR lpcwDllPath)
{
      BOOL bRet = FALSE;
      HANDLE hProcess = NULL, hThread = NULL;
      LPVOID pCode = NULL;
      LPVOID pThreadData = NULL;
      __try
      {
                if(!EnableDebugPrivilege())
                {
                        MyOutputDebugStringA("InjectDll() : EnableDebugPrivilege() 调用失败!错误代码: [%d]", GetLastError());
                        return -1;
                }
                //打开目标进程;
                hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessId);
                DWORD dwError = GetLastError();
                if (hProcess == NULL)
                        __leave;
                //申请空间,把我们的代码和数据写入目标进程空间里;
                //写入数据;
                THREAD_DATA data;
                HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
                data.fnRtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll,"RtlInitUnicodeString");
                data.fnLdrLoadDll = (pLdrLoadDll)GetProcAddress(hNtdll,"LdrLoadDll");
                memcpy(data.DllName, lpcwDllPath, (wcslen(lpcwDllPath) + 1)*sizeof(WCHAR));
                data.DllPath = NULL;
                data.Flags = 0;
                data.ModuleHandle = INVALID_HANDLE_VALUE;
                pThreadData = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
                if (pThreadData == NULL)
                        __leave;
                BOOL bWriteOK = WriteProcessMemory(hProcess, pThreadData,&data,sizeof(data), NULL);
                if (!bWriteOK)
                        __leave;
                MyOutputDebugStringA("pThreadData = 0x%p", pThreadData);
                //写入代码;
                DWORD SizeOfCode = (DWORD)ThreadProcEnd - (DWORD)ThreadProc;
                pCode = VirtualAllocEx(hProcess, NULL, SizeOfCode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
                if (pCode == NULL)
                {
                        MyOutputDebugStringA("InjectDll() : pCode = VirtualAllocEx() 调用失败!错误代码: [%d]", GetLastError());
                        __leave;
                }                  
                bWriteOK = WriteProcessMemory(hProcess, pCode, (PVOID)ThreadProc, SizeOfCode, NULL);
                if (!bWriteOK)
                        __leave;
                MyOutputDebugStringA("pCode = 0x%p", pCode);
                //创建远程线程,把ThreadProc作为线程起始函数,pThreadData作为参数;
                hThread = MyCreateRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pCode, pThreadData);
                if (hThread == NULL)
                        __leave;
                //等待完成;
                WaitForSingleObject(hThread, INFINITE);
                bRet = TRUE;
      }
      __finally
      {
                if (pThreadData != NULL)
                        VirtualFreeEx(hProcess, pThreadData, 0, MEM_RELEASE);
                if (pCode != NULL)
                        VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE);
                if (hThread != NULL)
                        CloseHandle(hThread);
                if (hProcess != NULL)
                        CloseHandle(hProcess);
      }
   
      return bRet;
}以上是远程线程注入类的两个核心函数,下面是调用实例:Cx64Inject inject;
if (inject.InjectDll(g_dwPID,g_szDllPath))
{
      ::MessageBox(NULL,L"注入成功",L":)",MB_ICONINFORMATION);
}
else
{
      ::MessageBox(NULL,L"注入失败!",L"失败",MB_ICONERROR);
}封装成类了,使用起来很简单的。
有一点需要注意的是x64注入的意思是只能将64位dll注入64位进程。
x86注入的意思是32位dll注入32位进程。
页: [1]
查看完整版本: VC++远程线程注入类x86 + x64 (NtCreateThreadEx + LdrLoadDll)