Jump to content

H5GG Tutorial on Dungreed Mod Menu Hack for Non-Jailbroken/Jailbreak Devices !


Happy Secret

39 posts in this topic

Recommended Posts

New Age of Non-jailbroken hacking has arrived. We can do Mod Menu hacking for Non-jailbroken with ease now. Thanks to H5GG ( @tuancc ).

Check out my Dungreed Mod Menu Hack in action below.

In this tutorial, I am going to run you through the Dungreed Hacking process. At the end, I will give you some hacking challenges. You can test out your knowledge in hacking Dungreed using H5GG and Mod Menu.

Great deal, right? Let’s get started.

First and foremost, this tutorial would be a bit long. I will probably can’t complete it all in one goal. So, forgive me from updating more content incrementally.

Secondly, this is NOT H5GG tutorial. There are a lot great H5GG tutorial from tuancc and ꞋꞌꞋꞌꞋꞌꞋꞌ. This tutorial is all about hacking Dungreed with H5GG. Assuming you have some very basic understanding of H5GG.

If you are not sure what is H5GG, and how to do some basic thing. Here is some good link reference for you.

H5GG Tutorial References:

Spoiler

H5GG Basic Tutorial - Getting Started with H5GG
https://iosgods.com/topic/161718-h5gg-basic-tutorial-getting-started-with-h5gg/

H5GG Full Tutorial [Offset Patching + Hooking] for Non-Jailbroken/Jailbreak Devices !
https://iosgods.com/topic/167720-h5gg-full-tutorial-offset-patching-hooking-for-non-jailbrokenjailbreak-devices/

H5GG Tricks to do Live (online) Code Patching for Non-Jailbroken Devices !
https://iosgods.com/topic/167806-h5gg-tricks-to-do-live-online-code-patching-for-non-jailbroken-devices/

Requirements:

Spoiler

- Sideloadly
- Dungreed v1.6.175 IPA (clean)    Newer Dungreed v1.6.181 for reference
- Creative mind with Patience

Stage 1 - Assessment: 

Spoiler

Before we actually move on to hack, the first thing we want to do is to assess if the game is hackable or how easy/difficult could it be. 

Dungreed (v1.6.175) apparently works offline (no internet connection required). We can start game and save game to local device. Things work normally without any complaint. 

Another indication is, it is a priced game without in-app purchase. Although it is a weak indication, but it likely be standalone game, without the expensive operation cost in running the server service. 

For other game, that requires a connection to start game. It doesn’t necessary mean it require active connection to sync data. You can try turn of the network mid of game to test it out. If it will timeout, or demand for connection. It is very likely the game is server sided. 

If a game is not server-based game, it is normally easier to hack comparatively. The next question is, whether we can find out the logic of the game or whether we find where it store the game data.

Stage 2 - Choosing the tools

Spoiler

There are many different way in hacking a game. Even under Non-jailbroken, there are still multiple options. For examples:

1. IGameGod (cheat engine)
2. H5GG (cheat engine with scripting capability)
3. HTTP Catcher
4. Xcode + LLDB
5. DnSpy 
6. IDA
7. Il2cpp dumper for Unity games
... Etc

My usual preference is to first test iGameGod (iGG) works on the game. In this case, iGG can install with game, can do some scanning. But not 100% sure why, it crash the game every now and then, especially when doing Fuzzy search (but not only this). 

