You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NSIS反模拟器实现:大内存区域填充方法技术问询

NSIS反模拟器:填充大内存区域的实现方案

嘿,我明白你想通过强制分配并占用物理内存来识别模拟器的思路——毕竟大多数模拟器没法提供足够的真实物理内存,这招确实靠谱。你已经用LocalAlloc分配了内存,但关键是要主动写入数据,才能让内核真正把虚拟内存页提交到物理内存(单纯分配可能只是保留了地址空间,模拟器可能能蒙混过去)。

下面给你两种可行的实现方式:

方式一:用memset快速填充(推荐)

这是最高效的方式,直接调用系统API来填充整块内存,避免NSIS脚本循环的性能问题:

; 分配143978374字节的固定内存,返回指针到$0
System::Call "kernel32::LocalAlloc(i 0, i 143978374) p .r0"

; 先检查内存分配是否成功——模拟器大概率会在这里失败
${If} $0 == 0
    MessageBox MB_OK "检测到模拟器环境,程序退出"
    Quit
${EndIf}

; 用memset填充整个内存区域,这里选0xCC(x86的int3指令,也可以换成0/0x90等任意值)
; 参数:目标内存指针、填充字节、填充长度
System::Call "kernel32::memset(p r0, i 0xCC, i 143978374)"

; 可选:添加内存验证,防止模拟器拦截memset调用
System::Call "kernel32::ReadProcessMemory(i -1, p r0, p .r1, i 4, *i 0)"
${If} $1 != 0xCCCCCCCC
    MessageBox MB_OK "内存写入验证失败,疑似运行在模拟器中"
    Quit
${EndIf}

; 用完别忘了释放内存
System::Call "kernel32::LocalFree(p r0)"

关键说明:

  • LocalAlloc(0, size)默认会初始化内存为0,但有些模拟器会优化“未被实际使用”的内存,主动写入数据能确保内存被真正提交到物理内存。
  • 填充值选0xCC只是个例子,用任何字节值都可以;添加验证步骤是为了防止模拟器hook掉memset,假装完成了填充。

方式二:用VirtualAlloc精确控制内存状态

如果你想更精细地控制内存的“保留-提交”流程,VirtualAlloc是更好的选择,能明确区分地址空间保留和物理内存提交:

; 先保留200MB的虚拟地址空间(比你需要的143MB大一点,留冗余)
; MEM_RESERVE = 0x1000,PAGE_EXECUTE_READWRITE = 0x40
System::Call "kernel32::VirtualAlloc(p 0, i 209715200, i 0x1000, i 0x40) p .r0"

${If} $0 == 0
    MessageBox MB_OK "内存保留失败,疑似模拟器"
    Quit
${EndIf}

; 提交你需要的143978374字节内存到物理内存
; MEM_COMMIT = 0x2000
System::Call "kernel32::VirtualAlloc(p r0, i 143978374, i 0x2000, i 0x40) p .r1"

${If} $1 != $0
    MessageBox MB_OK "内存提交失败,疑似模拟器"
    System::Call "kernel32::VirtualFree(p r0, i 0, i 0x8000)" ; MEM_RELEASE = 0x8000
    Quit
${EndIf}

; 填充内存,这里用0x90(NOP指令)
System::Call "kernel32::memset(p r0, i 0x90, i 143978374)"

; 验证内存写入结果
System::Call "kernel32::ReadProcessMemory(i -1, p r0, p .r2, i 4, *i 0)"
${If} $2 != 0x90909090
    MessageBox MB_OK "内存验证失败,疑似模拟器"
    System::Call "kernel32::VirtualFree(p r0, i 0, i 0x8000)"
    Quit
${EndIf}

; 释放整块内存
System::Call "kernel32::VirtualFree(p r0, i 0, i 0x8000)"

关键说明:

  • 先保留地址空间,再提交物理内存,能更准确地触发模拟器的内存限制——模拟器通常很难模拟大量物理内存的提交操作。
  • 权限参数0x40是可执行可读可写,如果你不需要执行权限,可以换成0x04(PAGE_READWRITE)。

内容的提问来源于stack exchange,提问作者Robot Coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:16:01