Jump to content

CmP

Contributor
  • Posts

    640
  • Joined

  • Last visited

  • Days Won

    43

Posts posted by CmP

  1. 23 minutes ago, MAARS said:

    This would be possible if @Enyby add the Coroutine library that permit to run asynchronous code. I know some m***ed gg that people have implemented that lib you can dm me if you want to know more

    Can you explain how would coroutines make that possible? How would you pass execution to a coroutine after calling "searchNumber", when it is doing it's job? Coroutines don't make it possible to execute code in parallel.

  2. 21 minutes ago, MAARS said:

    Nope

    "Aarch64 = arm64" statement is correct. AArch64 is the name of 64-bit ARM architecture. Both names refer to the same thing.

  3. 8 hours ago, ctbear said:

    1. Add an API for converting byte array to string, such as

    gg.bytesToString({0,104,0,105}, "utf-16");

    , returns the string "Hi", similar to Java:

    return new String ({0,104,0,105}, "utf-16"); 

    To add to discussion of this suggestion:

    Lua strings by themselves are encoding-agnostic, so desired conversion is actually from bytes that represent string in one encoding to bytes that represent the same string in other encoding (utf-8 in this case, it seems). Input and output bytes of a hypothetical API function for such conversion can be in the form of strings or tables with values of bytes, but strings seem to be more reasonable option, because internally they are represented as array of bytes (as opposed to table with 8-byte integers).

    It's also worth to mention that GG API already has bytes function that converts bytes from utf-8 encoding to specified one, so it may be not a bad idea to extend the function by adding new parameter for source encoding (how to interpret string that is passed to the function) instead of creating a new function.

    As for what can be done currently, without such function:

    Since there is "utf8" library with functionality to construct a string from list of character codepoints, to be able to convert bytes from, for example, UTF-16LE encoding to UTF-8, it is enough to implement parsing of bytes that represent string in UTF-16LE encoding to list of character codepoints. The list then just need to be passed to "utf8.char" function and it will return desired string in UTF-8 encoding.

  4. 2 hours ago, XxhentaixX said:

    But its odd. So this means that when all the values of the elements are setted equal to the value of the first element it keeps a record of that current value saved, even if the value in the game has changed.

    This understanding is based on fundamental misconception that GG automatically updates anything in tables that have been returned with "getResults", "getValues" or other GG API functions. GG not only doesn't do that, but also wouldn't be able to do that without significant performance impact (just imagine having to read values from process memory for all elements of all tables that have been returned by GG API functions every N milliseconds).

    So changes in process memory "automatically" don't affect anything in script anyhow. To get updated data from process memory, corresponding GG API function ("getValues") needs to be called, but even it doesn't change anything in table that is passed to it as argument, instead it returns new table that has new values in "value" field of it's sub-tables.

  5. There is one other detail regarding the comparison to "0" (string).

    Behavior of comparison operators for this case is described in the manual as follows: 

    Quote

    Equality (==) first compares the type of its operands. If the types are different, then the result is false. Otherwise, the values of the operands are compared. Strings are compared in the obvious way. Numbers are equal if they denote the same mathematical value.

    Equality comparisons do not convert strings to numbers or vice versa. Thus, "0"==0 evaluates to false, and t[0] and t["0"] denote different entries in a table.

    The operator ~= is exactly the negation of equality (==).

    For our case it means that the following condition

    _x[i].value ~= '0'

    will always evaluate to "true", because "value" field has value of number type.

    Correspondingly, correct comparison to check for value being not equal to zero is: 

    _x[i].value ~= 0
  6. 3 minutes ago, TisNquyen said:
    gg.searchNumber('', gg.TYPE_FLOAT)
    gg.refineNumber('', gg.TYPE_FLOAT)
    local count = gg.getResultsCount()
    local results = gg.getResults(count)
    
    local _x, _y = {}, {}
    for i, v in ipairs(results) do
      _x[i] = {address = v.address + 0x44, flags = gg.TYPE_FLOAT}
      _y[i] = {address = v.address + 0x4C, flags = gg.TYPE_FLOAT}
    end
    _x, _y = gg.getValues(_x), gg.getValues(_y)
    
    local x, y = {}, {}
    for i, v in ipairs(results) do
      if _x[i].value ~= '0' then
        table.insert(x, x[i])
      end
      if _y[i].value ~= '0' then
       table.insert(y, y[i])
      end
    end
    
    if #x ~= #y then
      return print "the results from x and y may not be the same!"
    end
    local xValue, yValue = x, y
    
    for loop = 1, #x do
      for i, v in ipairs(x) do
        x[i].value = xValue[loop].value
        y[i].value = yValue[loop].value
      end
      gg.setValues(x)
      gg.setValues(y)
      gg.sleep(500)
    end

     

    This code is equivalent to your previous version.

    You don't make a copy of tables with this line: 

    local xValue, yValue = x, y

    Instead you create new variables that refer to the same tables, so it doesn't make any difference.

    Lua reference manual explains this pretty clearly: 

    Quote

    Tables, functions, threads, and (full) userdata values are objects: variables do not actually contain these values, only references to them. Assignment, parameter passing, and function returns always manipulate references to such values; these operations do not imply any kind of copy.

  7. 28 minutes ago, XxhentaixX said:

    So x[i].value stays is equal to the element 1 as long it is in the "for loop"  ?

    No, that's because all values of the table are explicitly set to value of first element when the following code is executed: 

    for i = 1, #x do
      x[i].value = x[1].value
    end

    If, for example, "x" has 3 elements, the loop is then equivalent to: 

    x[1].value = x[1].value -- value of first element is set to itself
    x[2].value = x[1].value -- value of second element is set to value of first element
    x[3].value = x[1].value -- value of third element is set to value of first element

    And then, when next loop is executed: 

    for i = 1, #x do
      x[i].value = x[2].value
    end

    "x[2].value" no longer has it's original value, because new value (of "x[1].value") has been assigned to it during execution of previous loop.

    This is why only first loop works as intended and all subsequent ones don't. And this is why copy of values needs to be created before the first loop (to have access to original values after table values have been overwritten).

  8. The issue is in the code that needs to be repeated. When the code is executed for the first time, "value" fields of all sub-tables of the table ("x", for example) are set to "x[1].value", so that when the code is repeated and should set all values to second value, "x[2].value" is already modified to the value of "x[1].value", that's why each time the code is repeated, it sets all values to first value.

    To actually set all values of a table to value of different table element each time, make sure that there is a copy of values that doesn't get modified and in the code that gets repeated just use values from the copy to set "value" field of sub-tables. To make copy of values, construct a table in which indexes from original table (1, 2, 3, ...) are mapped to values of "value" field of corresponding sub-tables of the original table (x[1].value, x[2].value, x[3].value, ...), for example, like this: 

    local xValues = {}
    for i, v in ipairs(x) do
      xValues[i] = v.value
    end

    Then use values of constructed table in inner loop of the code that gets repeated (slightly modified version of the loop from @TisNquyen's post above): 

    for loop = 1, #x do
      for i = 1, #x do
        x[i].value = xValues[loop]
        y[i].value = yValues[loop]
      end
      gg.setValues(x)
      gg.setValues(y)
      gg.sleep(500)
    end
  9. On 1/4/2022 at 5:34 PM, Johnny50 said:

    for an example i search 2 Float and then an offset of 4 values underneeth it is an aim assist value of 15 Float

    Current capabilities of GG are more than enough to find values that meet this condition. There are 2 main approaches for this case:
      - ordered group search with "placeholder" values;
      - searching for target value and checking whether found results meet the condition(s) (like whether value at offset X is equal to Y).

    So the task is to find all float values equal to 15.0 for which float value at offset -16 (-0x10) is equal to 2.0.

    With the first approach the code may be next: 

    gg.clearResults()
    gg.searchNumber("2.0F;0D~~0D;0D~~0D;0~~0D;15.0F::17")
    gg.refineNumber("15.0", gg.TYPE_FLOAT)

    And the second approach can be implemented, for example, like this: 

    gg.clearResults()
    gg.searchNumber("15.0", gg.TYPE_FLOAT)
    local results = gg.getResults(gg.getResultsCount())
    local checkValues = {}
    for i, v in ipairs(results) do
      checkValues[i] = {address = v.address - 0x10, flags = gg.TYPE_FLOAT}
    end
    checkValues = gg.getValues(checkValues)
    for i, v in ipairs(checkValues) do
      if v.value ~= 2.0 then -- exact comparison of float values should be avoided in general, but for particular case of value "2.0" it will work
        results[i] = nil
      end
    end
    gg.loadResults(results)
  10. On 12/22/2021 at 7:32 PM, talkIRC said:

    open GG (either mode, sw or hw same results either way in the end)

    'start it' in the GG main window

    open game you want to hack

    tap GG floating above the app to select what process i want to 'inspect'

    result is hard lock on screen for about 10 seconds or so and then a total system restart (total reboot of the tablet)

    On 12/22/2021 at 8:20 PM, talkIRC said:

    I haven't found any records that would help with understanding the problem (what and why happens) in the log, so there may be 2 main possibilities: either they are present in the log but haven't been noticed or recognized as being related to the problem or log doesn't contain them.

    However, it seems worth to note that around 2 minutes and 17 seconds have passed between the moment when process has been selected in GG:

    12-22 13:05:18.975 14480 14480 E AndroidService: used: ProcessInfo [cmdline=com.fungames.sniper3d, name=Sniper 3D, packageName=com.fungames.sniper3d, icon=android.graphics.drawable.BitmapDrawable@8ef34cd, pid=10179, uid=10275, isSystem=false, isGame=true, weight=0, main=true, order=0, x64=false, rss=359392, getTracer()=0, getTrace()=-1]

    and the last record in the log:

    12-22 13:07:35.649 20370 20370 I SoundAlivePolicyManager: isGlobalEffectSupportCurrentAudioPath, currentDeviceType : 2

    This doesn't quite correspond to your description of steps that you do to reproduce the problem. Was process selection really the last action that you performed in GG that caused device to become unresponsive and to reboot after ~10 seconds?

    One thing that would greatly help with analyzing recorded logcat is to specify when certain actions have been performed. For example: 

    11:04:32 - "Start" button in GG's start screen was pressed
    11:04:38 - Process selection dialog was opened
    11:04:41 - Target process was selected
    11:04:55 - Device automatically initiated it's restart

    Time moments don't have to be exact, since it's not easy to precisely check when something is done, but even if it's +- 5 seconds, that's still significantly better than having no such information at all.

    For example, to illustrate, the log you provided is ~27 MB, but only ~2 MB from it is most likely to contain any information of interest, since other records are from before the moment of time when you initiated recording logcat in GG. And with information about when actions relevant to the problem have been performed, only, for example, ~200 kB of log records are most likely to contain any information of interest.

  11. I meant to attempt to check folder contents with file chooser, but there is no need anymore, since the situation supposedly became clear enough.

    GG doesn't use root to access file, path to which is provided by user in input field of "Execute script" dialog (nor does it for file chooser functionality in general). In most cases it works fine: just place script file(s) that needs to be executed in a folder that can be accessed without root and it will work. However, if target file is located in folders that require root to be accessed, GG may not be able to access it.

    In Android 11, as part of it's privacy-oriented changes, applications have been restricted from accessing other applications' data on external storage, i.e. contents of "/Android/data" and "/Android/obb" folders (source). So when GG runs on device with Android 11, it doesn't have access to those folders (with exception of it's own folder in "/Android/data"). For GG to be able to access files without restrictions, it most likely needs to delegate this functionality to it's daemon that runs with root, but there are security concerns related with such solution, so there need to be solid reasons to implement it.

    Actual question that needs to be asked in current case is why you need to be able to access contents of "/Android/data" with GG. For most use cases there should be alternatives that don't require accessing restricted folders, so it's not unlikely that there is an alternative for your case as well.

  12. 3 hours ago, zolotov123344 said:

    gg, in principle, does not try to develop towards authorship in terms of scripts? lol

    Let's not forget what scripts for GG are. They are automation of methods for certain modifications in games via process memory editing. Authorship of scripts essentially boils down to authorship of methods implemented in them, since value of scripts lies exactly in them. If methods are public, particular scripts that implement them in most cases aren't important, because methods can be applied manually and/or can be implemented in other scripts. So for authorship of scripts to be relevant, methods need to be not public, but this leads to contradiction: public release of scripts for GG fundamentally can't co-exist with keeping implemented methods private. Therefore, authorship of scripts for GG the way you want it to be can't exist.

    However, it can (and does) exist the same way as authorship of methods for using GG to achieve certain result in certain game that get published at this forum or anywhere else. It doesn't matter whether methods are published in form of text, video or script, their authors most often get the popularity they deserve (even though some of them don't even care about it). But popularity/recognition by themselves is a wrong goal, instead one should strive to become better at activities of one's interest.

  13. Thanks for the details. With them it appeared to be quite easy to find the answer.

    The value is tagged pointer that actually points to valid address in process address space. Top byte in tagged pointers is "implementation defined tag" that needs to be ignored to get the real address that pointer holds. More information about tagged pointers is present in Android documentation: https://source.android.com/devices/tech/debug/tagged-pointers

    So when you encounter such pointers, discard the top byte of their hex value (or replace it with "00") when navigating to the address to get to the correct address.

  14. I don't have any explanation for described behavior, but it may help, if you provide details regarding finding the value in problematic region. Which game/application is that? What is the algorithm to find any value from problematic region?

  15. My guess is that the values are actually from this region: 

    6e36d4b000-6e36dcb000 rw-p 00000000 00:00 0                              [anon:scudo:primary]

    but for some reason the address in GG starts with "B40000" instead of "000000".

    You should be able to check this assumption by navigating to presumably correct address (that starts with zeros) in GG's memory viewer.

  16. 5 hours ago, MonkeySAN said:

    what does the "Homedm = -1" do in a function really?

    It seems to be some kind of global state variable to control whether main menu should be opened immediately after execution returns to main loop. But more often than not such behavior isn't needed and when it is so, the variable becomes redundant and can be removed. Main loop can be then replaced with the following typical one: 

    while true do
      if gg.isVisible()
        gg.setVisible(false)
        Test()
      end
      gg.sleep(100)
    end
×
×
  • 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.