RISE OF THE TOMB RAIDER Health hacking

dl748

Expert Cheater
Jul 9, 2017
111
1
16
#41
I have a really old LUA script that doesn't use code injection. Just tested and it still works.
Code:
  if HealthLocation == nil then
    HealthLocation = AOBScan("48 8B 0D ?? ?? ?? ?? 30 DB 45 30 ED","+W-C+X")
    HealthLocation2 = AOBScan("45 30 FF FF 50 ?? 48 8B 0D ?? ?? ?? ?? 48 89 C2 45 31 C0","+W-C+X")
  end
  if HealthLocation ~= nil and HealthLocation2 ~= nil then
    count = stringlist_getCount(HealthLocation)
    count2 = stringlist_getCount(HealthLocation2)
    if count == 1 and count2 == 1 then
      address = getAddress(stringlist_getString(HealthLocation,0))
      offset = readInteger(address+3)
      address = address + 6
      if offset >= 0x80000000 then
        address = address - bAnd(bNot(offset),0xFFFFFFFF)
      else
        address = address + offset
      end
      address = readPointer(address)
      local id = readQword(address+0x348)
      address = getAddress(stringlist_getString(HealthLocation2,0))
      offset = readInteger(address+9)
      address = address + 12
      if offset >= 0x80000000 then
        address = address - bAnd(bNot(offset),0xFFFFFFFF)
      else
        address = address + offset
      end
      address = readPointer(address)
      local count = readInteger(address + 0x328)
      address = readPointer(address + 0x330)
      local addr = 0
      for i=0,count-1 do
        local tempaddr = readPointer(address + (i*0x8))
        if tempaddr ~= 0 then
          local tempaddr2 = readPointer(tempaddr + 0x338)
          if tempaddr2 ~= 0 then
            local tempid = readQword(tempaddr2+0x28)
            if id == tempid then
              addr = tempaddr
            end
          end
        end
      end
      if addr ~= 0 then
        address = readPointer(addr+0x60E8)
        if address ~= 0 then
          address = readPointer(address+0x3198)
          address = readPointer(address+0xD8)
          local healthpos = 0x20
          local healthloc = readPointer(address + (healthpos * 0x8))
          registerSymbol("MaxHealthLocation", healthloc + 0x2C4)
          address = readPointer(healthloc + 0x2A8)
          registerSymbol("HealthLocation", address + 0x2C)
          value = readInteger(healthloc+0x2C4)
          writeFloat(address + 0x2C, value)
        end
      end
    end
  end
This gets the internal ID of health, and then loops through though the objects to find that ID and then registers a symbol for HealthLocation and MaxHealthLocation. It then will write the HealthLocation with the float from the MaxHealthLocation. I have newer scripting functions that would make this a lot cleaner.
 
Aug 5, 2017
46
0
6
#42
SunBeam post_id=19269 time=1507243144 user_id=57 said:
^ Either next question would be how that works OR "it's too advanced for me". Just anticipating.
at least he is trying to help not just commenting like you do
 
Aug 5, 2017
46
0
6
#43
SunBeam post_id=19307 time=1507297669 user_id=57 said:
^ Here we go: https://software.intel.com/en-us/articles/introduction-to-x64-assembly. Hope it helps.
thx
 

dl748

Expert Cheater
Jul 9, 2017
111
1
16
#44
It follows a static address down to the correct health pointer by using similar code that the engine uses but in LUA.

