Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


DnSpy integration would be amazing...

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
jgoemat
Master Cheater
Reputation: 23

Joined: 25 Sep 2011
Posts: 264

PostPosted: Tue Jan 26, 2021 11:21 pm    Post subject: DnSpy integration would be amazing... Reply with quote

I've just started using ILSpy and dnSpy and they're pretty cool. Editing C# methods with dnSpy and saving an updated 'Assembly-CSharp.dll' works so well, but then any update or reinstall means the changes have to be done all over again. I thought about something that could call the MonoDataCollector and have it load an assembly with updated or new types, or JIT some IL code for a new method. Is there any way to do that? Are there other ways? Trying different things I created a separate solution, referenced the game classes, and tried to create a new method, but the code referenced private and protected fields and a nested enum, so I had to copy the whole class. If I could load that assembly and in ASM, hook the game method, and just jump to the code for my method if the cheat is enabled, would that work? It would be nice to have a method in MonoDataCollector to load a managed assembly. It wouldn't be too hard then to do that.

What about compiling IL in MonoDataCollector? I'm fairly new to this, but check out this method (handling dropping one item from a stack):

Code:

.method family hidebysig virtual
   instance void HandleDropOne () cil managed
{
   // Method begins at RVA 0x21d530
   // Code size 157 (0x9d)
   .maxstack 3
   .locals init (
      [0] class ItemStack,
      [1] int32,
      [2] class ItemStack
   )

   // ItemStack currentStack = base.xui.dragAndDrop.CurrentStack;
   IL_0000: ldarg.0
   IL_0001: call instance class XUi XUiController::get_xui()
   IL_0006: callvirt instance class XUiC_DragAndDropWindow XUi::get_dragAndDrop()
   IL_000b: callvirt instance class ItemStack XUiC_DragAndDropWindow::get_CurrentStack()
   IL_0010: stloc.0
   // if (currentStack.IsEmpty())
   IL_0011: ldloc.0
   IL_0012: callvirt instance bool ItemStack::IsEmpty()
   IL_0017: brtrue IL_009c

   // int num = 1;
   IL_001c: ldc.i4.1
   IL_001d: stloc.1
...



My thoughts were something like this...

1. Use dnSpy to create a new method on the class that is a 'cheat' version of the existing, or just a method I can call in ASM to do some cheat
2. Grab the IL for my new method
3. Put the IL into my cheat table and call the MonoDataCollector to JIT the IL into the game

I don't know if that's even possible. The actual bytes from the IL have the method signatures as values created at compile time I think, like IL_0001 is 5 bytes, the opcode and an identifier for the method that could change between versions, so just grabbing bytes wouldn't work.

I wrote some code for work a long time ago to parse binary data with xml definitions for the data types. It generated IL code based on the definitions for the data types and was about 10x as fast as doing it manually. It used It looks like mono has the same functionality with DynamicMethod and System.Reflection to generate code at runtime (though those would have to be loaded into the game as well). It seems like that can be made to access private variables on classes...

I don't have enough time to really dig into it and don't want to waste time going down the wrong path. Maybe there's an easier way? dnSpy is open source, it shouldn't be too difficult to create 'patch' files that could be applied to the game assembly using the command line so it would be easy to update newer versions with new or modified methods. I wouldn't want to use much of the game's code though. It seems like the cleanest way would be to just create new methods and do hooking using cheat engine to call the new version based on activation of a cheat.

Sorry for the rambling, I just didn't want to put too much work into something if there was already a way to do some of this stuff. Just being able to write my own assembly and load it using MonoDataCollector would be cool.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25796
Location: The netherlands

PostPosted: Wed Jan 27, 2021 11:46 am    Post subject: Reply with quote

perhaps someday
it depends on how mono deals with an unexpected pointerswap for native code back to IL


tip: Look into mono_loadAssemblyFromFile and https://github.com/pardeike/Harmony

edit:
I guess I could always use a c# dll that I control with CE, make it build a method and then compile the original method, and replace it with a jmp to the new method delegate

edit2: You're going to like what i'm adding to CE

e.g kindergarten 2:
Code:

LaunchMonoDataCollector()

if dotnetdetours==nil then
  dotnetdetours={}
else
  local di=dotnetdetours['Interactable.Interact']
  if di and di.processid==getOpenedProcessID() then
    --already detoured. Undo first
    local r,err=autoAssemble(di.disablescript, di.disableinfo)

    if not r then
      error(err)
    else
      dotnetdetours['Interactable.Interact']=nil
    end
  end
end
local detourinfo={}

local csharpscript=[[
using System.Runtime.CompilerServices; //for NoInlining
//feel free to add more


public class patchedInteractable : Interactable
{

  public void newInteract()
  {
    //you have access to public fields.  Use reflection if you wish to access private fields
    oldInteract();
    if (this.player)
    {
      this.player.Explode();
    }

    return;
  }

  [MethodImpl(MethodImplOptions.NoInlining)]
  public void oldInteract()
  {
    //don't bother putting code in here. It will get replaced (just some stuff to make sure there's space)
    return ;
  }
}

]]
local references, sysfile=dotnetpatch_getAllReferences() --you're free to build your own list
local csfile,msg=compileCS(csharpscript, references, sysfile)

if csfile==nil then
  if msg==nil then msg=' (?Unknown error?)' end
  messageDialog('Compilation error:'..msg, mtError) --show compile error in a dialog instead of a lua error only
  error(msg)
end

--still here, c# dll created, now inject and hook
local result, disableinfo, disablescript=InjectDotNetDetour(csfile, "Interactable::Interact","patchedInteractable::newInteract","patchedInteractable::oldInteract")

if result then
  detourinfo.disableinfo=di
  detourinfo.disablescript=disablescript
  detourinfo.processid=getOpenedProcessID()
  dotnetdetours['Interactable.Interact']=detourinfo
else
  if disableinfo==nil then disableinfo='no reason' end
  error('InjectDotNetDetour failed : '..disableinfo) --prevents checking
end

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
MMM-304
Expert Cheater
Reputation: 0

Joined: 17 Aug 2020
Posts: 170
Location: Milkey Way

PostPosted: Mon Oct 04, 2021 11:38 am    Post subject: Reply with quote

Q1: how do i eject the code and free memory in disable section when using InjectDotNetDetour to inject the CSCompiled code?

Q2: sorry i do not understand? how do I get access to private fields of parent class from inherited class?
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25796
Location: The netherlands

PostPosted: Mon Oct 04, 2021 1:17 pm    Post subject: Reply with quote

1: replace it with a version that does nothing. It just calls the old function and nothing else

2: use the reflection library.

'this' is the class to inspect

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
MMM-304
Expert Cheater
Reputation: 0

Joined: 17 Aug 2020
Posts: 170
Location: Milkey Way

PostPosted: Tue Oct 05, 2021 1:34 am    Post subject: Reply with quote

1. what I meant by ejecting is removing the images too when the script is disabled. I am using autoAssemble in disable section. It does restore the code but it does not dealloc the compiled CS code (free memory) as expected, neither does it remove the assembly image from the list:

every time I (re)enable the same script, it creates a new image but does not destroy the old one.

2. I tried it:


but it gives an error:


Also it using netstandard as sys in CompileCS does not work so i left it nil. dotnetpatch_getAllReferences could not find mscorlib even though it is in game's directory.
Another question how do I create my own reference that can have both netstandard and mscorlib?
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25796
Location: The netherlands

PostPosted: Tue Oct 05, 2021 2:24 am    Post subject: Reply with quote

1: Check https://docs.microsoft.com/en-us/dotnet/standard/assembly/load-unload
Basically, it's not that easy as you'll have to unload the whole appdomain, and with multiple threads that can be quite a hassle

Best is to compile once, or use unique/randomized patch classnames
or I guess I could adjust InjectDotNetDetour to get the patched module just from the assembly it just injected instead of relying on the default symbol handler

2:
with reflection I mean something like:
Code:

using System.Reflection;
...
            Type thistype = this.GetType();
            FieldInfo f = thistype.GetField("stats", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

            if (f != null)
            {
                NeedsStat[] stats= (NeedsStat[])f.GetValue(this);               
                //and now you can access stats.  If you need to access private fields of stats, do something similar

            }


dotnetpatch_getAllReferences returns 2 results. the references list and the main sys file

i'm not sure a cs-library can have both netstandard and mscordlib. I think it has to be either one of them

but you can of course add custom references to the references list

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
MMM-304
Expert Cheater
Reputation: 0

Joined: 17 Aug 2020
Posts: 170
Location: Milkey Way

PostPosted: Wed Oct 06, 2021 12:02 am    Post subject: Reply with quote

ah thanks, I will try it next time I open the game.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites