远程线程注入
线程是什么
如果说进程是个大房子,那么线程是进程中干活的人
线程是进程的灵魂
使用进程提供的数据 执行进程提供的代码
临时数据存储在计算机的寄存器中
创建线程
//在自己的进程中创建线程
CreateThread()
//在别人的进程中创建线程
HANDLE WINAPI CreateRemoteThread
(
_In_ HANDLE hProcess, //目标进程句柄
_In_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ SIZE_T dwStackSize, //目标线程栈大小
_In_ LPTHREAD_START_ROUTINE lpStartAddress,//目标线程地址
_In_ LPVOID lpParameter, //目标线程参数
_In_ DWORD dwCreationFlags,//创建标志位
_Out_ LPDWORD lpThreadId //返回被创建线程的ID
);
远程线程注入的关键点
- 通过
CreateRemoteThread
创建线程 - 被创建的线程的本体在
目标进程内部
- 被创建的线程使用的各类资源
均依赖于目标进程
思考:
如果利用之前学习过的知识将我们想要实现的代码加入到目标进程中去?
远程线程的几个关键点
- 被创建的线程在别的进程中执行
- 呗创建的线程锁依赖的代码或数据
都来自于目标进程
如果想要在目标进程中干我们想干的事,我们就需要吧自己的功能代码加入到目标进程内部,这个也就是常说的代码注入
我们目前学过的知识就可以实现一些注入的功能
- 内存的操作
- 动态链接库
通过直接读写内存的方式
- 利用
VirtualAllocEx
在目标进程中申请一段内存空间 - 通过
WriteProcessMemory
在目标进程中刚申请的空间内将我们的功能代码的硬编码写入 - CreateRemoteThread 启动我们的目标代码
优点: 操作简单不易呗发现
缺点: 因为远程线程锁执行的代码和利用的资源只能是目标进程提供的,那么我们写入的这段硬编码必须得脱离其他依赖独立运行,只能直接调用API,不能使用静态库提供的函数,不能直接使用动态库使用的函数,不能出现随意的调用或者jmp,在构造这种代码的时候会非常复杂,当然按照以上要求构造出来的代码我们还有一种叫法,叫做ShellCode
DllMain
BOOL WINAPI DllMain
(
HINSTANCE hinstDLL;//DLL模块举办(DLL 被加载的位置)
DWORD fwdReason, // 制定本地DLLMain被调用的原因
LPVOID ipvReserved; //保留位
)
//fdwReason的一些宏说明:
DLL_PROCESS_ATTACH:
当进程第一次将该DLL映射到内存空间时,我们的进程就会调用一次这个DllMain并传入这个参数
DLL_PROCESS_DETACH:
当进程将当前DLL从内存空间解除映射的时候,就会调用一次DllMain并传入这个参数
DLL_THREAD_ATTCH:
每当有一个新的线程创建,都会调用一次DllMain并传入这个参数
DLL_THREAD_DEACH:
每当有一个线程结束(ExitThread)时就会调用一次DllMain并传入这个参数,如果线程是因为TerminateThread函数而结束的则不会调用
通过动态链接库的方式
- 利用一些手段加载带有我们功能函数的DLL
- 通过DLLMAIN来启动我们的功能
优点:操作简单实现也简单,写在DLL中的功能函数不需要想 ShellCode那样做到什么也不依赖
,因为DLL被加载后重定位会替我们搞定这些麻烦事,所以在DLL中可以像写我们普通的正常程序一样来写我们的功能代码
缺点:容易被检测
加载DLL: