Axibug.MHFSaveDataAutoConve.../Data/MH2DosSaveDataLoader.cs
2025-09-19 18:25:00 +08:00

195 lines
6.9 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.IO;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace MonsterHunterSaveBruteForce
{
class MH2DosSaveDataLoader
{
// 已知数值常量
private const ushort KnownMoney = 5929; // 0x1729
private const ushort KnownExp = 6525; // 0x197D
private const ushort ItemLargePotion = 0x0008; // 回復藥・大 的ID
private const ushort ItemLargePotionQty = 5; // 回復藥・大 的数量
// 道具箱特征前6个道具
private static readonly List<(ushort id, ushort quantity)> ItemPattern = new List<(ushort, ushort)>
{
(0x0001, 1), // 調合書①入門編
(0x0002, 1), // 調合書②初級編
(0x0003, 1), // 調合書③中級編
(0x0007, 3), // 回復藥
(ItemLargePotion, ItemLargePotionQty), // 回復藥・大
(0x0015, 2) // 冷飲
};
public static void LoadSaveData()
{
Console.WriteLine("===== PS2怪物猎人2存档暴力破解工具 =====");
Console.WriteLine("此工具使用金钱、经验和道具特征进行暴力破解");
// 1. 加载存档
byte[] saveData = File.ReadAllBytes("play00.bin");
Console.WriteLine($"存档大小: {saveData.Length} 字节");
// 2. 暴力破解
BruteForceDecryption(saveData);
}
static void BruteForceDecryption(byte[] data)
{
Console.WriteLine("开始暴力破解,这可能需要一些时间...");
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
int totalAttempts = 0;
const int reportInterval = 100000; // 每100,000次尝试报告一次进度
// 限制搜索范围提高效率
//int searchRange = Math.Min(0x10000, data.Length - 20);
int searchRange = data.Length - 20;
// 尝试所有可能的密钥组合 (0x0000 - 0xFFFF)
for (ushort key = 0; key < ushort.MaxValue; key++)
{
// 解密整个存档
byte[] decrypted = DecryptWithKey(data, key);
// 验证金钱和经验值
var (moneyFound, expFound) = ValidateMoneyAndExp(decrypted);
// 验证道具箱特征
//bool itemsValid = ValidateItemBox(decrypted);
bool itemsValid = true;
// 如果三项验证都通过
//if (moneyFound && expFound && itemsValid)
if(ValidateName(decrypted))
{
stopwatch.Stop();
Console.WriteLine($"\n暴力破解成功! 密钥: 0x{key:X4}");
Console.WriteLine($"耗时: {stopwatch.Elapsed.TotalSeconds:F2} 秒");
Console.WriteLine($"尝试次数: {totalAttempts}");
// 保存解密文件
//File.WriteAllBytes("decrypted_play00.bin", decrypted);
Console.WriteLine("解密文件已保存: decrypted_play00.bin");
return;
}
// 报告进度
if (++totalAttempts % reportInterval == 0)
{
Console.WriteLine($"已尝试 {totalAttempts} 种密钥组合... 当前密钥: 0x{key:X4}");
}
}
stopwatch.Stop();
Console.WriteLine($"\n暴力破解完成但未找到有效密钥。耗时: {stopwatch.Elapsed.TotalSeconds:F2} 秒");
Console.WriteLine($"总尝试次数: {totalAttempts}");
}
static byte[] DecryptWithKey(byte[] data, ushort key)
{
byte[] keyBytes = BitConverter.GetBytes(key);
byte[] decrypted = new byte[data.Length];
for (int i = 0; i < data.Length; i++)
{
decrypted[i] = (byte)(data[i] ^ keyBytes[i % 2]);
}
return decrypted;
}
static (bool moneyFound, bool expFound) ValidateMoneyAndExp(byte[] decrypted)
{
bool moneyFound = false;
bool expFound = false;
// 扫描整个文件寻找金钱和经验值
for (int i = 0; i < decrypted.Length - 1; i++)
{
ushort value = BitConverter.ToUInt16(decrypted, i);
// 检查是否是金钱值
if (value == KnownMoney)
{
moneyFound = true;
}
// 检查是否是经验值
if (value == KnownExp)
{
expFound = true;
}
// 如果两个都已找到,提前退出
if (moneyFound && expFound)
{
break;
}
}
return (moneyFound, expFound);
}
static bool ValidateName(byte[] data)
{
byte[] checkdata = new byte[4] { 0xE1, 0xA9, 0x8C, 0x8E };
// 扫描整个文件寻找道具箱特征
for (int offset = 0; offset < data.Length - checkdata.Length; offset++)
{
for (int i = 0; i < checkdata.Length; i++)
{
if (data[0] == checkdata[0]
&& data[1] == checkdata[1]
&& data[2] == checkdata[2]
&& data[3] == checkdata[3])
return true;
}
}
return false;
}
static bool ValidateItemBox(byte[] decrypted)
{
// 尝试不同的道具结构 (4字节和8字节)
return ValidateItemStructure(decrypted, 4) || ValidateItemStructure(decrypted, 8);
}
static bool ValidateItemStructure(byte[] data, int slotSize)
{
// 扫描整个文件寻找道具箱特征
for (int offset = 0; offset < data.Length - (slotSize * 6); offset++)
{
bool patternMatch = true;
// 检查前6个道具是否匹配已知模式
for (int slot = 0; slot < 6; slot++)
{
int slotOffset = offset + (slot * slotSize);
// 获取道具ID和数量
ushort itemId = BitConverter.ToUInt16(data, slotOffset);
ushort quantity = BitConverter.ToUInt16(data, slotOffset + 2);
// 检查是否匹配预期值
if (itemId != ItemPattern[slot].id || quantity != ItemPattern[slot].quantity)
{
patternMatch = false;
break;
}
}
// 如果找到匹配模式
if (patternMatch)
{
return true;
}
}
return false;
}
}
}