This commit is contained in:
HolographicHat
2023-02-28 19:16:51 +08:00
parent 8e2e438c96
commit c325b5f754
12 changed files with 116 additions and 144 deletions

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0-windows7</TargetFramework>
<TargetFramework>net7.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>preview</LangVersion>

View File

@@ -105,7 +105,7 @@
<AdditionalDependencies>detours-x64.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>copy $(TargetPath) $(ProjectDir)..\bin\Debug\net6.0\win-x64\YaeAchievementLib.dll /y</Command>
<Command>copy $(TargetPath) $(ProjectDir)..\bin\Debug\net7.0-windows\win-x64\YaeAchievementLib.dll /y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>

View File

@@ -8,7 +8,8 @@ using std::to_string;
HWND unityWnd = 0;
HANDLE hPipe = 0;
std::set<UINT16> PacketWhitelist = { 105, 155, 187, 198, 2688, 20, 74 }; // Allow Protocol: GetPlayerToken, PlayerLogin, AchievementAllDataNotify, Ping
// Allow Protocol: GetPlayerToken, PlayerLogin, AchievementAllDataNotify, Ping
std::set<UINT16> PacketWhitelist = { 167, 175, 154, 164, 2698, 14, 34, 106 };
bool OnPacket(KcpPacket* pkt) {
if (pkt->data == nullptr) return true;
@@ -29,14 +30,15 @@ bool OnPacket(KcpPacket* pkt) {
return false;
}
printf("Passed cmdid: %d\n", ReadMapped<UINT16>(data->vector, 2));
if (ReadMapped<UINT16>(data->vector, 2) == 2688) {
if (ReadMapped<UINT16>(data->vector, 2) == 2698) {
auto headLength = ReadMapped<UINT16>(data->vector, 4);
auto dataLength = ReadMapped<UINT32>(data->vector, 6);
auto iStr = Genshin::ToBase64String(data, 10 + headLength, dataLength, nullptr);
auto cStr = ToString(iStr) + "\n";
WriteFile(hPipe, cStr.c_str(), cStr.length(), nullptr, nullptr);
CloseHandle(hPipe);
ExitProcess(0);
auto manager = Genshin::GetSingletonInstance(Genshin::GetSingletonManager(), il2cpp_string_new("GameManager"));
Genshin::ForceQuit(manager);
}
delete[] data;
return true;

View File

@@ -1 +1 @@
DO_API(0x02D2E840, 0x02D2C0A0, Il2CppString*, il2cpp_string_new, (const char* str));
DO_API(0x991b10, 0x99ad10, Il2CppString*, il2cpp_string_new, (const char* str));

View File

@@ -2,36 +2,30 @@ using namespace Genshin;
// DO_APP_FUNC(CN_OFFSET, OS_OFFSET, RETURN, FUNC_NAME, (ARGS...));
// N: System.Convert$ToBase64String
// L: mscorlib
DO_APP_FUNC(0x08F056A0, 0x08F1A0F0, Il2CppString*, ToBase64String, (ByteArray* value, int offset, int length, void* method));
DO_APP_FUNC(0x728c160, 0x71cc2e0, Il2CppString*, ToBase64String, (ByteArray* value, int offset, int length, void* method));
// N: MoleMole.MonoLoginMainPage.version$set
// L: Assembly-CSharp
DO_APP_FUNC(0X05265A70, 0x052704C0, void, SetVersion, (void* obj, Il2CppString* value, void* method));
DO_APP_FUNC(0x2e2c930, 0x2dc4b90, void, SetVersion, (void* obj, Il2CppString* value, void* method));
// N: UnityEngine.Application$RecordUserData
// L: UnityEngine.CoreModule
DO_APP_FUNC(0x09932F30, 0x09947590, ByteArray*, RecordUserData, (int32_t nType));
DO_APP_FUNC(0x7c318d0, 0x7b69060, ByteArray*, RecordUserData, (int32_t nType));
// N: MoleMole.Packet$XorEncrypt [Obfuscated]
// L: Assembly-CSharp
DO_APP_FUNC(0x054B3120, 0x054BD670, void, XorEncrypt, (ByteArray** data, int length, void* method)); // OHOBJBNAMJM
DO_APP_FUNC(0x1ba7d30, 0x1b7b9f0, void, XorEncrypt, (ByteArray** data, int length, void* method));
// N: Kcp.KcpNative$kcp_client_send_packet [Obfuscated]
// L: Assembly-CSharp
DO_APP_FUNC(0x050BB390, 0x050C5AC0, int, KcpSend, (void* client, KcpPacket* pkt, void* method)); // CKKPANHPFAP
DO_APP_FUNC(0xc3fe80, 0xc47280, int, KcpSend, (void* client, KcpPacket* pkt, void* method));
// N: MoleMole.KcpClient$TryDequeueEvent [Obfuscated]
// L: Assembly-CSharp
DO_APP_FUNC(0x04496B50, 0x0449DBF0, bool, KcpRecv, (void* client, ClientKcpEvent* evt, void* method)); // GFFOOBHMCOJ
DO_APP_FUNC(0xf1ec70, 0xf1bca0, bool, KcpRecv, (void* client, ClientKcpEvent* evt, void* method));
DO_APP_FUNC(0x09254010, 0x09269550, LPVOID, GetDefaultEncoding, ());
DO_APP_FUNC(0x75a6880, 0x74e4b80, LPVOID, GetDefaultEncoding, ());
DO_APP_FUNC(0x092538C0, 0x09268DE0, Il2CppString*, GetString, (LPVOID encoding, LPVOID bytes));
DO_APP_FUNC(0x75a6130, 0x74e4420, Il2CppString*, GetString, (LPVOID encoding, LPVOID bytes));
DO_APP_FUNC(0x09252750, 0x09267C60, ByteArray*, GetBytes, (LPVOID encoding, LPVOID str));
DO_APP_FUNC(0x75a4fc0, 0x74e32b0, ByteArray*, GetBytes, (LPVOID encoding, LPVOID str));
DO_APP_FUNC(0X05069690, 0X05073B60, VOID, RequestLogin, (LPVOID obj, LPVOID token, UINT uid));
DO_APP_FUNC(0x1bf31f0, 0x1bc5f60, VOID, RequestLogin, (LPVOID obj, LPVOID token, UINT uid));
DO_APP_FUNC(0x03C751A0, 0x0500F3D0, VOID, SetChecksum, (LPVOID obj, Il2CppString* value));
DO_APP_FUNC(0x4922d40, 0x4879590, VOID, SetChecksum, (LPVOID obj, Il2CppString* value));
DO_APP_FUNC(0x34780d0, 0x3401460, VOID, ForceQuit, (LPVOID obj));
DO_APP_FUNC(0x57df820, 0x5727410, LPVOID, GetSingletonManager, ());
DO_APP_FUNC(0x57df550, 0x5727140, LPVOID, GetSingletonInstance, (LPVOID obj, Il2CppString* value));

View File

@@ -1,3 +1,3 @@
using namespace Genshin;
DO_UNI_FUNC(0x00100550, 0x00100550, ByteArray*, UnityEngine_RecordUserData, (int32_t nType));
DO_UNI_FUNC(0x00100570, 0x00100570, ByteArray*, UnityEngine_RecordUserData, (int32_t nType));

View File

@@ -2,7 +2,6 @@
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.Graphics.Gdi;
//using YaeAchievement.Win32;
namespace YaeAchievement.AppCenterSDK;
@@ -26,7 +25,7 @@ public static class DeviceHelper {
public static string GetScreenSize() {
var desktop = Native.GetDC(HWND.Null);
var size = $"{Native.GetDeviceCaps(desktop, GET_DEVICE_CAPS_INDEX.DESKTOPHORZRES)}x{Native.GetDeviceCaps(desktop, GET_DEVICE_CAPS_INDEX.DESKTOPVERTRES)}";
Native.ReleaseDC(HWND.Null, desktop);
_ = Native.ReleaseDC(HWND.Null, desktop);
return size;
}

View File

@@ -1,10 +1,11 @@
using System.Diagnostics;
using System.ComponentModel;
using System.Diagnostics;
using System.Net;
using System.Runtime.Versioning;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Win32;
using YaeAchievement.AppCenterSDK;
using YaeAchievement.res;
using static AchievementAllDataNotify.Types.Achievement.Types;
@@ -213,4 +214,11 @@ public static class Export {
var b = Utils.GetBucketFileAsByteArray("schicksal/metadata");
return AchievementInfo.Parser.ParseFrom(b);
}
public static int PrintMsgAndReturnErrCode(this Win32Exception ex, string msg) {
// ReSharper disable once LocalizableElement
Console.WriteLine($"{msg}: {ex.Message}");
AppCenter.TrackCrash(ex, false);
return ex.NativeErrorCode;
}
}

View File

@@ -1,19 +1,17 @@
using Microsoft.Win32.SafeHandles;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.ComponentModel;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Memory;
using Windows.Win32.System.Threading;
using YaeAchievement.Win32;
namespace YaeAchievement;
public static class Injector {
public static unsafe bool CreateProcess(string path, out HANDLE hProc, out HANDLE hThread, out uint pid) {
Span<char> cmdLines = stackalloc char[1]; // "\0"
var si = new STARTUPINFOW() { cb = unchecked((uint)sizeof(STARTUPINFOW)) };
var si = new STARTUPINFOW {
cb = unchecked((uint)sizeof(STARTUPINFOW))
};
var dir = Path.GetDirectoryName(path)!;
var result = Native.CreateProcess(
path, ref cmdLines, default, default, false,
@@ -26,48 +24,34 @@ public static class Injector {
}
// todo: refactor
public static unsafe int LoadLibraryAndInject(HANDLE hProc, ReadOnlySpan<byte> libPath)
{
fixed (char* lpModelName = "kernel32.dll")
{
HINSTANCE hKernel = Native.GetModuleHandle(lpModelName);
if (hKernel.IsNull)
{
public static unsafe int LoadLibraryAndInject(HANDLE hProc, ReadOnlySpan<byte> libPath) {
fixed (char* lpModelName = "kernel32.dll") {
var hKernel = Native.GetModuleHandle(lpModelName);
if (hKernel.IsNull) {
return new Win32Exception().PrintMsgAndReturnErrCode("GetModuleHandle fail");
}
fixed(byte* lpProcName = "LoadLibraryA"u8)
{
fixed(byte* lpProcName = "LoadLibraryA"u8) {
var pLoadLibrary = Native.GetProcAddress(hKernel, (PCSTR)lpProcName);
if (pLoadLibrary.IsNull)
{
if (pLoadLibrary.IsNull) {
return new Win32Exception().PrintMsgAndReturnErrCode("GetProcAddress fail");
}
var pBase = Native.VirtualAllocEx(hProc, default, unchecked((uint)libPath.Length + 1), VIRTUAL_ALLOCATION_TYPE.MEM_RESERVE | VIRTUAL_ALLOCATION_TYPE.MEM_COMMIT, PAGE_PROTECTION_FLAGS.PAGE_READWRITE);
if ((nint)pBase == 0)
{
if ((nint)pBase == 0) {
return new Win32Exception().PrintMsgAndReturnErrCode("VirtualAllocEx fail");
}
fixed (void* lpBuffer = libPath)
{
if (!Native.WriteProcessMemory(hProc, pBase, lpBuffer, unchecked((uint)libPath.Length), default))
{
fixed (void* lpBuffer = libPath) {
if (!Native.WriteProcessMemory(hProc, pBase, lpBuffer, unchecked((uint)libPath.Length))) {
return new Win32Exception().PrintMsgAndReturnErrCode("WriteProcessMemory fail");
}
}
var lpStartAddress = pLoadLibrary.CreateDelegate<LPTHREAD_START_ROUTINE>();
var hThread = Native.CreateRemoteThread(hProc, default, 0, lpStartAddress, pBase, 0, default);
if (hThread.IsNull)
{
var hThread = Native.CreateRemoteThread(hProc, default, 0, lpStartAddress, pBase, 0);
if (hThread.IsNull) {
var e = new Win32Exception();
Native.VirtualFreeEx(hProc, pBase, 0, VIRTUAL_FREE_TYPE.MEM_RELEASE);
return e.PrintMsgAndReturnErrCode("CreateRemoteThread fail");
}
if (Native.WaitForSingleObject(hThread, 2000) == 0)
{
if (Native.WaitForSingleObject(hThread, 2000) == 0) {
Native.VirtualFreeEx(hProc, pBase, 0, VIRTUAL_FREE_TYPE.MEM_RELEASE);
}
return !Native.CloseHandle(hThread) ? new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail") : 0;

View File

@@ -23,10 +23,10 @@ public static partial class AchievementAllDataNotifyReflection {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"Ch5BY2hpZXZlbWVudEFsbERhdGFOb3RpZnkucHJvdG8iowIKGEFjaGlldmVt",
"ZW50QWxsRGF0YU5vdGlmeRIzCgRsaXN0GAQgAygLMiUuQWNoaWV2ZW1lbnRB",
"ZW50QWxsRGF0YU5vdGlmeRIzCgRsaXN0GA8gAygLMiUuQWNoaWV2ZW1lbnRB",
"bGxEYXRhTm90aWZ5LkFjaGlldmVtZW50GtEBCgtBY2hpZXZlbWVudBIRCgl0",
"aW1lc3RhbXAYBiABKA0SDwoHY3VycmVudBgKIAEoDRINCgV0b3RhbBgOIAEo",
"DRIKCgJpZBgNIAEoDRI8CgZzdGF0dXMYBSABKA4yLC5BY2hpZXZlbWVudEFs",
"aW1lc3RhbXAYDSABKA0SDwoHY3VycmVudBgCIAEoDRINCgV0b3RhbBgFIAEo",
"DRIKCgJpZBgJIAEoDRI8CgZzdGF0dXMYBiABKA4yLC5BY2hpZXZlbWVudEFs",
"bERhdGFOb3RpZnkuQWNoaWV2ZW1lbnQuU3RhdHVzIkUKBlN0YXR1cxILCgdJ",
"TlZBTElEEAASDgoKVU5GSU5JU0hFRBABEgwKCEZJTklTSEVEEAISEAoMUkVX",
"QVJEX1RBS0VOEANiBnByb3RvMw=="));
@@ -85,9 +85,9 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
}
/// <summary>Field number for the "list" field.</summary>
public const int ListFieldNumber = 4;
public const int ListFieldNumber = 15;
private static readonly pb::FieldCodec<global::AchievementAllDataNotify.Types.Achievement> _repeated_list_codec
= pb::FieldCodec.ForMessage(34, global::AchievementAllDataNotify.Types.Achievement.Parser);
= pb::FieldCodec.ForMessage(122, global::AchievementAllDataNotify.Types.Achievement.Parser);
private readonly pbc::RepeatedField<global::AchievementAllDataNotify.Types.Achievement> list_ = new pbc::RepeatedField<global::AchievementAllDataNotify.Types.Achievement>();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@@ -188,7 +188,7 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 34: {
case 122: {
list_.AddEntriesFrom(input, _repeated_list_codec);
break;
}
@@ -207,7 +207,7 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 34: {
case 122: {
list_.AddEntriesFrom(ref input, _repeated_list_codec);
break;
}
@@ -270,7 +270,7 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
}
/// <summary>Field number for the "timestamp" field.</summary>
public const int TimestampFieldNumber = 6;
public const int TimestampFieldNumber = 13;
private uint timestamp_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@@ -282,7 +282,7 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
}
/// <summary>Field number for the "current" field.</summary>
public const int CurrentFieldNumber = 10;
public const int CurrentFieldNumber = 2;
private uint current_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@@ -294,7 +294,7 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
}
/// <summary>Field number for the "total" field.</summary>
public const int TotalFieldNumber = 14;
public const int TotalFieldNumber = 5;
private uint total_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@@ -306,7 +306,7 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
}
/// <summary>Field number for the "id" field.</summary>
public const int IdFieldNumber = 13;
public const int IdFieldNumber = 9;
private uint id_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@@ -318,7 +318,7 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
}
/// <summary>Field number for the "status" field.</summary>
public const int StatusFieldNumber = 5;
public const int StatusFieldNumber = 6;
private global::AchievementAllDataNotify.Types.Achievement.Types.Status status_ = global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@@ -379,25 +379,25 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) {
output.WriteRawTag(40);
output.WriteEnum((int) Status);
}
if (Timestamp != 0) {
output.WriteRawTag(48);
output.WriteUInt32(Timestamp);
}
if (Current != 0) {
output.WriteRawTag(80);
output.WriteRawTag(16);
output.WriteUInt32(Current);
}
if (Total != 0) {
output.WriteRawTag(40);
output.WriteUInt32(Total);
}
if (Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) {
output.WriteRawTag(48);
output.WriteEnum((int) Status);
}
if (Id != 0) {
output.WriteRawTag(104);
output.WriteRawTag(72);
output.WriteUInt32(Id);
}
if (Total != 0) {
output.WriteRawTag(112);
output.WriteUInt32(Total);
if (Timestamp != 0) {
output.WriteRawTag(104);
output.WriteUInt32(Timestamp);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
@@ -409,25 +409,25 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) {
output.WriteRawTag(40);
output.WriteEnum((int) Status);
}
if (Timestamp != 0) {
output.WriteRawTag(48);
output.WriteUInt32(Timestamp);
}
if (Current != 0) {
output.WriteRawTag(80);
output.WriteRawTag(16);
output.WriteUInt32(Current);
}
if (Total != 0) {
output.WriteRawTag(40);
output.WriteUInt32(Total);
}
if (Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) {
output.WriteRawTag(48);
output.WriteEnum((int) Status);
}
if (Id != 0) {
output.WriteRawTag(104);
output.WriteRawTag(72);
output.WriteUInt32(Id);
}
if (Total != 0) {
output.WriteRawTag(112);
output.WriteUInt32(Total);
if (Timestamp != 0) {
output.WriteRawTag(104);
output.WriteUInt32(Timestamp);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
@@ -496,24 +496,24 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 40: {
Status = (global::AchievementAllDataNotify.Types.Achievement.Types.Status) input.ReadEnum();
break;
}
case 48: {
Timestamp = input.ReadUInt32();
break;
}
case 80: {
case 16: {
Current = input.ReadUInt32();
break;
}
case 104: {
case 40: {
Total = input.ReadUInt32();
break;
}
case 48: {
Status = (global::AchievementAllDataNotify.Types.Achievement.Types.Status) input.ReadEnum();
break;
}
case 72: {
Id = input.ReadUInt32();
break;
}
case 112: {
Total = input.ReadUInt32();
case 104: {
Timestamp = input.ReadUInt32();
break;
}
}
@@ -531,24 +531,24 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 40: {
Status = (global::AchievementAllDataNotify.Types.Achievement.Types.Status) input.ReadEnum();
break;
}
case 48: {
Timestamp = input.ReadUInt32();
break;
}
case 80: {
case 16: {
Current = input.ReadUInt32();
break;
}
case 104: {
case 40: {
Total = input.ReadUInt32();
break;
}
case 48: {
Status = (global::AchievementAllDataNotify.Types.Achievement.Types.Status) input.ReadEnum();
break;
}
case 72: {
Id = input.ReadUInt32();
break;
}
case 112: {
Total = input.ReadUInt32();
case 104: {
Timestamp = input.ReadUInt32();
break;
}
}

View File

@@ -12,7 +12,6 @@ using Windows.Win32.Foundation;
using Windows.Win32.System.Console;
using YaeAchievement.AppCenterSDK;
using YaeAchievement.res;
using YaeAchievement.Win32;
namespace YaeAchievement;

View File

@@ -1,14 +0,0 @@
using System.ComponentModel;
using YaeAchievement.AppCenterSDK;
namespace YaeAchievement.Win32;
public static class Extensions {
public static int PrintMsgAndReturnErrCode(this Win32Exception ex, string msg) {
Console.WriteLine($"{msg}: {ex.Message}");
AppCenter.TrackCrash(ex, false);
return ex.NativeErrorCode;
}
}