
CmP
-
Posts
672 -
Joined
-
Last visited
-
Days Won
49
Content Type
Profiles
Forums
Downloads
Gallery
Posts posted by CmP
-
-
5 minutes ago, nok1a said:
How you found the key?
Checked implementation of "GetTripleDESCryptoServiceProvider" method that shows how key is derived from "KEY" constant:
14 minutes ago, nok1a said:but i got an error that im using invalid characters
Because one can't just convert binary data to text and back and expect it to work, that leads to information loss. Use representation that is suitable for binary data. Or use a tool that allows to perform multiple transformations without a need for intermediate representations of data between steps, like the above-mentioned CyberChef.
1 -
Option for loading third result directly with one operation:
gg.getResults(1, 2)
1 -
As for encoding of data that the game uses in preferences (and not only), dump with meaningful names also significantly simplifies research, revealing most of information that needs to be known.
First step for decoding, that is specific to data in shared preferences, is mentioned in first post of the topic - URL decoding. Then, after base64 decoding, the data needs to be decrypted with Triple DES in ECB mode with 128-bit key "8a76f557475b615a6dcaedeaadd4d27b" (bytes of the key in hex). The result is also base64 encoded, so it needs to be decoded and the last step is to decompress the data as gzip. Below is a CyberChef recipe that implements the decoding:
https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',false,true)Triple_DES_Decrypt({'option':'Hex','string':'8a76f557475b615a6dcaedeaadd4d27b'},{'option':'Hex','string':''},'ECB','Raw','Raw')From_Base64('A-Za-z0-9%2B/%3D',false,true)Gunzip()And to illustrate it with examples, value for level 5 from topic's first post after decoding is:
{"CheckSum":"1EBXq7XeVC5e6TxnIVs/T9kE2J8rLG9IeYdOBc3Nxs9INiuzkhi6urMRRl858UeQdgjO1dLqpfw=","Offset":620,"Value":625}
and value for level 6 after decoding is:
{"CheckSum":"1EBXq7XeVC5e6TxnIVs/T9kE2J8rLG9IOjAKjtrE26cgX17n25az4rF8y2+JN4AVv8YyOpD9PI8AmbJGj0p2sw==","Offset":-836,"Value":-830}
both of which are JSON serializations of structures of "SafeInt" type that the game uses for values that it needs to protect.
1 -
47 minutes ago, nok1a said:
But why would they have it in process memory if they already have it in the shared pref?
Because shared preferences is merely a way of preserving data between different runs of application. There is no way to read/write value from/to shared preferences without having it in process memory.
54 minutes ago, nok1a said:Not to sure how you found that out, may i know where in dump you see that it says both encrypted and unencrypted exist?
Search for fields named "currentAdventureLevel":
57 minutes ago, nok1a said:As far i understand my GG search skill the dump doesn't usually provide me more advantage in finding something then i would without.
When names of things are not obfuscated, data from the dump provides everything one needs to know to find basically any value in scope of (used by) libil2cpp.so.
1 -
7 hours ago, nok1a said:
I am not sure if it would be more easy to do it in process memory. If it is a method of a class then i would not say it is easy, at least for my opinion because i never edit methods since the results after editing usually don´t make sense to me.
Didn't mean modifying the code, meant the regular GG-way of modifying the value. The only challenge here may be that the value is encrypted, so need to figure out how it works first. Though, I am not sure that it's encrypted value that needs to be modified, since according to the dump value of level exists in both encrypted and unencrypted forms.
7 hours ago, nok1a said:How so not?
Because finding the value in process memory doesn't require figuring out how it is stored in preferences.
7 hours ago, nok1a said:But if i need to dump the game for find it then i will do that.
I am somewhat surprised that you haven't checked it as one of the first things, since I see it as the "usual way" of finding desired values in Unity games.
0 -
On 11/1/2023 at 10:07 PM, nok1a said:
I want to locate the level value in the com.unicostudio.gemdoku.v2.playerprefs.xml file so i can edit it with GG
That doesn't require doing anything with preferences file though and in this case it seems easier to do it in process memory.
But if I understood correctly, you are researching how storing data in preferences works in case of this game. If that's so, start by doing the usual analysis of Unity games. Get the dump, open dummy dlls in dnSpy, look for things with relevant names within Assembly-CSharp.dll. Then check how those things are implemented in libil2cpp.so. First step should give a surface-level understanding of what's going on there. Second step will provide you with particular answers on how exactly it works.
1 -
39 minutes ago, adhammogza said:
My brother, I ask you to modify the game for us and give it to us without a protection system
That's way too unrealistic thing to ask, it requires decent qualification and serious investments of time. The way it can work for you is if someone shares which tools to use and how to not get detected, so it makes more sense to ask for that.
1 -
There are no issues with initial version of your code, it correctly sets value of S0 register to 0.06. It may be that you just need different value to make the character run slower. Does setting the value to 2 increase movement speed or decrease?
0 -
6 hours ago, Count_Nosferatu said:
Why are they doing this?
That's just code produced by script recording feature. Supposedly, when recording script, call to "processResume" function is inserted each time user returns from GG to game.
1 -
Again, the same reason, function "BP1" needs to be defined before it is called. If you don't want to reorder all of the functions, then moving block of code from lines 135-143 to the end of the file may work.
1 -
6 hours ago, SamePerson said:
I got an error at line 92
Because you need to define the functions before calling them as has been mentioned in the comment in the code above. For example:
function HOME1() -- ... end HOME1()
And not:
HOME1() function HOME1() -- ... end
1 -
I guess you should use "versionName" field for that:
-- ... if v.versionName == VN1 then HOME1() -- Functions HOME1, HOME2, HOME3 need to be defined before they are used elseif v.versionName == VN2 then HOME2() elseif v.versionName == VN3 then HOME3() else os.exit() end
1 -
This merely means that GG hasn't correctly identified that libraries belong to the application, process of which is selected. It doesn't affect anything other than how GG classifies the regions. The regions can still be found manually and from script just fine without relying on region being classified as "Xa", "Cd", etc.
0 -
local POINTER_TAG = 0xB4 << 56 local function addTag(pointer) return pointer | POINTER_TAG end gg.clearResults() gg.searchNumber("123456789", gg.TYPE_DWORD) local results = gg.getResults(1) local address = results[1].address - 0x8 -- applying the offset local taggedAddress = addTag(address) gg.clearResults() gg.searchNumber(taggedAddress, gg.TYPE_QWORD)
1 -
No, Google translate works fine, you just haven't specified what you need to implement in script. You just mentioned:
6 minutes ago, toanpham6001 said:my value is "123" and offset is 0x10
but you haven't specified what script needs to do. Search for "123"? Then apply offset? How is this related to tagged pointers?
Again, either describe what script needs to implement with text or show it with video.
0 -
6 minutes ago, toanpham6001 said:
how would i script it?
Script what? Where is description of what needs to be implemented? Is it searching, is it editing, is it something else? If describing with text is too hard, at least show what script needs to do with a video.
0 -
Yes, conversions from/to tagged pointer can be implemented in script. The code to add tag to pointer can be found in this post:
Need help in script. I don't know if it's possible to do it automatically (#298r5x2m)And removing tag from tagged pointer can be implemented like the following:
local ADDRESS_MASK = ~(0xFF << 56) local function removeTag(pointer) return pointer & ADDRESS_MASK end
0 -
This is tagged pointer. There is no problem with it. You misunderstood the post from other topic, you shouldn't edit top byte of the pointer. You only need to remove it for navigating to the address in memory editor tab. For example, value of the pointer at address 0x754799F000 from the video is 0xB4000076B220F9F0, remove "B4" from it and leading zeros to get pointed address 0x76B220F9F0, then go to this address in memory editor tab and region label will be shown.
1 -
2 minutes ago, toanpham6001 said:
my top byte is already 0 what should i do?
Since you have already created separate topic for your question, provide the details there. Include region log, address of the value and the value itself.
0 -
Lua also allows to implement custom iterators to be used with generic "for", so one can implement traversal from 0 that way and use it like ipairs/pairs functions:
-- Modified function from http://lua-users.org/wiki/IteratorsTutorial function ipairs0(t) local function iterator(t, i) i = i + 1 local v = t[i] if v ~= nil then return i, v else return nil end end return iterator, t, -1 end -- Usage example for i, v in ipairs0(t) do print(string.format("[%d] = %s", i, v)) end
0 -
17 minutes ago, nok1a said:
Could you perhaps provide an example function for print table starting at index zero*?
It's not more complicated than to print table elements starting from key 1. Looks more like the question is about how to print table elements at all. In the most basic case to print elements with integer keys starting from 0 and without printing contents of any nested tables it's enough to have one loop:
local t = {[0] = 0, 1, 2, 3} print("{") local index = 0 local element = nil while true do element = t[index] if element == nil then break end local representation = string.format(" [%d] = %s", index, element) -- implement custom type-dependent converion of value to string if needed, this one uses default conversion, i.e. string "1" and number 1 will result in the same output print(representation) index = index + 1 end print("}")
1 -
16 minutes ago, nok1a said:
It's for readability.
For readability of the code or the output with table representation? If for the latter, one can simply create custom function to print table contents.
35 minutes ago, nok1a said:There are no regular arrays in Lua, only tables that are associative arrays and can be used to implement many different data structures. Tables in Lua don't have starting element by themselves, but length operator and functions from "table" library operate only on part of table with consecutive integer keys starting from 1. Your interpretation is wrong, because tables don't have defined order of traversal, it's implementation-specific. In fact official Lua doesn't include table contents in it's default procedure to convert table to string. So instead of relying on default table to string conversion in GG implementation of Lua, implement custom function that will perform conversion the way you need.
0 -
Note that metatable-based solution suggested above doesn't work as expected in all cases when key used in indexing access or indexing assignment exists in table, because "__index" and "__newindex" events are used only when key is not present in table. Though, XEKEX is right that it's not a good practice to have 0-based arrays in Lua. What is your use case for that and why 1-based arrays don't suffice?
0 -
22 minutes ago, nok1a said:
Hmm, i don't exactly understand why string.format over string concatenation, could you perhaps explain?
Because string concatenation produces new string and there are multiple usages of it in the code.
29 minutes ago, nok1a said:I applied it like this to the script, This is ok?
Mostly yes, but format strings don't need to be passed as parameters in this case and instead of separate call to format address, do it in the same one.
1
Just like we change the address "value" can we also change the address "name" while using the script?
in Help
Posted
It's done exactly as in his example. For your code it may be: