什么是远线程注入
在一个进程中,调用CreateThread或CreateRemoteThreadEx函数,在另一个进程内创建一个线程(因为不在同一个进程中,所以叫做远程线程)。创建的线程一般为Windows API函数LoadLibrary,来加载一个动态链接库(DLL),从而达到在另一个进程中运行自己所希望运行的代码的目的。
代码
下面例子是根据查询一打开窗口中的计算器进程,然后
注释都很详细
#include "windows.h"
#include "Tlhelp32.h"
int InjectDll(DWORD dwProcessId, PTCHAR szDllName);
int EnablePrivilege(bool isStart);
DWORD GetProcessId(PTCHAR pszProcessName);
void main()
{
DWORD ProcessId = GetProcessId("calc.exe");\\目标程序
InjectDll(ProcessId ,"C:\\Users\\sam\\Desktop\\A.dll");\\注入dll的地址
}
int InjectDll(DWORD dwProcessId, PTCHAR szDllName)
{
if (szDllName[0] == NULL)
return -1;
//提高权限相关操作
EnablePrivilege(TRUE);
//1. 打开进程
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, //打开进程权限
FALSE, //是否可继承
dwProcessId); //进程ID
if (hProcess == INVALID_HANDLE_VALUE)
return -1;
//2. 在远程进程中申请空间
LPVOID pszDllName = VirtualAllocEx(hProcess, //远程进程句柄
NULL, //建议开始地址
4096, //分配空间大小
MEM_COMMIT, //空间初始化全0
PAGE_EXECUTE_READWRITE); //空间权限
if (NULL == pszDllName)
{
return -1;
}
//3. 向远程进程中写入数据
BOOL bRet = WriteProcessMemory( hProcess, pszDllName,
szDllName, MAX_PATH, NULL);
if (NULL == bRet)
{
return -1;
}
//4. 在远程进程中创建远程线程
HANDLE m_hInjecthread = CreateRemoteThread(hProcess, //远程进程句柄
NULL, //安全属性
0, //栈大小
(LPTHREAD_START_ROUTINE)LoadLibrary, //进程处理函数
pszDllName, //传入参数
NULL, //默认创建后的状态
NULL); //线程ID
if (NULL == m_hInjecthread)
{
DWORD dwErr = GetLastError();
return -1;
}
//5. 等待线程结束返回
DWORD dw = WaitForSingleObject(m_hInjecthread, -1);
//6. 获取线程退出码,即LoadLibrary的返回值,即dll的首地址
DWORD dwExitCode;
GetExitCodeThread(m_hInjecthread, &dwExitCode);
HMODULE m_hMod = (HMODULE)dwExitCode;
//7. 释放空间
BOOL bReturn = VirtualFreeEx(hProcess, pszDllName,
4096, MEM_DECOMMIT);
if (NULL == bReturn)
{
return -1;
}
CloseHandle(hProcess);
hProcess = NULL;
//恢复权限相关操作
EnablePrivilege(FALSE);
return 0;
}
int EnablePrivilege(bool isStart)
{
//1. 得到令牌句柄
HANDLE hToken = NULL; //令牌句柄
if (!OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_READ,
&hToken))
{
return FALSE;
}
//2. 得到特权值
LUID luid = {0}; //特权值
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
{
return FALSE;
}
//3. 提升令牌句柄权限
TOKEN_PRIVILEGES tp = {0}; //令牌新权限
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = isStart ? SE_PRIVILEGE_ENABLED : 0;
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL))
{
return FALSE;
}
//4. 关闭令牌句柄
CloseHandle(hToken);
return 0;
}
DWORD GetProcessId(PTCHAR pszProcessName)
{
HANDLE hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//获取当前系统的快照,这种方法能拿到想要的进程ID
if (INVALID_HANDLE_VALUE == hProcess)
{
return 0;
}
DWORD dwProcessId = 0;
PROCESSENTRY32 process32 = {0};
process32.dwSize = sizeof(PROCESSENTRY32);
BOOL bRetProcess = FALSE;
bRetProcess = Process32First(hProcess, &process32);
do
{
if (strcmp(pszProcessName, process32.szExeFile) == 0)//名称对上,获取其进程ID
{
dwProcessId = process32.th32ProcessID;
break;
}
bRetProcess = Process32Next(hProcess, &process32);
}while (bRetProcess);
CloseHandle(hProcess);
return dwProcessId;
}