通过CreateRemoteThread&WriteProcessMemory实现远程线程注入,没有通过加载DLL注入,有更好的隐蔽性。 参考:http://www.vckbase.com/index.php/wv/1653/
0x01前言
远程线程技术指的是通过在其他进程中创建新线程的方法进入该进程的内存地址空间,从而获得对该进程的控制权的方法。 在进程中可以通过CreateThread函数创建线程,被创建的新线程与主线程共享地址空间以及其他的资源。同样,通过CreateRemoteThread函数可以在其他进程内创建新线程,新创建的的远程线程可以共享远程进程的地址空间。 所以通过在远程进程中创建新的方法,就可以进入到远程进程的内存地址空间,也就拥有了和那个远程进程相当的权限,可以在远程进程中执行代码,从而达到远程进程控制、进程隐藏的目的。
0x02基本原理
思路: 将程序自身映像写入远程线程然后进行重定位 然后创建远程线程调用其中的入口函数 之后线程运行后先写好AIT 其实就是手动完成PE loader进行模块导入时重定向和写AIT。 可以先看实现代码再回头看,实现代码注释比较详细。。
1.OpenProcess获得远程进程句柄
1 | hRemoteProcess = OpenProcess(PROCESS\_ALL\_ACCESS, FALSE, dwProcessID); |
2.VirtualAllocEx在远程进程申请空间,申请大小为程序自身映像大小。
1 | lpInjectPoint = (LPBYTE)VirtualAllocEx(hRemoteProcess, 0, dwImageSize, MEM\_COMMIT, PAGE\_EXECUTE_READWRITE); |
3.将程序自身的映像的的重定位并且写入远程线程
1 | RelocCode(lpNewMoudle, lpInjectPoint); WriteProcessMemory(hRemoteProcess, lpInjectPoint, lpNewMoudle, dwImageSize, NULL); |
4.运行远程线程
得到ThreadEntry在远程进程中的地址,利用函数在模块中的相对地址+注入点地址 lpRemoteEntryPoint = (LPTHREAD_START_ROUTINE)(lpInjectPoint + (DWORD)fnRemoteThread_Main - lpMoudle); 将插入点地址作为参数传递给线程函数 lpParam = lpInjectPoint; 运行远程线程 hRemoteThread = CreateRemoteThread(hRemoteProcess, NULL, 0, lpRemoteEntryPoint, lpParam, 0, NULL);
5.远程线程运行的入口函数
1 | //CreateRemoteThread的线程运行入口 |
先运行LoadAPI函数写入AIT,之后调用自己的编写的fnRemoteThread_Main函数执行自己的操作
6.其中的重定位及AIT操作
重定位表
参考http://hi.baidu.com/_achillis/item/7e324e08db884b94a2df4313 重定位表由一个个的重定位块组成,如果重定位表存在的话,必定是至少有一个重定位块。 因为每个块只负责定位0x1000大小范围内的数据,因此如果要定位的数据范围比较大的话, 就会有多个重定位块存在。 每个块的首部是如下定义:
1 | typedef struct \_IMAGE\_BASE_RELOCATION { |
把内存中需要重定位的数据按页的大小0x1000分为若干个块,而这个VirtualAddress就是每个块的起始RVA.只知道块的RVA当然还不行,我们要知道每一个需要重定位数据的具体地址。 每个需重定位的数据其地址及定位方式用两个字节来表示,记为RelocData,紧跟在IMAGE_BASE_RELOCATION结构之后。
每个块中重定位信息的个数
这个可由每个块结构中的Size来确定。Size的值是以DWORD表示的当前整个块的大小,先减去IMAGE_BASE_RELOCATION的大小,因为重定位数据是16位WORD的,再除以2,就得到个重定位数据的个数。
遍历每个重定位块
由Size可以直接到达下一个重定位块即当前块地址+Size 某个块首结构的VirtualAddress为0,表明重定位表结束。
修改每个需重定位的地址
每个16位重定位信息包括低12位的重定位位置和高4位的重定位类型。要得到重定位的RVA,IMAGE_BASE_RELOCATION’的’VirtualAddress’需要加上12位位置偏移量. 类型可以查询MSDN 以一个重定位数据0x34AC为例,其高四位表明了重定位类型为3,即IMAGE_REL_BASED_HIGHLOW,Win32环境下的重定位基本都是这个类型的。 其低12位则表明了相对于VirtualAddress的RVA偏移量。VirtualAddress即需重定位的数据块的起始RVA,再加上这低12位的值就得到了具体的需要进行重定位处理的数据的RVA。 就是说: 要进行重定位处理的数据的RVA=VirtualAddress+RelocData&0x0FFF 函数如下:
1 | //完成重定位 |
写入AIT表
实现如下:
1 | //用于完成API函数的导入,参数为要插入代码处地址 |
0x03编程实现
编程的实现,注释的比较详细
1 |
|
0x04 封装成类
把整个实现封装成了一个类,方便调用
1 |
|