> For the complete documentation index, see [llms.txt](https://ret2basic.gitbook.io/ctfwriteup/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ret2basic.gitbook.io/ctfwriteup/game-hacking/pwn-adventure-3-pwnie-island/prep-infinite-health-and-mana-offline.md).

# Prep: Infinite Health and Mana (Offline)

## Motivation

This chapter is just for fun, it is kind of useless since we only care about the online version.

After the speed hack we do a quick infinite health and mana hack. <mark style="color:red;">**Beware that this hack only works locally**</mark> because we will only modify `GameLogic.dll` instead of tampering the messages between client and server. The game server performs checks on the value of health and mana, therefore this simple hack only works in offline mode.

## Infinite Mana Hack

<mark style="color:red;">**Search "Mana" in symbols**</mark> and we find a function named `Player::UseMana(int)`:

<figure><img src="https://223316867-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MWVtlSxURaW2QQu6RU5%2Fuploads%2Fs2iVRS8zZxL7JNMYoNQT%2Fimage.png?alt=media&amp;token=359b0afe-e6ec-4c6e-b728-8e356a1cf5cb" alt=""><figcaption></figcaption></figure>

WTF is `this->m_inventory._Myhead`??? Rename the vars a bit:

```cpp
char __thiscall Player::UseMana(Player *this, int manaUsed)
{
  World *gameWorld; // ecx
  std::_Tree_node<std::pair<IItem * const,ItemAndCount>,void *> *oldMana; // eax
  std::_Tree_node<std::pair<IItem * const,ItemAndCount>,void *> *newMana; // eax

  gameWorld = GameWorld;
  if ( GameWorld )
  {
    if ( !GameWorld->IsAuthority(GameWorld) )
      return 0;
    gameWorld = GameWorld;
  }
  oldMana = this->m_inventory.mana;
  if ( (int)oldMana < manaUsed )
    return 0;
  newMana = (std::_Tree_node<std::pair<IItem * const,ItemAndCount>,void *> *)((char *)oldMana - manaUsed);
  this->m_inventory.mana = newMana;
  gameWorld->SendManaUpdateEvent(gameWorld, (Player *)((char *)this - 112), (int)newMana);
  return 1;
}
```

The mana deduction happens at:

```cpp
newMana = (std::_Tree_node<std::pair<IItem * const,ItemAndCount>,void *> *)((char *)oldMana - manaUsed);
```

We can "NOP" out the mana subtraction:

<figure><img src="https://223316867-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MWVtlSxURaW2QQu6RU5%2Fuploads%2FmxDi1ApAtmKo8oEMezrz%2Fimage.png?alt=media&amp;token=11456bc6-a309-46fc-a9ab-4e269b4f6cff" alt=""><figcaption></figcaption></figure>

Save the patch and go back to the game. Click "Offline Play" and test if mana is infinite now. It should work.

## Infinite Health Hack (failed attempt)

Similarly, we can search for "Damage" in symbols and find this `Player::Damage()` function:

<figure><img src="https://223316867-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MWVtlSxURaW2QQu6RU5%2Fuploads%2FwPxPmaZXwJlo3FCawhw4%2Fimage.png?alt=media&amp;token=7f4e64b5-1cc9-4cc2-9170-bdfbb59ba1c7" alt=""><figcaption></figcaption></figure>

Pseudocode:

```cpp
void __thiscall Player::Damage(Player *this, Player *instigator, IItem *item, int dmg, DamageType type)
{
  int v6; // eax
  int m_health; // esi
  World *v8; // ecx
  int dmga; // [esp+14h] [ebp+10h]

  if ( (!GameWorld || GameWorld->IsAuthority(GameWorld)) && !this->m_changingServerRegion )
  {
    if ( instigator == this )
    {
      v6 = (int)(float)((float)dmg * 0.25);
    }
    else
    {
      if ( instigator
        && instigator->IsPlayer(instigator)
        && (!this->m_pvpEnabled || !instigator->IsPvPEnabled(instigator)) )
      {
        return;
      }
      v6 = dmg;
    }
    m_health = this->m_health;
    dmga = v6;
    Actor::Damage(this, instigator, item, v6, type);
    if ( this->m_health < m_health )
      this->m_healthRegenCooldown = 20.0;
    if ( item )
    {
      if ( dmga > 0 )
      {
        v8 = GameWorld;
        this->m_lastHitByItem = item;
        this->m_lastHitItemTimeLeft = 5.0;
        v8->SendLastHitByItemEvent(v8, this, item);
      }
    }
  }
}
```

If we set `v6` to 0 we should be free from damage. So here we can patch the binary to `mov eax, 0`:

<figure><img src="https://223316867-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MWVtlSxURaW2QQu6RU5%2Fuploads%2Fca7mGZm1SVbIpbdSgz5r%2Fimage.png?alt=media&amp;token=6a990153-76e6-4f16-8066-e3c18cc87a6a" alt=""><figcaption></figcaption></figure>

Press space key and hover your mouse on this line. Go to "Edit -> Patch program -> Assemble":

<figure><img src="https://223316867-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MWVtlSxURaW2QQu6RU5%2Fuploads%2Fyx2Hhkx9GgPMmYWdIE49%2Fimage.png?alt=media&amp;token=1bcee57b-20e5-467d-9a4e-871c7899daad" alt=""><figcaption></figcaption></figure>

Well, the game crashes. We will try patching something else.

## Infinite Health Hack (success)

Note that there is a "respawn" functionality in the game. <mark style="color:red;">**Search "Respawn" in symbols**</mark> and we can find a function named `Player::PerformRespawn()`:

<figure><img src="https://223316867-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MWVtlSxURaW2QQu6RU5%2Fuploads%2FhMDlWC1uV4zVd9HnvUD0%2Fimage.png?alt=media&amp;token=f5147d16-cbab-4cff-a500-18b32deafe8f" alt=""><figcaption></figcaption></figure>

Pseudocode:

```cpp
void __thiscall Player::PerformRespawn(Player *this)
{
  IUE4Actor *m_target; // ecx
  LocationAndRotation choice; // [esp+Ch] [ebp-18h] BYREF

  if ( this->GetHealth(this) <= 0 )
  {
    this->m_health = 100;
    this->m_mana = 100;
    Player::GetSpawnLocation(this, &choice);
    GameWorld->SendRespawnEvent(GameWorld, this, (const Vector3 *)&choice, &choice.rotation);
    m_target = this->m_target;
    if ( m_target )
      m_target->LocalRespawn(m_target, &choice.location, &choice.rotation);
  }
}
```

Basically this code says the character can be respawned with 100 health and 100 mana. If we set `this->m_health` to something like max Int32 (`0x7fffffff`), we could gain an insane amount of health when we respawn. This is the relevant assembly:

<figure><img src="https://223316867-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MWVtlSxURaW2QQu6RU5%2Fuploads%2FHVaFSpZbsW0zfMdZKYOt%2Fimage.png?alt=media&amp;token=50727b49-9325-4554-b4e9-ec16eb5ef1b7" alt=""><figcaption></figcaption></figure>

Patch `0x00000064` to `0x7fffffff`:

<figure><img src="https://223316867-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MWVtlSxURaW2QQu6RU5%2Fuploads%2FtTZYmRu7vL1sL9taELvT%2Fimage.png?alt=media&amp;token=881b52be-57e7-471e-9d70-d83e289f3839" alt=""><figcaption></figcaption></figure>

Go back to the game. Find a rat and get killed, respawn, now we have max Int32 amount of health :sunglasses:
