ChuckHearthstone / SilverFish

Hearthstone AI derived from https://github.com/noHero123/silverfish
53 stars 16 forks source link

Process must have frozen or gotten out of sync: Injection Finished Event was never fired #39

Closed chucklu closed 5 years ago

chucklu commented 5 years ago
// GreyMagic.Executor
// Token: 0x060001D9 RID: 473 RVA: 0x003761F0 File Offset: 0x0036B5F0
private void WaitForInjection(int timeout)
{
    if (!this._injectionFinishedEvent.WaitOne(timeout, false))
    {
        throw new InjectionDesyncException("Process must have frozen or gotten out of sync: Injection Finished Event was never fired");
    }
    if (this._initParams.Veh)
    {
        int num = this._mem.Read<int>(this._statusPtr);
        switch (num)
        {
        case 0:
            break;
        case 1:
            throw new InjectionException("Injection cannot proceed because there are no TLS slots available");
        case 2:
            throw new InjectionException("Injection cannot proceed because VEH couldn't be registered");
        case 3:
            throw new InjectionException("Injection cannot proceed because TlsSet failed");
        case 4:
            throw new InjectionSEHException(this._mem.Read<uint>(this._returnedDataPtr));
        default:
        {
            int num2 = num;
            throw new InjectionException("Injection resulted in invalid status 0x" + num2.ToString("X"));
        }
        }
    }
}
chucklu commented 5 years ago

WaitOne(Int32, Boolean) Blocks the current thread until the current WaitHandle receives a signal, using a 32-bit signed integer to specify the time interval and specifying whether to exit the synchronization domain before the wait.

Parameters millisecondsTimeout Int32 The number of milliseconds to wait, or Infinite (-1) to wait indefinitely.

exitContext Boolean true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it afterward; otherwise, false.

Returns Boolean true if the current instance receives a signal; otherwise, false.

chucklu commented 5 years ago
this._injectionFinishedEvent = new EventWaitHandle(false, EventResetMode.AutoReset, text3, ref flag, eventWaitHandleSecurity);

    private void SharedExecuteLogicEnd(int timeout)
        {
            this._injectionFinishedEvent.Reset();
            this._injectionWaitingEvent.Set();
            if (!this._firstExecution)
            {
                this._injectionContinueEvent.Set();
            }
            else
            {
                this._firstExecution = false;
            }
            try
            {
                this.WaitForInjection(timeout);
            }
            catch (InjectionDesyncException)
            {
                this._injectionWaitingEvent.Reset();
                throw;
            }
            this._mem.WriteBytesForced(this._injectedCode, this._clearBytes);
        }
chucklu commented 5 years ago

WaitHandle.Close Method Releases all resources held by the current WaitHandle.

Remarks This method is the public implementation of the IDisposable.Dispose method for the WaitHandle class and its derived classes. It provides a standard implementation that calls the Dispose(Boolean) overload with a true argument and then calls the GC.SuppressFinalize method. Call this method to release all resources held by an instance of WaitHandle or a derived class.

Once this method is called, references to the current instance cause undefined behavior.

chucklu commented 5 years ago
// ns27.Class276
// Token: 0x04000D49 RID: 3401
private readonly Dictionary<Type, IntPtr> dictionary_0 = new Dictionary<Type, IntPtr>();
// Token: 0x06001A74 RID: 6772 RVA: 0x000DD378 File Offset: 0x000DB578
internal Class276(ExternalProcessMemory memory)
{
    this.externalProcessMemory_0 = memory;
    this.intptr_0 = this.method_18("mono.dll");
    this.intptr_31 = this.intptr_0 + 522030;
    this.intptr_28 = this.intptr_0 + 91559;
    this.intptr_13 = this.intptr_0 + 226176;
    this.intptr_16 = this.intptr_0 + 91615;
    this.intptr_6 = this.intptr_0 + 78677;
    this.intptr_1 = this.intptr_0 + 102855;
    this.intptr_15 = this.intptr_0 + 230512;
    this.intptr_14 = this.intptr_0 + 224970;
    this.intptr_7 = this.intptr_0 + 73617;
    this.intptr_19 = this.intptr_0 + 120353;
    this.intptr_29 = this.intptr_0 + 162866;
    this.intptr_17 = this.intptr_0 + 525190;
    this.intptr_25 = this.intptr_0 + 389455;
    this.intptr_24 = this.intptr_0 + 385464;
    this.intptr_32 = this.intptr_0 + 389677;
    this.intptr_34 = this.intptr_0 + 384279;
    this.intptr_36 = this.intptr_0 + 382675;
    this.intptr_35 = this.intptr_0 + 91327;
    this.intptr_23 = this.intptr_0 + 428289;
    this.intptr_33 = this.intptr_0 + 378912;
    this.intptr_27 = this.intptr_0 + 515937;
    this.intptr_12 = this.intptr_0 + 176417;
    this.intptr_10 = this.intptr_0 + 176976;
    this.intptr_4 = this.intptr_0 + 77237;
    this.intptr_8 = this.intptr_0 + 107261;
    this.intptr_21 = this.intptr_0 + 231261;
    this.intptr_18 = this.intptr_0 + 522401;
    this.intptr_5 = this.intptr_0 + 733279;
    this.intptr_30 = this.intptr_0 + 91701;
    this.intptr_2 = this.intptr_0 + 733427;
    this.intptr_9 = this.intptr_0 + 162872;
    this.intptr_3 = this.intptr_0 + 91604;
    this.intptr_26 = this.intptr_0 + 383139;
    this.intptr_22 = this.intptr_0 + 385556;
    this.intptr_20 = this.intptr_0 + 91570;
    this.intptr_11 = this.intptr_0 + 401933;
    this.method_15<bool>("boolean");
    this.method_15<object>("object");
    this.method_15<sbyte>("sbyte");
    this.method_15<byte>("byte");
    this.method_15<short>("int16");
    this.method_15<ushort>("uint16");
    this.method_15<int>("int32");
    this.method_15<uint>("uint32");
    this.method_15<long>("int64");
    this.method_15<ulong>("uint64");
    this.method_15<float>("single");
    this.method_15<double>("double");
    this.method_15<char>("char");
    this.method_15<string>("string");
    this.method_15<Enum>("enum");
}
chucklu commented 5 years ago

Faulting application name: Hearthstone.exe, version: 15.4.0.34670, time stamp: 0x5cc8c3bc Faulting module name: mono.dll, version: 1.0.0.1, time stamp: 0x5c8516c9 Exception code: 0xc0000005 Fault offset: 0x00027c32 Faulting process id: 0x4b7c Faulting application start time: 0x01d57ea2aa96a066 Faulting application path: C:\Program Files (x86)\Hearthstone\Hearthstone.exe Faulting module path: C:\Program Files (x86)\Hearthstone\Mono\EmbedRuntime\mono.dll Report Id: f0fc0d51-28b7-4dcb-9abf-de656ddb6ba1 Faulting package full name: Faulting package-relative application ID:

chucklu commented 5 years ago
// Triton.Game.Mapping.CollectionDeckBoxVisual
// Token: 0x06003D7C RID: 15740 RVA: 0x00033AB5 File Offset: 0x00031CB5
public bool IsValidForCurrentMode()
{
    return base.method_11<bool>("IsValidForCurrentMode", Array.Empty<object>());
}
chucklu commented 5 years ago

GreyMagic.InjectionDesyncException: Process must have frozen or gotten out of sync: Injection Finished Event was never fired at GreyMagic.Executor.WaitForInjection(Int32 timeout) at GreyMagic.Executor.SharedExecuteLogicEnd(Int32 timeout) at GreyMagic.Executor.Execute(Int32 timeout) at GreyMagic.ExternalProcessMemory.CallInjected[T](IntPtr address, CallingConvention callingConvention, Object[] args) at HearthstoneBot.Class276.method_17[T](IntPtr intptr_37, Object[] object_0) in C:\repository\GitHub\ChuckLu\Test\HearthstoneBot\HearthstoneBot\Class276.cs:line 209 at HearthstoneBot.Class276.method_4() in C:\repository\GitHub\ChuckLu\Test\HearthstoneBot\HearthstoneBot\Class276.cs:line 233 at HearthstoneBot.Class276.method_2() in C:\repository\GitHub\ChuckLu\Test\HearthstoneBot\HearthstoneBot\Class276.cs:line 227 at HearthstoneBot.Game.TritonHs.smethod_0(Process process_0, Delegate6 delegate6_0, String& string_0) in C:\repository\GitHub\ChuckLu\Test\HearthstoneBot\HearthstoneBot\Game\TritonHs.cs:line 138

