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 


[Help] Two questions regarding Mono Features (CE 7.1)

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
ApacheTech
Newbie cheater
Reputation: 0

Joined: 26 Jun 2020
Posts: 14

PostPosted: Fri Jun 26, 2020 12:02 pm    Post subject: [Help] Two questions regarding Mono Features (CE 7.1) Reply with quote

First of all, is is possible to programmatically disable Mono Features? I can use

Code:
LaunchMonoDataCollector();


to Enable them, but I'd like to Disable them programmatically as well. The reason for this is because the game I am programming against hangs on Exit, if the library is still injected.

My second question is a bit more specific. I'm trying to invoke a method that has a parameter for a System.Action callback. In dnSpy, I can see that this method is almost always called with "null" as the callback, but I seem to be unable to send "null", "nil", "0", or any other form of nullified value to the method via CE because it expects a Type of System.Action.

This is the method signature from dnSpy:

Code:

public void SetNotification(string text, Action callback = null)
{
    // Do stuff.
}


No matter what I try, I receive this error in return:

Quote:
Error:C:\Program Files\Cheat Engine 7.1\autorun\monoscript.lua:1683: attempt to index a nil value (global 'monopipe')


How do you pass a null value to an invoked method?
Back to top
View user's profile Send private message
blankTM
Cheater
Reputation: 0

Joined: 03 May 2020
Posts: 49

PostPosted: Fri Jun 26, 2020 12:23 pm    Post subject: Re: [Help] Two questions regarding Mono Features (CE 7.1) Reply with quote

Close mono:
Code:

monopipe.OnTimeout()

No need to pass in the second parameter
Back to top
View user's profile Send private message
ApacheTech
Newbie cheater
Reputation: 0

Joined: 26 Jun 2020
Posts: 14

PostPosted: Fri Jun 26, 2020 2:57 pm    Post subject: Reply with quote

Thank you for that. I've added:

Code:

[DISABLE]
{$lua}

    -- Clean the registered symbols.
    for k, v in pairs(aPointerList) do
        unregisterSymbol(k);
    end

    -- Close Mono Features.
    if (monopipe) then
       monopipe.OnTimeout();
    end

{$asm}


to the script and it works fine.

As for the second part, I've added an overload for the method, for testing, and recompiled the library.

Code:

   public void SetNotification(string text)
   {
      this.SetNotification(text, null);
   }


Using this, I'm at least able to get some feedback. For some reason now, when I try to invoke this, even via the GUI, I get this error:

Quote:
parameter 1: "Hello World" is not a valid value


Even though the value type is "string".

To do this programmatically, I've adapted the "my_mono_invoke_method" example from the wiki:

Code:

--- </summary>
    ---     Wrapper to safely invoke mono methods within Cheat Engine.
    --- </summary>
    function InvokeMethod(domain, method, args, instanceAddress)
      local c=mono_method_getClass(method);
      local instance;
      if (instanceAddress == nil) then
        instance = mono_class_findInstancesOfClassListOnly(domain,c);
        instance = instance[1];
      else
        instance = instanceAddress;
      end

      local params = mono_method_get_parameters(method)
      if #args ~= #params.parameters then
        print('ERROR:InvokeMethod : wrong length of args');
        return
      end

      local i;
      local args_t={};
      for i=1, #params.parameters do
        args_t[i] = {};
        args_t[i].type = monoTypeToVartypeLookup[params.parameters[i].type];
       args_t[i].value = args[i];
      end

      if method==nil or method==0 then
        print('ERROR:InvokeMethod : method==0');
       return;
      end

      if instance==nil or instance==0 then
        print('ERROR:InvokeMethod : instance==0');
       return;
      end

      local r=mono_invoke_method(domain, method, instance, args_t);
      return r;
    end


I'm using this within a script:

Code:

