远程线程注入(dll注入)

今天想来记录一下远程线程注入这个项目的实现

先前我有看过别的博主关于远程线程注入的视频
这一次想尝试一下独立写出来,按照思路然后去完成这个项目

吐槽:这个远程线程注入是通过往目标进程里面加载dll的方式实现的

巧妙之处就是创建远程进程的线程函数中的线程函数用到了LoadLibraryA
如果不用种方式,按照我现在学习的,还有hook, shellcode,硬编码
这些都可以把一小段代码实现类似注入的效果
shellcode 就是以硬编码的方式存在与正常的程序之中,正常的程序可以运行shellcode以达到不可预测的效果,先前我在恶意代码分析这本书里,好像看过用到了shellcode的样本,但是我现在不记得了,shellcode怎么编写我并不大清楚。

回到远程线程注入的这个话题
思路其实很简单:获取目标进程,然后创建远程线程
感觉跟没说一样

首先,我们需要目标进程的句柄,为什么需要?因为远程线程创建函数,进程申请内存,往进程内存写入数据都需要进程句柄,所以获取目标进程的句柄是必不可少的
那怎么获取呢
OpenProcess()可以根据PID然后获取对应的进程句柄,很便利

然后,我们直接开始远程线程注入?显然是不可以的,我们需要搞清楚一个点,我们的操作对象是目标进程,我们编写的代码和目标进程,不在同一内存空间下,他们都有独立的4G空间,我们在目标进程创建线程,线程函数执行,达到注入的效果,这里有一个前置知识,一个dll可以以什么样的方式加载到进程的4GB空间
dll的加载可以分为显示链接和隐式链接
显示链接 -> 程序代码主动调用 LoadLibrary
隐式链接 -> 操作系统加载器 -> 双击.exe程序运行,在mian函数之前,由操作系统根据程序PE结构中的导出表,加载dll
在这里我们使用显示链接,我们要让创建的线程加载dll,实现注入的效果
所以,创建的线程函数必须使用LoadLibrary

接下来,我们还有一些准备工作要做,一个程序加载dll需要是需要加载dll的路径,我们编写的代码所在进程和目标进程是两个独立的4GB空间,我们在代码里声明的路径字符串,目标进程是无法使用的,所以这里又涉及到了一个很关键的点,我们需要在目标进程声明一小段内存存储路径字符串,这里就需要用到VirtualAllocEx,可以指定进程句柄然后申请内存,非常便利。好了,申请完内存空间,我们还需要把路径字符写到我们申请的内存里面,WriteProcessMemory就可以解决我们的问题

最后,就是用使用远程线程函数CreateRemoteThread,和创建线程函数类似,这里需要注意的就是加了一个目标句柄。这里我有一个疑问,为什么创建的线程函数是LoadLibrary,为什么不可以直接一个function作为线程函数,然后在函数里面调用LoadLibrary,我写代码测试了一下,目标程序会直接崩掉,我并不知道原因,于是去问了deekseek,我这样想的原应该是因为我认为和线程创建函数差不多,但是我忽略了这是不同的进程,我创建的函数只在当前空间下可以使用,而目标进程是不能使用function,因为目标进程的空间下根本不存在,用LoadLibrary可以是因为他在系统dll里面,mian函数开始之前以及把相关信息写进了IAT表里面了,使用可以使用这个函数,按我目前的想法,远程线程注入受限与目标进程,是存在局限性的,老师是第一个想出这样做法的人真的很厉害啊!崇拜一手。

我们把思路简单整理一下
1.获取目标进程句柄
2.在目标进程中申请内存空间,然后把路径字符写入申请的内存空间
3.创建远程线程

代码参考,dll需要自己去写一个,具体的代码编写这里就不多赘述了,不会的函数就去查手册,会查手册可是一项很重要的技能。

#include <stdio.h>
#include <windows.h>
#include <string.h>

char DllPath[20] = "D:\\test.dll";

int main()
{
	DWORD dwProcessId = 0;
	scanf_s("%d", &dwProcessId);
	//1.获取目标进程的句柄
	HANDLE A_Handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);

	//2.申请远程内存空间
	LPVOID ptr = VirtualAllocEx(A_Handle, NULL, strlen(DllPath) + 1, MEM_COMMIT, PAGE_READWRITE); //线程函数的参数

	//3.路径字符写到我们申请的内存
	WriteProcessMemory(A_Handle, ptr, DllPath, strlen(DllPath) + 1, NULL);

	//4.创建远程线程
	CreateRemoteThread(A_Handle, //目标进程A的句柄
		NULL,	//默认的安全描述符
		0,		//堆栈使用默认大小
		(LPTHREAD_START_ROUTINE)LoadLibraryA,      //线程函数
		ptr,	//线程函数的参数
		0,		//创建后立刻执行
		NULL);  //不返回线程标识符
	return 0;
}

验证我随便找了应该CrackMe做了测试

PixPin_2026-05-24_19-14-03
PixPin_2026-05-24_19-14-38

总结

远程线程注入这个项目也算简单完成了,细节处理上并没有完善,代码上设置没有写closehandle,内存也没用释放,才不是因为我懒。。。
总之还是收获颇丰,期间也查缺补漏了一些知识,手册还是查的磕磕碰碰,不是很习惯。

posted @ 2026-05-24 19:22  书与兔子  阅读(16)  评论(0)    收藏  举报