摘 要 探讨了利用C++实现远程线程的方法,该方法可以使编写远程线程代码变得更加简单高效,同时给出了完整的C++源代码。
关键词 远程线程;重定位表;导入表;进程隐藏
1 引言
远程线程技术指的是通过在其他进程中创建新线程的方法进入该进程的内存地址空间,从而获得对该进程的控制权的方法。在进程中可以通过CreateThread函数创建线程,被创建的新线程与主线程共享地址空间以及其他的资源。同样,通过CreateRemoteThread函数可以在其他进程内创建新线程,新创建的远程线程可以共享远程进程的地址空间。所以通过在远程进程中创建新线程的方法,就可以进入到远程进程的内存地址空间,也就拥有了和那个远程进程相当的权限,可以在远程进程中执行代码,从而达到远程进程控制、进程隐藏等目的。
2基本原理
2.1 API函数
其中VirtualAllocEx和CreateRemoteThread两个API函数只能在NT内核下用。实现的基本过程如下:
(1)通过OpenProcess 函数打开进程PID为ProcessId的远程进程:
hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, ProcessId) ;
(2)通过VirtualAllocEx函数在刚打开的进程中申请ImageSize个字节的内存:
InjectPoint = VirtualAllocEx(hProcess, 0, ImageSize,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
(3)通过WriteProcessMemory函数将NewModule开始的ImageSize个字节的代码写入已申请到的内存中:
WriteProcessMemory(hProcess, InjectPoint, NewModule, ImageSize, NULL);
(4)通过CreateRemoteThread函数启动刚写入的代码:
CreateRemoteThread(hProcess, NULL, 0, EntryPoint, Param, 0, NULL);
2.2重定位和函数导入问题
在远程进程执行的代码中最重要的是要解决代码的重定位和API函数导入的问题,对于参考文献1的方法是通过在远程进程中执行LoadLibrary函数将DLL文件载入,所以系统会自动完成代码的重定位和API函数导入工作;而参考文献2中提到的方法是通过汇编语言进行编程来解决,相对来讲会使编程难度增大,但隐藏性是最好的。在这里,探讨一种新的方法既能使用高级语言进行编程又有完美的隐藏效果的方法。
首先要解决的是重定位问题,这就要用到PE文件中的重定位表,利用重定位表将即将写入远程进程的代码按照在远程进程申请到的内存首地址通过RelocCode函数进行重定位,然后将重定位好的代码写入远程进程的内存空间。这些写入的代码必然要用到API函数,所以在远程线程代码调用第一个API之前,要替系统来完成装入API函数对应的DLL文件,并填好相关API函数入口地址的工作,这就要用到PE文件的输入表提供的信息,输入表记录了一个Win32程序需要加载的所有DLL文件名及从中引入的API函数名,这样就可以用LoadLibrary函数装入需要用到的DLL文件,再通过GetProcAddress函数获得相应的API函数地址,这里是通过LoadAPI函数来完成这些工作。对于上面提到的PE文件的重定位表和输入表等相关知识,请读者参考有关资料,这里不再赘述。下面程序中的LoadAPI函数作为远程线程的入口,其用到的API函数LoadLibrary和GetProcAddress的入口地址又是如何确定的呢?事实上几乎所有的Windows进程都会装入“kernel32.dll”,而这两个函数就位于“kernel32.dll”中,而且所有装入“kernel32.dll”的进程都会把它装入到同一个虚拟内存地址,即在本地进程中使用到“kernel32.dll”中的API函数和远程进程中对应的API函数地址是一样的,所以在远程进程代码中可以象本地进程一样调用LoadLibrary加载dll文件,然后用GetProcAddress获得输入函数的入口地址并写入相应的数据结构中,完成API函数的导入。
|