{$lua}

    --NB: SingletonPrefab<Backbone>.instance.gameUI.notificationBox.SetNotification(SS.Get("expandFillInDisabled"), null);

    function Test()
        local methodId = mono_findMethod('', 'NotificationBox', 'SetNotification');
        local instanceId = getAddress('[[[["mono.dll"+00265110]+BD0]+60]+E8]+0');
        print(string.format("Method ID: %X", methodId));
        print(string.format("Instance ID: %X", instanceId));
        InvokeMethod('', methodId, {"Hello World!"}, instanceId);
    end

{$asm}
[ENABLE]
{$lua}
    Test();
    memrec.OnActivate = function(memrec, preState, curState)
      if (not preState) and curState then
        local t = createTimer()
        t.Interval = 100;
        t.OnTimer = function(t)
          t.destroy();
          memrec.Active = enabled;
        end
      end
      return true;
    end
{$asm}
[DISABLE]
{$lua}

{$asm}

// EOF



But, I always get back the error:

Quote:

Error:C:\Program Files\Cheat Engine 7.1\autorun\monoscript.lua:1683: attempt to index a nil value (global 'monopipe')


and it shuts the pipe down.
Back to top
View user's profile Send private message
blankTM
Cheater
Reputation: 0

Joined: 03 May 2020
Posts: 49

PostPosted: Fri Jun 26, 2020 5:16 pm    Post subject: Reply with quote

This method returns an instance array
There may be multiple instances of this class
Code:

instance = mono_class_findInstancesOfClassListOnly(domain,c)


For specific tests, you need to right-click the method and select the options in the figure



20200627071836.png
 Description:
 Filesize:  40.99 KB
 Viewed:  4888 Time(s)

20200627071836.png


Back to top
View user's profile Send private message
ApacheTech
Newbie cheater
Reputation: 0

Joined: 26 Jun 2020
Posts: 14

PostPosted: Fri Jun 26, 2020 5:28 pm    Post subject: Reply with quote

I have the correct instance. Invoking other methods within that instance works fine. I've tested methods that take Boolean, and Integer parameters, as well as methods with no parameters. It's only Strings and complex types that I have difficulties with.


CheatEngine.PNG
 Description:
 Filesize:  17.13 KB
 Viewed:  4886 Time(s)

CheatEngine.PNG


Back to top
View user's profile Send private message
blankTM
Cheater
Reputation: 0

Joined: 03 May 2020
Posts: 49

PostPosted: Fri Jun 26, 2020 6:36 pm    Post subject: Reply with quote

You can try to get an instance of type System.Action and pass the instance pointer to the second parameter

Specifically, you can also use DNSpy analysis or CE breakpoint debugging to obtain the System.Action pointer
Back to top
View user's profile Send private message
ApacheTech
Newbie cheater
Reputation: 0

Joined: 26 Jun 2020
Posts: 14

PostPosted: Fri Jun 26, 2020 9:31 pm    Post subject: Reply with quote

blankTM wrote:
You can try to get an instance of type System.Action and pass the instance pointer to the second parameter

Specifically, you can also use DNSpy analysis or CE breakpoint debugging to obtain the System.Action pointer


That would be ok if I wanted a callback. I could create a new Action, and redirect to it. But, I specifically want to send NULL as a parameter, which should be a valid input.
Back to top
View user's profile Send private message
blankTM
Cheater
Reputation: 0

Joined: 03 May 2020
Posts: 49

PostPosted: Fri Jun 26, 2020 10:33 pm    Post subject: Reply with quote

Error location mono_method_get_parameters method error

Can you successfully call it after decompiling with dnspy
Back to top
View user's profile Send private message
ApacheTech
Newbie cheater
Reputation: 0

Joined: 26 Jun 2020
Posts: 14

PostPosted: Sat Jun 27, 2020 7:07 pm    Post subject: Reply with quote

I've changed out "mono_method_get_parameters " for "mono_method_getSignature".

My invocation functions now read:

Code:

