什么是远程线程注入?

远程线程注入

首先,要说明白远程线程注入,必须得弄明白什么是远程线程以及什么是注入!

远程线程

这里的远程指的是别的进程空间,大家应该都在自己代码中或多或少运用过多线程,这里给出常见的win32创建线程接口的使用,如下:

本地线程创建

1 、官方给的接口:

HANDLE CreateThread(
  [in]  LPSECURITY_ATTRIBUTES   lpThreadAttributes, //安全描述符,一般填NULL
  [in]  SIZE_T                  dwStackSize, //栈空间,一般写0,系统给我们默认值
  [in]  LPTHREAD_START_ROUTINE  lpStartAddress, //线程函数
  [in]  LPVOID					lpParameter,  //线程函数的传入参数
  [in]   DWORD                  dwCreationFlags, //创建标志,一般为0 
  [out] LPDWORD                 lpThreadId  //传出的线程ID
);

2、基本使用

//线程函数
DWORD WINAPI threadFunc(LPVOID lpThreadParameter)
{
	for (int i = 0; i < 5; i++)
	{
		printf("---------------\n");
		Sleep(500);
	}
	return 0;
}

int main()
{
	HANDLE hThread = CreateThread(NULL, 0, threadFunc, NULL, 0, NULL);//创建线程
	WaitForSingleObject(hThread, INFINITE); //阻塞等待线程执行完毕
	CloseHandle(hThread); 
	return 0;
}

3、执行结果
什么是远程线程注入?_第1张图片

远程线程创建

1 、官方给的接口:

HANDLE CreateRemoteThread(
  [in]  HANDLE                 hProcess,           //要在哪个线程创建,这边是线程句柄
  [in]  LPSECURITY_ATTRIBUTES  lpThreadAttributes, //安全描述符
  [in]  SIZE_T                 dwStackSize,        //默认为0
  [in]  LPTHREAD_START_ROUTINE lpStartAddress,     //对方进程空间的线程函数地址
  [in]  LPVOID                 lpParameter,        //对方进程空间的参数地址
  [in]  DWORD                  dwCreationFlags,    //默认0
  [out] LPDWORD                lpThreadId          //系统唯一的线程id
);

2、基本使用

//参数为要目的进程ID , 目的进程空间的函数地址
//为了清晰整洁,错误判断就没有写
void DoRemoteThreadFunc(DWORD pid, DWORD funcaddr)
{
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); //根据进程id ,获取进程句柄
	DWORD threadid = 0;
	HANDLE hThread = INVALID_HANDLE_VALUE;
	//在目的进程中   创建远程线程
	hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)funcaddr, NULL, 0, &threadid);
	CloseHandle(hThread);
	CloseHandle(hProcess);
}
int main()
{
	//这里千万要注意,第一个进程id,咱们测试,通过任务管理器找出正在运行目的进程的pid
	//第二个,只要目标程序没有重新编译,咱们可以通过打断点,查看反汇编,找到函数地址进行测试
	DoRemoteThreadFunc(4788,0x1001730);
	return 0;
}

以上为A端,是需要在B端创建线程的程序
------------------------------------------------------------------------------------------------------------------------------------------------
以下为B端,是被创建线程的程序
void func()
{
	for (int i = 0; i < 5; i++)
	{
		printf("----------------func\n");
		Sleep(500);
	}
}

int main()
{
	func();
	printf("********\n");
	getchar();
	return 0;
}

B端程序运行后,查看进程ID
在这里插入图片描述
查看B端的一个函数的地址
什么是远程线程注入?_第2张图片

3、执行结果
什么是远程线程注入?_第3张图片
4、总结
咱们发现最主要的就是理解每个进程空间的地址都是虚拟地址,进程A的地址0x40000到进程B后,就完全不是一回事了!!!!!!!

这样咱们就知道,远程线程就是在别的进程空间创建一个线程而已!!!!


注入

1、定义
注入就是在对方不知情的情况下,将第三方的模块或者代码注入到对方的进程空间中,并使其运行的手段。

咱们上面写的创建远程线程有一个最大的弊端就是,只能使用对方自己的函数。而注入,就是让对方远程线程使用咱们自己的函数!!!!

2、常见注入-----远程线程注入

  • 1、将LoadLibraryA这个系统函数作为咱们的远程线程函数入口
  • 2、在对方开辟一个物理页,将需要注入的DLL的完整路径写进去,这个地址会作为线程函数参数!
  • 3、然后咱们就可以在DLL入口函数中,在被附加的时候执行咱们自己的程序了,想执行啥执行啥,因为咱们的DLL现在在对方的进程空间中!!!!!

注意: 这边咱们需要理解一下LoadLibraryA这个是kernal32模块的函数,并且对于每个进程来说,这个函数地址都是一样的,32位程序下,属于共享高2G的内存区域。

3、代码如下:(为了简洁,不做错误判断了哈)

//参数一: 注入的进程id
//参数二:需要注意的DLL路径 
void RemoteInject(DWORD pid,char* dllPath)
{
	//1 获取对方进程句柄
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

	//2 对方开辟物理页,存放Loadlibrary 传入的参数,也就是dll路径
	VOID* paraAddr = VirtualAllocEx(hProcess, NULL, strlen(dllPath) + 1, MEM_COMMIT, PAGE_READWRITE);

	//3 往物理页写入 路径
	WriteProcessMemory(hProcess, paraAddr, dllPath, strlen(dllPath) + 1, NULL);

	//4 获取loadlibrary函数的地址
	HINSTANCE LibHandle = LoadLibrary("kernel32");
	DWORD ProcAdd = (DWORD)GetProcAddress(LibHandle, "LoadLibraryA");
	
	//5 创建远程线程
	DWORD threadid = 0;
	HANDLE hThread = INVALID_HANDLE_VALUE;
	hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)ProcAdd, paraAddr, 0, &threadid);

	CloseHandle(hThread);
	CloseHandle(hProcess);
}

下面是被注入的DLL的代码:

DWORD WINAPI threadFunc(LPVOID lpThreadParameter)
{
	for (int i = 0; i < 5; i++)
	{
		printf("myfunc is doing....----------------\n");
	}
	return 0;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
		CreateThread(NULL, 0, threadFunc, NULL, 0, NULL); //线程是函数执行体,必须创建
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

4、运行结果如下
什么是远程线程注入?_第4张图片
5、总结

  • 理解32位程序下,每个进程的4GB虚拟内存空间
  • 合理利用CreateRemoteThread函数
  • DLL注入的方法很容易被检测

结尾: 我是航行的土豆,喜欢我的朋友们,欢迎点赞+关注哦!希望大家多多支持我哦!有相关不懂问题,可以留言一起探讨哦!

你可能感兴趣的:(安全,指针,c++,系统安全,windows)