I decided to drop iGG and switch to H5GG, which also offers good memory search capability (see H5GG Tutorial references #1). 

H5GG works perfectly fine with Dungreed. The only downside of H5GG is, it cannot do fuzzy search. But it is fine, just get use to it. Don’t ask for it, there seems no plan to implement this features. But if you are good JavaScript programmer, feel free to develop your own fuzzy search tool with the H5GG API provided, or you can make your own Dylib with C and load it into H5GG. H5GG claims that it allow us to call those new library through JavaScript. Personally, I never tested that. 

For an action game like Dungreed, we know with H5GG Cheat engine alone, might not be sufficient.

Quickly look into game package, I found .app/Data/Managed/Metadata/global-metadata.dat and .app/Frameworks/UnityFramework.framework. It means it is a Unity game. Nice! Il2cpp dumper into my tool set for this game.

With Il2cpp dump, we will need tool like DnSpy or IDA as static analysis tool. I am a Mac user, DnSpy actually not an option for me. So, IDA becomes part of my tool set as well. 

What else do I need? IOS Debugger is normally my friend on hacking game. As Mac user, Xcode + LLDB is my favourite iOS Debugger. So, they are in as well.

 

To conclude, I have H5GG, IL2cpp dumper, IDA, Xcode + LLDB in my tool set. 

Stage 3 - Memory Hack with Cheat Engine (Simple H5GG use)

Spoiler

As explained earlier, H5GG is my cheat engine for Dungreed. 

Quickly do some search, the most eye catching things could hack with Memory Cheat Engine in Dungreed is HP and Money. But I know if this game has any protection mechanism. These two would definitely be the primary candidate to protect. 

The result is,
HP -> I can’t find a spot. Very likely, it is a float number, and damage is not a whole number. That is the reason why I can’t find it with whole number. With H5GG, I do not have fuzzy search capability. It is pretty much a dead end. 
Money- > Surprisingly there are some search result and one of it actually can modify the money I have on screen.  With some more testing, the behaviour is not completely as expected. I seems can continue to spend money to buy things. But it seems not saving properly. I believe there are some weak money protection somewhere. 
Dash count -> It is also very eye catching. But as it is recovering very fast, there is no way to search probably on it. 

To conclude, the only usual things is Money. Although I cannot completely hack it with H5GG Cheat Engine alone, but the memory location identified can further be used with iOS Debugger. 

Stage 4 - Dynamic Analysis with iOS Debugger - Hacking Money (non-H5GG Specific)

Spoiler

From Stage 3, we have identified a set of memory address that holds the Money of Dungreed. 

It is time to have a detail look into it. 

Turn on Xcode -> Load a random iOS project -> Change the target to our iOS device -> “Debug > Attach to Process by PID or Name > Type in Dungreed”
Hint: The process name is the app name inside the Payload after decompile the ipa file. Sometime the app name could be very odd like app store. They seems want to hide itself with the real App Store app.

Wait a bit for the debugger to attach successfully. If it is first time, it will take longer. As it need to prepare your iOS device for debugging first. 
Hint: Sometime the game might crash on attach, it doesn’t matter just restart and do it again. No worries.  

Once you see the Xcode saying Running…(on the top bar), you are set.

LET’s START DEBUGGING!!!

With the memory address we got from Stage 3, say 0x12345678, we create a watchpoint on it. We want to break/pause the game at the spot it try to modify this memory address. Pause the debugger (you will see the game freeze), in the debugging console (usually appear at the bottom right of Xcode), type in the watchpoint command.

The command for LLDB is w s e 0x12345678

Then resume the debugger. Go spend or get some money. It depends what you want to hack here.

  • If you want to hack the amount of money you get, go for a place you can get money. In Dungreed, just kill some mods or objects in the dungeon. Collect the money drop. 
  • If you want to hack the amount of money you spent, go for a place you can spent money. In Dungreed, you can find merchant in the dungeon or in Village (a bit later in game). Buy something. 

In my case, I do not want to do too artificial hack on money, which is risky, as we do not know what data protection mechanism the game has. I prefer to change the way how the shop works, which normally work better. 

So, I go find a shop and spent money. On the moment I spent the money, the game will pause and Xcode will show the current assembly and nearby assembly in debugger window. 
Hint: If you game did not pause, it might mean your address no longer valid, go back to H5GG, follow Stage 3 steps to find the money address again.

OK, this is the interesting and tough part. Who knows assembly!!! Crazy…but yes, you need to live with it. Go Google to search for any instruction you can’t guess what it mean. Normally it should stop at an instruction (line of Arm code) right after a store instruction. It is a STR instruction or its variants. 

UnityFramework`___lldb_unnamed_symbol77363:
    0x1097d21a0 <+0>:   stp    x24, x23, [sp, #-0x40]!
    0x1097d21a4 <+4>:   stp    x22, x21, [sp, #0x10]
    0x1097d21a8 <+8>:   stp    x20, x19, [sp, #0x20]
    0x1097d21ac <+12>:  stp    x29, x30, [sp, #0x30]
    0x1097d21b0 <+16>:  add    x29, sp, #0x30
    0x1097d21b4 <+20>:  mov    x19, x1
    0x1097d21b8 <+24>:  mov    x21, x0
    0x1097d21bc <+28>:  adrp   x20, 4922
    0x1097d21c0 <+32>:  ldrb   w8, [x20, #0xb89]
    0x1097d21c4 <+36>:  tbnz   w8, #0x0, 0x1097d21e8     ; <+72>
    0x1097d21c8 <+40>:  adrp   x0, 4690
    0x1097d21cc <+44>:  add    x0, x0, #0x460
    0x1097d21d0 <+48>:  bl     0x1095f37a4               ; ___lldb_unnamed_symbol68946
    0x1097d21d4 <+52>:  adrp   x0, 4691
    0x1097d21d8 <+56>:  add    x0, x0, #0x98
    0x1097d21dc <+60>:  bl     0x1095f37a4               ; ___lldb_unnamed_symbol68946
    0x1097d21e0 <+64>:  mov    w8, #0x1
    0x1097d21e4 <+68>:  strb   w8, [x20, #0xb89]
    0x1097d21e8 <+72>:  ldr    w22, [x21, #0x250]
    0x1097d21ec <+76>:  subs   w8, w22, w19
    0x1097d21f0 <+80>:  b.lt   0x1097d239c               ; <+508>
    0x1097d21f4 <+84>:  adrp   x20, 4691
    0x1097d21f8 <+88>:  add    x20, x20, #0x98
    0x1097d21fc <+92>:  str    w8, [x21, #0x250]
->  0x1097d2200 <+96>:  str    w8, [x21, #0x254]
    0x1097d2204 <+100>: ldr    x0, [x20]

You can see, we stoped as 0x1097d220. This instruction address might change on every restart of the game, we need to do ASLR (Address Space Layout Randomisation) treasure before it is useful in other setting or game session. 

To learn more about this arm instruction, just search in google “STR arm instruction”, you will find good reference info in developer.arm.com. 

Anyway, store is not something we have most interest in. We just want to know which Register is storing info to where. 

On 0x1097d21fc, we see “str w8, [x21, #0x250]”. It try to store w8 into address hold inside x21 with offset #0x250 (last instruction not current instruction, last instruction is the instruction which trigger the watchpoint.) 
Hint: w8 and x21 are registers. You can treat them as in memory variable for arm instruction. There is a predefined set of registers or variables. We cannot create more. 
more info here: Arm assembly registers explained, Register organisation, Floating point register organisation

Interestingly, you see it then store into another memory address pointing by x21 with offset #0x254. This is obviously creating a backup. It is likely being used to protect the Money being hack easily. 

We look a bit upward (earlier instruction). We try to look for any subtraction or addition. We are buying thing. Price of item will be deducted from Current Money.
Hint: Some game implement subtraction by adding a Negative number. They change the price into negative and add to the Current Money.

On 0x1097d21ec, we see “subs w8, w22, w19”. It essentially mean Subtract w19 from w22 and store it to w8. We are lucky. The subtraction happens so near the store and not hiding in another sub_x. So, we guess w19 is the price, while w22 is Current Money.

Do a quick validation in Xcode, on bottom left panel, you see a window, expand the item to find w19 and w22. You will see the value store in Hex.  
Hint: Here is Decemal to Hexadecimal converter. Here is a Floating Point to Hexadecimal converter.

Our guess is correct. GREAT! We have found the place it perform subtraction/deduction!! This is where we could hack/change.

In fact, on 0x1097d21e8, we see “ldr w22, [x21, #0x250]”. It means load data stored in address pointed by x21 with offset #0x250 to w22. Yes, it is [x21, #0x250] again. We are pretty sure it store the Current Money

So, what if we change the 0x1097d21ec instruction into “adds w8, w22, w19”. Subtraction become addition!!

Let’s test it out. 

First, let’s find out the hex code of “adds w8, w22, w19” from Online ARM to HEX Converter. It is C8 02 13 2B. In LLBD ARM64 Big Endian form will be 0x2B1302C8

In Xcode Debugger Console (bottom right), type “memory write -s 4 0x1097d21ec 0x2B1302C8“. It will replace 4 bytes memory content of 0x1097d21ec with what we want (0x2B1302C8 - adds instruction). 

Then disable the watchpoint with “watchpoint disable 1”. Disable the first watchpoint. Then resume the game. 

Yes, that simple. You have patched the memory version of the game logic. (Only memory, if you restart the game everything is gone, the address I will be different as well)

Quickly go test it out. You will see the game start adding money whenever you buy things.

Congratulations! We have got the memory address of the instruction to hack and we got the target instruction tested.

Let’s get back to Xcode, we have one final and very important thing to do, before we complete this Stage 4.

Pause the Debugger again, in the Debugger console (bottom right) type in “image list UnityFramework”. You will then get something like below.

[  0] 2047147E-8318-3416-B521-FC9DA88EEDCD 0x00000001089ec000 /private/var/containers/Bundle/Application/6AE0F34B-5341-4A4B-AE27-076B7E7A3B22/Dungreed.app/Frameworks/UnityFramework.framework/UnityFramework (0x00000001089ec000)

It includes the Binary address of UnityFramework - 0x00000001089ec000. It is very important for us to remove the ASLR effect on our memory address 0x1097d21ec.

Use Hex Calculator to deduct the UnityFramework binary address from our target memory address.

1097d21ec – 01089ec000 = DE61EC

This DE61EC (0xDE61EC) is the offset of the arm instruction we want to hack in UnityFramework binary. This address will not change, unless you have upgrade Dungreed to newer version. 

To conclude, we have got the UnityFramework binary offset (0xDE61EC) for Money Hack and the target instruction hex code (C802132B).

Stage 5 - Apply the Money hack with H5GG script (without Mod Menu)

Spoiler

With the hack offset and hex code to patch, let’s apply it with H5GG script. Below is the most simple form of the script to use.

h5gg.require(7.9); 
var h5frida=h5gg.loadPlugin("h5frida", "h5frida-15.1.24.dylib");
if(!h5frida) throw "Failed to load h5frida plugin";

function ActiveCodePatch(fpath, vaddr, bytes) {
    if(!h5frida.ActiveCodePatch(fpath, vaddr, bytes)) {
        var result = h5frida.ApplyCodePatch(fpath, vaddr, bytes);
        alert(fpath+":0x"+vaddr.toString(16)+"-修改失败!\n" + fpath+":0x"+vaddr.toString(16)+"-PatchFailed!\n" + result);return false;
    } return true;
}
function DeactiveCodePatch(fpath, vaddr, bytes) {
    return h5frida.DeactiveCodePatch(fpath, vaddr, bytes);
}

/*HERE IS OUR OFFSET PATCHING CODE*/
ActiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDE61EC "C802132B");

To run this code with H5GG in the Dungreed, please follow the earlier H5GG Tutorial Reference #2 - Step 1 and 2 (stop at right before Hooking). 
Reminder: We need H5GG injected as part of sideload. We H5frida (3 files for non-jailbroken - frida-gadget-15.1.24.config, frida-gadget-15.1.24.dylib, h5frida-15.1.24.dylib) packaged inside root of IPA (right inside Payload, not in any subfolder).
Hint: Remember that first run will report error, just ignore it, just download the patched UnityFramework and repackage the ipa. When you run the H5GG script the second time in Dungreed (patched version), it will start effect. If you do not run the script, you will find the binary behave as normal (no Money hack).

To conclude, you have applied the Money Hack to the Dungreed game binary and you can trigger it with H5GG script whenever you want. 
Hint: Even though I didn't mention the Mod Menu part, but you can see this is a Javascript. You can easily include this to a HTML page. More importantly, H5GG can load HTML page the same way you load Javascript. You know what I mean, right!

 

Stage 6 - Static Analysis with Il2cpp dumper + IDA - Hacking Dash (non-H5GG Specific)

Spoiler

We are at dead end, we do not have more address to look into. We need to find a different way out. 

Traditionally, if we want to understand the game/app logic, we would use IDA to disassemble the binary and do string search for Static Analysis on the game binary. The bad news is, every game nowadays is sub_x game. All the core game method names are becoming sub_xxxxx. This makes the Static Analysis process super challenging and requires exception patience and knowledge on arm assembly. 

For Unity game, we have a great news. Il2cpp dumper can dump the method name through the use of the Unity binary and the global-metadata.dat. Then the result can be used by IDA to rename all the sub_x back to its original form, a human readable form. The dump.cs file can even be open by any text editor. This make the entire Static Analysis 10 times easier. 

This Stage 6, we will be covering the static analysis of Dungreed. 

To begin with, we will need to do Il2cpp dump. As explained earlier, Dungreed has .app/Frameworks/UnityFramework.framework as the core binary. It also has  .app/Data/Managed/Metadata/global-metadata.dat at standard location and the metadata file has no encryption. This makes our lives a little bit easier. 
Hint: If you happens to face a game with metadata.dat either encrypted, changed file name / hidden somewhere, or even embedded in binary. You have new way to get the readable version through iGameGod. From version 0.3.0 it has new feature -> Unity Il2cpp Runtime Dumper - Bypass protections by dumping global-metadata.dat from memory!.

Just put these two files into Il2cpp dumper (Online version can be find here). After the dumping, you have able to download an archive called UnityFramework-il2cppdumper

There are quite a number of files inside. But only a few file of our interest here. 

  • dump.cs (store all the human readable metadata of the game core library (classes, properties, methods).
  • ida.py + script.json (to be used by IDA Pro)

For IDA, after you load and UnityFramework library (after it completely finish the process, bottom left hand corner status bar should show "Idle".), to go File -> Script file -> Open the ida.py. It will then pop up a windows and ask for script file. Direct it to open the script.json. Like the initial processing of the UnityFramework file, it will take quite quite sometime to complete the process. 

Let it complete. Again bottom left hand corner status bar should show "Idle". Boom, all the Sub_x function name has changed to human readable name!!!

Happy Static Analysis on IDA. 

For me, I will normally begin with analysing the dump.cs file. Just search for whatever interest you most and see if you are luck enough to get some hits. 

For Dungreed, an action game. Of course, we interest in Player, Character, Enemy,Boss, Money, HP, Damage, Defence, Evade, Speed, Dash, Control status, etc. It might return a bunch of things. You might want to scope down the area to somewhere inside those Key objects of interest Player, Character, Enemy, Boss, etc. 
Hint: If you happens to fail finding any of these classes, it means the developer used some odd name and try to hide from cheater 

In Dungreed, Key classes are Player, Creature, where creature could be any object that can produce damage. Below is an extract of a few interesting class. 
Hint: Every class has 3 sections. i) Fields, ii) Properties, iii) Methods

Class Player

Spoiler
public class Player : MonoBehaviour // TypeDefIndex: 6397
{
	// Fields
	public Player_2P player2P; // 0x18
	public bool doingTrial; // 0x20
	public bool canRun; // 0x21
	public bool mouseUpDash; // 0x22
	[HideInInspector] // RVA: 0x32A80 Offset: 0x32A80 VA: 0x32A80
	public bool mouseUpDash_Start; // 0x23
	public AudioClip mouseUpDashStartClip; // 0x28
	public Timer mouseDashSlowTimer; // 0x30
	[HideInInspector] // RVA: 0x32A90 Offset: 0x32A90 VA: 0x32A90
	public bool endTutorial; // 0x38
	[HideInInspector] // RVA: 0x32AA0 Offset: 0x32AA0 VA: 0x32AA0
	public int directionX; // 0x3C
	[HideInInspector] // RVA: 0x32AB0 Offset: 0x32AB0 VA: 0x32AB0
	public CharacterController2D _characterController2D; // 0x40
	[HideInInspector] // RVA: 0x32AC0 Offset: 0x32AC0 VA: 0x32AC0
	public PlayerDashAttackModule _dashAttackModule; // 0x48
	[HideInInspector] // RVA: 0x32AD0 Offset: 0x32AD0 VA: 0x32AD0
	public JetPackModule _jetPackModule; // 0x50
	[HideInInspector] // RVA: 0x32AE0 Offset: 0x32AE0 VA: 0x32AE0
	public Creature _creature; // 0x58
	[HideInInspector] // RVA: 0x32AF0 Offset: 0x32AF0 VA: 0x32AF0
	public PlayerAbility _ability; // 0x60
	public InteractiveObjectChecker _interactiveObjectChecker; // 0x68
	public GameObject lightObject; // 0x70
	public Transform foodContainer; // 0x78
	public GameObject teleportToTownFx; // 0x80
	public AudioClip teleportClip; // 0x88
	public AudioClip getItemClip; // 0x90
	public AudioClip equipClip; // 0x98
	public AudioClip changeItemSlotClip; // 0xA0
	public AudioClip destroyItemClip; // 0xA8
	public bool canDementionVaultSrorage; // 0xB0
	public int dementionVaultSrorage; // 0xB4
	public int resetTributeOnGameOver; // 0xB8
	public float discountRatio; // 0xBC
	public UI_TargetSelector currentTargetUI; // 0xC0
	public List<UI_AdditionalEffectIcon> additionalEffectIcons; // 0xC8
	public int rewiredPlayerID; // 0xD0
	public Vector2 lastInput; // 0xD4
	public Vector2 lastSubInput; // 0xDC
	public Action<IProceduralDungeon> moveRoomDelegate; // 0xE8
	public Action markNewRoomDelegate; // 0xF0
	public Action clearRoomDelegate; // 0xF8
	private Timer simpleDescendOnewayTimer; // 0x100
	[HeaderAttribute] // RVA: 0x32B00 Offset: 0x32B00 VA: 0x32B00
	public Timer emergencyEscapeTimer; // 0x108
	private bool canUseEmergencyEscape; // 0x110
	public Timer emergencyEscapeCooldownTimer; // 0x118
	public Vector3 latestAvailablePosition; // 0x120
	public bool isInBossBattle; // 0x12C
	[HeaderAttribute] // RVA: 0x32B38 Offset: 0x32B38 VA: 0x32B38
	public int life; // 0x130
	public int minotaurLife; // 0x134
	public bool onRevive; // 0x138
	public GameObject wagonPrefab; // 0x140
	public GameObject wagonObject; // 0x148
	[HeaderAttribute] // RVA: 0x32B70 Offset: 0x32B70 VA: 0x32B70
	public Timer autoAttackInputTimer; // 0x150
	private bool autoAttackState; // 0x158
	private bool inputState; // 0x159
	private bool canAutoAttack; // 0x15A
	private bool isAutoAttack; // 0x15B
	[HideInInspector] // RVA: 0x32BA8 Offset: 0x32BA8 VA: 0x32BA8
	public bool attackInputState; // 0x15C
	public int masterChefCounter; // 0x160
	private List<Creature> allyCreatures; // 0x168
	public List<NPC_Rescuable> rescueNPC; // 0x170
	[HideInInspector] // RVA: 0x32BB8 Offset: 0x32BB8 VA: 0x32BB8
	public int itemShopRerollCounter; // 0x178
	[HideInInspector] // RVA: 0x32BC8 Offset: 0x32BC8 VA: 0x32BC8
	public int itemShopGoldRerollCounter; // 0x17C
	[HideInInspector] // RVA: 0x32BD8 Offset: 0x32BD8 VA: 0x32BD8
	public int foodShopGoldRerollCounter; // 0x180
	[CompilerGeneratedAttribute] // RVA: 0x32BE8 Offset: 0x32BE8 VA: 0x32BE8
	private bool <SoulPerk_ShowPathToRestaurant>k__BackingField; // 0x184
	[CompilerGeneratedAttribute] // RVA: 0x32BF8 Offset: 0x32BF8 VA: 0x32BF8
	private bool <SoulPerk_ShopReroll>k__BackingField; // 0x185
	public List<Status> addedSavableStatus; // 0x188
	public float addedSavableAtkSpeedBonus; // 0x190
	public float addedSavableReloadSpeedBonus; // 0x194
	public List<Player.PerkData> addedPerkList; // 0x198
	public Dictionary<int, MySetEffectInstance> setEffectInstances; // 0x1A0
	public int killExp; // 0x1A8
	public int killEnemyCount; // 0x1AC
	public bool canControl; // 0x1B0
	public int canControlCount; // 0x1B4
	public bool hasPortalShortcut; // 0x1B8
	public int portalShortcutFloor; // 0x1BC
	public Player_Accessory hungerEffectPrefab; // 0x1C0
	public int satiety; // 0x1C8
	public int maxSatiety; // 0x1CC
	public int foodEatCountInTheDungeon; // 0x1D0
	public int satiety_ClearBonus; // 0x1D4
	public int satiety_MoveBonus; // 0x1D8
	public int satiety_FloorMoveBonus; // 0x1DC
	public float satietyDiscount; // 0x1E0
	public List<MyFoodData> foodAlreadyViewed; // 0x1E8
	public List<MyFood> ateFoods; // 0x1F0
	private List<BuildBuff> buffs; // 0x1F8
	private int lockEquipment; // 0x200
	public bool lockSwap; // 0x204
	public Action<Player, ItemOwnInfo> onGetItemDelegate; // 0x208
	public Action<Player, ItemOwnInfo> onThrowItemDelegate; // 0x210
	public List<ItemOwnInfo> bank; // 0x218
	public List<ItemOwnInfo> inventory; // 0x220
	public List<ItemOwnInfo> anvil; // 0x228
	public List<ItemOwnInfo> mysticForge; // 0x230
	private int soul; // 0x238
	public float goldPaneltyRatio; // 0x23C
	public int maxGoldOnDie; // 0x240
	public int additionalGoldOnDie; // 0x244
	public int preventToBringGold; // 0x248
	public int coinBonus; // 0x24C
	public int money; // 0x250
	public int lastMoney; // 0x254
	private int exp; // 0x258
	public int fortune; // 0x25C
	public GameObject basicHandPrefab; // 0x260
	public GameObject basicOffHandPrefab; // 0x268
	public Action<Character_Hand, Character_Hand> onActivateWeapon; // 0x270
	public int activatedWeaponNum; // 0x278
	public bool allowBackgroundReloading; // 0x27C
	public float backgroundReloadingSpeed; // 0x280
	private float swapTime; // 0x284
	private float swapTimer; // 0x288
	public Action<int> swapDelegate; // 0x290
	public Action<Character_Hand[], Character_Hand[]> updateWeaponDelegate; // 0x298
	public AudioClip swapClip; // 0x2A0
	[HeaderAttribute] // RVA: 0x32C08 Offset: 0x32C08 VA: 0x32C08
	public Char_Costume mainCostume; // 0x2A8
	private Char_Costume currentCostume; // 0x2B0
	[HeaderAttribute] // RVA: 0x32C40 Offset: 0x32C40 VA: 0x32C40
	public Character_Hand[] mainHands; // 0x2B8
	public Character_Hand[] offHands; // 0x2C0
	[HeaderAttribute] // RVA: 0x32C78 Offset: 0x32C78 VA: 0x32C78
	public List<Player_Accessory> playerAccessories; // 0x2C8
	[HeaderAttribute] // RVA: 0x32CB0 Offset: 0x32CB0 VA: 0x32CB0
	public ItemOwnInfo equippedCostume; // 0x2D0
	public ItemOwnInfo[] equippedMainWeapons; // 0x2D8
	public ItemOwnInfo[] equippedOffWeapons; // 0x2E0
	public List<ItemOwnInfo> equippedAccessory; // 0x2E8
	public PlayerEquipment[] mainWeaponsEffect; // 0x2F0
	public PlayerEquipment[] offWeaponsEffect; // 0x2F8
	public List<PlayerEquipment> accessoryEffects; // 0x300
	private PlayerEquipment costumeEffect; // 0x308
	public MyWeaponData basicHandData; // 0x310
	public int Test; // 0x318
	[HideInInspector] // RVA: 0x32CE8 Offset: 0x32CE8 VA: 0x32CE8
	public string killerName; // 0x320
	public GameObject explosivePrefab; // 0x328

	// Properties
	public Creature CurrentTarget { get; }
	public bool CanAutoAttack { get; }
	public bool IsAutoAttack { get; }
	public bool SoulPerk_ShowPathToRestaurant { get; set; }
	public bool SoulPerk_ShopReroll { get; set; }
	public bool CanControl { get; }
	public int CountOfEmptyInventory { get; }
	public int Soul { get; }
	public int Money { get; }
	public int EXP { get; }
	public Character_Hand CurrentMainHand { get; }
	public Character_Hand CurrentOffHand { get; }
	public List<ItemOwnInfo> EquippedItems { get; }
	public List<ItemOwnInfo> AllItems { get; }

	// Methods

	// RVA: 0xDE06A0 Offset: 0xDE06A0 VA: 0xDE06A0
	public Creature get_CurrentTarget() { }

	// RVA: 0xDE06C0 Offset: 0xDE06C0 VA: 0xDE06C0
	public bool get_CanAutoAttack() { }

	// RVA: 0xDE06C8 Offset: 0xDE06C8 VA: 0xDE06C8
	public bool get_IsAutoAttack() { }

	// RVA: 0xDE06D0 Offset: 0xDE06D0 VA: 0xDE06D0
	public void SaveMasterChefCount() { }

	// RVA: 0xDE07A8 Offset: 0xDE07A8 VA: 0xDE07A8
	public void LoadMasterChefCount() { }

	// RVA: 0xDE0858 Offset: 0xDE0858 VA: 0xDE0858
	public void AddAllyCreature(Creature creature) { }

	// RVA: 0xDE096C Offset: 0xDE096C VA: 0xDE096C
	public void RemoveAllyCreature(Creature creature) { }

	// RVA: 0xDE0A80 Offset: 0xDE0A80 VA: 0xDE0A80
	public Creature[] GetAllys() { }

	[CompilerGeneratedAttribute] // RVA: 0x43634 Offset: 0x43634 VA: 0x43634
	// RVA: 0xDE0AD4 Offset: 0xDE0AD4 VA: 0xDE0AD4
	public bool get_SoulPerk_ShowPathToRestaurant() { }

	[CompilerGeneratedAttribute] // RVA: 0x43644 Offset: 0x43644 VA: 0x43644
	// RVA: 0xDE0ADC Offset: 0xDE0ADC VA: 0xDE0ADC
	private void set_SoulPerk_ShowPathToRestaurant(bool value) { }

	[CompilerGeneratedAttribute] // RVA: 0x43654 Offset: 0x43654 VA: 0x43654
	// RVA: 0xDE0AE4 Offset: 0xDE0AE4 VA: 0xDE0AE4
	public bool get_SoulPerk_ShopReroll() { }

	[CompilerGeneratedAttribute] // RVA: 0x43664 Offset: 0x43664 VA: 0x43664
	// RVA: 0xDE0AEC Offset: 0xDE0AEC VA: 0xDE0AEC
	private void set_SoulPerk_ShopReroll(bool value) { }

	// RVA: 0xDE0AF4 Offset: 0xDE0AF4 VA: 0xDE0AF4
	public void ActivateSoulPerk(string key) { }

	// RVA: 0xDD57C8 Offset: 0xDD57C8 VA: 0xDD57C8
	public void AddSavableStatus(Status s) { }

	// RVA: 0xDE0B98 Offset: 0xDE0B98 VA: 0xDE0B98
	public void RemoveSavableStatus(Status s) { }

	// RVA: 0xDE0C54 Offset: 0xDE0C54 VA: 0xDE0C54
	public void AddSavableAtkSpeedBonus(float value) { }

	// RVA: 0xDE0C88 Offset: 0xDE0C88 VA: 0xDE0C88
	public void RemoveSavableAtkSpeedBonus(float value) { }

	// RVA: 0xDE0CBC Offset: 0xDE0CBC VA: 0xDE0CBC
	public void AddSavableReloadSpeedBonus(float value) { }

	// RVA: 0xDE0CF0 Offset: 0xDE0CF0 VA: 0xDE0CF0
	public void RemoveSavableReloadSpeedBonus(float value) { }

	// RVA: 0xDDF0E0 Offset: 0xDDF0E0 VA: 0xDDF0E0
	public void AddPerk(Player.PerkData data) { }

	// RVA: 0xDE0D24 Offset: 0xDE0D24 VA: 0xDE0D24
	private MySetEffectData[] Match(int weaponIdx = -1) { }

	// RVA: 0xDE128C Offset: 0xDE128C VA: 0xDE128C
	public void InitializeSetEffect() { }

	// RVA: 0xDE164C Offset: 0xDE164C VA: 0xDE164C
	public void UpdateSetEffect() { }

	// RVA: 0xDE18C4 Offset: 0xDE18C4 VA: 0xDE18C4
	private void OnKillEnemy(Creature deadCreature) { }

	// RVA: 0xDE195C Offset: 0xDE195C VA: 0xDE195C
	public bool get_CanControl() { }

	// RVA: 0xDE197C Offset: 0xDE197C VA: 0xDE197C
	public void Inactivate(bool follow2P) { }

	// RVA: 0xDE1A34 Offset: 0xDE1A34 VA: 0xDE1A34
	public void Inactivate() { }

	// RVA: 0xDE1E28 Offset: 0xDE1E28 VA: 0xDE1E28
	public void Activate(bool follow2P = True) { }

	// RVA: 0xDE3144 Offset: 0xDE3144 VA: 0xDE3144
	public void AddSatiety(int s) { }

	// RVA: 0xDE3164 Offset: 0xDE3164 VA: 0xDE3164
	public void UseSatiety(int s) { }

	// RVA: 0xDE3178 Offset: 0xDE3178 VA: 0xDE3178
	public bool BuffCheck(MyFood food) { }

	// RVA: 0xDE3348 Offset: 0xDE3348 VA: 0xDE3348
	public void AddBuff(MyFood food) { }

	[IteratorStateMachineAttribute] // RVA: 0x43674 Offset: 0x43674 VA: 0x43674
	// RVA: 0xDE37D0 Offset: 0xDE37D0 VA: 0xDE37D0
	private IEnumerator RequestDecreaseSatietyOnMoveFloor(int s) { }

	// RVA: 0xDE3858 Offset: 0xDE3858 VA: 0xDE3858
	public void LockEquipment() { }

	// RVA: 0xDE3868 Offset: 0xDE3868 VA: 0xDE3868
	public void UnlockEquipment() { }

	// RVA: 0xDE3878 Offset: 0xDE3878 VA: 0xDE3878
	public int get_CountOfEmptyInventory() { }

	// RVA: 0xDE3958 Offset: 0xDE3958 VA: 0xDE3958
	public void SetInventory(int index, ItemOwnInfo info) { }

	// RVA: 0xDDA400 Offset: 0xDDA400 VA: 0xDDA400
	public bool GetItem(ItemOwnInfo ownInfo, bool popup = True, bool autoEquipment = True) { }

	// RVA: 0xDE5C28 Offset: 0xDE5C28 VA: 0xDE5C28
	public bool GetItem_Inventory(ItemOwnInfo ownInfo, int i) { }

	// RVA: 0xDE5E08 Offset: 0xDE5E08 VA: 0xDE5E08
	public int get_Soul() { }

	// RVA: 0xDE5E10 Offset: 0xDE5E10 VA: 0xDE5E10
	public void GetSoul(int s) { }

	// RVA: 0xDE5E20 Offset: 0xDE5E20 VA: 0xDE5E20
	public void UseSoul(int s) { }

	// RVA: 0xDE5F00 Offset: 0xDE5F00 VA: 0xDE5F00
	public int get_Money() { }

	// RVA: 0xDE5F08 Offset: 0xDE5F08 VA: 0xDE5F08
	public void AddMoney(int m, bool openMessage = False) { }

	// RVA: 0xDE6190 Offset: 0xDE6190 VA: 0xDE6190
	public bool HasMoney(int m) { }

	// RVA: 0xDE61A0 Offset: 0xDE61A0 VA: 0xDE61A0 -------------------->  + 4C (DE61EC Spend to Increase) 
	public bool UseMoney(int m) { }

	// RVA: 0xDE63BC Offset: 0xDE63BC VA: 0xDE63BC
	public int get_EXP() { }

	// RVA: 0xDE63C4 Offset: 0xDE63C4 VA: 0xDE63C4
	public void AddEXP(int e) { }

	// RVA: 0xDE63D4 Offset: 0xDE63D4 VA: 0xDE63D4
	public bool UseEXP(int e) { }

	// RVA: 0xDE22F8 Offset: 0xDE22F8 VA: 0xDE22F8
	public void UpdateActivatedWeapon() { }

	// RVA: 0xDE63F0 Offset: 0xDE63F0 VA: 0xDE63F0
	public void UpdateSkillCooldownUI() { }

	// RVA: 0xDDC7F4 Offset: 0xDDC7F4 VA: 0xDDC7F4
	public Character_Hand get_CurrentMainHand() { }

	// RVA: 0xDDC834 Offset: 0xDDC834 VA: 0xDDC834
	public Character_Hand get_CurrentOffHand() { }

	// RVA: 0xDE6774 Offset: 0xDE6774 VA: 0xDE6774
	public List<ItemOwnInfo> get_EquippedItems() { }

	// RVA: 0xDD4C64 Offset: 0xDD4C64 VA: 0xDD4C64
	public List<ItemOwnInfo> get_AllItems() { }

	// RVA: 0xDD9BFC Offset: 0xDD9BFC VA: 0xDD9BFC
	public void AddAccessorySlot() { }

	// RVA: 0xDD9CF8 Offset: 0xDD9CF8 VA: 0xDD9CF8
	public void RemoveAccessorySlot() { }

	// RVA: 0xDE69C8 Offset: 0xDE69C8 VA: 0xDE69C8
	public void RemoveAllEquipEffect() { }

	// RVA: 0xDE6C68 Offset: 0xDE6C68 VA: 0xDE6C68
	public void ApplyAllEquipEffect() { }

	// RVA: 0xDE39F4 Offset: 0xDE39F4 VA: 0xDE39F4
	public void EquipItemInInventory(int inventoryIndex, EquipmentSlot slot, bool autoRequest) { }

	// RVA: 0xDE75F0 Offset: 0xDE75F0 VA: 0xDE75F0
	public void ClearInventoryAndEquipments() { }

	// RVA: 0xDE7810 Offset: 0xDE7810 VA: 0xDE7810
	public void ClearInventoryAndEquipments_IgnoreCostume() { }

	// RVA: 0xDDACC8 Offset: 0xDDACC8 VA: 0xDDACC8
	public void UnequipItem(EquipmentSlot slot, bool ignoreBattleState = False, bool ignoreLockEquipment = False) { }

	// RVA: 0xDE6E40 Offset: 0xDE6E40 VA: 0xDE6E40
	public GameObject EquipWeapon(GameObject weaponPrefab, WeaponHandType handType, int weaponIndex) { }

	// RVA: 0xDE79A0 Offset: 0xDE79A0 VA: 0xDE79A0
	public void EquipBasicMainWeapon(int weaponIndex) { }

	// RVA: 0xDE7554 Offset: 0xDE7554 VA: 0xDE7554
	public void EquipBasicOffWeapon(int weaponIndex) { }

	// RVA: 0xDE7BE4 Offset: 0xDE7BE4 VA: 0xDE7BE4
	public void EquipCostume(MyCostumeData costume) { }

	// RVA: 0xDE7F64 Offset: 0xDE7F64 VA: 0xDE7F64
	private void EquipCostume(GameObject equipmentPrefab) { }

	// RVA: 0xDE8648 Offset: 0xDE8648 VA: 0xDE8648
	public void MoveRoom(IProceduralDungeon dungeon) { }

	// RVA: 0xDE8734 Offset: 0xDE8734 VA: 0xDE8734
	public void OnMarkNewRoom(IProceduralDungeon dungeon) { }

	// RVA: 0xDE8760 Offset: 0xDE8760 VA: 0xDE8760
	public void OnClearRoom(EnemyZone zone) { }

	// RVA: 0xDE88AC Offset: 0xDE88AC VA: 0xDE88AC
	public void OnMoveFloor(int floor) { }

	// RVA: 0xDE8908 Offset: 0xDE8908 VA: 0xDE8908
	private void Awake() { }

	// RVA: 0xDE8FC8 Offset: 0xDE8FC8 VA: 0xDE8FC8
	private void Start() { }

	// RVA: 0xDE8FD4 Offset: 0xDE8FD4 VA: 0xDE8FD4
	private void Update() { }

	// RVA: 0xDEFBF8 Offset: 0xDEFBF8 VA: 0xDEFBF8
	private void LateUpdate() { }

	// RVA: 0xDEFB34 Offset: 0xDEFB34 VA: 0xDEFB34
	public void StartMouseUpDash() { }

	// RVA: 0xDEFB6C Offset: 0xDEFB6C VA: 0xDEFB6C
	public bool UpdateMouseUpDash() { }

	// RVA: 0xDEFBC0 Offset: 0xDEFBC0 VA: 0xDEFBC0
	public void EndMouseUpDash() { }

	// RVA: 0xDEF9D4 Offset: 0xDEF9D4 VA: 0xDEF9D4
	public void AutoAttackEnd() { }

	// RVA: 0xDF00BC Offset: 0xDF00BC VA: 0xDF00BC
	private void OnHit(Creature creature, Creature.HitData data) { }

	// RVA: 0xDF00C0 Offset: 0xDF00C0 VA: 0xDF00C0
	private void OnDie(Creature creature, string hitterName) { }

	// RVA: 0xDF02DC Offset: 0xDF02DC VA: 0xDF02DC
	public void ActivateAutoAttack() { }

	// RVA: 0xDF02E8 Offset: 0xDF02E8 VA: 0xDF02E8
	public void InactivateAutoAttack() { }

	// RVA: 0xDED868 Offset: 0xDED868 VA: 0xDED868
	public void EmergencyEscape() { }

	[IteratorStateMachineAttribute] // RVA: 0x436DC Offset: 0x436DC VA: 0x436DC
	// RVA: 0xDF01DC Offset: 0xDF01DC VA: 0xDF01DC
	private IEnumerator ReviveCoroutine() { }

	[IteratorStateMachineAttribute] // RVA: 0x43744 Offset: 0x43744 VA: 0x43744
	// RVA: 0xDF025C Offset: 0xDF025C VA: 0xDF025C
	private IEnumerator MinotaurReviveCoroutine() { }

	[IteratorStateMachineAttribute] // RVA: 0x437AC Offset: 0x437AC VA: 0x437AC
	// RVA: 0xDED7E8 Offset: 0xDED7E8 VA: 0xDED7E8
	public IEnumerator MoveToTownCoroutine() { }

	// RVA: 0xDF0968 Offset: 0xDF0968 VA: 0xDF0968
	public void TeleportToTown() { }

	// RVA: 0xDF0C60 Offset: 0xDF0C60 VA: 0xDF0C60
	private void _TeleportToTown() { }

	// RVA: 0xDF0C68 Offset: 0xDF0C68 VA: 0xDF0C68
	private void OnCompleteReload(bool rapidReload) { }

	// RVA: 0xDF0D78 Offset: 0xDF0D78 VA: 0xDF0D78
	private void OnCompleteReload_Off(bool rapidReload) { }

	// RVA: 0xDF0E88 Offset: 0xDF0E88 VA: 0xDF0E88
	private void OnBeginStun() { }

	// RVA: 0xDF0F78 Offset: 0xDF0F78 VA: 0xDF0F78
	public void WorldLoaded(Scene scene, LoadSceneMode mode) { }

	// RVA: 0xDF02F0 Offset: 0xDF02F0 VA: 0xDF02F0
	public void SetRoomPosition(Vector3 roomPos) { }

	// RVA: 0xDED648 Offset: 0xDED648 VA: 0xDED648
	public void Pause() { }

	// RVA: 0xDEEA9C Offset: 0xDEEA9C VA: 0xDEEA9C
	public void SwapWeapon() { }

	// RVA: 0xDF1774 Offset: 0xDF1774 VA: 0xDF1774
	public void CalculateKillInfo() { }

	// RVA: 0xDF1AE0 Offset: 0xDF1AE0 VA: 0xDF1AE0
	public void DropGold() { }

	// RVA: 0xDF1C30 Offset: 0xDF1C30 VA: 0xDF1C30
	public void ResetGold() { }

	// RVA: 0xDF1D10 Offset: 0xDF1D10 VA: 0xDF1D10
	public void AddDieCount() { }

	// RVA: 0xDF1E10 Offset: 0xDF1E10 VA: 0xDF1E10
	public void SavePlayerInfo() { }

	// RVA: 0xDE5E30 Offset: 0xDE5E30 VA: 0xDE5E30
	public void SaveSoul() { }

	// RVA: 0xDF1FA8 Offset: 0xDF1FA8 VA: 0xDF1FA8
	public void LoadSavedData() { }

	// RVA: 0xDEFD80 Offset: 0xDEFD80 VA: 0xDEFD80
	public void MouseUpDash_Slow(bool slow) { }

	// RVA: 0xDF2A04 Offset: 0xDF2A04 VA: 0xDF2A04
	public void CreateExplosiveToBullet(Bullet bullet) { }

	// RVA: 0xDEEC68 Offset: 0xDEEC68 VA: 0xDEEC68
	private void AutoFindTarget() { }

	// RVA: 0xDEF1A0 Offset: 0xDEF1A0 VA: 0xDEF1A0
	private void ChangeTargetBySubInput(Vector2 subInput) { }

	// RVA: 0xDEF808 Offset: 0xDEF808 VA: 0xDEF808
	private bool IsTheEnemyInCameraArea(Creature enemy) { }

	// RVA: 0xDF2C88 Offset: 0xDF2C88 VA: 0xDF2C88
	public void SavePlayerData() { }

	// RVA: 0xDF567C Offset: 0xDF567C VA: 0xDF567C
	public void LoadPlayerData() { }

	// RVA: 0xDF5034 Offset: 0xDF5034 VA: 0xDF5034
	private void SaveItem(ItemOwnInfo info, string slotKey) { }

	// RVA: 0xDF76F0 Offset: 0xDF76F0 VA: 0xDF76F0
	private ItemOwnInfo GetSavedItem(string slotKey) { }

	// RVA: 0xDF7D0C Offset: 0xDF7D0C VA: 0xDF7D0C
	public void .ctor() { }
}

 

From Player's Fields, we find a whole lot of interesting attributes of Player. Short list of examples are like:

  • public CharacterController2D _characterController2D; // 0x40 ---> Take note on it first, we will talk about it later

  • public Creature _creature; // 0x58 ---> Linkage to player's creature object. Yes, a Player in Dungreed is also a creature.
  • public int money; // 0x250  ----> Does it looks familiar? Yes, it is our previous Money Hack Offset
  • public int lastMoney; // 0x254 ----> We finally know what is this money backup. It is last Money we have. 
  • private int exp; // 0x258 ----> Experience? Does it mean we can immediately level max? I let you to try it out. 
  • public int fortune; // 0x25C ----> Crazy! What are we looking at!! Fortune (Luck), it is a very important attribute that affect our drop in game. 

This is just a very short list. There are so many possibility here. 

From Player's Method (generally, I will skip the Properties part as I will find similar thing in Methods part anyway). 

  • public bool UseMoney(int m) { } // RVA: 0xDE61A0 Offset: 0xDE61A0 VA: 0xDE61A0 ----> This contains the offset that we hack in Money hack + 4C (DE61EC Spend to Increase) 
  • public void RemoveAllEquipEffect() { } // RVA: 0xDE69C8 Offset: 0xDE69C8 VA: 0xDE69C8 ----> Might be we can do something with it, as it is the legit method in game to change the Equipment effect on Player. 
  • public void ApplyAllEquipEffect() { } // RVA: 0xDE6C68 Offset: 0xDE6C68 VA: 0xDE6C68 ----> Might be we can do something with it, as it is the legit method in game to change the Equipment effect on Player. 

Anyway, spend sometime to on things that interest you. Mark your own note on them, reserve them to do your own test later. 

Class Creature

Spoiler
public class Creature : MonoBehaviour // TypeDefIndex: 5889
{
	// Fields
	public Creature.CreatureType creatureType; // 0x18
	public bool canBeTarget; // 0x1C
	public string aName; // 0x20
	public Vector2 size; // 0x28
	public float autoAttackBonusValue; // 0x30
	public List<ActiveSkill> skills; // 0x38
	public int expAmount; // 0x40
	private float shieldRegenTimer; // 0x44
	private float shieldRegenTime; // 0x48
	private float shieldRegenSpeed; // 0x4C
	private int onBattleCount; // 0x50
	public bool allowRapidReload; // 0x54
	public AudioClip rapidReloadSucceededClip; // 0x58
	public AudioClip rapidReloadFailedClip; // 0x60
	public Status status; // 0x68
	private float regenerationTimer; // 0x70
	public bool ignoreDefense; // 0x74
	public float atkSpeedBonus; // 0x78
	public float reloadSpeedBonus; // 0x7C
	public float atkBonusRatio; // 0x80
	public float defBonusRatio; // 0x84
	public int boostPower; // 0x88
	public int goldDamageBonus; // 0x8C
	public int infinityShot; // 0x90
	public float meleeRangeBonusPercent; // 0x94
	[CompilerGeneratedAttribute] // RVA: 0x2FEFC Offset: 0x2FEFC VA: 0x2FEFC
	private float <WeaponChargeBonus>k__BackingField; // 0x98
	public bool canUseAbsolusteDodge; // 0x9C
	private int remainingAbsoluteDodge; // 0xA0
	public GameObject absoluteDodgeObject; // 0xA8
	public float activeSkillCoolDownBonus; // 0xB0
	[HeaderAttribute] // RVA: 0x2FF0C Offset: 0x2FF0C VA: 0x2FF0C
	public int absoluteInvincible; // 0xB4
	[HeaderAttribute] // RVA: 0x2FF44 Offset: 0x2FF44 VA: 0x2FF44
	public int hitOnlyInvincible; // 0xB8
	[HeaderAttribute] // RVA: 0x2FF7C Offset: 0x2FF7C VA: 0x2FF7C
	public float invincibleTime; // 0xBC
	private float invincibleTimer; // 0xC0
	private bool isInvincible; // 0xC4
	[HeaderAttribute] // RVA: 0x2FFB4 Offset: 0x2FFB4 VA: 0x2FFB4
	public bool isUseDamageLimit; // 0xC5
	public float dpsLimit; // 0xC8
	private Timer damageLimitResetTimer; // 0xD0
	private Timer damageCheckTimer; // 0xD8
	private float damageStack; // 0xE0
	private float damageLimitRatio; // 0xE4
	private bool onDamageLimit; // 0xE8
	[SpaceAttribute] // RVA: 0x2FFEC Offset: 0x2FFEC VA: 0x2FFEC
	public bool isRealCreature; // 0xE9
	private bool isDie; // 0xEA
	public bool isQuietdeath; // 0xEB
	public bool canAttack; // 0xEC
	public bool isReviving; // 0xED
	public float revivingTimer; // 0xF0
	public float revivingTime; // 0xF4
	public AudioClip hitClip; // 0xF8
	public AudioClip blockClip; // 0x100
	public AudioClip evadeClip; // 0x108
	public AudioClip absoluteEvadeClip; // 0x110
	public AudioClip dieClip; // 0x118
	public AudioClip dieVoiceClip; // 0x120
	public GameObject corpsePrefab; // 0x128
	public Action<ConditionElement> onAppliedCondition; // 0x130
	public Action<ConditionElement> onRemovedCondition; // 0x138
	public EnhancedEnemy _enhancedEnemy; // 0x140
	[HideInInspector] // RVA: 0x30000 Offset: 0x30000 VA: 0x30000
	public Rigidbody2D _rigidbody2D; // 0x148
	[HideInInspector] // RVA: 0x30010 Offset: 0x30010 VA: 0x30010
	public CharacterController2D _controller2D; // 0x150
	public SpriteRenderer _renderer; // 0x158
	[HideInInspector] // RVA: 0x30020 Offset: 0x30020 VA: 0x30020
	public List<SpriteRenderer> _otherRenderers; // 0x160
	public Material hitMaterial; // 0x168
	private Material mainMaterial; // 0x170
	private List<Material> otherMaterials; // 0x178
	private Player player; // 0x180
	[HeaderAttribute] // RVA: 0x30030 Offset: 0x30030 VA: 0x30030
	public Sprite handSprite; // 0x188
	[HeaderAttribute] // RVA: 0x30068 Offset: 0x30068 VA: 0x30068
	public bool destroyOnDie; // 0x190
	public GameObject dieEffectPrefab; // 0x198
	public GameObject hitEffectPrefab; // 0x1A0
	public Action<Creature, int> onBlockByLasleyShield; // 0x1A8
	public Action<Creature, int> onBlockBySuperShield; // 0x1B0
	public Action<Creature, Creature.HitData> beHitDelegate; // 0x1B8
	public Action<Creature, Creature.HitData> beHitDelegate_after; // 0x1C0
	public Action<Creature, string> dieDelegate; // 0x1C8
	public Action<Creature, Creature.HitData> onHitTargetDelegate; // 0x1D0
	public Action<Creature, Creature.HitData> onHitTargetDelegate_Phase2; // 0x1D8
	public Action<Creature> onKillTargetDelegate; // 0x1E0
	public Action<Creature, Creature.HitData> lastHitDelegate; // 0x1E8
	public Action<Creature> onStartBattle; // 0x1F0
	public Action<Creature> onEndBattle; // 0x1F8
	public Action reviveDelegate; // 0x200
	public Action beginStun; // 0x208
	public Action endStun; // 0x210
	public List<CreatureCondition> conditions; // 0x218
	public float dropGoldRatio; // 0x220
	private Coroutine hitProcCoroutine; // 0x228

	// Properties
	public Vector3 CenterPosition { get; set; }
	public bool IsOnBattle { get; }
	public float WeaponChargeBonus { get; set; }
	public int RemainingAbsoluteDodge { get; set; }
	public bool IsDie { get; }

	// Methods

	// RVA: 0x1010A9C Offset: 0x1010A9C VA: 0x1010A9C
	public Vector3 get_CenterPosition() { }

	// RVA: 0x1010B70 Offset: 0x1010B70 VA: 0x1010B70
	public void set_CenterPosition(Vector3 value) { }

	// RVA: 0x1010C18 Offset: 0x1010C18 VA: 0x1010C18
	public ActiveSkill FindSkill(SkillData data) { }

	// RVA: 0x1010D30 Offset: 0x1010D30 VA: 0x1010D30
	public bool get_IsOnBattle() { }

	// RVA: 0x1010D40 Offset: 0x1010D40 VA: 0x1010D40
	public void BeginBattle() { }

	// RVA: 0x1010DA4 Offset: 0x1010DA4 VA: 0x1010DA4
	public void EndBattle() { }

	[CompilerGeneratedAttribute] // RVA: 0x3FE3C Offset: 0x3FE3C VA: 0x3FE3C
	// RVA: 0x1010E10 Offset: 0x1010E10 VA: 0x1010E10
	public float get_WeaponChargeBonus() { }

	[CompilerGeneratedAttribute] // RVA: 0x3FE4C Offset: 0x3FE4C VA: 0x3FE4C
	// RVA: 0x1010E18 Offset: 0x1010E18 VA: 0x1010E18
	public void set_WeaponChargeBonus(float value) { }

	// RVA: 0x1010E20 Offset: 0x1010E20 VA: 0x1010E20
	public int get_RemainingAbsoluteDodge() { }

	// RVA: 0x1010E28 Offset: 0x1010E28 VA: 0x1010E28
	public void set_RemainingAbsoluteDodge(int value) { }

	// RVA: 0x1010F7C Offset: 0x1010F7C VA: 0x1010F7C
	public float GetFinalDamage(float damage, Creature.HitData.AttackFromType attackFromType) { }

	// RVA: 0x1011180 Offset: 0x1011180 VA: 0x1011180
	public float GetFinalDEF() { }

	// RVA: 0x10111AC Offset: 0x10111AC VA: 0x10111AC
	public float GetDamageResist(float finalDEF) { }

	// RVA: 0x1011214 Offset: 0x1011214 VA: 0x1011214
	public float GetEvasionValue(float evasion) { }

	// RVA: 0x1011274 Offset: 0x1011274 VA: 0x1011274
	public float GetBlockValue(float block) { }

	// RVA: 0x1011290 Offset: 0x1011290 VA: 0x1011290
	public float GetCriticalValue(float critical) { }

	// RVA: 0x10112E4 Offset: 0x10112E4 VA: 0x10112E4
	public bool get_IsDie() { }

	// RVA: 0x10112EC Offset: 0x10112EC VA: 0x10112EC
	public void SetRenderer(SpriteRenderer r) { }

	// RVA: 0x1011334 Offset: 0x1011334 VA: 0x1011334
	private void OnDrawGizmos() { }

	// RVA: 0x101135C Offset: 0x101135C VA: 0x101135C
	private void Awake() { }

	// RVA: 0x1011560 Offset: 0x1011560 VA: 0x1011560
	private void Update() { }

	// RVA: 0x10118DC Offset: 0x10118DC VA: 0x10118DC
	public float Heal(float h) { }

	// RVA: 0x1011948 Offset: 0x1011948 VA: 0x1011948
	public float HealPercent(float ratio) { }

	// RVA: 0x10119E0 Offset: 0x10119E0 VA: 0x10119E0
	public void ApplyDamage(Creature hitter, float damage, Color color, string hitterName = "", bool absolute = False, bool changeWarningColor = False, bool playHitClip = False) { }

	// RVA: 0x1012578 Offset: 0x1012578 VA: 0x1012578
	public bool Hit(Creature hitter, float damage, Vector2 attVelocity, Vector3 hitPoint, string hitterName = "", ForceMode2D forceMode = 0, Creature.HitType hitType = 0, Creature.HitData.AttackFromType fromType = 0, Bullet bulletObject, int trueDamage = 0, bool isMainWeapon = False) { }

	// RVA: 0x10121B0 Offset: 0x10121B0 VA: 0x10121B0
	public void Die(Creature hitter, string hitterName) { }

	// RVA: 0x1014BA4 Offset: 0x1014BA4 VA: 0x1014BA4
	public void MakeInvincible(bool invincible) { }

	// RVA: 0x1013F48 Offset: 0x1013F48 VA: 0x1013F48
	public bool IsInvincible() { }

	// RVA: 0x1014BC0 Offset: 0x1014BC0 VA: 0x1014BC0
	public void Revive(float hpRatio) { }

	// RVA: 0x1014CE0 Offset: 0x1014CE0 VA: 0x1014CE0
	public void GetStun(float duration) { }

	[IteratorStateMachineAttribute] // RVA: 0x3FE5C Offset: 0x3FE5C VA: 0x3FE5C
	// RVA: 0x10124F8 Offset: 0x10124F8 VA: 0x10124F8
	private IEnumerator HitProc() { }

	// RVA: 0x1014D90 Offset: 0x1014D90 VA: 0x1014D90
	public void ReturnToMainMaterial() { }

	// RVA: 0x10147B8 Offset: 0x10147B8 VA: 0x10147B8
	public void ApplyConditions(Creature hitter, bool applyBurn, bool applyPoison, bool applyShock, bool applyStun, bool applyChill, AudioClip burnClip, bool ignoreInvincible = False) { }

	// RVA: 0x1014EE4 Offset: 0x1014EE4 VA: 0x1014EE4
	public void AddOtherSpriteRenderer(SpriteRenderer r) { }

	// RVA: 0x1014FC0 Offset: 0x1014FC0 VA: 0x1014FC0
	public void RemoveOtherSpriteRenderer(SpriteRenderer r) { }

	// RVA: 0x101509C Offset: 0x101509C VA: 0x101509C
	public void .ctor() { }
}

 

From Creature's Fields, we find a whole lot of interesting attributes of Creature. Short list of examples are like:

  • public Status status; // 0x68 ---> Take note on it first, we will talk about it later

  • public int absoluteInvincible; // 0xB4 ---> This make you Invincible. Hello God mode!
  • public int hitOnlyInvincible; // 0xB8  ----> This make you Invincible on Hit. Looks like you will still die by other mean
  • public bool isRealCreature; // 0xE9 ----> Interesting, are there any non real creature? Yes, there are creature that is object but which will provide damage like traps.  
  • public CharacterController2D _controller2D; // 0x150 ----> Take note on it first, we will talk about it later
  • private Player player; // 0x180 ----> Linkage to creature's player object, if the creature is a player  

This is just a very short list. Like Player class, there are so many possibility here. 

From Creature's Method (as said earlier, I will generally skip the Properties part). 

  • public void ApplyDamage(Creature hitter, float damage, Color color, string hitterName = "", bool absolute = False, bool changeWarningColor = False, bool playHitClip = False) { } // RVA: 0x10119E0 Offset: 0x10119E0 VA: 0x10119E0

  • public bool Hit(Creature hitter, float damage, Vector2 attVelocity, Vector3 hitPoint, string hitterName = "", ForceMode2D forceMode = 0, Creature.HitType hitType = 0, Creature.HitData.AttackFromType fromType = 0, Bullet bulletObject, int trueDamage = 0, bool isMainWeapon = False) { } // RVA: 0x1012578 Offset: 0x1012578 VA: 0x1012578
  • public void MakeInvincible(bool invincible) { } // RVA: 0x1014BA4 Offset: 0x1014BA4 VA: 0x1014BA4 ----> This make a creature invincible? What if I disable this? Will it make tough boss easier? 
  • public void ApplyConditions(Creature hitter, bool applyBurn, bool applyPoison, bool applyShock, bool applyStun, bool applyChill, AudioClip burnClip, bool ignoreInvincible = False) { } // RVA: 0xDE6C68 Offset: 0xDE6C68 VA: 0xDE6C68 ----> Wow, burn, poison, shock, stun, chill, so many condition there. 

Anyway, spend sometime to on things that interest you. Mark your own note on them, reserve them to do your own test later. 

Class Status

Spoiler
public class Status // TypeDefIndex: 6521
{
	// Fields
	public bool lockHP; // 0x10
	public float hp; // 0x14
	public float maxHP; // 0x18
	public float bonusHPRatio; // 0x1C
	public float shield; // 0x20
	public float maxShield; // 0x24
	public int tempSuperShield; // 0x28
	public int superShield; // 0x2C
	public float offense; // 0x30
	public float maxOffense; // 0x34
	public float defense; // 0x38
	public float additionalTrueDamage; // 0x3C
	public int power; // 0x40
	public int power_direct; // 0x44
	public int toughness; // 0x48
	public int vitality; // 0x4C
	public float critical; // 0x50
	public float evasion; // 0x54
	public float block; // 0x58
	public int ignoreDefensePercent; // 0x5C
	public float criticalDamageRate; // 0x60
	public int regeneration; // 0x64
	public int regeneration_nobattle; // 0x68
	public float burnPower; // 0x6C
	public float poisonPower; // 0x70
	public float stunPower; // 0x74
	public float chillPower; // 0x78
	public float shockPower; // 0x7C
	public float bleedPower; // 0x80
	public int immuneBurn; // 0x84
	public int immunePoison; // 0x88
	public int immuneStun; // 0x8C
	public int immuneChill; // 0x90
	public int immuneShock; // 0x94
	public int precision; // 0x98
	public int enhancedChill; // 0x9C
	public int allowedOverlapPoison; // 0xA0
	public int allowedOverlapBurn; // 0xA4
	public int burnAdditionalDamage; // 0xA8
	public int poisonAdditionalDamage; // 0xAC
	public int burnSpeed; // 0xB0
	public int poisonSpeed; // 0xB4
	public int burnDuration; // 0xB8
	public int poisonDuration; // 0xBC
	public int chillDuration; // 0xC0
	public int shockDuration; // 0xC4
	public int stunDuration; // 0xC8
	public int shockDefense; // 0xCC
	public int chillDecreaseSpeed; // 0xD0
	public float bulletResist; // 0xD4
	public float meleeResist; // 0xD8
	private List<Status> added; // 0xE0

	// Methods

	// RVA: 0xE656D0 Offset: 0xE656D0 VA: 0xE656D0
	public float GetMAXHP() { }

	// RVA: 0xE656E0 Offset: 0xE656E0 VA: 0xE656E0
	public void AddMAXHP(float value) { }

	// RVA: 0xE65728 Offset: 0xE65728 VA: 0xE65728
	public void AddMAXHPPercent(float value) { }

	// RVA: 0xE6576C Offset: 0xE6576C VA: 0xE6576C
	public float GetCurHPRatio() { }

	// RVA: 0xE6578C Offset: 0xE6578C VA: 0xE6578C
	public void .ctor() { }

	// RVA: 0xE59AD8 Offset: 0xE59AD8 VA: 0xE59AD8
	public void Add(Status s) { }

	// RVA: 0xE59C08 Offset: 0xE59C08 VA: 0xE59C08
	public void Remove(Status s) { }
}

 

From Status Fields, we find a whole lot of interesting attributes of Status. Short list of examples are like:

  • public float hp; // 0x14 ---> HP!!!! It hides so deep...We finally find it

  • public float maxHP; // 0x18 ---> maxHP should next to HP as expected
  • public float defense; // 0x38  ----> Defense as well, nice
  • public float critical; // 0x50 ----> Critical, from its name not sure it is Critical Rate or Critical Damage. Anyway, we do not see the other one in status. Hiding again?  
  • public float evasion; // 0x54 ----> Evasion, can we evade everything? or make enemy cannot evade any hit (we will never miss)
  • public float block; // 0x58 ----> Block, same as above, interesting attribute that we can play around
  • private List<Status> added; // 0xE0 ---> Apparently, there is not only one status object?

This is just a very short list. Like Player class, there are so many possibility here. 

From Status's Method (as said earlier, I will generally skip the Properties part). 

  • public void AddMAXHP(float value) { } // RVA: 0xE656E0 Offset: 0xE656E0 VA: 0xE656E0 ---> Buff on HP? Can we amplify the buff for Player? 

  • public void AddMAXHPPercent(float value) { } // RVA: 0xE65728 Offset: 0xE65728 VA: 0xE65728 ---> Same as above, just Buff on HP base on a percentage
  • public float GetCurHPRatio() { }public void MakeInvincible(bool invincible) { } // RVA: 0xE6576C Offset: 0xE6576C VA: 0xE6576C ---> Does it affect the current HP after adding MAXHP? If current HP is full, even after adding MaxHP, our HP is full as well? 

Anyway, spend sometime to on things that interest you. Mark your own note on them, reserve them to do your own test later. 

Class CharacterController2D

Spoiler
public class CharacterController2D : MonoBehaviour // TypeDefIndex: 5858
{
	// Fields
	public const string anim_IsGrounded = "IsGrounded";
	public const string anim_VerticalMove = "VerticalMove";
	public const string anim_IsHorizontalMove = "IsHorizontalMove";
	public const string anim_HorizontalMove = "HorizontalMove";
	public const string anim_IsWalk = "IsWalk";
	public int animHash_IsGrounded; // 0x18
	public int animHash_VerticalMove; // 0x1C
	public int animHash_IsHorizontalMove; // 0x20
	public int animHash_HorizontalMove; // 0x24
	public int animHash_IsWalk; // 0x28
	private bool hasHash_IsGrounded; // 0x2C
	private bool hasHash_VerticalMove; // 0x2D
	private bool hasHash_IsHorizontalMove; // 0x2E
	private bool hasHash_HorizontalMove; // 0x2F
	private bool hasHash_IsWalk; // 0x30
	public CharacterController2D.State state; // 0x34
	public Action idleDelegate; // 0x38
	public Action runDelegate; // 0x40
	public Action attackDelegate; // 0x48
	public Action downDelegate; // 0x50
	public Action dashDelegate; // 0x58
	public Action dashEndDelegate; // 0x60
	public Action onGroundedDelegate; // 0x68
	public Action airbourneDelegate; // 0x70
	public Action beginJumpDelegate; // 0x78
	public Action jumpPressingDelegate; // 0x80
	public float mass; // 0x88
	public float accelerationTimeAirborne; // 0x8C
	public float accelerationTimeGrounded; // 0x90
	public float moveSpeed; // 0x94
	public float speedBonus; // 0x98
	[HideInInspector] // RVA: 0x2FCA4 Offset: 0x2FCA4 VA: 0x2FCA4
	public bool inputWalk; // 0x9C
	[HideInInspector] // RVA: 0x2FCB4 Offset: 0x2FCB4 VA: 0x2FCB4
	public float applySlowRatio; // 0xA0
	public int maxDashCount; // 0xA4
	[HideInInspector] // RVA: 0x2FCC4 Offset: 0x2FCC4 VA: 0x2FCC4
	public int ramainingDashCount; // 0xA8
	public float dashChargeInterval; // 0xAC
	public float dashChargeSpeedBonus; // 0xB0
	public float dashChargeTimer; // 0xB4
	public bool canUseDash; // 0xB8
	[CompilerGeneratedAttribute] // RVA: 0x2FCD4 Offset: 0x2FCD4 VA: 0x2FCD4
	private bool <IsMoonWalking>k__BackingField; // 0xB9
	public BasicModule[] modules; // 0xC0
	[HeaderAttribute] // RVA: 0x2FCE4 Offset: 0x2FCE4 VA: 0x2FCE4
	public int flyModeCount; // 0xC8
	public int unstableFlyModeCount; // 0xCC
	[HideInInspector] // RVA: 0x2FD1C Offset: 0x2FD1C VA: 0x2FD1C
	public bool canFly; // 0xD0
	[HeaderAttribute] // RVA: 0x2FD2C Offset: 0x2FD2C VA: 0x2FD2C
	public bool applyInput; // 0xD1
	[CompilerGeneratedAttribute] // RVA: 0x2FD64 Offset: 0x2FD64 VA: 0x2FD64
	private int <ApplyInputCount>k__BackingField; // 0xD4
	public Vector2 inputVelocity; // 0xD8
	public bool canMove; // 0xE0
	public const float GRAVITY = 42.5;
	public float gravityScale; // 0xE4
	public CharacterController2D.GravityType gravityType; // 0xE8
	public float jumpVelocity; // 0xEC
	public Vector3 velocity; // 0xF0
	public Vector3 realVelocity; // 0xFC
	[HeaderAttribute] // RVA: 0x2FD74 Offset: 0x2FD74 VA: 0x2FD74
	public int jumpCount; // 0x108
	public int currentJumpCount; // 0x10C
	public bool jumpOnGroundFx_UseFxPool; // 0x110
	public GameObject jumpOnGroundFxPrefab; // 0x118
	public GameObject jumpOnAirborneFxPrefab; // 0x120
	public GameObject landingFxPrefab; // 0x128
	public float maxJumpTime; // 0x130
	private float jumpTimer; // 0x134
	private bool jumpPressed; // 0x138
	public bool useCoyoteTime; // 0x139
	public Timer coyteTimer; // 0x140
	[HeaderAttribute] // RVA: 0x2FDAC Offset: 0x2FDAC VA: 0x2FDAC
	public Vector3 dashStartVelocity; // 0x148
	public bool isDashing; // 0x154
	public bool dashMove; // 0x155
	private float dashTimer; // 0x158
	private float dashTime; // 0x15C
	public float dashTimeMultiplyer; // 0x160
	public readonly float DashSpeed; // 0x164
	[HeaderAttribute] // RVA: 0x2FDE4 Offset: 0x2FDE4 VA: 0x2FDE4
	public GameObject dashFxPrefab; // 0x168
	public GameObject dashStartFxPrefab; // 0x170
	private float dashFxTimer; // 0x178
	[HeaderAttribute] // RVA: 0x2FE1C Offset: 0x2FE1C VA: 0x2FE1C
	public bool createFootstepFx; // 0x17C
	public bool createFootstepFx_UseFxPool; // 0x17D
	public GameObject footDustFx; // 0x180
	private float footDustFxTimer; // 0x188
	[HeaderAttribute] // RVA: 0x2FE54 Offset: 0x2FE54 VA: 0x2FE54
	public AdvancedBasicController _controller; // 0x190
	public SpriteRenderer _spriteRenderer; // 0x198
	public Animator _animator; // 0x1A0
	private Creature _creature; // 0x1A8
	[HeaderAttribute] // RVA: 0x2FE8C Offset: 0x2FE8C VA: 0x2FE8C
	public AudioClip jumpClip; // 0x1B0
	public AudioClip dashClip; // 0x1B8
	public AudioClip[] footstepClips; // 0x1C0
	[CompilerGeneratedAttribute] // RVA: 0x2FEC4 Offset: 0x2FEC4 VA: 0x2FEC4
	private Action OnRequestJump; // 0x1C8
	private bool dashIgnoreOneway; // 0x1D0

	// Properties
	public int Direction { get; }
	public bool IsMoonWalking { get; set; }
	public bool IsFlyMode { get; }
	public int FlyModeCount { get; set; }
	public int ApplyInputCount { get; set; }
	public bool IsExceedJumpCount { get; }
	public bool IsJumpTimeMax { get; }
	public Creature Creature { get; }
	public bool IsGrounded { get; }

	// Methods

	// RVA: 0xFDAB6C Offset: 0xFDAB6C VA: 0xFDAB6C
	public int get_Direction() { }

	[CompilerGeneratedAttribute] // RVA: 0x3FDDC Offset: 0x3FDDC VA: 0x3FDDC
	// RVA: 0xFDABB8 Offset: 0xFDABB8 VA: 0xFDABB8
	public bool get_IsMoonWalking() { }

	[CompilerGeneratedAttribute] // RVA: 0x3FDEC Offset: 0x3FDEC VA: 0x3FDEC
	// RVA: 0xFDABC0 Offset: 0xFDABC0 VA: 0xFDABC0
	public void set_IsMoonWalking(bool value) { }

	// RVA: 0xFDABC8 Offset: 0xFDABC8 VA: 0xFDABC8
	public bool get_IsFlyMode() { }

	// RVA: 0xFDABEC Offset: 0xFDABEC VA: 0xFDABEC
	public int get_FlyModeCount() { }

	// RVA: 0xFDABF4 Offset: 0xFDABF4 VA: 0xFDABF4
	public void set_FlyModeCount(int value) { }

	// RVA: 0xFDABFC Offset: 0xFDABFC VA: 0xFDABFC
	public void BeginFlyMode() { }

	// RVA: 0xFDAC0C Offset: 0xFDAC0C VA: 0xFDAC0C
	public void EndFlyMode() { }

	[CompilerGeneratedAttribute] // RVA: 0x3FDFC Offset: 0x3FDFC VA: 0x3FDFC
	// RVA: 0xFDAC1C Offset: 0xFDAC1C VA: 0xFDAC1C
	public int get_ApplyInputCount() { }

	[CompilerGeneratedAttribute] // RVA: 0x3FE0C Offset: 0x3FE0C VA: 0x3FE0C
	// RVA: 0xFDAC24 Offset: 0xFDAC24 VA: 0xFDAC24
	public void set_ApplyInputCount(int value) { }

	// RVA: 0xFDAC2C Offset: 0xFDAC2C VA: 0xFDAC2C
	public bool get_IsExceedJumpCount() { }

	// RVA: 0xFDAC40 Offset: 0xFDAC40 VA: 0xFDAC40
	public bool get_IsJumpTimeMax() { }

	// RVA: 0xFDAC54 Offset: 0xFDAC54 VA: 0xFDAC54
	public Creature get_Creature() { }

	[CompilerGeneratedAttribute] // RVA: 0x3FE1C Offset: 0x3FE1C VA: 0x3FE1C
	// RVA: 0xFDAC5C Offset: 0xFDAC5C VA: 0xFDAC5C
	public void add_OnRequestJump(Action value) { }

	[CompilerGeneratedAttribute] // RVA: 0x3FE2C Offset: 0x3FE2C VA: 0x3FE2C
	// RVA: 0xFDAD00 Offset: 0xFDAD00 VA: 0xFDAD00
	public void remove_OnRequestJump(Action value) { }

	// RVA: 0xFDADA4 Offset: 0xFDADA4 VA: 0xFDADA4
	public bool get_IsGrounded() { }

	// RVA: 0xFDADC4 Offset: 0xFDADC4 VA: 0xFDADC4
	private void Awake() { }

	// RVA: 0xFDB180 Offset: 0xFDB180 VA: 0xFDB180
	private void Start() { }

	// RVA: 0xFDB20C Offset: 0xFDB20C VA: 0xFDB20C
	private void Update() { }

	// RVA: 0xFDBD10 Offset: 0xFDBD10 VA: 0xFDBD10
	public void Jump() { }

	// RVA: 0xFDBFC4 Offset: 0xFDBFC4 VA: 0xFDBFC4
	public void JumpPressed() { }

	// RVA: 0xFDC02C Offset: 0xFDC02C VA: 0xFDC02C
	public void DownJump() { }

	// RVA: 0xFDC090 Offset: 0xFDC090 VA: 0xFDC090
	public void Dash(Vector3 dashVelocity) { }

	// RVA: 0xFDC2CC Offset: 0xFDC2CC VA: 0xFDC2CC
	public void StopDash() { }

	// RVA: 0xFDC364 Offset: 0xFDC364 VA: 0xFDC364
	public void OnDie(Creature hitter, string hitterName) { }

	// RVA: 0xFDC3F0 Offset: 0xFDC3F0 VA: 0xFDC3F0
	public void OnRevive() { }

	// RVA: 0xFDA978 Offset: 0xFDA978 VA: 0xFDA978
	public void FootstepAudio() { }

	// RVA: 0xFDC478 Offset: 0xFDC478 VA: 0xFDC478
	public void AddForce(Vector3 vel, ForceMode2D mode) { }

	// RVA: 0xFDA734 Offset: 0xFDA734 VA: 0xFDA734
	public void CreateFootstepFx() { }

	// RVA: 0xFDB18C Offset: 0xFDB18C VA: 0xFDB18C
	public void UpdateHasParameterHash() { }

	// RVA: 0xFDC4E4 Offset: 0xFDC4E4 VA: 0xFDC4E4
	public void .ctor() { }
}

 

From CharacterController2D's Fields, we find a whole lot of interesting attributes of Character Control. Short list of examples are like:

  • public int maxDashCount; // 0xA4 ---> max Dash Count ---> Again, it is hiding do deep

  • public int ramainingDashCount; // 0xA8 ---> remaining Dash Count ---> it even spell it wrongly, try to make me can't spot it.
  • public int jumpCount; // 0x108 ---> likely the max jump count
  • public int currentJumpCount; // 0x10C ---> current jump count, make more jump or even infinite jump?
  • private Creature _creature; // 0x1A8 ---> Linkage to character's creature object. Yes, not only a Player in Dungreed is a character. Enemy also has CharacterController2D.

This is just a very short list. There are so many possibility here. 

From CharacterController2D's Method (generally, I will skip the Properties part as I will find similar thing in Methods part anyway). 

  • public void Jump() { } // RVA: 0xFDBD10 Offset: 0xFDBD10 VA: 0xFDBD10----> It looks like to control character to jump
  • public void Dash(Vector3 dashVelocity) { } // RVA: 0xFDC090 Offset: 0xFDC090 VA: 0xFDC090 ----> Dash function! This is where we implement the Infinity Dash

Again, spend sometime to on things that interest you. Mark your own note on them, reserve them to do your own test later. 

OK, these four classes (Player, Creature, Status, and CharacterController2D) are the main class of interest for Dungreed

The next question is, with these info in mind, how do we make the hack? 

First of all, for non-jailbroken, we can't do those simple Theos's hook. I am not expert in Theos either. In this Tutorial for non-jailbroken. I will not talk on those. 

Secondly, more complicated game normally requires us to understand a bit its logic before hack or we might accidentally break the game at unknown point. 

My answer to this is, let's do next around of Static Analysis with IDA based on the valuable information we collected above. 

I hope your IDA has already completed the Analysis and applied the script to restore the metadata (IDA in idle state).

Let’s look into more detail around the Dash. 

  • public void Dash(Vector3 dashVelocity) { } // RVA: 0xFDC090 Offset: 0xFDC090 VA: 0xFDC090 ----> void function, that mean it has no return value. Good, we have less thing to worry about. It has one parameter dashVelocity, which doesn’t look relevant to our infinite dash hack.
  • public int ramainingDashCount; // 0xA8 ---> remaining Dash Count ---> int Field, meaning it store integer value (not floating point, less thing to worry as well)


In IDA (with UnityFramework opened, of course), Jump -> Address -> 0xFDC090   

You should arrive the starting point of CharacterController2D.Dash method. Look like this.

Spoiler

1UZFpGwk_o.png

If you are not in this Graph mode, just right click on the Assembly code, choose Graph mode.

You may also generate pseudo code by F5 (in Mac, fn + F5). You will see something like below.

Spoiler

pgqGj5oE_o.png

Anyway, let’s go back to Graph mode. 

To implement an Infinite Dash, the easiest way is to prevent the remaining Dash count from changing. 

Like what we did for Money Hack, let's locate the area that change the ramainingDashCount (0xA8). 

Let do a Text search on , #0xA8] . This should quickly direct us to the nearest appearance of this 0xA8 offset. Like below:

Spoiler

9KhNAuR8_o.png

Great! We see following subtraction instruction. It deducts 1 (ONE) from the ramainingDashCount (0xA8).  

  • subs w8, w8, #1

It looks like if we NOP that instruction, the dash count will not drop. 

But wait, do you experience some hack on skill cool down time which make enemy also using skill like crazy. The cool down code is actually "linked" or in other word shared by both Player and enemy. 

In fact, if you look take a look who would be calling this CharacterController2D.Dash (Right click on the method name -> list cross references to). You will see AI_Mercenary$$MoveUpdate. I have no good feeling with anything start with AI. A player do not need AI obviously. Of course a Mercenary could also be someone we can hire to help us out. But after a quick check on Dungreed's Fandom site. I cannot found there are things that we can hire to help us. So, I will play it save and make the Infinite Dash hack only on Player. 

The next question is, how can we achieve this?

From CharacterController2D Class, we found a linkage to Creature. While in Creature class, we found a linkage to Player. Although it is a bit indirect, we have way to check if this CharacterController2D object belongs to Player.

In conclusion, though Static Analysis, we have found the way to do Infinite Dash Hack

  1. We get the pointer to Creature object with reference to offset 0x1A8 of the CharacterController2D object
  2. Use that Creature object (pointed by the pointer in CharacterController2D object) and find it's offset 0x180, which holds pointer to Player object
  3. If pointer to Player object is not Null/Empty, we apply the Infinite Dash hack. Or otherwise, leave the logic untouched


 

To understand more about Variables and Pointers, you might find more info here.

 

 

Stage 7 - Apply the Dash hack with H5GG script (without Mod Menu)

Spoiler

The challenge is, it will not be easy to find a code cave for this much logic. That is why I decided to implement it as Hook.

Implementing a hook is different from implementing a patch.

In patch, we could generally change the inline assembly flow or logic. We could also change value of certain register in order to achieve the result we want. The limitation is, we cannot change the size of the method. In assembly code, offset are everywhere. If we change the size of the method, there would affect a lot offset and the game will break. So, in general, we do one replace one, two replace two instructions, etc. That is why, we can’t suddenly add too much logic to it.

However in hook, the logic is basically programmed in a different place and then hook it to the normal assembly flow. It is like the branching out to complete new logic and return to original flow.

In our Infinite Dash hack, I implement the logic mentioned in Stage 6 as H5Frida hook as below.

 

Spoiler
h5gg.require(7.9); 
var h5frida=h5gg.loadPlugin("h5frida", "h5frida-15.1.24.dylib");
if(!h5frida) throw "加载h5frida插件失败\n\nFailed to load h5frida plugin";

if(!h5frida.loadGadget("frida-gadget-15.1.24.dylib"))
    throw "加载frida-gadget守护模块失败\n\nFailed to load frida-gadget daemon module";
    
var frontapp = h5frida.get_frontmost_application();

if (!frontapp) throw "frida can't get frontapp";

var session = h5frida.attach(frontapp.pid);
if(!session) throw "frida附加进程失败\n\nfrida attach process failed";

//监听frida目标进程连接状态, 比如异常退出
session.on("detached", function(reason) {
	 alert("Infinite Dash is gone, please restart game to turn back on!");
});

var frida_script_line = frida_script("getline"); //safari console will auto add 2 line
var frida_script_code = "("+frida_script.toString()+")()"; //将frida脚本转换成字符串
var script = session.create_script(frida_script_code); //注入frida的js脚本代码

if(!script) throw "frida注入脚本失败\n\nfrida inject script failed!";

script.on('message', function(msg) {
    if(msg.type=='error') {
        script.unload(); //如果脚本发生错误就停止frida脚本
        try {if(msg.fileName=="/frida_script.js") msg.lineNumber += frida_script_line-1;} catch(e) {}
        if(Array.isArray(msg.info)) msg.info.map(function(item){ try { if(item.fileName=="/frida_script.js")
            item.lineNumber += frida_script_line-1;} catch(e) {}; return item;});
        var errmsg = JSON.stringify(msg,null,1).replace(/\/frida_script\.js\:(\d+)/gm,
            function(m,c,o,a){return "/frida_script.js:"+(Number(c)+frida_script_line-1);});
        alert("frida(脚本错误)script error:\n"+errmsg.replaceAll("\\n","\n"));
    }
    
    if(msg.type=='send')
		  alert("HACK msg:\n"+JSON.stringify(msg.payload,null,1));
    if(msg.type=='log')
		  alert("HACK log:\n"+msg.payload);
});

if(!script.load()) throw "frida启动脚本失败\n\nfrida load script failed"; //启动脚本

/**********************************************************************************/

//获取frida脚本中的rpc.exports导出函数列表

if(script.call("hook_dash"))
{
    //alert("inline hook拦截成功\ndo inline hook success");
    
} else {
    alert("inline hook拦截失败, 请检查日志信息!\nDo inline hook failed, Please check log message");
}

//script.unload(); //卸载脚本

//session.detach(); //断开目标进程

/***************************************************************/

/*
 下面是frida的js脚本代码, 运行在目标进程, 不能在h5gg中直接调用这个js函数
 frida的js脚本代码中不能使用任何h5gg的函数和变量, 也不能使用window对象
 h5gg和frida只能通过console.log和send/recv/post还有rpc.exports进行通信
 The following is the js script code of frida, which runs in the target process, and this js function cannot be called directly in h5gg
 You cannot use any h5gg functions and variables in frida's js script code, nor can you use the window object
 h5gg and frida can only communicate through console.log and send/recv/post and rpc.exports
 */
function frida_script() { if(arguments.length) return new Error().line; //do not modify this line!!!

    //发送frida脚本的日志消息给h5gg
	 //console.log("Infinite Dash is enabled...");

    //HOOK拦截.app中的任何模块中的任意地址的函数或指令
    rpc.exports.hook_dash=function()
    {
        var hook1 = h5frida.StaticInlineHookInstrument("Frameworks/UnityFramework.framework/UnityFramework", //要HOOK的模块在.app中的相对路径
                 0xFDC130, //要HOOK的指令偏移地址 //instruction offset
                 function(context)
                 {
            			//console.log(JSON.stringify(context));
							var creature = context.x[0];
							creature = Number(creature) + 0x1A8;
							creature= new NativePointer(creature);
							creature=creature.readPointer();
							
							var player = Number(creature) + 0x180;
							player= new NativePointer(player);
							player=player.readPointer();
							//send(["Creature->Player ", player]);
							
							if (!player.isNull()) //Check if it is Player or Enemy
							{
                    		var r = context.x[8]; 
            
                    		//send(["Intercept the execution of the substract instruction of CharacterController2D$$Dash) ", r]);
            
                    		r = Number(r) + 1; //Add 1 before game deduct 1
            
                    		context.x[8] = new NativePointer(r);  
							}
                 }
        );
       
        
        //返回是否全部HOOK成功 //Check if all hooks are successful
        return hook1;
    };

	 rpc.exports.hook_nodash=function()
    {
        var hook2 = h5frida.StaticInlineHookInstrument("Frameworks/UnityFramework.framework/UnityFramework", //要HOOK的模块在.app中的相对路径
                 0xFDC130, //要HOOK的指令偏移地址 //instruction offset
                 function(context)
                 {
                    //put nothing here, aims to remove other hook only
                 }
        );
       
        
        //返回是否全部HOOK成功 //Check if all hooks are successful
        return hook2;
    };
}

 

To run this code with H5GG in the Dungreed, please follow the earlier H5GG Tutorial Reference #2 - Step 1 and 2 (you may focus on Hooking). 
Hint: Remember that first run will report error, just ignore it, just download the patched UnityFramework and repackage the ipa. When you run the H5GG script the second time in Dungreed (patched version), it will start effect. If you do not run the script, you will find the binary behave as normal (no Infinity Dash hack).

To conclude, you have applied the Infinity Dash Hack to the Dungreed game binary and you can trigger it with H5GG script whenever you want. 
Hint: Even though I didn't mention the Mod Menu part, but you can see this is a Javascript. You can easily include this to a HTML page. More importantly, H5GG can load HTML page the same way you load Javascript. You know what I mean, right!

 

Stage 8 - Mix everything together and build Mod Menu

Spoiler

We have the hack detail ready now, including their H5GG scripts. How do we blend them all together and create Mod Menu? 

First of all, Mod Menu is just a H5GG script (Javascript) embedded html page. If you have expert in HTML, you are do whatever fancy thing you want on it. 

For those less experience in HTML, there are some pre-build Mod Menu template for you as well. You may find more detail from below Tutorial.

In my Dungreed hack, I have actually leveraged the H5Menu DarkStyle. I did not remove those unused menu options from HTML code. I just hide them from showing/appearing on screen when rendering the page. Who knows when am I going to need them for more hack features on Dungreed. 

In general, we attached different javascript function to different toggle state on buttons. 

For Patch, we have ActiveCodePatch (enabling) and DeactiveCodePatch (disabling) different patch. We can include as much as Patch we want.

For Hook, we have to implement different Javascript Export to achieve the same. For Infinite Dash, we have hook_dash (enabling) and hook_nodash (disabling) the hack. 

With the two Javascript export in place, I prepare two functions to trigger individual of them on radio button click.

Spoiler
function EnableDashHook(){
	if(script.call("hook_dash"))
	{
    	//alert("inline hook拦截成功\ndo inline hook success");
    
	} else {
      alert("inline hook拦截失败, 请检查日志信息!\nDo inline hook failed, Please check log message");
	}
}

function DisableDashHook(){
	if(script.call("hook_nodash"))
	{
    	//alert("inline hook拦截成功\ndo inline hook success");
    
	} else {
      alert("inline hook拦截失败, 请检查日志信息!\nDo inline hook failed, Please check log message");
	}
}

function radioclick(input)
{
    //alert("radio clicked: group = "+input.name+" = "+input.parentElement.innerText+" = "+input.value);
	if (input.value=='hp') {
		ActiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFD508, "083540F91F1940BD1F1500BD");
	} else if (input.value=='god'){
		ActiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFD594, "2900805209B500B9083540F9");
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFD508, "083540F91F1940BD1F1500BD");
	} else if (input.value=='nil'){
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFD508, "083540F91F1940BD1F1500BD");
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFD594, "2900805209B500B9083540F9");
	} else 	if (input.value=='dash'){
		EnableDashHook();
	} else 	if (input.value=='nodash'){
		DisableDashHook();
	} else if (input.value=='money'){
		ActiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDE7F74, "C802132B");
	} else if (input.value=='nilmoney'){
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDE7F74, "C802132B");
	}

}

 

 

Hint: We just need to be sure we will trigger them all hack at once (all patch and hook) in order to make the game binary patched (make ready) for the ALL real hack to happens. Everytime you add a new patch, you will need to undergo the same process of Execute the hack first time to patch the game binary and trigger the hack second time (with the patched binary) to enable it. 

 

Below is the full version of the HTML for your reference. 

Spoiler
<html>
<head>
<title>Dungreed v1.6.175 Hack</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
html {
    zoom:1.2;
}

body {
    width: 100%;
    height: 100%;
}

* {
    color: #E8E8E8;
    font-size: 12px;
    font-family: Arial, sans-serif;
    
    /* DebugMode:delete next line to show dashed border */
    /*
    border: 1px dashed gray;/**/
    
}

*:not(input,checkbox,textarea) {
    /*禁止文本选择*/
   -webkit-touch-callout: none;
   -webkit-user-select: none;
   user-select: none; /* Non-prefixed version, currently */
   outline: none;
   -webkit-tap-highlight-color: transparent;
}

input {
    background-color: rgba(0,0,0,0);
    height: 30px;
}

button {
    height: 30px;
    background-color: #E8E8E850;
    display: inline-block;
    cursor: pointer;
    text-align: center;
    text-decoration: none;
    outline: none;
    border: none;
    border-radius: 5px;
}

button:active {
     transform: translateY(2px);
}

input[type=radio]  {
    width:20px;
    height:20px;
    margin-right:6px;
    border:none;
    outline-style:none;
    -webkit-appearance:none;
    vertical-align:middle;
    border:1px solid #DDDDDDF0;
    border-radius:50%;
}
input[type=radio]:checked {
    border:5px solid #2F7DCDF0;
    background:#FFFFFF;
}
    
input[type=checkbox]{
 visibility: hidden;
 vertical-align:middle; margin-bottom:2px;
 cursor: pointer;
 position: relative;
 width: 24px;
 height: 24px;
}
input[type=checkbox]::after{
 position: absolute;
 top: 0;
 margin-top:2px;
 width: 14px; height: 14px;
 border: 1px solid #EEEEEE;
 border-radius: 3px;
 background-color: rgba(0,0,0,0);
 display: inline-block;
 visibility: visible;
 text-align: center;
 content: ' ';
}
input[type=checkbox]:checked::after{
 content: "✓";
 border-color: #4498F7;
 background-color: #4498F7;
 font-size: 12px;
 font-weight: bold;
}

input[type=range] {
  -webkit-appearance: none;
}
input[type=range]:focus {
  outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
  height: 15px;
  cursor: pointer;
  animate: 0.2s;
  background: #D1D1D130;
  border-radius: 1.3px;
  border: 0.2px solid #010101;
}
input[type=range]::-webkit-slider-thumb {
  border: 1px solid #000000;
  height: 18px;
  width: 16px;
  border-radius: 3px;
  background: #FFFFFFE0;
  cursor: pointer;
  -webkit-appearance: none;
  margin-top: -2px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
  background: #367ebd;
}

    
/* 滚动条整体部分 */
.scrollbar {
    overflow-x: hidden;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}
.scrollbar::-webkit-scrollbar {
    width: 5px; /* 纵向滚动条宽度 */
    height: 5px;/* 横向滚动条高度 */
    background-color: #F5F5F5; /* 滚动条整体背景,一般被覆盖着 */
}
/* 滚动条的轨道(里面装有Thumb) */
.scrollbar::-webkit-scrollbar-track {
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); /* 滚动条轨道阴影 */
    /*border-radius: 10px; /* 滚动条轨道圆角 */
    background-color: #F5F5F5; /* 滚动条轨道背景 */
}
/* 滚动条里面的滑块 */
.scrollbar::-webkit-scrollbar-thumb {
    border-radius: 15px; /* 滚动条滑块圆角 */
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3); /* 滚动条滑块阴影 */
    background-color: #B8B8B8; /* 滚动条滑块颜色 */
}
    
.menubox {
        width: 60px;
        height: 30px;
        line-height: 30px; /*height和line-height设置一样即可文字垂直居中*/
        text-align:center;
			display:none;
}
.menubox.current {
    background-color: #494949;
	 display:block;
}

.menuview {
    display:none;
}

.menuview.current {
    display:block;
    overflow-x: hidden;
    overflow-y: scroll;
    height: 100%;
}

</style>


<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>

<script>
h5gg.require(7.9); 
var h5frida=h5gg.loadPlugin("h5frida", "h5frida-15.1.24.dylib");
if(!h5frida) throw "加载h5frida插件失败\n\nFailed to load h5frida plugin";

if(!h5frida.loadGadget("frida-gadget-15.1.24.dylib"))
    throw "加载frida-gadget守护模块失败\n\nFailed to load frida-gadget daemon module";
    
var frontapp = h5frida.get_frontmost_application();

if (!frontapp) throw "frida can't get frontapp";

var session = h5frida.attach(frontapp.pid);
if(!session) throw "frida附加进程失败\n\nfrida attach process failed";

//监听frida目标进程连接状态, 比如异常退出
session.on("detached", function(reason) {
    //alert("frida目标进程会话已终止(frida target process session terminated):\n"+reason);
	 alert("Infinite Dash is gone, please restart game to turn back on!");
});

var frida_script_line = frida_script("getline"); //safari console will auto add 2 line
var frida_script_code = "("+frida_script.toString()+")()"; //将frida脚本转换成字符串
var script = session.create_script(frida_script_code); //注入frida的js脚本代码

if(!script) throw "frida注入脚本失败\n\nfrida inject script failed!";

script.on('message', function(msg) {
    if(msg.type=='error') {
        script.unload(); //如果脚本发生错误就停止frida脚本
        try {if(msg.fileName=="/frida_script.js") msg.lineNumber += frida_script_line-1;} catch(e) {}
        if(Array.isArray(msg.info)) msg.info.map(function(item){ try { if(item.fileName=="/frida_script.js")
            item.lineNumber += frida_script_line-1;} catch(e) {}; return item;});
        var errmsg = JSON.stringify(msg,null,1).replace(/\/frida_script\.js\:(\d+)/gm,
            function(m,c,o,a){return "/frida_script.js:"+(Number(c)+frida_script_line-1);});
        alert("frida(脚本错误)script error:\n"+errmsg.replaceAll("\\n","\n"));
    }
    
    if(msg.type=='send')
        //alert("frida(脚本消息)srcipt msg:\n"+JSON.stringify(msg.payload,null,1));
		  alert("HACK msg:\n"+JSON.stringify(msg.payload,null,1));
    if(msg.type=='log')
        //alert("frida(脚本日志)script log:\n"+msg.payload);
		  alert("HACK log:\n"+msg.payload);
});

if(!script.load()) throw "frida启动脚本失败\n\nfrida load script failed"; //启动脚本

/**********************************************************************************/

//获取frida脚本中的rpc.exports导出函数列表
//alert("frida脚本导出函数列表:\nfrida export method list:\n" + script.list_exports());

if(script.call("hook_dash"))
{
    //alert("inline hook拦截成功\ndo inline hook success");
    
} else {
    alert("inline hook拦截失败, 请检查日志信息!\nDo inline hook failed, Please check log message");
}

//script.unload(); //卸载脚本

//session.detach(); //断开目标进程

/***************************************************************/

/*
 下面是frida的js脚本代码, 运行在目标进程, 不能在h5gg中直接调用这个js函数
 frida的js脚本代码中不能使用任何h5gg的函数和变量, 也不能使用window对象
 h5gg和frida只能通过console.log和send/recv/post还有rpc.exports进行通信
 The following is the js script code of frida, which runs in the target process, and this js function cannot be called directly in h5gg
 You cannot use any h5gg functions and variables in frida's js script code, nor can you use the window object
 h5gg and frida can only communicate through console.log and send/recv/post and rpc.exports
 */
function frida_script() { if(arguments.length) return new Error().line; //do not modify this line!!!

    //发送frida脚本的日志消息给h5gg
	 //console.log("Infinite Dash is enabled...");

    //HOOK拦截.app中的任何模块中的任意地址的函数或指令
    rpc.exports.hook_dash=function()
    {
        var hook1 = h5frida.StaticInlineHookInstrument("Frameworks/UnityFramework.framework/UnityFramework", //要HOOK的模块在.app中的相对路径
                 0xFDC130, //要HOOK的指令偏移地址 //instruction offset
                 function(context)
                 {
            			//console.log(JSON.stringify(context));
							var creature = context.x[0];
							creature = Number(creature) + 0x1A8;
							creature= new NativePointer(creature);
							creature=creature.readPointer();
							
							var player = Number(creature) + 0x180;
							player= new NativePointer(player);
							player=player.readPointer();
							//send(["Creature->Player ", player]);
							
							if (!player.isNull()) //Check if it is Player or Enemy
							{
                    		var r = context.x[8]; 
            
                    		//send(["Intercept the execution of the substract instruction of CharacterController2D$$Dash) ", r]);
            
                    		r = Number(r) + 1; //Add 1 before game deduct 1
            
                    		context.x[8] = new NativePointer(r);  
							}
                 }
        );
       
        
        //返回是否全部HOOK成功 //Check if all hooks are successful
        return hook1;
    };

	 rpc.exports.hook_nodash=function()
    {
        var hook2 = h5frida.StaticInlineHookInstrument("Frameworks/UnityFramework.framework/UnityFramework", //要HOOK的模块在.app中的相对路径
                 0xFDC130, //要HOOK的指令偏移地址 //instruction offset
                 function(context)
                 {
                    //put nothing here, aims to remove other hook only
                 }
        );
       
        
        //返回是否全部HOOK成功 //Check if all hooks are successful
        return hook2;
    };
}

function EnableDashHook(){
	if(script.call("hook_dash"))
	{
    	//alert("inline hook拦截成功\ndo inline hook success");
    
	} else {
      alert("inline hook拦截失败, 请检查日志信息!\nDo inline hook failed, Please check log message");
	}
}

function DisableDashHook(){
	if(script.call("hook_nodash"))
	{
    	//alert("inline hook拦截成功\ndo inline hook success");
    
	} else {
      alert("inline hook拦截失败, 请检查日志信息!\nDo inline hook failed, Please check log message");
	}
}


function ActiveCodePatch(fpath, vaddr, bytes) {
    if(!h5frida.ActiveCodePatch(fpath, vaddr, bytes)) {
        var result = h5frida.ApplyCodePatch(fpath, vaddr, bytes);
        alert(fpath+":0x"+vaddr.toString(16)+"-修改失败!\n" + fpath+":0x"+vaddr.toString(16)+"-PatchFailed!\n" + result);return false;
    } return true;
}
function DeactiveCodePatch(fpath, vaddr, bytes) {
    return h5frida.DeactiveCodePatch(fpath, vaddr, bytes);
}

</script>

<script>
    
if(typeof $ == 'undefined') alert("网络连接失败, 请重新启动!");

$(document).ready(function(){
    //alert();
    //绑定菜单点击切换子页面
    $("div.menubox").click(function(){
        $("div.menubox").removeClass("current");
        $("div.menuview").removeClass("current");
        $(this).addClass("current");
        
        var menuid = $(this).attr("menu");
        $("div#"+menuid).addClass("current");
    });
    
    /*禁止文本Option和拖动*/
    document.body.onselectstart = document.body.ondrag =function(){
        return false;
    }
    
    $("input").blur(function(){
        window.scroll(0,0); //文本框等输入完毕后页面自动滚动到顶部
    });
    
    //激活webkit的button:active
    document.body.addEventListener('touchstart', function () {});

    if(typeof h5gg!='undefined') {
        //设置标题栏区域可拖动悬浮窗
        setWindowDrag(0, 0, 400, 80);
        //设置尺寸和位置
        setWindowRect(60,60,300,300);
    }
});

function login()
{
    if(!$("#username").val()) {
        alert("please input your account");
        return;
    }
    
    if(!$("#password").val()) {
        alert("please input your password");
        return;
    }
    
    alert("test login\n\nusername:"+$("#username").val() + "\n" + "password:"+$("#password").val());
}
    
function buttonclick(input)
{
    alert("button clicked = "+input.innerText);
}
    
function checkboxclick(input)
{
    alert("checkbox clicked = "+input.parentElement.innerText+" = "+input.checked);
}
   
function rangechange(input)
{
    alert("slider chagne = "+input.value);
}
    
function radioclick(input)
{
    //alert("radio clicked: group = "+input.name+" = "+input.parentElement.innerText+" = "+input.value);
	if (input.value=='hp') {
		ActiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFB768, "083540F91F1940BD1F1500BD");
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFB7F4, "2900805209B500B9083540F9");
	} else if (input.value=='god'){
		ActiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFB7F4, "2900805209B500B9083540F9");
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFB768, "083540F91F1940BD1F1500BD");
	} else if (input.value=='nil'){
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFB768, "083540F91F1940BD1F1500BD");
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFB7F4, "2900805209B500B9083540F9");
	} else 	if (input.value=='dash'){
		EnableDashHook();
	} else 	if (input.value=='nodash'){
		DisableDashHook();
	} else if (input.value=='money'){
		ActiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDE61EC, "C802132B");
	} else if (input.value=='nilmoney'){
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDE61EC, "C802132B");
	}

}
</script>



</head>

<body bgcolor="#202C3E" style="margin:0;">
<!--标题栏-->
<div id="titleBar" style="background-color:#122220; padding:5px; margin:0px;">
&nbsp;Dungreed v1.6.175 Hack
</div>
<!--用一个表格来布局左右两栏-->
<table id="bodyView" width="100%" style="table-layout:fixed;height: calc(100% - 30px) ;">
    
<tr>
    
<td width="30%" style="vertical-align:top">
    
<div>
    <div class="menubox" menu="menu1">Menu 1</div>
    <div class="menubox" menu="menu2">Menu 2</div>
    <div class="menubox" menu="menu3">Menu 3</div>
    <div class="menubox current" menu="menu4">Hack</div>
    <div class="menubox" menu="menu5">Menu 5</div>
</div>
</td>
<td style="vertical-align:top" class="scrollbar">
<div id="menu1" class="menuview">
<p>CheckBox</p>
    <label><input type="checkbox" checked="checked" onclick="checkboxclick(this)" />Option1</label>
    <label><input type="checkbox"  onclick="checkboxclick(this)" />Option2</label>
    <p>
    <label><input type="checkbox"  onclick="checkboxclick(this)" />Option3</label>
    <label><input type="checkbox" onclick="checkboxclick(this)" />Option4</label>
    <p>
</div>

<div id="menu2" class="menuview">
<p>Button</p>
    <button onclick="buttonclick(this)">Button1</button>
    <button onclick="buttonclick(this)">Button2</button>
    <p>
    <button onclick="buttonclick(this)">Button3</button>
    <button onclick="buttonclick(this)">Button4</button>
</div>

<div id="menu3" class="menuview">
    <p>Slider1</p>
  <input type="range" min="0" max="100" style="width:100%" onchange="rangechange(this)" />
    <p>Slider2</p>
  <input type="range" min="10" max="20"  onchange="rangechange(this)" />
</div>

<div id="menu4" class="menuview current">
    <p>Survival (Switch Weapon to trigger)</p>
  <label><input name="radio-group1" type="radio" value="nil" checked onclick="radioclick(this)" />Normal</label>
	<p><label><input name="radio-group1" type="radio" value="hp" onclick="radioclick(this)" />Heal Hp</label>
	<p><label><input name="radio-group1" type="radio" value="god" onclick="radioclick(this)" />Tempoary God Mode</label>
	<p>Money</p>
  <label><input name="radio-group2" type="radio" value="nilmoney" checked="checked"  onclick="radioclick(this)" />Normal</label>
  <p><label><input name="radio-group2" type="radio" value="money" onclick="radioclick(this)" />Spend to Increase</label>

  <p>Infinite Dash</p>
  <label><input name="radio-group3" type="radio" value="nodash" onclick="radioclick(this)" />Normal</label>
  <p><label><input name="radio-group3" type="radio" value="dash" checked="checked" onclick="radioclick(this)" />Enable</label>
  
</div>

<div id="menu5" class="menuview">
<p>Input</p>
<p><label>Username: <input id="username" name="username" type="text" placeholder="input your username" /></label>
<p>Password: <input id="password" name="password" type="password" placeholder="input your password" />
<p align="center"><button onclick="login()">Login</button>
</div>

</td>

</tr>

</table>

</body>
</html>

 

 

To conclude, you design your mod menu with HTML and embedded the H5GG script to the HTML mod menu. Run though all the hack once, so that the binary would be patched for all hack. Then, override the patched binary to the IPA and reinstall. You have your Mod Menu built. 
Hint: We cannot apply different patch/hook on same Offset. So, for every new hack, you will need a new offset.

 

 

Stage 9 - Package the H5GG HTML and build IPA

Spoiler

If you are going to use the hack yourself, you actually do not need to package it. As mentioned above, we just need to load the HTML through the Scripts button on H5GG. Your H5GG UI will be replaced by your HTML. 

If you gonna package it for others, your may leverage the Make Treak button on H5GG. 

  1. Select a picture file for float button --> Yes, use whatever icon you like. Just put the photo on your iOS device accessible by Files. 
  2. Select a html file that needs to load automatically --> here, you input the html mod menu we created earlier. Again just put the html on your iOS device accessible by Files. 
  3. It will then has the H5GG.dylib generated in game directory. 

Hint: If you happens to have your Icons or HTML in your PC, you may follows H5GG Tutorial References #2 to move file in/out from your iOS device. Or if you are on Mac, you can do Airdrop as well. 

To package this H5GG.dylib inside your IPA, you may leverage the Export IPA feature of Sideloadly.

  1. Draft your H5GG Packaged IPA to Sideloadly
  2. Under Signing mode, choose Export IPA then click Start
  3. Then it will ask you for the location you want to put the new IPA

It is that simple. You have a H5GG Patched IPA with Mod Menu build-in

 

 

Stage 10 - Test the Hack Build and Share

Spoiler

Before you share hack with more people, you better do some testing on it.

For me, I would remove all installation and do fresh install on my available devices. Sometime hack might not work will with fresh install, like those Tutorial. Your hack might eventually block the game from progressing.

Normally, with Mod menu, all hack are OFF by default (before you click/touch the first time on the H5GG icon to LOAD/TRIGGER it), the game should behave as normal. 

Anyway, it is always a good idea to give some warning or warm reminder to our user what might happens.

 

Of course, we cannot test all different iOS or devices. Just try our best to test it.

 

 


FINAL - Challenge yourself and hack Dungreed with more features to strengthen your knowledge on H5GG Mod Menu Hacking.

Spoiler

Dungreed is a great game with good game design. It is only US$5 with no in-app purchase. If you enjoy the game, I suggest you buy it from App Store to support them.

Current version (v1.6.175) of this game does not have much sophisticated protection scheme. It is a good playground for new game hacker to play around.

If you are new to game hacking, I suggest you to spend more time on this to sharpen your hacking skill. You can completely mod the game your want here.

 

Here comes some challenges for you.

  • Can you make every drop decent?
  • Can you make the player damage 3 time higher?
  • Can you weaken the enemy? 

Remember to share with us your hack down below in the comments.

 


BONUS #1- Further cheat features
 

Spoiler

Known Player attributes explained

  • Fortune (0x25C) - Affect drop quality
  • Satiety (0x1C8) - Affect how much you can eat
  • Coinbonus (0x24C) - Affect how much money more, every coin will give. If you put 1000 here, every coin give 1000 more money
  • Kill Enemy Count (0x1AC) - Count the number of enemy killed, MUST HACK TOGETHER WITH Killexp (0x1A8)
  • Kill Experience (0x1A8) - FAKE. It is not exp. It is also the killed enemy count. MUST HACK TOGETHER WITH Kill Enemy Count (0x1AC)


BONUS #2- Advanced Dungreed Mod Menu (V2)

Spoiler

This section is about an advanced Mod Menu, decided to make adding Variable cheating with Hook easier.

With this, we just need 2+1 simple steps to extend mod menu with new Variable cheat.

  1. Defining list of Variables to cheat plus default value for the cheat
    Spoiler
    var cheats={
    	ramainingDashCount: ["charactercontroller2d", 0xA8, 1, "int", "ON"],
    	fortune: ["player", 0x25C, 99, "int", "ON"],
    	satiety: ["player", 0x1C8, 0, "int", "ON"],
    	coinbonus: ["player", 0x24C, 100, "int", "ON"],//coinbonus, every coin give this amount of money more
    	killenemycount: ["player", 0x1AC, 200, "int", "ON"],//kill enemy count and kill exp must be same
    	killexp: ["player", 0x1A8, 200, "int", "ON"],
    }

     

  2. Adding Input (Range, i.e. Slider) to Menu UI
    Spoiler
    <p><label>Fortune / Luck <output>(99)</output><input name="fortune" type="range" min="0" max="100" value="99" style="width:90%" onchange="rangechange(this)" /></label>
    <br><label>Satiety / Hungry <output>(0)</output><input name="satiety"type="range" min="0" max="100" value="0" style="width:90%" onchange="rangechange(this)" /></label>
    <br><label>Coin Bonus <output>(100)</output><input name="coinbonus"type="range" min="0" max="200" value="100" style="width:90%" onchange="rangechange(this)" /></label>
    <br><label>Kill Count <output>(200)</output><input name="killenemycount"type="range" min="0" max="500" value="200" style="width:90%" onchange="rangechange(this)" /></label>

     

  3. Optional special treatment on specific cheat requirement (like backup values)
    Spoiler
    //killenemycount and killexp must be same
    if (input.name=="killenemycount"){
    	cheats["killexp"][2]=Number(input.value);
    }

     

     

The newly added Variable Cheat Loader logic will process the list of variable cheats all at once with the latest slider value.

This makes Hook related cheats become as simple as Patch.
More importantly, hacking with Hook only need one anchor point for infinite number of variables cheat even with complicated delink logic. This make Hook would be a better options over Patch, assume we are not intended to change the game logic flow. 
The only drawback is, H5Frida would got disconnected/detached whenever we move out of game (put game in background). We will need to restart the game.

Here attached Version 2 of the Dungreed Mod Menu.

Spoiler
<!--
	Mod Menu logic evolved from original H5GG Sample. 
	This should enable easier Mod Menu development for non-jailbroken. 
	Please preserve this note, if you are gonna reuse the loader logic in other game.
	Contribute by Happy Secret on iOSGods (2023)
-->


<html>
<head>
<title>Dungreed v1.6.175 Hack</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
html {
    zoom:0.9;
}

body {
    width: 100%;
    height: 100%;
}

* {
    color: #E8E8E8;
    font-size: 12px;
    font-family: Arial, sans-serif;
    
    /* DebugMode:delete next line to show dashed border */
    /*
    border: 1px dashed gray;/**/
    
}

*:not(input,checkbox,textarea) {
    /*禁止文本选择*/
   -webkit-touch-callout: none;
   -webkit-user-select: none;
   user-select: none; /* Non-prefixed version, currently */
   outline: none;
   -webkit-tap-highlight-color: transparent;
}

input {
    background-color: rgba(0,0,0,0);
    height: 30px;
}

button {
    height: 30px;
    background-color: #E8E8E850;
    display: inline-block;
    cursor: pointer;
    text-align: center;
    text-decoration: none;
    outline: none;
    border: none;
    border-radius: 5px;
}

button:active {
     transform: translateY(2px);
}

input[type=radio]  {
    width:20px;
    height:20px;
    margin-right:6px;
    border:none;
    outline-style:none;
    -webkit-appearance:none;
    vertical-align:middle;
    border:1px solid #DDDDDDF0;
    border-radius:50%;
}
input[type=radio]:checked {
    border:5px solid #2F7DCDF0;
    background:#FFFFFF;
}
    
input[type=checkbox]{
 visibility: hidden;
 vertical-align:middle; margin-bottom:2px;
 cursor: pointer;
 position: relative;
 width: 24px;
 height: 24px;
}
input[type=checkbox]::after{
 position: absolute;
 top: 0;
 margin-top:2px;
 width: 14px; height: 14px;
 border: 1px solid #EEEEEE;
 border-radius: 3px;
 background-color: rgba(0,0,0,0);
 display: inline-block;
 visibility: visible;
 text-align: center;
 content: ' ';
}
input[type=checkbox]:checked::after{
 content: "✓";
 border-color: #4498F7;
 background-color: #4498F7;
 font-size: 12px;
 font-weight: bold;
}

input[type=range] {
  -webkit-appearance: none;
}
input[type=range]:focus {
  outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
  height: 15px;
  cursor: pointer;
  animate: 0.2s;
  background: #D1D1D130;
  border-radius: 1.3px;
  border: 0.2px solid #010101;
}
input[type=range]::-webkit-slider-thumb {
  border: 1px solid #000000;
  height: 18px;
  width: 16px;
  border-radius: 3px;
  background: #FFFFFFE0;
  cursor: pointer;
  -webkit-appearance: none;
  margin-top: -2px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
  background: #367ebd;
}

    
/* 滚动条整体部分 */
.scrollbar {
    overflow-x: hidden;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
	 -webkit-appearance: none;
}
.scrollbar::-webkit-scrollbar {
    width: 5px; /* 纵向滚动条宽度 */
    height: 5px;/* 横向滚动条高度 */
    background-color: #F5F5F5; /* 滚动条整体背景,一般被覆盖着 */
}
/* 滚动条的轨道(里面装有Thumb) */
.scrollbar::-webkit-scrollbar-track {
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); /* 滚动条轨道阴影 */
    /*border-radius: 10px; /* 滚动条轨道圆角 */
    background-color: #F5F5F5; /* 滚动条轨道背景 */
}
/* 滚动条里面的滑块 */
.scrollbar::-webkit-scrollbar-thumb {
    border-radius: 15px; /* 滚动条滑块圆角 */
    -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3); /* 滚动条滑块阴影 */
    background-color: #B8B8B8; /* 滚动条滑块颜色 */
}
    
.menubox {
        width: 60px;
        height: 30px;
        line-height: 30px; /*height和line-height设置一样即可文字垂直居中*/
        text-align:center;
			/*display:none; hide all other menu item*/
}
.menubox.current {
    background-color: #494949;
	 display:block;
}

.menuview {
    display:none;
}

.menuview.current {
    display:block;
    overflow-x: hidden;
    overflow-y: scroll;
    height: 100%;
}

</style>


<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>

<script>
h5gg.require(7.9); 
var h5frida=h5gg.loadPlugin("h5frida", "h5frida-15.1.24.dylib");
if(!h5frida) throw "加载h5frida插件失败\n\nFailed to load h5frida plugin";

if(!h5frida.loadGadget("frida-gadget-15.1.24.dylib"))
    throw "加载frida-gadget守护模块失败\n\nFailed to load frida-gadget daemon module";
    
var frontapp = h5frida.get_frontmost_application();

if (!frontapp) throw "frida can't get frontapp";

var session = h5frida.attach(frontapp.pid);
if(!session) throw "frida附加进程失败\n\nfrida attach process failed";

//监听frida目标进程连接状态, 比如异常退出
session.on("detached", function(reason) {
    //alert("frida目标进程会话已终止(frida target process session terminated):\n"+reason);
	 alert("Infinite Dash is gone, please restart game to turn back on!\n"+reason);
});

var frida_script_line = frida_script("getline"); //safari console will auto add 2 line
var frida_script_code = "("+frida_script.toString()+")()"; //将frida脚本转换成字符串
var script = session.create_script(frida_script_code); //注入frida的js脚本代码

if(!script) throw "frida注入脚本失败\n\nfrida inject script failed!";

script.on('message', function(msg) {
    if(msg.type=='error') {
		  script.unpin();
        script.unload(); //如果脚本发生错误就停止frida脚本
        try {if(msg.fileName=="/frida_script.js") msg.lineNumber += frida_script_line-1;} catch(e) {}
        if(Array.isArray(msg.info)) msg.info.map(function(item){ try { if(item.fileName=="/frida_script.js")
            item.lineNumber += frida_script_line-1;} catch(e) {}; return item;});
        var errmsg = JSON.stringify(msg,null,1).replace(/\/frida_script\.js\:(\d+)/gm,
            function(m,c,o,a){return "/frida_script.js:"+(Number(c)+frida_script_line-1);});
        alert("frida(脚本错误)script error:\n"+errmsg.replaceAll("\\n","\n"));
    }
    
    if(msg.type=='send')
        //alert("frida(脚本消息)srcipt msg:\n"+JSON.stringify(msg.payload,null,1));
		  alert("HACK msg:\n"+JSON.stringify(msg.payload,null,1));
    if(msg.type=='log')
        //alert("frida(脚本日志)script log:\n"+msg.payload);
		  alert("HACK log:\n"+msg.payload);
});

if(!script.load()) throw "frida启动脚本失败\n\nfrida load script failed"; //启动脚本

/**********************************************************************************/

//获取frida脚本中的rpc.exports导出函数列表
//alert("frida脚本导出函数列表:\nfrida export method list:\n" + script.list_exports());

var cheats={
	ramainingDashCount: ["charactercontroller2d", 0xA8, 1, "int", "ON"],
	fortune: ["player", 0x25C, 99, "int", "ON"],
	satiety: ["player", 0x1C8, 0, "int", "ON"],
	coinbonus: ["player", 0x24C, 100, "int", "ON"],//coinbonus, every coin give this amount of money more
	killenemycount: ["player", 0x1AC, 200, "int", "ON"],//kill enemy count and kill exp must be same
	killexp: ["player", 0x1A8, 200, "int", "ON"],
}

if(script.call("hook_hack",[cheats]))
{
    //alert("inline hook拦截成功\ndo inline hook success");
    
} else {
    alert("inline hook拦截失败, 请检查日志信息!\nDo inline hook failed, Please check log message");
}

//script.unload(); //卸载脚本

//session.detach(); //断开目标进程

/***************************************************************/

/*
 下面是frida的js脚本代码, 运行在目标进程, 不能在h5gg中直接调用这个js函数
 frida的js脚本代码中不能使用任何h5gg的函数和变量, 也不能使用window对象
 h5gg和frida只能通过console.log和send/recv/post还有rpc.exports进行通信
 The following is the js script code of frida, which runs in the target process, and this js function cannot be called directly in h5gg
 You cannot use any h5gg functions and variables in frida's js script code, nor can you use the window object
 h5gg and frida can only communicate through console.log and send/recv/post and rpc.exports
 */
function frida_script() { if(arguments.length) return new Error().line; //do not modify this line!!!

    //发送frida脚本的日志消息给h5gg
	 //console.log("Infinite Dash is enabled...");

    //HOOK拦截.app中的任何模块中的任意地址的函数或指令
    rpc.exports.hook_hack=function(cheats)
    {
        var hook1 = h5frida.StaticInlineHookInstrument("Frameworks/UnityFramework.framework/UnityFramework", //要HOOK的模块在.app中的相对路径
                 0xFDC130, //要HOOK的指令偏移地址 //instruction offset
                 function(context)
                 {
            			//console.log(JSON.stringify(context));
							/*
								Hack Loader logic developed by Happy Secret on iOSGods (2023)
								Please preserve this note, if you are gonna reuse the loader logic in another game.
							*/
							
							var charactercontroller2d = new NativePointer(context.x[0]);
							
							var creature = charactercontroller2d.add(0x1A8).readPointer();
							
							var player = creature.add(0x180).readPointer();
							
							var status = creature.add(0x68).readPointer();
							
							if (!player.isNull()) //Check if it is Player or Enemy
							{
                    		var r = context.x[8]; //x8 is storing current dash count
            
                    		r = Number(r) + 1; 
								//Add input parameter before game deduct 1. cheats["ramainingDashCount"][2]
            
                    		context.x[8] = new NativePointer(r);
								
								var obj = charactercontroller2d;
								for (var prop in cheats){
									if (Object.prototype.hasOwnProperty.call(cheats, prop)){
										if (cheats[prop][4]=="ON"){
										
										switch(cheats[prop][0]){
											case "charactercontroller2d":
												obj = charactercontroller2d;
												break;
											case "player":
												obj = player;
												break;
											case "creature":
												obj = creature;
												break;j
											case "status":
												obj = status;
												break;
										}
										switch(cheats[prop][3]){
											case "int":
												obj.add(cheats[prop][1]).writeInt(cheats[prop][2]);
												break;
											case "float":
												obj.add(cheats[prop][1]).writeFloat(cheats[prop][2]);
												break;
											case "double":
												obj.add(cheats[prop][1]).writeDouble(cheats[prop][2]);
												break;
											case "bool":
												obj.add(cheats[prop][1]).writeS8(cheats[prop][2]);
												break;
										}
										
										} //end if TURN ON
									}
								}
								
							}//end if not Null
                 }
        );
       
        
        //返回是否全部HOOK成功 //Check if all hooks are successful
        return hook1;
    };

	 rpc.exports.hook_nohack=function()
    {
        var hook2 = h5frida.StaticInlineHookInstrument("Frameworks/UnityFramework.framework/UnityFramework", //要HOOK的模块在.app中的相对路径
                 0xFDC130, //要HOOK的指令偏移地址 //instruction offset
                 function(context)
                 {
                    //put nothing here, aims to remove other hook only
                 }
        );
       
        
        //返回是否全部HOOK成功 //Check if all hooks are successful
        return hook2;
    };
}

function EnableDashHook(){
	//Reset Apply Button Color
	document.getElementById("applybutton").style.backgroundColor = '#E8E8E850';
	
	if(script.call("hook_hack",[cheats]))
	{
    	//alert("inline hook拦截成功\ndo inline hook success");
    
	} else {
      alert("inline hook拦截失败, 请检查日志信息!\nDo inline hook failed, Please check log message");
	}
}

function DisableDashHook(){
	if(script.call("hook_nohack"))
	{
    	//alert("inline hook拦截成功\ndo inline hook success");
    
	} else {
      alert("inline hook拦截失败, 请检查日志信息!\nDo inline hook failed, Please check log message");
	}
}


function ActiveCodePatch(fpath, vaddr, bytes) {
    if(!h5frida.ActiveCodePatch(fpath, vaddr, bytes)) {
        var result = h5frida.ApplyCodePatch(fpath, vaddr, bytes);
        alert(fpath+":0x"+vaddr.toString(16)+"-修改失败!\n" + fpath+":0x"+vaddr.toString(16)+"-PatchFailed!\n" + result);return false;
    } return true;
}
function DeactiveCodePatch(fpath, vaddr, bytes) {
    return h5frida.DeactiveCodePatch(fpath, vaddr, bytes);
}

</script>

<script>
    
if(typeof $ == 'undefined') alert("网络连接失败, 请重新启动!");

$(document).ready(function(){
    //alert();
    //绑定菜单点击切换子页面
    $("div.menubox").click(function(){
        $("div.menubox").removeClass("current");
        $("div.menuview").removeClass("current");
        $(this).addClass("current");
        
        var menuid = $(this).attr("menu");
        $("div#"+menuid).addClass("current");
    });
    
    /*禁止文本Option和拖动*/
    document.body.onselectstart = document.body.ondrag =function(){
        return false;
    }
    
    $("input").blur(function(){
        window.scroll(0,0); //文本框等输入完毕后页面自动滚动到顶部
    });
    
    //激活webkit的button:active
    document.body.addEventListener('touchstart', function () {});

    if(typeof h5gg!='undefined') {
        //设置标题栏区域可拖动悬浮窗
        setWindowDrag(0, 0, 400, 80);
        //设置尺寸和位置
        setWindowRect(60,60,300,300);
    }
});

function login()
{
    if(!$("#username").val()) {
        alert("please input your account");
        return;
    }
    
    if(!$("#password").val()) {
        alert("please input your password");
        return;
    }
    
    alert("test login\n\nusername:"+$("#username").val() + "\n" + "password:"+$("#password").val());
}
    
function buttonclick(input)
{
    alert("button clicked = "+input.innerText);
}
    
function checkboxclick(input)
{
    alert("checkbox clicked = "+input.parentElement.innerText+" = "+input.checked);
}
   
function rangechange(input)
{
	 cheats[input.name][2]=Number(input.value);
	 //alert("slider change = "+cheats[input.name][2]);
	 
	 //killenemycount and killexp must be same
	 if (input.name=="killenemycount"){
		 cheats["killexp"][2]=Number(input.value);
	 }
	 
	 input.previousElementSibling.value=input.value;
	
	 //Change Apply Button Color to remind user to press Apply
	 document.getElementById("applybutton").style.backgroundColor = '#911';
}
    
function radioclick(input)
{
    //alert("radio clicked: group = "+input.name+" = "+input.parentElement.innerText+" = "+input.value);
	if (input.value=='hp') {
		ActiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFB768, "083540F91F1940BD1F1500BD");
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFB7F4, "2900805209B500B9083540F9");
	} else if (input.value=='god'){
		ActiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFB7F4, "2900805209B500B9083540F9");
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFB768, "083540F91F1940BD1F1500BD");
	} else if (input.value=='nil'){
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFB768, "083540F91F1940BD1F1500BD");
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDFB7F4, "2900805209B500B9083540F9");
	} else 	if (input.value=='dash'){
		EnableDashHook();
	} else 	if (input.value=='nodash'){
		DisableDashHook();
	} else if (input.value=='money'){
		ActiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDE61EC, "C802132B");
	} else if (input.value=='nilmoney'){
		DeactiveCodePatch("Frameworks/UnityFramework.framework/UnityFramework", 0xDE61EC, "C802132B");
	} 

}
</script>



</head>

<body bgcolor="#202C3E" style="margin:0;">
<!--标题栏-->
<div id="titleBar" style="background-color:#122220; padding:5px; margin:0px;">
&nbsp;Dungreed v1.6.175 Hack
</div>
<!--用一个表格来布局左右两栏-->
<table id="bodyView" width="100%" style="table-layout:fixed;height: calc(100% - 30px) ;">
    
<tr>
    
<td width="30%" style="vertical-align:top">
    
<div>
    <div class="menubox" menu="menu1" hidden="hidden">Menu 1</div>
    <div class="menubox" menu="menu2" hidden="hidden">Menu 2</div>
    <div class="menubox" menu="menu3">Advance</div>
    <div class="menubox current" menu="menu4">Basic</div>
    <div class="menubox" menu="menu5" hidden="hidden">Menu 5</div>
</div>
</td>
<td style="vertical-align:top" class="scrollbar">
<div id="menu1" class="menuview">
<p>CheckBox</p>
    <label><input type="checkbox" checked="checked" onclick="checkboxclick(this)" />Option1</label>
    <label><input type="checkbox"  onclick="checkboxclick(this)" />Option2</label>
    <p>
    <label><input type="checkbox"  onclick="checkboxclick(this)" />Option3</label>
    <label><input type="checkbox" onclick="checkboxclick(this)" />Option4</label>
    <p>
</div>

<div id="menu2" class="menuview">
<p>Button</p>
    <button onclick="buttonclick(this)">Button1</button>
    <button onclick="buttonclick(this)">Button2</button>
    <p>
    <button onclick="buttonclick(this)">Button3</button>
    <button onclick="buttonclick(this)">Button4</button>
</div>

<div id="menu3" class="menuview">
    <p><label>Fortune / Luck <output>(99)</output><input name="fortune" type="range" min="0" max="100" value="99" style="width:90%" onchange="rangechange(this)" /></label>
	 <br><label>Satiety / Hungry <output>(0)</output><input name="satiety"type="range" min="0" max="100" value="0" style="width:90%" onchange="rangechange(this)" /></label>
    <br><label>Coin Bonus <output>(100)</output><input name="coinbonus"type="range" min="0" max="200" value="100" style="width:90%" onchange="rangechange(this)" /></label>
	 <br><label>Kill Count <output>(200)</output><input name="killenemycount"type="range" min="0" max="500" value="200" style="width:90%" onchange="rangechange(this)" /></label>
	 <p align="center"><button onclick="EnableDashHook()" id="applybutton">Trigger on Dash</button>
</div>

<div id="menu4" class="menuview current">
    <p>Survival (Switch Weapon to trigger)</p>
  <label><input name="radio-group1" type="radio" value="nil" checked onclick="radioclick(this)" />Normal</label>
	<p><label><input name="radio-group1" type="radio" value="hp" onclick="radioclick(this)" />Heal Hp</label>
	<p><label><input name="radio-group1" type="radio" value="god" onclick="radioclick(this)" />Tempoary God Mode</label>
	<p>Money</p>
  <label><input name="radio-group2" type="radio" value="nilmoney" checked="checked"  onclick="radioclick(this)" />Normal</label>
  <p><label><input name="radio-group2" type="radio" value="money" onclick="radioclick(this)" />Spend to Increase</label>

  <p>Infinite Dash</p>
  <label><input name="radio-group3" type="radio" value="nodash" onclick="radioclick(this)" />Normal</label>
  <p><label><input name="radio-group3" type="radio" value="dash" checked="checked" onclick="radioclick(this)" />Enable</label>
  
</div>

<div id="menu5" class="menuview">
<p>Input</p>
<p><label>Username: <input id="username" name="username" type="text" placeholder="input your username" /></label>
<p>Password: <input id="password" name="password" type="password" placeholder="input your password" />
<p align="center"><button onclick="login()">Login</button>
</div>

</td>

</tr>

</table>

</body>
</html>

 

 

 


 

 

 

New content could be added later

Updated by Happy Secret
  • Like 37
  • Winner 2
  • Thanks 3
  • Haha 2
  • Agree 1
  • Informative 8
Link to comment
Share on other sites

Fantastic post! 👍

I just had to say that this tutorial is simply outstanding and deserves to be pinned.

I want to extend my gratitude to you, @Happy Secret for taking the time and effort to document this tutorial. You've done the community a tremendous service, and we're all better off because of it. Thank you!

I can confidently say that this is hands down the best 101 tutorial on iOS game debugging, sdk extraction, static and dynamic analysis, mod menu design, implementation, and beginner coding and hacking that I have ever come across on any forum!

What's even more impressive is that you're utilizing cutting-edge tools like H5GG to create a custom mod menu game hack that doesn't require a jailbreak. The fact that H5GG leverages the coding language of the web (JavaScript and HTML) is a testament to the evolution of iOS game hacking in 2023.

  • Thanks 1
Link to comment
Share on other sites

On 4/9/2023 at 1:05 AM, julesvandor said:

Fantastic post! 👍

I just had to say that this tutorial is simply outstanding and deserves to be pinned.

I want to extend my gratitude to you, @Happy Secret for taking the time and effort to document this tutorial. You've done the community a tremendous service, and we're all better off because of it. Thank you!

I can confidently say that this is hands down the best 101 tutorial on iOS game debugging, sdk extraction, static and dynamic analysis, mod menu design, implementation, and beginner coding and hacking that I have ever come across on any forum!

What's even more impressive is that you're utilizing cutting-edge tools like H5GG to create a custom mod menu game hack that doesn't require a jailbreak. The fact that H5GG leverages the coding language of the web (JavaScript and HTML) is a testament to the evolution of iOS game hacking in 2023.

Thanks, May be you want to let more of your friend know about this tutorial. 
 

You may also want to check out my other cheat posts. Every cheat I made, I would document some hacking note for people reference. Those would be good case studies for cheat learner as well.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below. For more information, please read our Posting Guidelines.
Reply to this topic... Posting Guidelines

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Our picks

    • Idle Ninja Online v2121 Cheats +15
      Modded/Hacked App: Idle Ninja Online By Puzzle Monsters Inc.
      Bundle ID: com.puzzlemonsters.growninja
      iTunes Store Link: https://apps.apple.com/us/app/idle-ninja-online/id1559182313?uo=4


      Hack Features:
      - no cool skill
      - no need mana
      - speed
      - max level
      - fast shot
      - penetration
      - multi shot
      - far FOV (in setting)
      - can move 
      - reduce animation
      - skin dame (need show damege skin in setting, from 1 to 23)
      - antiban (not sure 100%) 


      Non-Jailbroken & No Jailbreak required hack(s): https://iosgods.com/forum/79-no-jailbreak-section/
      Modded Android APK(s): https://iosgods.com/forum/68-android-section/
      For more fun, check out the Club(s): https://iosgods.com/clubs/
      • 539 replies
    • Top Troops: Adventure v1.5.5 Cheats +1
      Modded/Hacked App: Top Troops: Adventure RPG By Zynga Inc.
      Bundle ID: game.socialempiresmerge
      iTunes Store Link: https://apps.apple.com/us/app/top-troops-adventure-rpg/id1574634455?uo=4

      Mod Requirements:
      - Non-Jailbroken/Jailed or Jailbroken iPhone/iPad/iPod Touch.
      - Sideloadly / Cydia Impactor or alternatives.
      - A Computer Running Windows/macOS/Linux with iTunes installed.


      Hack Features:
      - x4 currency earn
      • 59 replies
    • Top Troops v1.5.5 Cheats +2
      Modded/Hacked App: Top Troops: Adventure RPG By Zynga Inc.
      Bundle ID: game.socialempiresmerge
      iTunes Store Link: https://apps.apple.com/us/app/top-troops-adventure-rpg/id1574634455?uo=4


      Mod Requirements:
      - Jailbroken iPhone/iPad/iPod Touch.
      - iGameGod / Filza / iMazing or any other file managers for iOS.
      - Cydia Substrate, Substitute or libhooker depending on your jailbreak.
      - PreferenceLoader (from Cydia, Sileo or Zebra).


      Hack Features:
      - Frozen currency
      - x4 currency earn
      • 99 replies
    • [ Sausage Man CN ] 香肠派对 v17.60 +9 Cheats
      Modded/Hacked App: 香肠派对 By X.D. Network Inc.
      Bundle ID: com.xd.Sausage
      iTunes Store Link: https://apps.apple.com/cn/app/%E9%A6%99%E8%82%A0%E6%B4%BE%E5%AF%B9/id1326730621?uo=4


      Mod Requirements:
      - Jailbroken iPhone/iPad/iPod Touch.
      - Filza / iMazing or any other file managers for iOS.
      - Cydia Substrate, Substitute or libhooker depending on your jailbreak.
      - PreferenceLoader (from Cydia or Sileo).


      Hack Features:
      - Rainbow Wall Hack
      - Walk On Water
      - Custom FOV
      - Custom Speed
      - No Recoil
      - No Shake
      - No Muzzle Flash
      - Superman
      - No Fire Sound
      - No Reload Sound
      - No Bow Sound
      Notes:
      - First time doing wall hack and is buggy, for some reason, the game stops registering players if they're not in your vision so it still useful to see enemies easily but works best against bots
      - FOV set it to around 100.
      - Speed, set it around 10 and see if the server registers your speed.


      Non-Jailbroken & No Jailbreak required hack(s): https://iosgods.com/forum/79-no-jailbreak-section/
      Modded Android APK(s): https://iosgods.com/forum/68-android-section/
      For more fun, check out the Club(s): https://iosgods.com/clubs/


      iOS Hack Download Link:

      Hidden Content
      Download Hack







      Installation Instructions:
      STEP 1: Download the .deb Cydia hack file from the link above.
      STEP 2: Copy the file over to your iDevice using any of the file managers mentioned above or skip this step if you're downloading from your iDevice.
      STEP 3: Using Filza or iFile, browse to where you saved the downloaded .deb file and tap on it.
      STEP 4: Once you tap on the file, you will need to press on 'Install' or 'Installer' from the options on your screen.
      STEP 5: Let Filza / iFile finish the cheat installation. Make sure it successfully installs, otherwise see the note below.
      STEP 6: If the hack is a Mod Menu, which is usually the case nowadays, the cheat features can be toggled in-game. Some cheats have options that can be enabled from your iDevice settings.
      STEP 7: Turn on the features you want and play the game. You may need to follow further instructions inside the hack's popup in-game.

       

      NOTE: If you have any questions or problems, read our Troubleshooting topic & Frequently Asked Questions & Answers topic. If you still haven't found a solution, post your issue down below and we'll do our best to help! If the hack does work for you, post your feedback below and help out other fellow members that are encountering issues.


      Credits:
      - @Zahir


      Cheat Video/Screenshots:

      N/A
      • 414 replies
    • Hero Wars: Alliance v1.200.003 +2 Cheats
      Modded/Hacked App: Hero Wars - Fantasy World By Nexters Global LTD
      Bundle ID: com.nexters.titanhunters
      iTunes Store Link: https://apps.apple.com/us/app/hero-wars-fantasy-world/id1158967485?uo=4


      Mod Requirements:
      - Jailbroken iPhone/iPad/iPod Touch.
      - Filza / iMazing or any other file managers for iOS.
      - Cydia Substrate, Substitute or libhooker depending on your jailbreak.
      - PreferenceLoader (from Cydia or Sileo).


      Hack Features:
      - x dmg
      - x def


      Non-Jailbroken & No Jailbreak required hack(s): https://iosgods.com/forum/79-no-jailbreak-section/
      Modded Android APK(s): https://iosgods.com/forum/68-android-section/
      For more fun, check out the Club(s): https://iosgods.com/clubs/


      iOS Hack Download Link:

      Hidden Content
      Download Hack







      Installation Instructions:
      STEP 1: Download the .deb Cydia hack file from the link above.
      STEP 2: Copy the file over to your iDevice using any of the file managers mentioned above or skip this step if you're downloading from your iDevice.
      STEP 3: Using Filza or iFile, browse to where you saved the downloaded .deb file and tap on it.
      STEP 4: Once you tap on the file, you will need to press on 'Install' or 'Installer' from the options on your screen.
      STEP 5: Let Filza / iFile finish the cheat installation. Make sure it successfully installs, otherwise see the note below.
      STEP 6: If the hack is a Mod Menu, which is usually the case nowadays, the cheat features can be toggled in-game. Some cheats have options that can be enabled from your iDevice settings.
      STEP 7: Turn on the features you want and play the game. You may need to follow further instructions inside the hack's popup in-game.

       

      NOTE: If you have any questions or problems, read our Troubleshooting topic & Frequently Asked Questions & Answers topic. If you still haven't found a solution, post your issue down below and we'll do our best to help! If the hack does work for you, post your feedback below and help out other fellow members that are encountering issues.


      Credits:
      - AlyssaX64


      Cheat Video/Screenshots:

      N/A
      • 330 replies
    • Guardian War: RPG Pixel Games v0.2.80 +3 Cheats
      Modded/Hacked App: Guardian War: RPG Pixel Games By Pitado Viet Nam JSC
      Bundle ID: com.fansipan.guardian.war.rpg.pixel.hero.adventure.games
      iTunes Store Link: https://apps.apple.com/us/app/guardian-war-rpg-pixel-games/id6472647574?uo=4


      Mod Requirements:
      - Jailbroken iPhone/iPad/iPod Touch.
      - iGameGod / Filza / iMazing or any other file managers for iOS.
      - Cydia Substrate, Substitute or libhooker depending on your jailbreak.
      - PreferenceLoader (from Cydia, Sileo or Zebra).


      Hack Features:
      - Damage Multiplier
      - Defense Multiplier
      - No Ads
      - Unlimited Rerolls
      - Tutorial Bypassed


      Non-Jailbroken & No Jailbreak required hack(s): https://iosgods.com/forum/79-no-jailbreak-section/
      Modded Android APK(s): https://iosgods.com/forum/68-android-section/
      For more fun, check out the Club(s): https://iosgods.com/clubs/


      iOS Hack Download Link:

      Hidden Content
      Download Hack







      Installation Instructions:
      STEP 1: Download the .deb Cydia hack file from the link above. Use Safari/Google Chrome or other iOS browsers to download.
      STEP 2: Once the file has downloaded, tap on it and then you will be prompted on whether you want to open the deb with iGameGod or copy it to Filza.
      STEP 3: If necessary, tap on the downloaded file, and then, you will need to press 'Install' from the options on your screen.
      STEP 4: Let iGameGod/Filza finish the cheat installation. Make sure it successfully installs, otherwise see the note below.
      STEP 5: If the hack is a Mod Menu — which is usually the case nowadays — the cheat features can be toggled in-game. Some cheats have options that can be enabled from your iDevice settings.
      STEP 6: Turn on the features you want and play the game. You may need to follow further instructions inside the hack's popup in-game.

       

      NOTE: If you have any questions or problems, read our Troubleshooting topic & Frequently Asked Questions & Answers topic. If you still haven't found a solution, post your issue down below and we'll do our best to help! If the hack does work for you, please post your feedback below and help out other fellow members that are encountering issues.


      Credits:
      - AlyssaX64


      Cheat Video/Screenshots:

      N/A
      • 139 replies
    • Merge Manor : Sunny House v1.3.04 +1 Cheat
      Modded/Hacked App: Merge Manor : Sunny House By cookapps
      Bundle ID: com.cookapps.interiors.home.design.merge.sunnyhouse
      iTunes Store Link: https://apps.apple.com/us/app/merge-manor-sunny-house/id1573861950?uo=4


      Mod Requirements:
      - Jailbroken iPhone/iPad/iPod Touch.
      - Filza / iMazing or any other file managers for iOS.
      - Cydia Substrate, Substitute or libhooker depending on your jailbreak.
      - PreferenceLoader (from Cydia or Sileo).


      Hack Features:
      - freeze currencies





      Non-Jailbroken & No Jailbreak required hack(s): https://iosgods.com/forum/79-no-jailbreak-section/
      Modded Android APK(s): https://iosgods.com/forum/68-android-section/
      For more fun, check out the Club(s): https://iosgods.com/clubs/


      iOS Hack Download Link:

      Hidden Content
      Download Hack







      Installation Instructions:
      STEP 1: Download the .deb Cydia hack file from the link above.
      STEP 2: Copy the file over to your iDevice using any of the file managers mentioned above or skip this step if you're downloading from your iDevice.
      STEP 3: Using Filza or iFile, browse to where you saved the downloaded .deb file and tap on it.
      STEP 4: Once you tap on the file, you will need to press on 'Install' or 'Installer' from the options on your screen.
      STEP 5: Let Filza / iFile finish the cheat installation. Make sure it successfully installs, otherwise see the note below.
      STEP 6: If the hack is a Mod Menu, which is usually the case nowadays, the cheat features can be toggled in-game. Some cheats have options that can be enabled from your iDevice settings.
      STEP 7: Turn on the features you want and play the game. You may need to follow further instructions inside the hack's popup in-game.

       

      NOTE: If you have any questions or problems, read our Troubleshooting topic & Frequently Asked Questions & Answers topic. If you still haven't found a solution, post your issue down below and we'll do our best to help! If the hack does work for you, post your feedback below and help out other fellow members that are encountering issues.


      Credits:
      - AlyssaX64


      Cheat Video/Screenshots:

      N/A
      • 211 replies
    • 神魔之塔 - Tower of Saviors v2024.310 +1 [ Weak Enemies ]
      Modded/Hacked App: 神魔之塔 - Tower of Saviors By Mad Head Limited
      Bundle ID: com.madhead.tos.zh
      iTunes Store Link: https://apps.apple.com/us/app/神魔之塔-tower-of-saviors/id583798880

      Hack Features:
      - weak enemies


      Non-Jailbroken & No Jailbreak required hack(s): https://iosgods.com/forum/79-no-jailbreak-section/
      Modded Android APK(s): https://iosgods.com/forum/68-android-section/
      For more fun, check out the Club(s): https://iosgods.com/clubs/
      • 357 replies
    • PunBall Cheats v4.9.1 +2
      Modded/Hacked App: PunBall By HABBY PTE. LTD.
      Bundle ID: com.habby.punball
      iTunes Store Link: https://apps.apple.com/us/app/punball/id1585781366?uo=4


      Hack Features:
      - Dumb Enemies
      - One Hit Kill


      iOS Hack Download Link: https://iosgods.com/topic/151406-punball-cheats-v100-2/
      • 644 replies
    • Escape Time v2.4.0 +4 [Unlimited Currency]
      Modded/Hacked App: Escape Time Puzzle Brain Games By WEBELINX GAMES DOO
      Bundle ID: webelinx.EscapeRoom.Free.Portrait.Game.free2
      iTunes Store Link: https://apps.apple.com/us/app/escape-time-puzzle-brain-games/id1483021623?uo=4


      Mod Requirements:
      - Jailbroken iPhone/iPad/iPod Touch.
      - iGameGod / Filza / iMazing or any other file managers for iOS.
      - Cydia Substrate, ElleKit, Substitute or libhooker depending on your jailbreak.
      - PreferenceLoader (from Cydia, Sileo or Zebra).


      Hack Features:
      - No Ads
      - Freeze Lives
      - Unlimited Coins
      - Freeze Minigame Timers


      Non-Jailbroken & No Jailbreak required hack(s): https://iosgods.com/forum/79-no-jailbreak-section/
      Modded Android APK(s): https://iosgods.com/forum/68-android-section/
      For more fun, check out the Club(s): https://iosgods.com/clubs/


      iOS Hack Download Link:

      • 1 reply
    • Escape Time v2.4.0 +4 [Unlimited Currency]
      Modded/Hacked App: Escape Time Puzzle Brain Games By WEBELINX GAMES DOO
      Bundle ID: webelinx.EscapeRoom.Free.Portrait.Game.free2
      iTunes Store Link: https://apps.apple.com/us/app/escape-time-puzzle-brain-games/id1483021623?uo=4


      Mod Requirements:
      - Non-Jailbroken/Jailed or Jailbroken iPhone/iPad/iPod Touch.
      - Sideloadly / Cydia Impactor or alternatives.
      - A Computer Running Windows/macOS/Linux with iTunes installed.


      Hack Features:
      - No Ads
      - Freeze Lives
      - Unlimited Coins
      - Freeze Minigame Timers


      Jailbreak required hack(s): https://iosgods.com/forum/5-game-cheats-hack-requests/
      Modded Android APK(s): https://iosgods.com/forum/68-android-section/
      For more fun, check out the Club(s): https://iosgods.com/clubs/


      iOS Hack Download IPA Link:

      Hidden Content
      • 0 replies
    • Tanks A Lot - 3v3 Brawls Cheats v6.501 +6
      Modded/Hacked App: Tanks A Lot - 3v3 Brawls by BoomBit, Inc.
      Bundle ID: com.boombitgames.TanksALot
      iTunes Store Link: https://apps.apple.com/us/app/tanks-a-lot-3v3-brawls/id1344713773?uo=4&at=1010lce4


      Hack Features:
      - God Mode
      - Infinite Ammo
      - No Reload
      - Speed Hacks
      - Disable Enemy Shield
      - No Skill Cooldown


      Hack Download Link: https://iosgods.com/topic/76001-arm64-tanks-a-lot-3v3-brawls-cheats-v190-6/
      • 2,002 replies
×
  • Create New...

Important Information

We would like to place cookies on your device to help make this website better. The website cannot give you the best user experience without cookies. You can accept or decline our cookies. You may also adjust your cookie settings. Privacy Policy - Guidelines