--- <summary>
---     Returns a string array that contains the substrings in the
---     specified input string, delimited by elements of a specified
----    string, with an optional limit to the number of results.
--- </summary>
string.split = function(str, del, limit)
  local t = {};
  local fpat = "(.-)" .. del;
  local last_end = 1;
  local s, e, cap = str:find(fpat, 1);
  while s do
    if s ~= 1 or cap ~= "" then
      table.insert(t, cap);
    end

    last_end = e+1;
    s, e, cap = str:find(fpat, last_end);

    if limit ~= nil and limit <= #t then
      break;
    end
  end

  if last_end <= #str then
    cap = str:sub(last_end);
    table.insert(t, cap);
  end

  return t;
end

--- <summary>
---     Wrapper to safely invoke Mono methods within Cheat Engine.
--- </summary>
function InvokeMethod(domain, method, args, instanceAddress)
  local c=mono_method_getClass(method);
  local instance;
  if (instanceAddress == nil) then
    instance = mono_class_findInstancesOfClassListOnly(domain,c);
    instance = instance[1];
  else
    instance = instanceAddress;
  end

  local params = string.split(mono_method_getSignature(method),',');
  if #args ~= #params then
    print('ERROR:InvokeMethod : Invalid Parameter Signature.');
    print(string.format('ERROR:InvokeMethod : Expected: %d', #params));
    print(string.format('ERROR:InvokeMethod : Actual: %d', #args));
    return
  end

  local i;
  local args_t={};
  for i=1, #params do
    args_t[i] = {};
    args_t[i].type = monoTypeToVartypeLookup[params[i].type];
   args_t[i].value = args[i];
  end

  if method==nil or method==0 then
    print('ERROR:InvokeMethod : method==0');
   return;
  end

  if instance==nil or instance==0 then
    print('ERROR:InvokeMethod : instance==0');
   return;
  end

  local r=mono_invoke_method(domain, method, instance, args_t);
  return r;
end


This still doesn't allow me to pass NULL as a parameter. I've tested passing random valid Action instances, and it CTDs both the application, and Cheat Engine, every time. I need to pass NULL to the application as a parameter.

I can't even see an option for a NULL parameter within monoscript.lua.

Code:

MONO_TYPE_END        = 0x00       -- End of List
MONO_TYPE_VOID       = 0x01
MONO_TYPE_BOOLEAN    = 0x02
MONO_TYPE_CHAR       = 0x03
MONO_TYPE_I1         = 0x04
MONO_TYPE_U1         = 0x05
MONO_TYPE_I2         = 0x06
MONO_TYPE_U2         = 0x07
MONO_TYPE_I4         = 0x08
MONO_TYPE_U4         = 0x09
MONO_TYPE_I8         = 0x0a
MONO_TYPE_U8         = 0x0b
MONO_TYPE_R4         = 0x0c
MONO_TYPE_R8         = 0x0d
MONO_TYPE_STRING     = 0x0e
MONO_TYPE_PTR        = 0x0f       -- arg: <type> token
MONO_TYPE_BYREF      = 0x10       -- arg: <type> token
MONO_TYPE_VALUETYPE  = 0x11       -- arg: <type> token
MONO_TYPE_CLASS      = 0x12       -- arg: <type> token
MONO_TYPE_VAR         = 0x13          -- number
MONO_TYPE_ARRAY      = 0x14       -- type, rank, boundsCount, bound1, loCount, lo1
MONO_TYPE_GENERICINST= 0x15          -- <type> <type-arg-count> <type-1> \x{2026} <type-n> */
MONO_TYPE_TYPEDBYREF = 0x16
MONO_TYPE_I          = 0x18
MONO_TYPE_U          = 0x19
MONO_TYPE_FNPTR      = 0x1b          -- arg: full method signature */
MONO_TYPE_OBJECT     = 0x1c
MONO_TYPE_SZARRAY    = 0x1d       -- 0-based one-dim-array */
MONO_TYPE_MVAR       = 0x1e       -- number */
MONO_TYPE_CMOD_REQD  = 0x1f       -- arg: typedef or typeref token */
MONO_TYPE_CMOD_OPT   = 0x20       -- optional arg: typedef or typref token */
MONO_TYPE_INTERNAL   = 0x21       -- CLR internal type */

MONO_TYPE_MODIFIER   = 0x40       -- Or with the following types */
MONO_TYPE_SENTINEL   = 0x41       -- Sentinel for varargs method signature */
MONO_TYPE_PINNED     = 0x45       -- Local var that points to pinned object */

MONO_TYPE_ENUM       = 0x55        -- an enumeration */

monoTypeToVartypeLookup={}
monoTypeToVartypeLookup[MONO_TYPE_BOOLEAN]=vtByte
monoTypeToVartypeLookup[MONO_TYPE_CHAR]=vtString
monoTypeToVartypeLookup[MONO_TYPE_I1]=vtByte
monoTypeToVartypeLookup[MONO_TYPE_U1]=vtByte
monoTypeToVartypeLookup[MONO_TYPE_I2]=vtWord
monoTypeToVartypeLookup[MONO_TYPE_U2]=vtWord
monoTypeToVartypeLookup[MONO_TYPE_I4]=vtDword
monoTypeToVartypeLookup[MONO_TYPE_U4]=vtDword
monoTypeToVartypeLookup[MONO_TYPE_I8]=vtQword
monoTypeToVartypeLookup[MONO_TYPE_U8]=vtQword
monoTypeToVartypeLookup[MONO_TYPE_R4]=vtSingle
monoTypeToVartypeLookup[MONO_TYPE_R8]=vtDouble
monoTypeToVartypeLookup[MONO_TYPE_STRING]=vtPointer --pointer to a string object
monoTypeToVartypeLookup[MONO_TYPE_PTR]=vtPointer
monoTypeToVartypeLookup[MONO_TYPE_BYREF]=vtPointer
monoTypeToVartypeLookup[MONO_TYPE_CLASS]=vtPointer
monoTypeToVartypeLookup[MONO_TYPE_FNPTR]=vtPointer
monoTypeToVartypeLookup[MONO_TYPE_GENERICINST]=vtPointer
monoTypeToVartypeLookup[MONO_TYPE_ARRAY]=vtPointer
monoTypeToVartypeLookup[MONO_TYPE_SZARRAY]=vtPointer


Is this an oversight?

ADDENDUM:

Even with adding my own overload, removing the need to send a NULL parameter, it's saying that a string is not a valid input for a string parameter. Am I missing something very basic here, or has something gone very wrong with CE?



NotificationBox.PNG
 Description:
 Filesize:  22.25 KB
 Viewed:  4746 Time(s)

NotificationBox.PNG


Back to top
View user's profile Send private message
blankTM
Cheater
Reputation: 0

Joined: 03 May 2020
Posts: 49

PostPosted: Sat Jun 27, 2020 10:14 pm    Post subject: Reply with quote

Maybe you should analyze the Action instance structure

Then use createMemoryStream to create an empty structure passed to the second parameter



20200628121234.png
 Description:
 Filesize:  22.67 KB
 Viewed:  4733 Time(s)

20200628121234.png



20200628121244.png
 Description:
 Filesize:  38.63 KB
 Viewed:  4733 Time(s)

20200628121244.png


Back to top
View user's profile Send private message
ApacheTech
Newbie cheater
Reputation: 0

Joined: 26 Jun 2020
Posts: 14

PostPosted: Sun Jun 28, 2020 8:12 am    Post subject: Reply with quote

Passing NULL as a parameter is an extremely common occurrence. Is there really no way to do it in CE?
Back to top
View user's profile Send private message
Ahmed Jihad
How do I cheat?
Reputation: 0

Joined: 06 Jan 2024
Posts: 9

PostPosted: Mon Jan 08, 2024 1:53 pm    Post subject: Reply with quote

ApacheTech wrote:
I have the correct instance. Invoking other methods within that instance works fine. I've tested methods that take Boolean, and Integer parameters, as well as methods with no parameters. It's only Strings and complex types that I have difficulties with.


Hi please I need you answer in the following questions what is the ASM code to do this invoke???
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting 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