这个假设是否一直成立?注入(例如通过恶意软件)“受害者”进程内存中的代码是否始终属于具有RWX访问权限的页面?还是可以通过注入的代码来更改页面访问权限?如果是这样,如何通过winapi进行此更改?
#1 楼
该假设不成立,因为分配内存后可以更改页面保护标志。Windows上代码注入的常用机制如下:
为目标进程调用
OpenProcess
,以获得具有适当访问权限的句柄。使用
VirtualAllocEx
在目标进程中分配带有一组内存页访问标志的缓冲区。使用
WriteProcessMemory
将内存复制到目标。要么修补现有代码以跳转到新代码块,要么使用
CreateRemoteThread
通过新线程在进程内执行。现在,在那里这里有两个选择。第一个是可以将
PAGE_EXECUTE_READWRITE
指定为VirtualAllocEx
的标志,以便您有权在该页面上使用WriteProcessMemory
,并且有权在执行步骤4时执行该内存。这是“懒惰”的方式导致RWX缓冲区悬空。另一种方法是在分配块时传递PAGE_READWRITE
,然后编写代码,并在第4步之前调用VirtualProtectEx
将标志交换到PAGE_EXECUTE_READ
。这在复制数据时为您提供了RW缓冲区,在执行时为您提供了RX缓冲区。 /> 伪代码:
rights = PROCESS_VM_OPERATION |
PROCESS_VM_READ | PROCESS_VM_WRITE |
PROCESS_QUERY_INFORMATION |
PROCESS_CREATE_THREAD;
handle = OpenProcess(rights, false, pid);
targetAddr = VirtualAllocEx(handle, NULL, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
buffer = "Hello, world!q4312078q";
bytesWritten = 0;
WriteProcessMemory(handle, targetAddr, buffer, 14, &bytesWritten);
oldProtect = 0;
VirtualProtectEx(handle, targetAddr, 4096, PAGE_EXECUTE_READ, &oldProtect);
threadId = 0;
CreateRemoteThread(handle, NULL, 0, targetAddr, NULL, 0, &threadId);
#2 楼
定位RWX页面的原因是,注入的代码最经常在与代码相同的区域中承载数据,并且要求数据可写。因此,需要W标志。如果选择了进程,或者系统为每个人强制执行DEP,则需要X标志来支持DEP。请求页面时,R标志是完全可选的。 Windows会确保无论如何设置它。回想一下曾经使用过这种技术。一方面,它使注入的代码变得复杂。#3 楼
页面访问可以更改。请参阅VirtualProtect,内存保护常量和VirtualProtectEx文档。注入的代码应是可执行的且可读的,但不一定
可写。
评论
感谢您的详细回答。在您描述的替代代码注入方式(“非惰性”)中,是否可以将PAGE_EXECUTE_READWRITE与PAGE_EXECUTE或PAGE_EXECUTE_WRITECOPY交换,作为您在示例中提供的PAGE_EXECUTE_READ的替代方式?
–本尼
2014年1月19日15:48
PAGE_EXECUTE应该可以正常工作,但是看起来很奇怪,因为很少会在分配上看到PAGE_EXECUTE。使用PAGE_EXECUTE_WRITECOPY应该可以,但是VirtualAllocEx不支持它。我不知道VirtualProtectEx是否可以。
–多项式
2014年1月19日下午16:02