汇编中如何验证待访问地址属于当前进程的可读写内存范围
如何验证内存地址是否属于当前进程合法可访问范围
判断目标内存地址是否属于当前进程可访问范围、是否有对应读写权限,有两类常用实现方案:
方案1:调用系统提供的内存查询接口
不同操作系统内核都维护了当前进程的虚拟内存段映射信息,用户态可以直接调用官方接口查询:
- Windows平台:直接使用系统API
IsBadReadPtr、IsBadWritePtr、IsBadCodePtr,传入待验证的地址和要访问的长度,返回值为非0时代表地址不可访问,为0代表当前地址可操作。
注意该方案存在竞态条件缺陷:如果校验完成后、正式访问内存前,其他线程修改了这段内存的权限、或者直接释放了这段内存,还是会触发访问错误崩溃。 - Linux/Unix平台:读取当前进程的
/proc/self/maps文件,文件内每行对应一个合法内存段的信息,包含段的起始/结束地址、读写执行权限、映射的文件路径等内容。遍历所有段记录,判断目标地址是否落在某段的地址区间内、且该段权限符合你需要的读写要求即可。
方案2:通过异常/信号捕获机制兜底(更推荐)
该方案可以完全规避竞态问题,不需要提前校验,直接访问地址、出错时做兜底处理即可:
- Windows平台:将访问内存的代码放在
__try/__except结构化异常处理块中,如果访问的是非法地址,会触发访问违例异常,直接在__except分支中捕获异常做错误处理即可,进程不会直接崩溃。 - Linux/Unix平台:提前注册
SIGSEGV(段错误)信号的处理函数,访问非法地址时内核会向进程发送该信号,在信号处理函数中执行跳转或者错误逻辑,即可避免进程被系统直接杀死。
举个对应示例:你提到的
mov eax, [0x010]操作,如果你用Windows的API校验,调用IsBadReadPtr((void*)0x10, 4)就可以提前知道0x10地址不可读,直接跳过后续的内存访问操作就不会崩溃。如果用异常捕获方案,把这行汇编放在__try块里,访问失败直接进异常分支处理即可。
额外注意
- 除了调试、逆向工程、特殊工具开发这类场景外,正常业务代码中不建议访问来源不确定的内存地址,也不需要额外做这类校验。
- 如果你需要在多线程环境下做地址校验,优先选择异常捕获方案,完全规避竞态问题。
内容的提问来源于stack exchange,提问作者PeaceBeUponYou
相关产品推荐
相关产品推荐

