Jump to content
We are investigating issues where accounts became locked on login attempt #1. Lock feature disabled for now. ×


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by CmP

  1. The code is for determining whether chosen process is 32-bit or 64-bit, not the device. There can be 32-bit processes on 64-bit devices.
  2. Then you need sub-tables, for example: local Hack = {} Hack[1] = {} Hack[1].Name = "A" Hack[1].X_1 = 111 Hack[1].X_2 = 112 Hack[1].X_3 = 113 Hack[2] = {Name = "B", X_1 = 114, X_2 = 115, X_3 = 116} item = "/storage/emulated/0/Download/abc1.lua" gg.saveVariable(Hack, item)
  3. Don't use "table.insert" when you need to add elements with specific keys, just do it directly instead: local Hack = {} Hack.Name = "A" -- same as Hack["Name"] = "A" Hack.X_1 = 111 Hack.X_2 = 112 Hack.X_3 = 113 item = "/storage/emulated/0/Download/abc1.lua" gg.saveVariable(Hack, item)
  4. Yes, use string concatenation. For example: local str1 = "Value " .. "123" -- "Value 123" local str2 = 456 .. " value" -- "456 value" print(str1 .. str2) -- "Value 123456 value"
  5. Alright, here is an example of function with parameter: -- Function to do a new search for dword value passed to the function through parameter "value" function search(value) gg.clearResults() gg.searchNumber(value, gg.TYPE_DWORD) end -- Example of function usages search("123") search("500600") Same way your "ModAPet" function can accept that id as parameter.
  6. Try this option first. If it works, you don't necessarily need to change the code further.
  7. The problem is because you use global variable without previously assigning a value to it. By default global variables have value "nil", a special value that means absence of value. So when nil is passed to "refineNumber" function, it raises an error, because it expected first argument to be string. A simple way of fixing the problem (with minimal changes to the code) may be to assign needed value to global variable "IDAP" before "ModAPet" function is called: if choice ~= nil then IDAP = menuID[choice] menuFunctions[choice]() end A better option may be to refactor the code to make "ModAPet" function accept parameter of search string to use for the call to "refineNumber".
  8. Only as long as you keep GG running. To freeze values from script there is "addListItems" function. Set "freeze" field of tables to "true" for them to be frozen after the call to the function. For example: local results = gg.getResults(10) local values = {} for i, v in ipairs(results) do values[i] = {address = v.address + 0x1234, flags = gg.TYPE_DWORD, value = "4321", freeze = true} -- value will be frozen to 4321 end gg.addListItems(values)
  9. Don't call "setValues" function in loop. The code above from @HEROGAMEOfficial's post illustrates the approach that should be used instead: construct table with all desired values and pass it to "setValues" function. Something like this: gg.searchNumber("2219816;6::25", gg.TYPE_DWORD) gg.refineNumber("2219816", gg.TYPE_DWORD) local count = gg.getResultsCount() local results = gg.getResults(count) local values = {} for i, v in ipairs(results) do local index = (i - 1) * 4 local addr = v.address values[index + 1] = {address = addr + 64, flags = gg.TYPE_DWORD, value = "7"} values[index + 2] = {address = addr + 80, flags = gg.TYPE_DWORD, value = "8"} values[index + 3] = {address = addr + 96, flags = gg.TYPE_DWORD, value = "9"} values[index + 4] = {address = addr + 112, flags = gg.TYPE_DWORD, value = "10"} end gg.setValues(values)
  10. In your rebuilt code you have a mistake of calling "getResults" function 3 times when in original code it is called only once and returned value is used. Applying fix to your code: function slot1() gg.getRangesList("/data/data/example") gg.clearResults() gg.searchNumber("98,784,247,822", gg.TYPE_QWORD, false, gg.SIGN_EQUAL, 0, -1, 0) local results = gg.getResults(100) for i, j in ipairs(results) do if j.flags == gg.TYPE_QWORD then j.value = "98,784,247,817" j.freeze = true end end gg.toast("ENABLED") gg.setValues(results) end Also worth to mention that both original code and your rebuilt version ignore the value returned by "getRangesList" function, so that it doesn't influence anything and can be removed without any difference in code execution result.
  11. CmP

    Require module

    In your main script try the following code: package.path = package.path .. ";" .. gg.getFile():gsub("[^/]+$", "?.lua") local func = require "function" func.sayHello() The first line adds script directory to list of paths in which modules are searched.
  12. Regarding the needed details about "IsMatchHash" function in the variant of the library for arm64-v8a. The function is located at offset 0x18E078 from the start of the library. Here is the result of decompilation of function's code: The assignment on line 23 can be modified to achieve desired result (for function to always return 1). The assignment is performed by this instruction at offset 0x18E0EC from library start ("this" is a label for x0/w0 register): Modification of this instruction to MOV W0, #1 (hex bytes: 20 00 80 52) will cause the function to return 1 even when computed hash doesn't match stored hash. This modification of function's behavior is sufficient for bypassing in-memory data integrity check.
  13. CmP


    The solution above from MonkeySAN is correct, but has some minor issues and redundancies. Slightly modified version of it: gg.clearResults() gg.searchNumber("131842", gg.TYPE_DWORD) local t = gg.getResults(50000) for i, v in ipairs(t) do v.flags = gg.TYPE_QWORD -- referencing the constant by it's name instead of substituting it with it's value v.value = "288515153958273024" -- using value of type expected by the function instead of relying on implicit conversion of number to string end gg.setValues(t) gg.clearResults()
  14. You missed one important detail: The offset from library start to instructions of the function and new values for them that were mentioned are only applicable for library of the game for x86. On your device library for arm64-v8a is expected to be used, so the offset to the function and which instructions to modify in it need to be located exactly in this variant of library.
  15. From the documentation to "gg.prompt" function: https://gameguardian.net/help/classgg.html#afe6c5b86ba0ae295899fd259232aac2b
  16. No, with root in most cases something can be done. In this case, for example, you can modify file of installed library for the game to use it. Installed library is (should be) located at the following path: "/data/app/com.happylabs.hotelstory/lib/".
  17. Rooted devices usually don't have such limitation of not being able to modify values in memory ranges with application's code (or maybe in any memory range that doesn't have "w" permission). Possibly that it is somehow related with security improvements in android 11, but this is just a guess.
  18. The idea is correct, but implementation needs to be fixed for argument that is passed to getValues function to match the description from the documentation: Refer to the following post for an example of correct implementation: How to edit the pointer script (#6m08ph3)
  19. It's not necessary to convert values from decimal to hex or from hex to decimal, because GG understands both formats. Consider an example that you need to edit value of byte type to 0x88. Instead of converting 0x88 to decimal and using the result to edit the value, you can just edit the value right away by adding "h" suffix to hex value. So to edit the value you need to input "88h". Which device or emulator do you use to run the game and GG? Which version of android is used there? Is device/emulator rooted or a virtual space application is used?
  20. In memory editor's toolbar choose "Goto" option, then click on "Xa" button and locate entry with library name. Starting address will be specified there. Clicking on the entry will put the address in the input field. From there it can be copied and/or navigated to.
  21. Yes, this can be done to not create new table for result. The main difference is that "pairs" function will need to be used for iterating over elements of returned table because some of them may be set to nil ("ipairs" iterator will stop after encountering first nil element).
  22. No, it will return table of tables (that match condition) from passed table. Your claim is wrong because in the code "result" table is populated only with sub-tables of passed table and passed table isn't modified in the function.
  23. Apk of the game has 4 sets of libraries for different ABIs: armeabi-v7a, arm64-v8a, x86, x86_64. In my case 32-bit android emulator for Windows was used causing game libraries for x86 to be used. Correspondingly, all library-specific values like offsets that will be shown or mentioned in this post are only applicable to game's library for x86. Values of interest (coins, diamonds, max workers) are located in bss section of libnative-lib.so library. They can't be edited directly because game computes sha-256 hashes of several blocks of memory with important values and checks validity of stored hashes during every operation that includes reading or writing protected values. So in order to be able to directly edit values of interest in process memory verification of hashes needs to be disabled first. With GG it can be done by editing instructions in code segment of the library in process memory. The function that needs to be modified in library is named "IsMatchHash". It is located at offset 0x16E480 from library start. There are at least several different modifications of function's instructions to achieve desired result of function always returning 1 (true). One of the options is to modify 2 subsequent instructions at offsets 0x16E507 and 0x16E50A (see illustration below) to MOV AL, 0x1 (B0 01), MOV BYTE PTR [EDI + 0x29] (C6 47 29 01) and NOP (90) to edit all 7 bytes of original instructions. To find values of interest in process memory, besides using offsets to them from library start that can be discovered by analysis of library with the help of disassemblers, GG search capabilities can be used. Memory ranges with bss sections of application libraries in GG in most cases are classified as "Cb: C++ .bss". This can be used to find values of interest faster and more accurately by selecting only "Cb" type in list of memory ranges types. Having that done, there is one simple approach to find values of interest by searching for nearby value - player name string. For example, if player name is "TestPlayer123", in GG it can be searched with search string ":TestPlayer123". Colon as first character of search string means to search for specified UTF-8 encoded string. One occurrence of player name string is expected to be found. Values of interest are located within several hundred bytes from first byte of the string. After finding values of interest, adding them to saved list and assigning corresponding names to them, saved list looks like this: Maximal amount of workers is plain dword value that can be simply edited to desired one. Coins and diamonds are each stored as two separate dword values that give real value when they are XOR'ed (value1 XOR value2 = real_value). Either first or second value can be edited to 0 and the remaining value can then be edited to desired one. This works because value XOR 0 = value. Finally, here is an illustration of the result of modifying values of interest:
  24. Couldn't reproduce your issue. The following code successfully adds first result to saved list (without editing the value): gg.searchNumber("2", gg.TYPE_DWORD) local t = gg.getResults(1) t[1].value = "0" gg.addListItems(t)
  25. First answer to this stack overflow question has some explanations about it: https://stackoverflow.com/questions/24091566/why-does-the-arm-pc-register-point-to-the-instruction-after-the-next-one-to-be-e
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.