chucklu commented 5 years ago
this.intptr_29 = this.intptr_0 + 162866;

using (AcquireFrame())
                {
                    intptr_1 = class276_0.method_2();
                }
internal IntPtr method_2()
        {
            var ptr = method_4();
            return method_17<IntPtr>(intptr_31, ptr);
        }

internal IntPtr method_4()
        {
            return method_17<IntPtr>(intptr_29, Array.Empty<object>());
        }

internal T method_17<T>(IntPtr intptr_37, params object[] object_0) where T : struct
        {
            return externalProcessMemory_0.CallInjected<T>(intptr_37, CallingConvention.Cdecl, object_0);
        }
chucklu commented 5 years ago

CallingConvention Cdecl The caller cleans the stack. This enables calling functions with varargs, which makes it appropriate to use for methods that accept a variable number of parameters, such as Printf.

chucklu commented 5 years ago

intptr_37 0x100284DC System.IntPtr

image image

chucklu commented 5 years ago

image

chucklu commented 5 years ago

method2 this.intptr_31 = this.intptr_0 + 522030;

    internal IntPtr method_2()
        {
            return this.method_17<IntPtr>(this.intptr_31, new object[]
            {
                this.method_4()
            });
        }
chucklu commented 5 years ago

ChuckLu 2019-10-11 00:48:43.988+08:00 - [OnStartup] A top-level exception has been caught. GreyMagic.InjectionDesyncException: Process must have frozen or gotten out of sync: Injection Finished Event was never fired at GreyMagic.Executor.WaitForInjection(Int32 timeout) at GreyMagic.Executor.SharedExecuteLogicEnd(Int32 timeout) at GreyMagic.Executor.Execute(Int32 timeout) at GreyMagic.Executor.Execute() at GreyMagic.ExternalProcessMemory.CallInjected[T](IntPtr address, CallingConvention callingConvention, Object[] args) at ns27.Class276.method_17[T](IntPtr intptr_37, Object[] object_0) at ns27.Class276.method_29() at ns27.Class276.method_20(String string_0, Dictionary`2& dictionary_1) at Triton.Game.Mono.MonoClass.smethod_1() at Triton.Game.Mono.MonoClass.get_Dictionary_1() at Triton.Game.Mono.MonoClass.smethod_3(String string_4, String string_5, String string_6) at Triton.Game.Mono.MonoClass.smethod_5(String string_4, String string_5, String string_6, String string_7) at Triton.Game.Mono.MonoClass.smethod_9(String string_4, String string_5, String string_6, String string_7) at Triton.Game.Mono.MonoClass.smethod_6[T](String string_4, String string_5, String string_6, String string_7) at Triton.Game.Mapping.Version.get_version() at Hearthbuddy.Windows.MainWindow.method_21(Object object_0)

public static string MainAssemblyPath
        {
            get
            {
                return Path.Combine(TritonHs.MainAssemblyDir, "Assembly-CSharp.dll");
            }
        }
public static int version
        {
            get
            {
                return MonoClass.smethod_6<int>(TritonHs.MainAssemblyPath, "", "Version", "version");
            }
        }

// Triton.Game.Mono.MonoClass
// Token: 0x060019BB RID: 6587 RVA: 0x000DC0CC File Offset: 0x000DA2CC
private static void smethod_1()
{
    if (MonoClass.dictionary_1 == null)
    {
        MonoClass.dictionary_1 = new Dictionary<string, IntPtr>();
    }
    else
    {
        MonoClass.dictionary_1.Clear();
    }
    if (MonoClass.dictionary_2 == null)
    {
        MonoClass.dictionary_2 = new Dictionary<string, IntPtr>();
    }
    else
    {
        MonoClass.dictionary_2.Clear();
    }
    foreach (KeyValuePair<string, IntPtr> keyValuePair in TritonHs.Class276_0.method_20(TritonHs.UnityEngineAssemblyPath, ref MonoClass.dictionary_1))
    {
        MonoClass.dictionary_2.Add(keyValuePair.Key, keyValuePair.Value);
    }
    foreach (KeyValuePair<string, IntPtr> keyValuePair2 in TritonHs.Class276_0.method_20(TritonHs.MainAssemblyPath, ref MonoClass.dictionary_1))
    {
        MonoClass.dictionary_2.Add(keyValuePair2.Key, keyValuePair2.Value);
    }
}
internal IntPtr method_29()
        {
//this.intptr_33 = this.intptr_0 + 378912;
            return this.method_17<IntPtr>(this.intptr_33, Array.Empty<object>());
        }
chucklu commented 5 years ago

https://tieba.baidu.com/p/5940704799?red_tag=3359096564 https://gslab.qq.com/portal.php?mod=view&aid=241 四、 在加载dll的函数位置dump原来的dll代码,可绕过dll加密,修改源代码

(1) hook住mono_image_open_from_data_full函数,dump出dll可以,用IDA配合jdb挂起进程在那函数位置下断点dump也可以,源代码具体修改方案同“二”和“三”

四、 Ilasm和ildasm

Ildasm可以反编译dll,dump出反编译后的il码,而Ilasm则可以重打包il码,利用命令ilasm /dll *.il 即可。

chucklu commented 5 years ago

https://gslab.qq.com/portal.php?mod=view&aid=182 PE文件,不论是游戏还是外挂都是PE文件,无论是开发还是逆向PE文件格式都是核心基础知识。推荐读者阅读《加密解密(第三版)》第10章PE文件格式,此书对PE文件中的输入表、重定位等都有详细介绍,方便后续对PE文件加壳和脱壳的学习;而且用一个完整的PE文件分析工具作为实例,相信对读者PE文件的认识和Windows开发能力都会有提高。

注入,一般情况,外挂展现功能的第一步就是需要将自身完美注入到游戏进程中。注入的方式有很多,如:消息钩子、注册表、dll劫持、远程线程、APC等等,后续文章会进行详细介绍。这里推荐读者阅读《Windows核心编程》第19~22章,了解DLL注入的详细原理。

动态调试,首先得熟练使用Olldbg和Windbg两个调试工具。对于Olldbg,首先推荐读者阅读《加密解密(第三版)》第2章,了解Olldbg的基本使用方法

静态分析,首先得熟练使用IDA静态分析工具。IDA相对与Olldbg操作复杂一些,推荐读者阅读《IDA权威指南》第4~9章,了解使用IDA的基本操作和IDA的特性。在使用IDA分析游戏时,可能需要很多重复性操作,阅读《IDA权威指南》第15章掌握基于IDA的脚本编写是个不错的选择。

chucklu commented 5 years ago

Faulting application name: Hearthstone.exe, version: 15.4.0.34670, time stamp: 0x5cc8c3bc Faulting module name: mono.dll, version: 1.0.0.1, time stamp: 0x5c8516c9 Exception code: 0xc0000005 Fault offset: 0x00027c32 Faulting process id: 0x4b7c Faulting application start time: 0x01d57ea2aa96a066 Faulting application path: C:\Program Files (x86)\Hearthstone\Hearthstone.exe Faulting module path: C:\Program Files (x86)\Hearthstone\Mono\EmbedRuntime\mono.dll Report Id: f0fc0d51-28b7-4dcb-9abf-de656ddb6ba1 Faulting package full name: Faulting package-relative application ID:

Faulting application name: Hearthstone.exe, version: 15.4.0.34670, time stamp: 0x5cc8c3bc Faulting module name: UnityPlayer.dll, version: 2018.4.0.65448, time stamp: 0x5cc8c3f9 Exception code: 0xc0000005 Fault offset: 0x00402eb1 Faulting process id: 0x3d6c Faulting application start time: 0x01d580c1fc5c5726 Faulting application path: C:\Program Files (x86)\Hearthstone\Hearthstone.exe Faulting module path: C:\Program Files (x86)\Hearthstone\UnityPlayer.dll Report Id: 82f37942-cbb9-4aa9-ac19-a6a688cbd975 Faulting package full name: Faulting package-relative application ID:

chucklu commented 5 years ago

fix this by https://github.com/ChuckHearthstone/SilverFish/blob/master/MonoTest/mono-address.txt