SPT 启动器补丁分析
正版购买地址
4.0.5 版本分析
修改背景
在原始 commita 4ddd06 中,参考 M3351AN 的 SPT-Fuyu 项目中的思路,知道了 spt-launcher 函数中注册表路径检测逻辑。
spt-launcher原代码比较逻辑为:
11 04 IL_013b: ldloc.s 4 // 加载局部变量 num 16 IL_013d: ldc.i4.0 // 加载常数 0 FE 01 IL_013e: ceq // 比较是否相等 2A IL_0140: ret // 返回比较结果
修改为使用无符号大于比较(cgt.un),仅改变运算符,保持指令字节对齐:
11 04 IL_013b: ldloc.s 4 // 加载局部变量 num 16 IL_013d: ldc.i4.0 // 加载常数 0 FE 04 IL_013e: cgt.un // 无符号大于比较 2A IL_0140: ret // 返回比较结果
即
11 04 16 FE 01 2A
替换
11 04 16 FE 04 2A
4.0.6 启动器稍微变得复杂些
该版本分析得出
catch [System.Runtime]System.Object
{
26 IL_010e: pop
15 IL_010f: ldc.i4.m1
80 + <fieldToken> IL_0110: stsfld int32 SPT.Launcher.Helpers.ValidationUtil::v0
DE + <rel8> IL_0115: leave.s IL_0117
} // end handler
7E + <fieldToken> IL_0117: ldsfld int32 SPT.Launcher.Helpers.ValidationUtil::v0
16 IL_011c: ldc.i4.0
FE 01 IL_011d: ceq
2A IL_011f: ret
} // end of method ValidationUtil::Validate
貌似最容易的还是直接返回了,所以
catch [System.Runtime]System.Object
{
26 IL_010e: pop
15 IL_010f: ldc.i4.m1
80 + <fieldToken> IL_0110: stsfld int32 SPT.Launcher.Helpers.ValidationUtil::v0
DE + <rel8> IL_0115: leave.s IL_0117
} // end handler
17 ldc.i4.1
00 00 00 00 00 00 00 nop
2A ret
} // end of method ValidationUtil::Validate
这样就能无视前面的判断,直接返回真
即
26 15 80 ?? ?? ?? ?? DE ?? 7E ?? ?? ?? ?? 16 FE 01 2A
改为
26 15 80 ?? ?? ?? ?? DE ?? 17 00 00 00 00 00 00 00 2A
使用 Hex 编辑器(如 dnSpy、HxD、010Editor 等)手动修改.
以下是一个简单的 C++ 补丁工具,用于自动修改 SPT.Launcher.exe:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
int main()
{
std::cout << "Try patch\n";
std::ifstream in("SPT.Launcher.exe", std::ios::binary);
std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(in), {});
in.close();
const std::vector<unsigned char> original = { 0x11, 0x04, 0x16, 0xFE, 0x01, 0x2A };
const std::vector<unsigned char> replacement = { 0x11, 0x04, 0x16, 0xFE, 0x04, 0x2A };
auto it = std::search(buffer.begin(), buffer.end(), original.begin(), original.end());
if (it != buffer.end())
{
std::copy(replacement.begin(), replacement.end(), it);
std::ofstream out("SPT.Launcher.patch.exe", std::ios::binary);
out.write(reinterpret_cast<const char*>(buffer.data()), buffer.size());
out.close();
std::cout << "Success!\n";
}
else
{
std::cout << "No matching byte sequence was found. Please check the file version.\n";
}
std::cin.get();
return 0;
}
文档存档https://wwxc.lanzouo.com/ix2ci3bwjy7c









楼主棒棒哒,有和原贴主反应这个吗,改一下重新安排上fuyu网站使用
用Hex 编辑器手动修改成功了,感谢楼主
睡了一天,醒来发现大家已经研究出来了,其实直接把11 04 16 FE 01 2A改为00 16 16 FE 01 2A也是一样的,在原本压入局部变量的位置改成压入整数0就可以了,前一个字节直接nop不用管,改成cgt.un的话也可以,毕竟需要过验证的就不考虑有正版的情况了
好技术,哪里有成品链接,万分感谢。
666666666
我直接用火绒看他获取了什么信息就可以了