给程序添加保护时,如果函数列表里只有地址,挑选目标函数就比较费劲。项目重新编译以后,原来的地址还可能发生变化,照着旧记录填写容易选错位置。MAP文件记录了程序链接后的符号与地址信息,可以帮助VMProtect按名称找到函数。不过,文件放错目录、拿错编译版本,或者目标函数已经被优化掉,都会影响定位。下面以Windows下使用Visual Studio生成的原生程序为例,说明具体操作。
一、VMProtect怎么用MAP文件定位函数
MAP文件需要由生成目标程序的链接器输出。准备时应把程序和映射文件作为一组处理,避免混用不同配置或不同批次的文件。
1、在Visual Studio中生成MAP文件
只打开生成选项还不够,项目需要重新完成链接,才能得到对应的映射文件。设置前也要确认当前配置,防止改了调试配置,却拿发布配置的程序去处理。
①在【解决方案资源管理器】中右键单击目标项目,打开【属性】,确认顶部的【配置】和【平台】。
②依次展开【配置属性】→【链接器】→【调试】,将【生成映射文件】设为【是(/MAP)】。
③检查同页的【映射文件名】,确认输出路径。没有另行指定名称时,链接器使用程序基本名称并添加【.map】扩展名。
④点击【应用】,执行【生成】→【重新生成解决方案】,在输出目录中找到对应的【.exe】或【.dll】及【.map】文件。
2、在VMProtect中按名称选择函数
①将同次构建得到的程序和【MAP文件】放在同一目录,保留相同的基本名称,例如【Demo.exe】与【Demo.map】。
②在VMProtect中依次点击【文件】→【打开】,选择尚未经过保护处理的【Demo.exe】。
③点击工具栏的【添加函数】,在弹出窗口的【函数】列表中查找目标,或在搜索框内输入函数名称的一部分。
④核对候选函数的名称、所属类及地址,选择后确认添加,再通过【保存工程】保留配置。
函数名相近时,别只看搜索结果的前几个字。C++重载函数、类成员函数可能带有参数信息或修饰名称,需要结合实际代码核对。MAP中的符号记录也不等于源代码中的全部函数,能否按名称选择,还取决于链接结果中保留了哪些符号。
二、VMProtect未识别MAP文件怎么办
排查时要区分两种情况,一种是整个符号列表没有加载,另一种是列表正常但缺少某个函数。两者的检查方向不同,不宜反复更换文件名碰运气。
1、检查文件位置和程序版本
整个列表都没有预期的函数名时,可以先回到构建输出目录,排除复制和选错文件的问题。
①在【文件资源管理器】中打开【查看】,启用【文件扩展名】,确认映射文件没有被保存成【Demo.map.txt】。
②核对【Demo.exe】与【Demo.map】的所在目录和基本名称,检查是否误用了其他项目的同名文件。
③返回Visual Studio,确认【配置】、【平台】及生成输出路径,重新生成后成对复制程序与【MAP文件】。
④在VMProtect中关闭当前工程,再通过【文件】→【打开】加载这次复制的程序,重新查看【添加函数】窗口。
2、核对生成时间和文件内容
①用文本编辑器打开【MAP文件】,检查是否存在模块名称、地址、符号名称等内容,排除空文件和无关格式文件。
②在MSVC生成的文件中查找【Publics by Value】区域,搜索一个确定存在的业务函数名称。
③检查【MAP文件】头部的时间戳及构建记录,确认它对应当前程序;文件曾被替换时,重新执行【重新生成解决方案】。
加载MAP时,VMProtect会检查它与目标程序的时间信息是否匹配。MSVC映射文件还包含来自程序文件头的时间戳,所以只把文件资源管理器里的修改时间改成一致,无法证明两者对应。重新生成并保留整组产物,比手动修补时间可靠。
3、只有个别函数找不到时检查优化
当其他函数都能显示时,MAP读取过程可能已经正常。缺失函数可能被内联、被删除,也可能与其他函数合并了地址。
①在【MAP文件】内搜索函数名的关键部分,同时核对类名和参数,排除名称修饰造成的漏查。
②查看目标函数是否存在实际调用,在Visual Studio的【链接器】→【优化】中检查与【/OPT:REF】和【/OPT:ICF】对应的设置。
③如需验证优化影响,在单独的测试配置中使用【/OPT:NOREF】或【/OPT:NOICF】,重新生成后对比符号记录。
④怀疑成员函数被内联时,可在测试代码中对该函数使用【__declspec(noinline)】,重新构建并查找。
这些改动用于定位原因,不应未经评估直接沿用到发布配置。取消内联也不保证函数一定保留,未引用函数删除等其他处理仍可能影响结果。如果目标名称在MAP中根本不存在,VMProtect也无法凭空恢复相应的名称记录。
三、VMProtect定位函数后如何核对保护对象
函数已经显示出来,还要确认工程引用的是当前程序,并检查处理后能否正常执行目标功能。列表里出现名称,只完成了定位这一部分。
1、重新编译后检查工程中的函数记录
①打开原有【.vmp】工程,核对输入程序路径,确认它指向本次构建的【.exe】或【.dll】。
②查看待保护函数的名称和当前地址,检查是否出现找不到函数的提示。
③执行【编译】,检查编译日志中涉及目标函数的记录;遇到未找到函数的提示时,重新打开【添加函数】核对。
使用匹配的MAP文件时,VMProtect可以在重新编译后按符号信息确定函数的新地址。但函数改名、参数变化或优化处理发生变化,都可能影响原有选择。旧地址记录不宜跨版本直接复用,发现名称失配时,应回到本次构建结果中重新确认。
2、保留构建产物并验证目标功能
每次只选择少量目标函数,验证起来更容易判断问题范围。尤其是带有复杂调用关系的业务逻辑,不能仅凭保护编译完成就认定处理结束。
①保存本次的【原始程序】、【MAP文件】及【.vmp工程】,按构建日期或版本分别存放。
②将【输出文件】设置为独立路径,保留原始程序用于对照。
③运行保护后的【输出文件】,操作能够触发目标函数的功能,核对返回结果、异常处理和运行耗时。
④修改函数选择或【编译类型】后,重新执行对应功能,并记录测试结果。
总结
MAP文件让VMProtect中的函数选择更容易核对,也减少了手工维护地址的负担。使用时要把注意力放在构建产物的对应关系上,分清文件没有加载和函数没有保留这两类问题。定位成功之后,再用实际功能验证保护结果,才能让工程配置有可靠的依据。希望这些检查方法能帮助大家少走一些来回尝试的弯路。