1. Follows static pointer down to the ID of the health record.
2. Uses that ID to follow a hash/associative array down to the actual health record.
3. Creates/Updates a Symbol "HealthLocation" with the address of the health (I don't use symbol anymore, but create records in my latest code)

The first tomb raider uses the same exact method, I have updated the first game with my new code but not the latest.

http://fearlessrevolution.com/viewtopic.php?f=4&t=4118&p=13996#p13996

HealthLocation = AOBScan("48 8B 0D ?? ?? ?? ?? 30 DB 45 30 ED","+W-C+X") -- Locates assembly code of the static address. I've found its LESS likely that coders will change code that accesses a global variable than they would say, change how health is calculated. Which is why code like this will generally work from version to version instead of code that attacks where health is being modified.

HealthLocation + 3 = Static address (as a code offset, the integer located here is an offset to where the static address is)
[[Static + 0] + 0x348] = Id of the health record

HealthLocation2 + 9 = Static location of the hash
[[Static + 0] + 0x328] = Item count
[[Static + 0] + 0x330] = Address of hash

Loop through items (0,count-1) and read the pointer at HashAddr + (i*8)
[[itemaddr + 0x338]+0x28] = id of item -- find the id that matches the health id

[[[[[[itemaddr + 0x60E8] + 0x3198] + 0xD8] + (0x20 * 0x8)] + 0x2A8] + 0x2C] = float of health
[[[[[itemaddr + 0x60E8] + 0x3198] + 0xD8] + (0x20 * 0x8)] + 0x2C4] = int of max health

I prefer this reference http://x86.renejeschke.de/
 
Aug 5, 2017
46
0
6
#45
dl748 post_id=19478 time=1507468844 user_id=7080 said:
It follows a static address down to the correct health pointer by using similar code that the engine uses but in LUA.

1. Follows static pointer down to the ID of the health record.
2. Uses that ID to follow a hash/associative array down to the actual health record.
3. Creates/Updates a Symbol "HealthLocation" with the address of the health (I don't use symbol anymore, but create records in my latest code)

The first tomb raider uses the same exact method, I have updated the first game with my new code but not the latest.

http://fearlessrevolution.com/viewtopic.php?f=4&t=4118&p=13996#p13996

HealthLocation = AOBScan("48 8B 0D ?? ?? ?? ?? 30 DB 45 30 ED","+W-C+X") -- Locates assembly code of the static address. I've found its LESS likely that coders will change code that accesses a global variable than they would say, change how health is calculated. Which is why code like this will generally work from version to version instead of code that attacks where health is being modified.

HealthLocation + 3 = Static address (as a code offset, the integer located here is an offset to where the static address is)
[[Static + 0] + 0x348] = Id of the health record

HealthLocation2 + 9 = Static location of the hash
[[Static + 0] + 0x328] = Item count
[[Static + 0] + 0x330] = Address of hash

Loop through items (0,count-1) and read the pointer at HashAddr + (i*8)
[[itemaddr + 0x338]+0x28] = id of item -- find the id that matches the health id

[[[[[[itemaddr + 0x60E8] + 0x3198] + 0xD8] + (0x20 * 0x8)] + 0x2A8] + 0x2C] = float of health
[[[[[itemaddr + 0x60E8] + 0x3198] + 0xD8] + (0x20 * 0x8)] + 0x2C4] = int of max health

I prefer this reference http://x86.renejeschke.de/
great help man thanks lot
 
Mar 2, 2017
10
0
1
#46
I did this last year. I'm completely uncertain if this is any help since I haven't touched the game since the time stamp in the comment up top.

Script 1 (primary):
1. Find player health global (accessed every frame) right from the get go after loading game or whatever
2. Find a static value (pseudo "isPlayer" for example) found somewhere near

Script 2 (sub-script 1):
1: Find writable player health or object health since it iterates over enemies/npc's as wel
2: Use the static reference from Script 1 to do a compare (appears I used negative offset 2D0 which isn't exactly near but it worked)
3: Write player health if (pseudo) "isPlayer"

Good luck.
Code:
{
  Game   : ROTTR.exe
  Date   : 2016-02-14
  Author : Daijobu
}

[ENABLE]
aobscanmodule(rottr_fetchPlayerCheck,ROTTR.exe,48 8B 8F * * 00 00 8B 15 * * * * 4C 89 BC)
alloc(rottr_fetchPlayerCheckAlloc,$1000,rottr_fetchPlayerCheck)
registersymbol(rottr_fetchPlayerCheck)
label(rottr_fetchPlayerCheckAllocExit)
globalalloc(rottr_PlayerCheck,8)

registersymbol(rottr_StoreBytes1)
label(rottr_StoreBytes1)
rottr_fetchPlayerCheckAlloc+128:
rottr_StoreBytes1:
  readmem(rottr_fetchPlayerCheck,7)

rottr_fetchPlayerCheckAlloc:
  readmem(rottr_fetchPlayerCheck,7)
  mov [rottr_PlayerCheck],rbx
  jmp rottr_fetchPlayerCheckAllocExit

rottr_fetchPlayerCheck:
  jmp rottr_fetchPlayerCheckAlloc
  db 90 90
rottr_fetchPlayerCheckAllocExit:


[DISABLE]
rottr_fetchPlayerCheck:
  readmem(rottr_StoreBytes1,7)
unregistersymbol(rottr_StoreBytes1)
unregistersymbol(rottr_fetchPlayerCheck)
dealloc(rottr_PlayerCheck)
dealloc(rottr_fetchPlayerCheckAlloc)

{
// ORIGINAL CODE - INJECTION POINT: "ROTTR.exe"+33A662D

"ROTTR.exe"+33A65FE: E8 AD 23 DC FF                       -  call ROTTR.exe+31689B0
"ROTTR.exe"+33A6603: 48 8B 0D FE 15 44 FF                 -  mov rcx,[ROTTR.exe+27E7C08]
"ROTTR.exe"+33A660A: 48 89 C6                             -  mov rsi,rax
"ROTTR.exe"+33A660D: E8 4E 5B 12 00                       -  call ROTTR.exe+34CC160
"ROTTR.exe"+33A6612: 48 85 FF                             -  test rdi,rdi
"ROTTR.exe"+33A6615: 0F 84 0E 01 00 00                    -  je ROTTR.exe+33A6729
"ROTTR.exe"+33A661B: 8B 8F C8 00 00 00                    -  mov ecx,[rdi+000000C8]
"ROTTR.exe"+33A6621: C1 E9 05                             -  shr ecx,05
"ROTTR.exe"+33A6624: F6 C1 01                             -  test cl,01
"ROTTR.exe"+33A6627: 0F 84 FC 00 00 00                    -  je ROTTR.exe+33A6729
// ---------- INJECTING HERE ----------
"ROTTR.exe"+33A662D: 48 8B 8F D8 00 00 00                 -  mov rcx,[rdi+000000D8]
// ---------- DONE INJECTING  ----------
"ROTTR.exe"+33A6634: 8B 15 7A 44 C4 FD                    -  mov edx,[ROTTR.exe+FEAAB4]
"ROTTR.exe"+33A663A: 4C 89 BC 24 80 00 00 00              -  mov [rsp+00000080],r15
"ROTTR.exe"+33A6642: 48 8B 14 D1                          -  mov rdx,[rcx+rdx*8]
"ROTTR.exe"+33A6646: 48 8D 8C 24 88 00 00 00              -  lea rcx,[rsp+00000088]
"ROTTR.exe"+33A664E: 48 C7 84 24 88 00 00 00 00 00 00 00  -  mov [rsp+00000088],00000000
"ROTTR.exe"+33A665A: 4C 8B BA A8 02 00 00                 -  mov r15,[rdx+000002A8]
"ROTTR.exe"+33A6661: 48 8D 15 F0 99 8E FD                 -  lea rdx,[ROTTR.exe+C90058]
"ROTTR.exe"+33A6668: E8 B3 5D FD FF                       -  call ROTTR.exe+337C420
"ROTTR.exe"+33A666D: 84 C0                                -  test al,al
"ROTTR.exe"+33A666F: 0F 84 91 00 00 00                    -  je ROTTR.exe+33A6706
}
Code:
{
  Game   : ROTTR.exe
  Date   : 2016-02-14
  Author : Daijobu
}

[ENABLE]
aobscanmodule(rottr_HealthCheck,ROTTR.exe,0F 2E F0 74 20 F3 0F 11 70) // should be unique
aobscanmodule(rottr_HealthCheckSkip,ROTTR.exe,48 8B 8B * * 00 00 E8 * * * * 0F 28 74 24 20 48 83 C4 30 5B C3 * *) //+C
registersymbol(rottr_HealthCheck)
alloc(rottr_HealthCheckAlloc,$1000,rottr_HealthCheck)
label(rottr_HealthCheckAllocExit)
label(rottr_HealthCheckPlayer)

registersymbol(rottr_StoreBytes2)
label(rottr_StoreBytes2)
rottr_HealthCheckAlloc+128:
rottr_StoreBytes2:
  readmem(rottr_HealthCheck,5)

rottr_HealthCheckAlloc:
  sub [rottr_PlayerCheck],2D0 {check against rbx at health (global) onDamage trigger}
  cmp [rottr_PlayerCheck],rbx
  je rottr_HealthCheckPlayer
  jmp rottr_HealthCheckAllocExit

rottr_HealthCheckPlayer:
  movd xmm0,[rbx+2b4] {dword}
  movd [rax+28],xmm0 {dword}
  cvtdq2ps xmm0,xmm0 {dword to float}
  movss [rax+2c],xmm0 {float}
  movss [rsp+20],xmm0 {float}
  jmp rottr_HealthCheckSkip+c {aob}

rottr_HealthCheck:
  jmp rottr_HealthCheckAlloc
rottr_HealthCheckAllocExit:

[DISABLE]
rottr_HealthCheck:
  readmem(rottr_StoreBytes2,5)
unregistersymbol(rottr_StoreBytes2)
unregistersymbol(rottr_HealthCheck)
dealloc(rottr_HealthCheckAlloc)

{
// ORIGINAL CODE - INJECTION POINT: "ROTTR.exe"+3181BA3

"ROTTR.exe"+3181B78: 48 8B 0D 89 60 66 FF        -  mov rcx,[ROTTR.exe+27E7C08]
"ROTTR.exe"+3181B7F: 0F 29 74 24 20              -  movaps [rsp+20],xmm6
"ROTTR.exe"+3181B84: 48 8B 01                    -  mov rax,[rcx]
"ROTTR.exe"+3181B87: 0F 28 F1                    -  movaps xmm6,xmm1
"ROTTR.exe"+3181B8A: FF 90 08 01 00 00           -  call qword ptr [rax+00000108]
"ROTTR.exe"+3181B90: 84 C0                       -  test al,al
"ROTTR.exe"+3181B92: 75 34                       -  jne ROTTR.exe+3181BC8
"ROTTR.exe"+3181B94: 48 8B 83 A8 02 00 00        -  mov rax,[rbx+000002A8]
"ROTTR.exe"+3181B9B: 66 0F 6E 40 28              -  movd xmm0,[rax+28]
"ROTTR.exe"+3181BA0: 0F 5B C0                    -  cvtdq2ps xmm0,xmm0
// ---------- INJECTING HERE ----------
"ROTTR.exe"+3181BA3: 0F 2E F0                    -  ucomiss xmm6,xmm0
"ROTTR.exe"+3181BA6: 74 20                       -  je ROTTR.exe+3181BC8
// ---------- DONE INJECTING  ----------
"ROTTR.exe"+3181BA8: F3 0F 11 70 2C              -  movss [rax+2C],xmm6
"ROTTR.exe"+3181BAD: 48 8B 8B A8 02 00 00        -  mov rcx,[rbx+000002A8]
"ROTTR.exe"+3181BB4: F3 0F 2C 41 2C              -  cvttss2si eax,[rcx+2C]
"ROTTR.exe"+3181BB9: 89 41 28                    -  mov [rcx+28],eax
"ROTTR.exe"+3181BBC: 48 8B 8B A8 02 00 00        -  mov rcx,[rbx+000002A8]
"ROTTR.exe"+3181BC3: E8 38 8E FC FF              -  call ROTTR.exe+314AA00
"ROTTR.exe"+3181BC8: 0F 28 74 24 20              -  movaps xmm6,[rsp+20]
"ROTTR.exe"+3181BCD: 48 83 C4 30                 -  add rsp,30
"ROTTR.exe"+3181BD1: 5B                          -  pop rbx
"ROTTR.exe"+3181BD2: C3                          -  ret 
}
 

Attachments

  • ROTTR.CT

    ROTTR God Mode?

    7.6 KB Views: 107
Top Bottom