Jump to content

chateau

Members
  • Posts

    7
  • Joined

  • Last visited

Posts posted by chateau

  1. 4 hours ago, XEKEX said:

    should give you "PUSH" instruction (-- this will indicate the start of the function ) 
    -- "POP" instruction indicate the end of the function.

    Going to public double get_hp() offset address contains the following instructions: "LDR" then "RET", not "PUSH".

    Do I have to look for another offset address? Also, I don't think PUSH is common for ARM64, but I may be wrong. I do see a lot of STP (store pair) and LDP (load pair) when scrolling through memory, but not PUSH instruction. I'm not sure how to navigate to the 'start of the function' like you've mentioned, it would be nice if you can tell me what I should look for when inspecting the dump that contains many offset addresses, which is something like:

    // [Address(RVA = "0x1CC4FD4", Offset = "0x1CC4FD4", VA = "0x1CC4FD4")]
    // [Attribute(Name = "IteratorStateMachineAttribute", RVA = "0xF3BC10", Offset = "0xF3BC10")]
    // [Attribute(Name = "ObserverDelegateAttribute", RVA = "0xF3BC10", Offset = "0xF3BC10")]
    public IEnumerator HPChanged(double newHP, long order)
    
    // [Address(RVA = "0x1D4A118", Offset = "0x1D4A118", VA = "0x1D4A118")]
    public void ApplyAllHPChange(double, [Optional] List<>, [Optional] EnemySkill, [Optional] BattleEnemy)
    
    // [Token(Token = "0x5040822")]
    // [Address(RVA = "0x1F57230", Offset = "0x1F57230", VA = "0x1F57230")]
    public void SetHP(double newMaxHP, double newCurrentHP, bool immediate)
      
    // [Token(Token = "0x504061F")]
    // [Address(RVA = "0x1EBCBFC", Offset = "0x1EBCBFC", VA = "0x1EBCBFC")]
    public void SetAllHP(double newHP)

     

    5 hours ago, MC189 said:

    If the game has some kind of protection, then we should just 'Disable' it instead of tirelessly hiding cheats.

    I agree, when looking for offset addresses I found "CheatViolation" public enum which contains many enum constant values like Damage, EnemyHealthChange etc... I'll come to this later, most important part is that I understand how to patch memory at runtime.

    5 hours ago, MC189 said:

    I assume you're only want Increased Health and not Godmode?

    I want to be able to have control over health, just to learn about memory patching. The process is more important than the outcome.

  2. My understanding is that I have to use:

    1. branch instruction (jump instruction) to control the execution flow and jump to an unused section of memory.
    2. code cave (find unused section of memory) to inject additional instructions

    I have a feeling that this is going to be related to "allocate memory page" on GameGuardian.

    I've never used GameGuardian before this. I'm curious as to why this was never mentioned before.

  3. Wouldn't that crash the game as you're overwriting instructions you shouldn't?

    For example, I know the offset address from below (1D4CD45)

    public double currentHP
    {
        get // Offset = "0x1D4CD45"
        {
            return default(double);
        }
        set
        {
        }
    }

    Using "offset calculator" I go to the address (base addr + offset addr).

    Then, I see the following instructions and you're telling me I should just overwrite them all to the following instructions you gave me?

    (which will give us 0x1234567891234567, but the value here is not important, I'm trying to understand the process).

    LDR D0, [X0, #0x28]; 		-- Edit this instruction to: MOVZ X0, #0x4567
    RET;  				-- Edit this instruction to: MOVK X0, #0x9123, LSL #16
    STR X19, [SP, #-0x20]!; 	-- Edit this instruction to: MOVK X0, #0x5678, LSL #32
    STP X29, X30, [SP, #0x10]; 	-- Edit this instruction to: MOVK X0, #0x1234, LSL #48

     

    I can confirm that if I only edit the first line ^ from above to:

    FMOV     D0, #0x3FC0000000

    My health will decrease to 0, but I will have godmode (will not be able to die).

  4. 6 hours ago, XEKEX said:
    --X0 = 0x1234567891234567
    -- Load the lower 16 bits of the value into X0 (0x0000000000004567)
    MOVZ X0, #0x4567
    
    -- Load the next 16 bits of the value into X0, left-shifted by 16 bits (0x0000000091234567)
    MOVK X0, #0x9123, LSL #16
    
    -- Load the next 16 bits of the value into X0, left-shifted by 32 bits (0x0000567891234567)
    MOVK X0, #0x5678, LSL #32
    
    -- Load the upper 16 bits of the value into X0, left-shifted by 48 bits (0x1234567891234567)
    MOVK X0, #0x1234, LSL #48
    

    How do I apply those multiple lines of instructions using GameGuardian?
    Do I just overwrite existing instructions?

  5. Hey @MC189, thanks for sharing your insights and making it clear to understand.

    1 hour ago, MC189 said:

    For high precision you can read ARM Patching

    I'm skimming through the ARM docs, so we use FMOV because we're dealing with double-precision floating-point and D0 is used to store a double-precision value?

    1 hour ago, MC189 said:

    [ Schenario ]
    HP are really depends on Mechanism the game use. Here is some variation:

    • 1) In some RPG games, the Character has it's own HP Scope which then get_HP will catch changes in-game and save it on either Save files or Configs. get_HP on this type of game will not affect whole entity that you can apply above patches.
    • 2) It's common, especially in Online Games where get_HP are basically handles all Entity list. All Entity will have HP values derived from get_HP. Altho it affects All Entity, in P2P Games, modifying get_HP directly won't affect other players or NPC where the Server are hosted by another Player. Minecraft Realm for Example (Tho it is now patched on BDS)

    Thanks for making that clear, the game I'm currently working with is mostly client-sided where (I think) there is no network communication during a battle where I receive damage that changes my health.

    1 hour ago, MC189 said:

    [ Conclusion ]

    • - Player Health are always, either tricky to find or impossible. As it depends on How the game really implements it.

    I totally agree, there is like 50~ health related methods and fields when I search through the il2cpp dump using dnSpy and a lot of duplicate names. Which I'm guessing that means doing a lot of trial and error.

    1 hour ago, MC189 said:

    You should instead lookup for an Entity List and adjust it's attribute accordingly.

    I'm not sure if this is relevant in my case. Can you elaborate on this?

    1 hour ago, MC189 said:
    # Mid Precision: Double 101
    mov w0, #0x40590000  // Double 101 in Hex form
    fmov d0, w0  // Push Double in w0 to d0

    I think 40590000 hex corresponds to 100 double. How can I write two lines of instruction? Do I just overwrite the instruction below it, which is a RET?
    On godbolt, when I change the return value to 32 or above "double t() { return 32.0; }" It outputs multiple lines of instructions:

    .LCPI0_0:
      .xword 0x4040000000000000 // double 32
    t(): // @t()
      adrp x8, .LCPI0_0
      ldr d0, [x8, :lo12:.LCPI0_0]
      ret

    How am I suppose to apply this in GameGuardian?

    Before I read your post I actually tried to modify other health related methods, like get_currentHP(). I've applied arbitrary instructions (where it mostly failed to recognize ARM64 opcode, but a suggestion was made by GameGuardian), after applying the suggestion (shown below), my health was constantly 0, although I was never able to die:

    FMOV     D0, #0x3FC0000000
  6. 20 minutes ago, XEKEX said:

    editing get_hp method arm code isn't good in most cases because usally this method related to enemy aswell

    In the il2cpp dump there is actually two get_hp() method, one under EnemyState class and the other PlayerState class. I've used the get_hp() offset that is under PlayerState class.

     

    31 minutes ago, XEKEX said:

    look into the fields if there is an indice to player even a string searching the class name instead of the method and do some logic in a function to trigger the edit of the player hp only(by matching the player indice). 

    Can you elaborate? What do you mean by "do some logic in a function to trigger the edit"? There is only 1 player and 1 enemy.

  7. Hi there,

    I am trying to manipulate memory value (related to health) at runtime based on an identified offset address. I can currently access the memory address that holds the health value by manually searching the exact health value of double type, but this address changes when I close and open the application. I would eventually like to persistently modify the health value after closing and opening the application, without having to manually search for the address.

    I am unsure what to do next in order to modify the health value using libil2cpp offsets. These are the following steps I've done so far:

    1. Used a rooted 64-bit Android emulator (Nox Player) with arm64-v8a instruction set.
    2. Retrieved the latest .apk file directly from the Android emulator's root /data directory using "adb pull".
    3. Dumped the "libil2cpp.so" file from the game's .apk using il2cppdumper
    4. Used the dumped output from above to identify interesting function names "public double get_hp()" that contains offset addresses such as "Offset: 0x18D0258".
    5. On GameGuardian I've used "goto", then selected "Xa" and chose "libil2cpp.so".
    6. On GameGuardian I've used "Offset calculator" where the base address is from above and the offset is "18D0258"  from step 4.
    7. I am presented with a couple of interesting ARM64 instructions:  
      LDR D0, [X0, #0x28];
      RET;

       

    My understanding is that X0 (general-purpose register, like a variable) holds a memory address and 0x28 offset is added to the X0 register and the result of X0 + 0x28 becomes the accessed memory address, where the value inside it is loaded into the D0 register.

    Knowing that this is related to public double get_hp() what minimal changes do I need to make so that I can return a specific value to change the health or make it so that the health does not change at all?

    Thanks!

×
×
  • 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.