Sir, You Are Being Hunted

Memory scanning, code injection, debugger internals and other gamemodding related discussion
Post Reply
Slade
Expert Cheater
Expert Cheater
Posts: 63
Joined: Sat Apr 29, 2017 9:05 am
Reputation: 4

Sir, You Are Being Hunted

Post by Slade » Tue Jun 13, 2017 9:36 am

I know there is a table for this already, but it's a basic table, and I wanted to write a scripted version that might survive an update. So far, I've got Vitality working fine, but for some odd reason, Health is being difficult.

I've found the value/location. That's easy. The same routine is used to futz with both the player and the enemies health. So the obvious thing is to find a value to compare against. I've done that as well, but it still doesn't work.

Image

In the above image, [rdi+30] holds the current players health, [RDI+28] holds the maximum health (which the game moves into different xmm registers I've noticed). Also of note is that [rdi+30] is always the same, '1' for the enemies and '0.349999994' for the player. So I thought I would write the following code to differentiate between the player and the enemy:

Code: Select all

label(code)
label(return)
label(player)

newmem:
  push rax
  mov rax, [rdi+30]
  cmp rax,(float)1
  pop rax
  jl player

code:
  movss [rdi+34],xmm15
  jmp return

player:
  mov [rdi+14],(float)100
  movss xmm15,[rdi+14]
  jmp code
But it doesn't work. I've tried a few different things, but for some odd reason, any compares I do just fail. If anyone can point me onto the path of salvation (or at least a working script), then I'd be a happy person.

Cheers.

Schnitzelmaker
Expert Cheater
Expert Cheater
Posts: 99
Joined: Fri Mar 03, 2017 6:18 pm
Reputation: 54

Re: Sir, You Are Being Hunted

Post by Schnitzelmaker » Tue Jun 13, 2017 9:52 am

Since it uses xmm registers, i suggest to look into comiss.

Example:

Code: Select all

movss [temp], xmm0 //store orginial value
movss xmm0, [rdi+30]
comiss xmm0, [yourfloatvalue]
movss xmm0, [temp] //restore value
//jmp instruction
jl code
...

jmp return

yourfloatvalue:
  dd (float)1.0
  
temp:
  dd 0

Without xmm register its an anoying stuff with fcom. Not sure what values are required for test ah,... and if it should be jump if parry (jp) or jump if not parry (jnp)

Code: Select all

push rax
fld dword ptr [rdi+30]
fcomp dword ptr [yourfloatvalue]
fnstsw ax // store compare flags in ah
test ah,41 // check flags
pop rax
jnp code // or jp code
...
jmp return

yourfloatvalue:
  dd (float)1.0

Slade
Expert Cheater
Expert Cheater
Posts: 63
Joined: Sat Apr 29, 2017 9:05 am
Reputation: 4

Re: Sir, You Are Being Hunted

Post by Slade » Tue Jun 13, 2017 11:37 am

Thanks, that's a big help.

I rewrote the script, using your code to come up with this:

Code: Select all

label(code)
label(return)
label(player)

newmem:
movss [temp], xmm0 //store orginial value
movss xmm0, [yourfloatvalue]
comiss xmm0, [rdi+30]
movss xmm0, [temp] //restore value
jne code
jmp player

code:
  movss [rdi+34],xmm15
  jmp return

player:
  mov [rdi+14],(float)100
  movss xmm15,[rdi+14]
  jmp code

yourfloatvalue:
  dd (float)0.349999994

temp:
  dd 0
Which works well, so far. I'm sure I could simplify it by not having that player: section, but it works for now, so I'm not going to play with it too much.

I had to google comiss, it appears to be the x64 version of a cmp, yeah ?

And is this:

Code: Select all

yourfloatvalue:
  dd (float)0.349999994
the asm version of this:

Code: Select all

Float myVar = 6.3;
?

Thanks again for the assist.

Schnitzelmaker
Expert Cheater
Expert Cheater
Posts: 99
Joined: Fri Mar 03, 2017 6:18 pm
Reputation: 54

Re: Sir, You Are Being Hunted

Post by Schnitzelmaker » Tue Jun 13, 2017 12:51 pm

Slade wrote:
Tue Jun 13, 2017 11:37 am
And is this:

Code: Select all

yourfloatvalue:
  dd (float)0.349999994
the asm version of this:

Code: Select all

Float myVar = 6.3;
?

Thanks again for the assist.

Yes. Its one of the define Byte/Word/Doubleword... and converts specified values into bytes and write them into memory for access.

DB - Define Byte. 8 bits
DW - Define Word. Generally 2 bytes on a typical x86 32-bit system
DD - Define double word. Generally 4 bytes on a typical x86 32-bit system

Code: Select all

db      0x55                ; just the byte 0x55
db      0x55,0x56,0x57      ; three bytes in succession
db      'a',0x55            ; character constants are OK
db      'hello',13,10,'$'   ; so are string constants
dw      0x1234              ; 0x34 0x12
dw      'A'                 ; 0x41 0x00 (it's just a number)
dw      'AB'                ; 0x41 0x42 (character constant)
dw      'ABC'               ; 0x41 0x42 0x43 0x00 (string)
dd      0x12345678          ; 0x78 0x56 0x34 0x12
dq      0x1122334455667788  ; 0x88 0x77 0x66 0x55 0x44 0x33 0x22 0x11
dd      1.234567e20         ; floating-point constant
dq      1.234567e20         ; double-precision float
dt      1.234567e20         ; extended-precision float

User avatar
FreeER
Expert Cheater
Expert Cheater
Posts: 50
Joined: Fri Mar 10, 2017 7:11 pm
Reputation: 5
Contact:

Re: Sir, You Are Being Hunted

Post by FreeER » Tue Jun 13, 2017 6:43 pm

Code: Select all

dw      'A'                 ; 0x41 0x00 (it's just a number)
dw      'AB'                ; 0x41 0x42 (character constant)
dw      'ABC'               ; 0x41 0x42 0x43 0x00 (string)
might not do what you expect.

Here's 3 quick test scripts ("Tutorial-i386.exe"+290 (400290) is a code cave of 0 bytes in the CE tutorial v3.3 that I often use for testing):

Code: Select all

[ENABLE]
"Tutorial-i386.exe"+290:
  dw      'A'
  db 90
  dw      'AB'  // 0x41 0x42 (character constant)
  db 90
  dw      'ABC' // 0x41 0x42 0x43 0x00 (string)
  db 90
/*
my result in CE 6.7
41 00
90
41 42
90
41 42
90
*/
[DISABLE]
"Tutorial-i386.exe"+290:
  db 0 0 0 0 0 0 0 0 0

Code: Select all

[ENABLE]
"Tutorial-i386.exe"+290:
  db      'A'
  db 90
  db      'AB'  // 0x41 0x42 (character constant)
  db 90
  db      'ABC' // 0x41 0x42 0x43 0x00 (string)
  db 90
/*
my result in CE 6.7
41
90
41 42
90
41 42 43
90
*/
[DISABLE]
"Tutorial-i386.exe"+290:
  db 0 0 0 0 0 0 0 0 0

Code: Select all

[ENABLE]
"Tutorial-i386.exe"+290:
  dw      #65
  db 90
  dw      41 42  // 0x41 0x42 (character constant)
  db 90
  dw      41 42 43 0 // 0x41 0x42 0x43 0x00 (string)
  db 90
/*
my results in CE 6.7
41 00
90
41 00 42 00
90
41 00 42 00 43 00 00 00
90
*/
[DISABLE]
"Tutorial-i386.exe"+290:
{$lua}
return "db " .. string.rep("00 ", 18)
{$asm}
edit:

the floats also don't work as shown

Code: Select all

[ENABLE]
"Tutorial-i386.exe"+290:
dd      1.234567e20         // floating-point constant
db 90
dq      1.234567e20         // double-precision float
db 90
// CE just flat out complains about dt, even manually in disassembler context "Assembler" / enter option
//dt      1.234567e20         // extended-precision float
//db 90
/*
my results in CE 6.7
00 00 00 00
90
00 00 00 00 00 00 00 80
90
*/
[DISABLE]
"Tutorial-i386.exe"+290:
{$lua}
return "db " .. string.rep('00 ', 4+8+10)
{$asm}
pretty simple to fix this one though

Code: Select all

[ENABLE]
"Tutorial-i386.exe"+290:
dd      (float)1.234567e20         // floating-point constant
db 90
dq      (double)1.234567e20         // double-precision float
db 90
// CE just flat out complains about dt, even manually in disassembler context "Assembler" / enter option
//dt      1.234567e20         // extended-precision float
//db 90
/*
my results in CE 6.7
CA 29 D6 60 // verified as 1.234567016E20 in address list (addr 400290, float type)
90
DF 87 31 3A 39 C5 1A 44 // verified as 1.234567E20 in address list (addr 400295, double type)
90
*/
[DISABLE]
"Tutorial-i386.exe"+290:
{$lua}
return "db " .. string.rep('00 ', 4+8+10)
{$asm}

Post Reply

Who is online

Users browsing this forum: No registered users