|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
FauDrei Advanced Cheater Reputation: 4
Joined: 20 Nov 2013 Posts: 69 Location: bachLai
|
Posted: Sun Apr 03, 2016 5:09 pm Post subject: How to address different Mono methods with the same name? |
|
|
Regards,
I am trying to inject some code into a method of a Mono game, but I have encountered this:
Code: | a9fb058 : Assembly-CSharp
.
.
.
ae89f10 : CommissionFactory
static fields
fields
methods
ae8a540 : .ctor
.
.
.
ae8a700 : GenerateCommissionsFrequently
ae8a720 : GenerateCommissionsFrequently
|
...and, of course, I need to jit/get address of the second CommissionFactory:GenerateCommissionsFrequently method (ae8a720), but I always get the address of the first one (ae8a700).
Is there a way to jit/get address of the second (desired) method?
I know I can use aobscan to get my injection address, but it is not elegant, is much slower and it does not force jitting of the method.
Thanks.
P.S.
Does the assert AA function force jitting of a Mono method? If not - what does?
|
|
Back to top |
|
|
panraven Grandmaster Cheater Reputation: 55
Joined: 01 Oct 2008 Posts: 942
|
Posted: Sun Apr 03, 2016 9:16 pm Post subject: |
|
|
In CEDIR/autorun directory, the monoscript.lua has this related lua function
Code: | function mono_method_getSignature(method)
...
return result, parameternames, returntype;
end |
The 'result' is a string list of input parameter type/class name, which should be unique for each overloaded function of same name.
The 'method' parameter is a integer/number to identify the method/function. But if we already have this number, and the goal is to get the jit-address of the method, we don't need to call the signature function.
So to identify the target overloaded function, we need to enumerate every function/method in the target class and paired each function with its signature. Then compare a matching signature pattern of the method name to return the target method number, and get the jit-address by calling mono_compile_method(method).
That should be one of the possible approaches.
If you like, you may try my implementation.
The attached ct is a very wip Master-of-Orion table, which include my latest lua script about mono thing in table files. The lua will be ready to use by clicking the script '(click 1st: load Scripts)'.
After attached to a mono game process, then click '(click 2nd: Global Storage)'
In aa script, this line will get the function address to a define symbol (local, not registered symbol).
Code: | eval(bonus,$MONO'Backend.Civilizations.Civilization::GetBonus')
|
'Backend.Civilizations' is namespace,
'Civilization' before 1st ':' is class name,
'GetBonus' is the method name.
In most mono game, game logic related class don't need a namespace.
The equivalent define symbol with CE address symbol is like this:
Code: | define(bonus,"Backend:Civilizations:Civilization:GetBonus") |
---
"Does the assert AA function force jitting of a Mono method? If not - what does?"
'define' above will not jit the method, since the aa command 'define' alone just assign a (local) symbol to the textual pattern .
But when the symbol used in anywhere that force ce to eval the textual pattern, and it match the right method, the ce symbol-handler will call some function in monoscript.lua , and should jit the mono function.
eg:
someaddress:
dq bonus
equivalent:
someaddress:
dq "Backend:Civilizations:Civilization:GetBonus"
or
bonus:
jmp mycave
equivalent:
"Backend:Civilizations:Civilization:GetBonus":
jmp mycave
etc.
---
Now in case of overloaded methods.
Suppose we have these overloaded methods signature:
Code: |
1) public float GetBonus(float amount)
2) public float GetBonus(float amount, BuildingType b)
3) public float GetBonus(float amount, EquipType e)
4) public float GetBonus(int amount, BuildingType b, boolean restore)
5) public float GetBonus(float amount, EquipType e, boolean restore)
6) public float GetBonus(float amount, BuildingType b, boolean restore)
|
Then the following is the aa command to define the target method address:
Code: |
1) eval(bonus,$MONO'Backend.Civilizations.Civilization::GetBonus(1)')
2) eval(bonus,$MONO'Backend.Civilizations.Civilization::GetBonus(2-2-Building)')
3) eval(bonus,$MONO'Backend.Civilizations.Civilization::GetBonus(2-2-Equip)')
4) eval(bonus,$MONO'Backend.Civilizations.Civilization::GetBonus(3-1-int)')
5) eval(bonus,$MONO'Backend.Civilizations.Civilization::GetBonus(3-2-Equip)')
6) eval(bonus,$MONO'Backend.Civilizations.Civilization::GetBonus(3-2-Build)')
|
Since the 1st approaches need more typo, I use an alternative one. The rule are:
1) If number of parameter count can uniquely identify the target method, add '(count)' after method name;
Check example 1)
2) otherwise add '(count-<1st_position_of_unique_parameter_type>-<typename_at_that_position>)' ;
Check example 2)-6)
3) the last 'typename' inside '()', if used, need not be full text as long as no ambitious. it is a lua pattern match.
For instance method, the 1st parameter in assembler code (ie. this pointer) is not count as parameter (seems implied ).
--
NOTE:
The scripts are badly code and badly/no maintained, inconsistent and buggy.
Also, when mono feature is ON, no debug function is accessible; Conversely when there is debug function ON, the mono feature cannot be launch. They seems currently cannot be co-exist.
There is way to OFF mono feature, ie. monopipe.Destroy();monopipe=nil;
but there seems no way to detach an attached debugger (ie. removing all breakpoint still cannot re-launch mono feature)
oops, last thing, the script need ce 6.5
bye~
Description: |
|
Download |
Filename: |
0_MasterOfOrion.CT |
Filesize: |
42.76 KB |
Downloaded: |
1346 Time(s) |
_________________
- Retarded. |
|
Back to top |
|
|
FauDrei Advanced Cheater Reputation: 4
Joined: 20 Nov 2013 Posts: 69 Location: bachLai
|
Posted: Mon Apr 04, 2016 3:57 am Post subject: |
|
|
Well - thanks panraven.
I understand the logic of the procedures you have described, but I am not good at lua at all. My utmost lua achievement is: Code: | {$lua}
if (LaunchMonoDataCollector()==0) then
error("no mono")
end
{$asm}
| at the beginning of my scripts. So, normally, I have run into problems:
- I have copied your "click 1st" and "click 2nd" scripts into my table, but I must be missing something because I can not start them from my table (there is no X in the box beside them), and I have attached CE 6.5+ to the game process between "click 1st" and "click 2nd". I suppose I should add/customize them to work properly in my table - but I do not know where to start.
- Afterwards I have also tried including
Code: | eval(INJ_moreContractCommissions, $MONO'CommissionFactory::GenerateCommissionsFrequently(1)'+3eb)
| statements into my cheat scripts, but it says "This instruction can't be compiled", so I guess it is related to the 1st point problem.
I have no idea how to scrape up a chunk of lua code with "mono_method_getSignature" to the get desired signatures of two "CommissionFactory:GenerateCommissionsFrequently" methods that I have. I have tried the guessing approach you have described but I suppose the problems with 1st and 2nd point prevented any success here...
So, now I understand better the magnitude of how much I do not know... and since I also realize I would be asking too much to handguide me through my problem - could you please point me into the right RTFM direction?
Thanks again.
|
|
Back to top |
|
|
panraven Grandmaster Cheater Reputation: 55
Joined: 01 Oct 2008 Posts: 942
|
Posted: Mon Apr 04, 2016 5:09 am Post subject: |
|
|
hi,
if copy to another table file, also 'copy' the 2 script files in MENU/table/ please. They are 'monojunk160117.lua' and 'MRAA.lus'
To 'copy', they need to manually 'save to disk', then manually 'add file' into your ct table by the respective menu command. They are lua files embedded in the table file to extent ce functionality, 'monojunk160117.lua' mainly extent AA script and mono feature, while 'MRAA.lua' extent Memory Record. I coded them like a mess, not really independent with each other, so it is better 'copy' both.
After embedded these 2 files, and click the 2 script entry you already copied , and given attached to a mono game, the AA script extension should be usable.
May try with an non-overloaded function 1st. Then try your target overload function.
The 'eval' command will parse 2nd parameter as lua script expression if it start with '$', the offset "+3eb" will cause error as it is not lua expression.
Code: | eval(INJ_moreContractCommissions, $MONO'CommissionFactory::GenerateCommissionsFrequently(1)'+3eb) |
Try like these:
Code: | eval(function_entry,$MONO'CommissionFactory::GenerateCommissionsFrequently(1)')
eval(INJ_moreContractCommissions,function_entry+3eb) |
The second 'eval' don't start 2nd parameter with '$', so it is in normal AA script format.
A simple test script may be like this:
Code: | [ENABLE]
globalalloc(testarea,$100)
eval(function_entry,$MONO'CommissionFactory::nonOverloadedFunction')
eval(INJ_moreContractCommissions,function_entry+3eb)
testarea:
dq INJ_moreContractCommissions
[DISABLE] |
This not really a real cheat, but to get how the script extension work.
btw, which game is it?
And would like to see the list of the overloaded function's signature.
bye~
Description: |
|
Filesize: |
24.63 KB |
Viewed: |
23082 Time(s) |
|
_________________
- Retarded. |
|
Back to top |
|
|
FauDrei Advanced Cheater Reputation: 4
Joined: 20 Nov 2013 Posts: 69 Location: bachLai
|
Posted: Mon Apr 04, 2016 6:52 am Post subject: |
|
|
Hi panraven.
Yes, after some more digging into "click 1st" script I have realized myself that
Code: | local target= {"monojunk160117.lua","MRAA.lua"}
| had to be somewhere and I 've managed to find them exactly where you described (never knew that CE has ability to "sideload" scripts into a table).
After that I've also, after many tries, managed to blindly guess the parameter count of the second "CommissionFactory:GenerateCommissionsFrequently" that I wanted jitted and addressed. It was plainly "(1)"... go figure... So finally I got:
Code: | //define(INJ_moreContractCommissions, CommissionFactory:GenerateCommissionsFrequently+3eb)
eval(_INJ_moreContractCommissions, $MONO'CommissionFactory::GenerateCommissionsFrequently(1)')
define(INJ_moreContractCommissions, _INJ_moreContractCommissions+3eb)
define(AOB_moreContractCommissions, 83 C4 10 89 85 5C FF FF FF)
| which worked for me (have not realized that I can "eval" "INJ_moreContractCommissions" from "_INJ_moreContractCommissions+3eb" instead of "defining" it, but it still worked).
So many many thanks for help panraven, rep++ from me... Now I will try aesthetically fix my table and "strip down" your scripts just for the minimal required "eval" code which I intend to include as a part of my table - that is - if you have no objections to that?
Learning all what you presented me, I certainly hope that CE gurus and VIPs would consider officially expanding the original lua/AA with useful functions like "eval" and that "tibiscan" that I haven't managed to figure out how it works yet. Also, it would be much easier if Mono Dissector would be enhanced with right click options to display method's ID, signature, parameters...
And, yes... The game is TransOcean, but I do not know how to provide you the list of the overloaded function's signature...
P.S.
What does ":=" and ":@" (instead of "::") stand for in
Code: | eval(universe,$MONO'Backend.Core.Client:=universe')
eval(pciv,$MONO'Backend.Core.Client::GetLocalPlayerCivilization')
eval(client,$MONO'Backend.Core.Client:@self')
| ?
|
|
Back to top |
|
|
panraven Grandmaster Cheater Reputation: 55
Joined: 01 Oct 2008 Posts: 942
|
Posted: Mon Apr 04, 2016 8:15 am Post subject: |
|
|
Sure the script is free to use, but may not have sufficient support.
For meaning of the symbols after class name,
Code: |
classname::name -- function address
classname:^name -- function END address
classname:&name -- the method/function number, not useful in aa script
classname:=name -- the Instance field OFFSET
classname:#name -- the Static field OFFSET
classname:@name -- the Static field Address, this is prefer to offset
classname: -- the class static base address
|
The tibiscan is mimic ce 6.5 new aobscan command AOBScanRegion, with slight difference:
Code: |
tibiscan(symbol,start_address,+scan_length, aob_pattern) |
Currently the scan_length must prefix with a '+' symbol, and limit within a length of 64k, 10000h.
It will scan from start_address to start_address+scan_length for the 1st matching aob_pattern and assign the result address to symbol.
The cryptic !perk/4 mean converse the number value of perk to an aob pattern of 4 bytes. It can be !perk/ which default to 1 bytes. The !perk/4 has to be space separated from other aob pattern.
For example, if perk is in hex form 1234567h,
the !perk/4 will expand to 67 45 23 01, and !perk/ to just 67.
However, currently it won't work if the symbol is not in pure hex form, ie.
1234567+12, or _INJ_moreContractCommissions+3eb wont work.
The main different with AOBScanRegion is that AOBScanRegion is executed BEFORE define symbol parsing, so that it is not convenient to make a aob pattern that depend on DEFINED SYMBOL, eg. offset, static address etc. This feature should enhance update resistance of the aob pattern with game update.
ADDED:
The game logic can be view as source by viewing an assembly dll in a cil de-compiler. The dll can be found in XXX_data/managed directory. Usaually Assembly-CSharp.dll or Assembly-UnityScript.dll will contain main game logic. What the field or function or signature can be view via a de-compiler then.
bye~
_________________
- Retarded. |
|
Back to top |
|
|
FauDrei Advanced Cheater Reputation: 4
Joined: 20 Nov 2013 Posts: 69 Location: bachLai
|
Posted: Mon Apr 04, 2016 9:16 am Post subject: |
|
|
panraven wrote: | The main different with AOBScanRegion is that AOBScanRegion is executed BEFORE define symbol parsing, so that it is not convenient to make a aob pattern that depend on DEFINED SYMBOL, eg. offset, static address etc. This feature should enhance update resistance of the aob pattern with game update. |
...and this swiftly explains why my aobscans with defines in them have not worked... Now just to find out why aobscanmodule does not work for me at all...
panraven wrote: | The game logic can be view as source by viewing an assembly dll in a cil de-compiler. The dll can be found in XXX_data/managed directory. Usaually Assembly-CSharp.dll or Assembly-UnityScript.dll will contain main game logic. What the field or function or signature can be view via a de-compiler then. |
Any recommended de-compiler?
...I do not know how to thank you further panraven... Cheers mate.
|
|
Back to top |
|
|
panraven Grandmaster Cheater Reputation: 55
Joined: 01 Oct 2008 Posts: 942
|
Posted: Mon Apr 04, 2016 11:28 am Post subject: |
|
|
I use Telerik JustDecompile (free).
There are others like dotpeek (free), .net reflector (commercial?) etc., but I've not really tried, not sure which is better.
But they all should have a very useful feature (called 'find usage' in JustDecompile) that list all source that using a field, a function, or even a class.
_________________
- Retarded. |
|
Back to top |
|
|
FauDrei Advanced Cheater Reputation: 4
Joined: 20 Nov 2013 Posts: 69 Location: bachLai
|
Posted: Mon Apr 04, 2016 12:40 pm Post subject: |
|
|
Wow! Those CIL decompilers are amazing...
Code: | private void GenerateCommissionsFrequently();
Declaring Type: CommissionFactory
Assembly: Assembly-CSharp, Version=0.0.0.0
private void GenerateCommissionsFrequently(bool forceGeneration);
Declaring Type: CommissionFactory
Assembly: Assembly-CSharp, Version=0.0.0.0
|
Now, knowing those signatures - how do I get method ID (so I can get the address with mono_compile_method)?
|
|
Back to top |
|
|
panraven Grandmaster Cheater Reputation: 55
Joined: 01 Oct 2008 Posts: 942
|
Posted: Mon Apr 04, 2016 2:12 pm Post subject: |
|
|
If these lines succeeded, and give 2 distinct addresses (func_0,func_1), then the code should be working, (I'm not sure the no parameter case)
Code: | [ENABLE]
globalalloc(testarea,$10)
eval(func_0,$MONO'CommissionFactory::GenerateCommissionsFrequently(0)')
eval(func_1,$MONO'CommissionFactory::GenerateCommissionsFrequently(1)')
testarea:
dq func_0,func_1
[DISABLE]
|
The 'eval' should already called mono_compile_method (so jit-ed the function) if the symbols following classname is '::'. ie. func_0, func_1 above are the native code starting address of the respective jit-ed function. Usually the 1st instruction there will be either push ebp or push rbp depend on bit-ness.
If the symbols is ':&' it give the method/function number (method ID) to be feed to mono_compile_method, but this number alone should be not useful in AA script.
bye~
_________________
- Retarded. |
|
Back to top |
|
|
FauDrei Advanced Cheater Reputation: 4
Joined: 20 Nov 2013 Posts: 69 Location: bachLai
|
Posted: Mon Apr 04, 2016 3:16 pm Post subject: |
|
|
Yes, I have already implemented "eval" in my table and it works.
Thing is - I have 7 scripts in the table, all of them use mono, but just one of them needs "eval" functionality in just one injection point... So I am trying now to come up with minimal lua code to jit this one desired method and get it's start address it this one script instead of just copying your script and including both your lua files in my table... and learn some more in doing it
|
|
Back to top |
|
|
panraven Grandmaster Cheater Reputation: 55
Joined: 01 Oct 2008 Posts: 942
|
Posted: Mon Apr 04, 2016 4:26 pm Post subject: |
|
|
Ok, this use 1st approaches, which compare the signature returned by mono_method_getSignature. The 2 table files and the 2 'click 1st' 'click 2nd' cheat entries are not needed.
The main function is findMethodAddrBySignature . When the 5th parameter is 'true', it may consider a debug mode that it will print all signature until matched.
The following show how to use (function definition is snipped, see the source in attached ct).
bye~
Code: | {$lua}
-- assume LaunchMonoDataCollector has been called
-- one liner
-- <snip> see the attached ct
{$asm}
{$lua}
-- test
print('--') -- test to show/print all signature of a given function name
print(tohex(findMethodAddrBySignature('UnityEngine','Texture2D','.ctor','?',true)))
print('--') -- test to match a specific (third) signature of a function name
print(tohex(findMethodAddrBySignature('UnityEngine','Texture2D','.ctor','int,int,UnityEngine.TextureFormat,bool,bool$',true)))
-- the last '$' is lua match end-of-string, wthout this, the match MAY succeed on fourth one.
-- all other character should be compare as is, including upper/lower cases.
{$asm}
{$lua}
--define a lua Global INTEGER type variable for use in AA script, ce 6.5 feature
LUAVAR = findMethodAddrBySignature('UnityEngine','Texture2D','.ctor','int,int,UnityEngine.TextureFormat,bool,bool$') -- no 5th parameter 'true'
{$asm}
[ENABLE]
globalalloc(testarea,$10)
testarea:
dq $LUAVAR // using the Lua Variable in AA Script by prefixing a '$' symbol, Lua variable is case-sensitive.
dq $LUAVAR+111111
[DISABLE]
|
Description: |
|
Download |
Filename: |
monoSignature.CT |
Filesize: |
3.99 KB |
Downloaded: |
1139 Time(s) |
_________________
- Retarded. |
|
Back to top |
|
|
FauDrei Advanced Cheater Reputation: 4
Joined: 20 Nov 2013 Posts: 69 Location: bachLai
|
Posted: Mon Apr 04, 2016 5:23 pm Post subject: |
|
|
Excellent!
I assume I can use "$LUAVAR+3eb:" as a label in {$asm} part?
UPDATE:
Hmm... I am getting "This instruction can't be compiled" for "dq $LUAVAR" line...
|
|
Back to top |
|
|
panraven Grandmaster Cheater Reputation: 55
Joined: 01 Oct 2008 Posts: 942
|
Posted: Mon Apr 04, 2016 10:17 pm Post subject: |
|
|
FauDrei wrote: | Excellent!
I assume I can use "$LUAVAR+3eb:" as a label in {$asm} part?
UPDATE:
Hmm... I am getting "This instruction can't be compiled" for "dq $LUAVAR" line... |
oh, I've remove the one-liner in the message code block, it is too long, try the cheat entry in the attached ct file plz.
Then try either click menu/mono/activate mono feature, or run lua function LaunchMonoDataCollector() 1st.
And using Lua variable in AA Script with '$' is a ce 6.5 feature.
--
ADDED:
Ah I see where the error is...
yes, $LUAVAR+3eb: cannot be a label...
that's the inconvenient...
may need to assign another global Lua variable , eg
in Lua part
LUAVAR_3eb = LUAVAR+0x3eb,
then in AA script
$LUAVAR_3eb:
_________________
- Retarded. |
|
Back to top |
|
|
FauDrei Advanced Cheater Reputation: 4
Joined: 20 Nov 2013 Posts: 69 Location: bachLai
|
Posted: Tue Apr 05, 2016 12:54 am Post subject: |
|
|
'Morning panraven... thanks for still guiding my hand.
Latest code snippets do not work on my Windows 10... I am beginning to doubt that it is something wrong with my machine configuration... Will test on a different Windows 8.1 system later today to confirm (or not) that hypothesis.
Namely, on this machine of mine standard CE "aobscanmodule" never worked, couldn't figure out why. On the other hand "aobscan" does work.
I am using latest mgr.inz.Player's CE build (16.03.29), but I have also tried with clean 6.5 install and it behaves the same.
I have slightly modified your latest code. Here is the lua function script:
Code: | {$lua}
--
if syntaxcheck==true then return '' end
-- assume LaunchMonoDataCollector has been called
if (LaunchMonoDataCollector()==0) then
error("no mono")
end
function reEscape(s)
local escPatChars = [[().%+-*?[^]]
s = s:gsub('.',function(c) if escPatChars:find(c,1,true) then return '%'..c end end)
return s
end
function findMethodAddrBySignature(namespace,classname,methodname,signature,check)
local meth = findMethodBySignature(namespace,classname,methodname,signature,check)
if meth~=nil and meth>0 then
return mono_compile_method(meth)
end
end
function findMethodBySignature(namespace,classname,methodname,signature,check)
assert(type(signature)=='string',"invalid signature")
signature="^"..reEscape(signature:gsub(";",","))
local class = mono_findClass(namespace,classname)
if type(class)~='number' or class==0 then return nil end
local methods=mono_class_enumMethods(class)
if type(methods)~='table' or #methods<1 then return nil end
if check then print('check:'..methodname..": <"..signature.."> vs ") end
for i=1,#methods do
if methodname == methods[i].name then
local sign = mono_method_getSignature(methods[i].method)
if check then print(" >> <"..sign..'>') end
if sign:match(signature) then
return methods[i].method
end
end
end
end
-- Test
function tohex(n)return string.format('%X',n or 0)end
{$asm}
[ENABLE]
[DISABLE]
|
...and here is the test script:
Code: | {$lua}
-- test
print('--') -- test to show/print all signature of a given function name
print(tohex(findMethodAddrBySignature('Assembly-CSharp','CommissionFactory','GenerateCommissionsFrequently','?',true)))
print('--') -- test to match a specific (third) signature of a function name
print(tohex(findMethodAddrBySignature('Assembly-CSharp','CommissionFactory','GenerateCommissionsFrequently','bool$',true)))
-- the last '$' is lua match end-of-string, wthout this, the match MAY succeed on fourth one.
-- all other character should be compare as is, including upper/lower cases.
{$asm}
{$lua}
--define a lua Global INTEGER type variable for use in AA script, ce 6.5 feature
LUAVAR = findMethodAddrBySignature('Assembly-CSharp','CommissionFactory','GenerateCommissionsFrequently','bool')
{$asm}
[ENABLE]
globalalloc(testarea,$10)
testarea:
dq $LUAVAR // using the Lua Variable in AA Script by prefixing a '$' symbol, Lua variable is case-sensitive.
dq $LUAVAR+111111
[DISABLE]
|
The test script always reports "cannot compile dq $LUAVAR" errors and can not be started. Both print test lines always return 0 in lua engine window. I guess something in function findMethodBySignature does not sit right on my machine, but so far could not pinpoint the culprit. Could it be that I am missing some lua (sub)function definition? All that I've checked (mono_findClass, mono_class_enumMethods, mono_method_getSignature, mono_compile_method) exist in my monoscript.lua...
...and yes, I have attached the game to this test table before trying
UPDATE:
Nevermind all that...
With some additional lua debugging print lines I've realized that I have problem with namespace and after replacing 'Assembly-CSharp' with '' (that is two single quotes) everything just worked!
Thanks yet again panraven
|
|
Back to top |
|
|
|
|
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
|
|