首先,要说明白远程线程注入,必须得弄明白什么是远程线程以及什么是注入!
这里的远程指的是别的进程空间,大家应该都在自己代码中或多或少运用过多线程,这里给出常见的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;
}
远程线程创建
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;
}
3、执行结果
4、总结
咱们发现最主要的就是理解每个进程空间的地址都是虚拟地址,进程A的地址0x40000到进程B后,就完全不是一回事了!!!!!!!
这样咱们就知道,远程线程就是在别的进程空间创建一个线程而已!!!!
1、定义
注入就是在对方不知情的情况下,将第三方的模块或者代码注入到对方的进程空间中,并使其运行的手段。
咱们上面写的创建远程线程有一个最大的弊端就是,只能使用对方自己的函数。而注入,就是让对方远程线程使用咱们自己的函数!!!!
2、常见注入-----远程线程注入
注意: 这边咱们需要理解一下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;
}
结尾: 我是航行的土豆,喜欢我的朋友们,欢迎点赞+关注哦!希望大家多多支持我哦!有相关不懂问题,可以留言一起探讨哦!