原理
远程线程注入就是在目标进程体内开一个线程,通过LoadLibrary函数,将我们的动态链接库dll加载进去,从而达到在目标进程中运行我们的代码的目的
过程
1.首先通过函数OpenProcess打开目标进程
HANDLE OpenProcess(
[in] DWORD dwDesiredAccess, //进程访问权限
[in] BOOL bInheritHandle, //此进程创建的进程是否继承句柄
[in] DWORD dwProcessId //进程ID
);
2.再用VirtualAllocEx函数在目标进程中申请一段可读可写的内存空间
LPVOID VirtualAllocEx(
[in] HANDLE hProcess, //进程句柄
[in, optional] LPVOID lpAddress, //指定要分配的区域的起始地址,若值为NULL则函数自己分配
[in] SIZE_T dwSize, //申请内存的大小
[in] DWORD flAllocationType, //内存分配的类型
[in] DWORD flProtect //内存保护
);
3.然后通过WriteProcessMemory函数将我们准备好的dll写入目标内存,该函数的返回值为BOOL类型,可判断是否执行成功
BOOL WriteProcessMemory(
[in] HANDLE hProcess, //要修改的进程内存的句柄
[in] LPVOID lpBaseAddress, //指向将数据写入到的指定进程中基址的指针
[in] LPCVOID lpBuffer, //指向缓冲区的指针,该缓冲区用于存放需写入目标进程的数据
[in] SIZE_T nSize, //要写入目标进程的字节数
[out] SIZE_T *lpNumberOfBytesWritten //
);
第二个参数正是我们在目标进程申请的内存的基址,直接填VirtualAllocEx函数的返回值即可
4.接着通过CreateRemoteThread函数,创建一个远程线程,用于启动回调函数,加载动态链接库
HANDLE CreateRemoteThread(
[in] HANDLE hProcess, //要在其中创建线程的进程句柄
[in] LPSECURITY_ATTRIBUTES lpThreadAttributes, //指定新线程的安全描述符
[in] SIZE_T dwStackSize, //堆栈的初始字节大小
[in] LPTHREAD_START_ROUTINE lpStartAddress, //指向远程进程中线程的起始地址的指针,即为VirtualAllocEx函数的返回值
[in] LPVOID lpParameter, //指向要传递给线程函数的变量的指针
[in] DWORD dwCreationFlags, //控制线程创建的标志
[out] LPDWORD lpThreadId //指向接收线程标识符的变量的指针
);
5.然后通过WaitForSingleObject函数进行等待,当远程线程返回后函数结束,继续向下执行
DWORD WaitForSingleObject(
[in] HANDLE hHandle, //需要等待的对象的句柄
[in] DWORD dwMilliseconds
);
6.最后用VirtualFreeEx函数释放内存空间,用CloseHandle函数进程和线程句柄
BOOL VirtualFreeEx(
[in] HANDLE hProcess, //需要释放内存的进程的句柄
[in] LPVOID lpAddress, //指向要释放的内存区域的起始地址的指针
[in] SIZE_T dwSize, //要释放的内存区域的大小
[in] DWORD dwFreeType
);
先对notepad++进行过注入,但是失败了。所以我是从NewCrackMe中随便找的一个.exe程序注入的
可以看到,我们注入的Msg窗口和目标进程在同一级目录下
#include <stdio.h>
#include <Windows.h>
BOOL Inject(DWORD dwProcessId, const WCHAR * szPath)
{
//1.打开目标进程获取句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
//2.在目标进程体内申请空间
LPVOID lpAddress = VirtualAllocEx(hProcess, NULL, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
//3.写入DLL路径
SIZE_T sWriteLength = 0;
BOOL bRet = WriteProcessMemory(hProcess, lpAddress, szPath, ((wcslen(szPath) + 1) * 2), &sWriteLength);
if (bRet == FALSE)
{
MessageBox(NULL, L"WriteProcessMemory Failed!", L"Error", MB_OK);
return FALSE;
}
//4.创建远程线程,执行回调
HANDLE hThread = CreateRemoteThread(
hProcess, //要在其中创建线程的进程句柄
NULL, //安全属性
NULL, //堆栈起始大小
(LPTHREAD_START_ROUTINE)LoadLibraryW, //远程进程中线程的起始地址(回调函数)
lpAddress, //要传递给线程的参数的指针
NULL, //控制线程创建的标志
NULL //返回句柄
);
//5.等待远程线程执行结束(LoadLibraryW返回)
WaitForSingleObject(hThread, INFINITE);
//6.释放空间
VirtualFreeEx(hProcess, lpAddress, 0, MEM_RELEASE);
//7.释放句柄
CloseHandle(hProcess);
CloseHandle(hThread);
//8.返回结果
return TRUE;
}
int main()
{
Inject(11356, L"D:\\rkvir\\Windows系统编程\\远程线程注入\\Dll2\\Debug\\Dll2.dll");//notpad++有保护机制嘤嘤嘤,谁说的它好欺负我哭死T^T,随便找的个NewCrackme的程序用的
return 0;
}
本文为极安御信课程的学习笔记