Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Fetch static address from opcode using aob signature
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
fakuivan
Newbie cheater
Reputation: 0

Joined: 27 Dec 2018
Posts: 17

PostPosted: Thu Dec 27, 2018 6:49 pm    Post subject: Fetch static address from opcode using aob signature Reply with quote

How can I get a static address using the aob signature for an opcode that has it? The static address changes when the game gets updated.

This is what the "AOB Injection" template for that opcode looks like

Code:
{ Game   : Dishonored2.exe
  Version:
  Date   : 2018-12-27
  Author : fakui

  This script does blah blah blah
}

[ENABLE]

aobscanmodule(INJECT,Dishonored2.exe,F3 0F 10 05 38 54 81 03) // should be unique
alloc(newmem,$1000,"Dishonored2.exe"+3E78CC)

label(code)
label(return)

newmem:

code:
  movss xmm0,[Dishonored2.exe+3BFCD0C]
  jmp return

INJECT:
  jmp newmem
  nop
  nop
  nop
return:
registersymbol(INJECT)

[DISABLE]

INJECT:
  db F3 0F 10 05 38 54 81 03

unregistersymbol(INJECT)
dealloc(newmem)

{
// ORIGINAL CODE - INJECTION POINT: "Dishonored2.exe"+3E78CC

"Dishonored2.exe"+3E78A0: EB 04                       -  jmp Dishonored2.exe+3E78A6
"Dishonored2.exe"+3E78A2: 4C 89 49 10                 -  mov [rcx+10],r9
"Dishonored2.exe"+3E78A6: 48 8D 05 63 84 1B 03        -  lea rax,[Dishonored2.exe+359FD10]
"Dishonored2.exe"+3E78AD: 48 89 41 30                 -  mov [rcx+30],rax
"Dishonored2.exe"+3E78B1: 48 8B 05 28 83 1B 03        -  mov rax,[Dishonored2.exe+359FBE0]
"Dishonored2.exe"+3E78B8: 48 89 01                    -  mov [rcx],rax
"Dishonored2.exe"+3E78BB: 48 8B 45 B8                 -  mov rax,[rbp-48]
"Dishonored2.exe"+3E78BF: 48 85 C0                    -  test rax,rax
"Dishonored2.exe"+3E78C2: 74 5A                       -  je Dishonored2.exe+3E791E
"Dishonored2.exe"+3E78C4: F3 0F 10 98 6C 3A 00 00     -  movss xmm3,[rax+00003A6C]
// ---------- INJECTING HERE ----------
"Dishonored2.exe"+3E78CC: F3 0F 10 05 38 54 81 03     -  movss xmm0,[Dishonored2.exe+3BFCD0C]  // <--- This is the static address I need
// ---------- DONE INJECTING  ----------
"Dishonored2.exe"+3E78D4: F3 0F 59 05 7C 9B C8 01     -  mulss xmm0,[Dishonored2.exe+2071458]
"Dishonored2.exe"+3E78DC: F3 0F 10 2D 70 9D C8 01     -  movss xmm5,[Dishonored2.exe+2071654]
"Dishonored2.exe"+3E78E4: F3 0F 5E D8                 -  divss xmm3,xmm0
"Dishonored2.exe"+3E78E8: 0F 28 E3                    -  movaps xmm4,xmm3
"Dishonored2.exe"+3E78EB: F3 0F 5D E5                 -  minss xmm4,xmm5
"Dishonored2.exe"+3E78EF: F3 0F 59 25 55 7F 1B 03     -  mulss xmm4,[Dishonored2.exe+359F84C]
"Dishonored2.exe"+3E78F7: 0F 28 C4                    -  movaps xmm0,xmm4
"Dishonored2.exe"+3E78FA: F3 0F 5C C5                 -  subss xmm0,xmm5
"Dishonored2.exe"+3E78FE: 0F 28 C8                    -  movaps xmm1,xmm0
"Dishonored2.exe"+3E7901: 66 0F 6F 15 07 B1 C8 01     -  movdqa xmm2,[Dishonored2.exe+2072A10]
}
Back to top
View user's profile Send private message
OldCheatEngineUser
Whateven rank
Reputation: 20

Joined: 01 Feb 2016
Posts: 1587

PostPosted: Fri Dec 28, 2018 3:40 am    Post subject: Reply with quote

what do you mean?
if you want the address to be in address-list:

Dishonored2.exe+3BFCD0C <---copy / paste in "add address manually"

if you meant anorher thing, please tell.

_________________
About Me;
I Use CE Since Version 1.X, And Still Learning How To Use It Well!
Jul 26, 2020
STN wrote:
i am a sweetheart.
Back to top
View user's profile Send private message Visit poster's website
fakuivan
Newbie cheater
Reputation: 0

Joined: 27 Dec 2018
Posts: 17

PostPosted: Fri Dec 28, 2018 3:12 pm    Post subject: Reply with quote

I could just copy the static address, but it changes on game updates. Is there any way I can use the offset to that opcode to fetch it from there? Instead of copying manually.

Essentially I'm looking for a procedure to read the opcode at "Dishonored2.exe"+3E78CC and from there get the static address used by that opcode (Dishonored2.exe+3BFCD0C)
Back to top
View user's profile Send private message
OldCheatEngineUser
Whateven rank
Reputation: 20

Joined: 01 Feb 2016
Posts: 1587

PostPosted: Fri Dec 28, 2018 4:57 pm    Post subject: Reply with quote

fakuivan wrote:
Is there any way I can use the offset to that opcode to fetch it from there? Instead of copying manually.

maybe you can use ReadMem in your script, read 4 byte after inject symbol. (i mean after F3 0F 10 05)



you can use wildcards * or ? or both, example:
Code:
aobscanmodule(INJECT,Dishonored2.exe,F3 0F 10 05 ** ?? ?? **)


however this is not unique and must be extended, you can take bytes from following instruction. (instruction that comes next) F3 0F 59 05

Code:
F3 0F 10 05 ** ?? ?? ** F3 0F 59 05


you can take bytes from preceding instruction (previous instruction) 00 00, but you must change some contents of your script:

Code:
{ Game   : Dishonored2.exe
  Version:
  Date   : 2018-12-27
  Author : fakui

  This script does blah blah blah
}

[ENABLE]

aobscanmodule(INJECT,Dishonored2.exe,00 00 F3 0F 10 05 ** ?? ?? ** F3 0F 59 05) // should be unique
alloc(newmem,$1000,"Dishonored2.exe"+3E78CC)

label(code)
label(return)

newmem:

code:
  movss xmm0,[Dishonored2.exe+3BFCD0C] // you must fix it if it changed
  jmp return

INJECT+02:
  jmp newmem
  nop
  nop
  nop
return:
registersymbol(INJECT)

[DISABLE]

INJECT+02:
  db F3 0F 10 05 38 54 81 03 // you must fix it if it changed

unregistersymbol(INJECT)
dealloc(newmem)

{
// ORIGINAL CODE - INJECTION POINT: "Dishonored2.exe"+3E78CC

"Dishonored2.exe"+3E78A0: EB 04                       -  jmp Dishonored2.exe+3E78A6
"Dishonored2.exe"+3E78A2: 4C 89 49 10                 -  mov [rcx+10],r9
"Dishonored2.exe"+3E78A6: 48 8D 05 63 84 1B 03        -  lea rax,[Dishonored2.exe+359FD10]
"Dishonored2.exe"+3E78AD: 48 89 41 30                 -  mov [rcx+30],rax
"Dishonored2.exe"+3E78B1: 48 8B 05 28 83 1B 03        -  mov rax,[Dishonored2.exe+359FBE0]
"Dishonored2.exe"+3E78B8: 48 89 01                    -  mov [rcx],rax
"Dishonored2.exe"+3E78BB: 48 8B 45 B8                 -  mov rax,[rbp-48]
"Dishonored2.exe"+3E78BF: 48 85 C0                    -  test rax,rax
"Dishonored2.exe"+3E78C2: 74 5A                       -  je Dishonored2.exe+3E791E
"Dishonored2.exe"+3E78C4: F3 0F 10 98 6C 3A 00 00     -  movss xmm3,[rax+00003A6C]
// ---------- INJECTING HERE ----------
"Dishonored2.exe"+3E78CC: F3 0F 10 05 38 54 81 03     -  movss xmm0,[Dishonored2.exe+3BFCD0C]  // <--- This is the static address I need
// ---------- DONE INJECTING  ----------
"Dishonored2.exe"+3E78D4: F3 0F 59 05 7C 9B C8 01     -  mulss xmm0,[Dishonored2.exe+2071458]
"Dishonored2.exe"+3E78DC: F3 0F 10 2D 70 9D C8 01     -  movss xmm5,[Dishonored2.exe+2071654]
"Dishonored2.exe"+3E78E4: F3 0F 5E D8                 -  divss xmm3,xmm0
"Dishonored2.exe"+3E78E8: 0F 28 E3                    -  movaps xmm4,xmm3
"Dishonored2.exe"+3E78EB: F3 0F 5D E5                 -  minss xmm4,xmm5
"Dishonored2.exe"+3E78EF: F3 0F 59 25 55 7F 1B 03     -  mulss xmm4,[Dishonored2.exe+359F84C]
"Dishonored2.exe"+3E78F7: 0F 28 C4                    -  movaps xmm0,xmm4
"Dishonored2.exe"+3E78FA: F3 0F 5C C5                 -  subss xmm0,xmm5
"Dishonored2.exe"+3E78FE: 0F 28 C8                    -  movaps xmm1,xmm0
"Dishonored2.exe"+3E7901: 66 0F 6F 15 07 B1 C8 01     -  movdqa xmm2,[Dishonored2.exe+2072A10]
}


when CE found the given pattern, it will assign the symbol INJECT to that address and then it get replaced with a jump:

Code:
INJECT:
  jmp newmem
  nop
  nop
  nop


but since we added two-bytes in-front of our instruction bytes, then we must tell CE to place the jump two-byte after the current address of INJECT

Code:
INJECT+02:
  jmp newmem
  nop
  nop
  nop




if the scan failed, then replace the bytes with these:
Code:
00 00 F3 0F 10 ?D ** ?? ?? ** F3 0F 59 ?D // if failed again use ?5

yeah i know, you may ask why ?D while original byte 05

this have to do with instruction encoding, the Reg field of ModR/M Byte.

_________________
About Me;
I Use CE Since Version 1.X, And Still Learning How To Use It Well!
Jul 26, 2020
STN wrote:
i am a sweetheart.
Back to top
View user's profile Send private message Visit poster's website
fakuivan
Newbie cheater
Reputation: 0

Joined: 27 Dec 2018
Posts: 17

PostPosted: Fri Dec 28, 2018 6:07 pm    Post subject: Reply with quote

I appreciate your time but I don't think you understand the question. I don't want to inject anything, I'm merely using the aobscan directive to find the opcode that has the offset for the static address. Again I need some procedure that can read the opcode and extract the offset, just that.
Back to top
View user's profile Send private message
OldCheatEngineUser
Whateven rank
Reputation: 20

Joined: 01 Feb 2016
Posts: 1587

PostPosted: Fri Dec 28, 2018 6:10 pm    Post subject: Reply with quote

readmem, but must be injected. (told you that)
_________________
About Me;
I Use CE Since Version 1.X, And Still Learning How To Use It Well!
Jul 26, 2020
STN wrote:
i am a sweetheart.
Back to top
View user's profile Send private message Visit poster's website
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4289

PostPosted: Fri Dec 28, 2018 7:39 pm    Post subject: Reply with quote

Does that offset from the beginning of the module actually change, or are you using the absolute address instead of module+offset?

That instruction uses RIP-relative addressing. The displacement operand 0x3815438 is added to the next instruction's address Dishonored2.exe+3E78D4 which results in the effective address Dishonored2.exe+3BFCD0C.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 458

Joined: 09 May 2003
Posts: 25283
Location: The netherlands

PostPosted: Fri Dec 28, 2018 11:45 pm    Post subject: Reply with quote

"reassemble(address)" might help
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
fakuivan
Newbie cheater
Reputation: 0

Joined: 27 Dec 2018
Posts: 17

PostPosted: Fri Dec 28, 2018 11:50 pm    Post subject: Reply with quote

A proposed solution by Raijinili at irc://irc.p2p-network.net/cef ("Sorry, but you can't post url's yet", yes I can)

Code:

[21:11:03] <fakuivan> How can I programmatically extract a static address from the address to an opcode that accesses it?
[21:13:09] <Raijinili> Is it always the same opcode?
[21:13:46] <Raijinili> For example, if it's always of the form `add eax,[ADDR]`, you can read from an offset.
[21:14:37] <fakuivan> I think
[21:14:38] <Raijinili> You can also try https://wiki.cheatengine.org/index.php?title=Lua:disassemble with https://wiki.cheatengine.org/index.php?title=Lua:splitDisassembledString
[21:14:47] <Raijinili> and then parse the string.
[21:14:58] <fakuivan> Interesting
[21:15:12] <fakuivan> Is my question clear tho?
[21:15:44] <Raijinili> It is unclear whether you want to solve the general problem or a specific subproblem.
[21:15:53] <fakuivan> The thing is the static address changes in between updates
[21:16:16] <fakuivan> If I don't update the game, the address works fine
[21:17:09] <fakuivan> But when I update it, it changes the offset, I'm trying to use the opcode that read it
[21:17:34] <fakuivan> That reads it*
[21:17:40] <Raijinili> Then you're reading it from a specific instruction.
[21:17:51] <fakuivan> So when the address changes the signature to that opcode can be used to find it
[21:18:31] <Raijinili> The opcode is the bits that determine what operation to perform.
[21:19:01] <fakuivan> The key here is that I need to analyze the opcode and extract the static address from it
[21:19:22] <fakuivan> Yes
[21:20:22] <Raijinili> For `add eax,edx`, the operation is "add", and the operation is 01 or something.
[21:20:35] <Raijinili> opcode is 01 or something*
[21:22:12] <Raijinili> Is the instruction's address static?
[21:22:28] <fakuivan> The opcode will stay the same once I make the signature
[21:25:57] <fakuivan> https://forum.cheatengine.org/viewtopic.php?p=5744993#5744993
[21:25:57] <fakuivan> I went into more detail there
[21:26:12] <Raijinili> Take this example: "Dishonored2.exe"+3E78CC: F3 0F 10 05 38 54 81 03     -  movss xmm0,[Dishonored2.exe+3BFCD0C]
[21:26:27] <Raijinili> You see those bytes? F3 0F 10 05 38 54 81 03
[21:26:35] <Raijinili> The last four bytes determine the offset.
[21:27:07] <Raijinili> However, it seems to be relative.
[21:31:44] <Raijinili> Okay, it seems to be relative to the following address.
[21:35:12] <Raijinili> If your instruction is always of the form `movss xmm0,[ADDR]`, that instruction is always eight bytes long. Let's say the instruction's address is X. Then read a dword from X+4, and add X+8 to it.
[21:35:37] <Raijinili> Or use the disassemble+parse method.
[21:37:02] <Raijinili> I think OldCheatEngineUser gave the offset+read trick.
[21:40:25] <Raijinili> Instead of guessing, you can use this to get the current instruction's size: https://wiki.cheatengine.org/index.php?title=Lua:getInstructionSize
[21:40:31] <fakuivan> I think I'll use the disassemble+parse method as it sounds more stable
[21:40:57] <fakuivan> Wait
[21:41:07] <fakuivan> Do I have to parse the asm string?
[21:41:28] <Raijinili> https://wiki.cheatengine.org/index.php?title=Lua:splitDisassembledString
[21:42:30] <fakuivan> Neat!
[21:42:40] <fakuivan> That's just what I need
[21:43:10] <Raijinili> I linked it before.
[21:43:31] <Raijinili> Here's the reference list: https://wiki.cheatengine.org/index.php?title=Lua#Assembly
[21:44:32] <fakuivan> Ik, I'm on cellular so I avoid opening links unless necessary :p
[21:44:47] <fakuivan> Thanks a lot
[21:44:58] <fakuivan> I was on a dead end with this one
[21:45:35] <Raijinili> I had a similar question, but it didn't solidify enough for me to search for it.
Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 55

Joined: 01 Oct 2008
Posts: 942

PostPosted: Sat Dec 29, 2018 2:31 am    Post subject: Reply with quote

Code:

{$lua}
function RIP(n,ofs)n = (tonumber(n,16)or n)+(ofs or 0) return n+readInteger(n,true)+4  end
{$asm}

aobscan(relative, F3 0F 10 05 ?? ?? ?? ?? ... )
// relative address start at relative+4

  unregisterSymbol(absolute)
  label(absolute)
  registerSymbol(absolute)

//// ugly
  $((function(n)return n + readInteger(n,true)+4 end)(tonumber('relative',16)+4)):
  absolute:

//// neat
//$RIP('relative',4)): //   get RIP address at (aa format)relative+4
//absolute:


_________________
- Retarded.
Back to top
View user's profile Send private message
fakuivan
Newbie cheater
Reputation: 0

Joined: 27 Dec 2018
Posts: 17

PostPosted: Tue Jan 01, 2019 5:08 pm    Post subject: Reply with quote

I made a function in lua to extract an RIP-relative address from an arbitrary instruction at an arbitrary offset and size:

Code:

-- Reads a RIP-relative address from an instruction
-- All parameters should be integers
function extractRIPRelativeAddress(address, offset, offset_size)
  local instruction_size = getInstructionSize(address)
  readOffset = ({
    [1] = function(address_) return readBytes(address_, 1, false) end,
    [2] = readSmallInteger,
    [4] = readInteger,
    [8] = readQword
  })[offset_size]
  if readOffset == nil then return nil end
  offset = (tonumber(offset) or 0)
  -- Simple check to see if the offset and size move outside the instruction
  if instruction_size == nil or instruction_size < offset + offset_size then
    return nil
  end
  local stored_address_ptr = address + (offset or 0)
  return address + instruction_size + readOffset(stored_address_ptr)
end

-- Extracts the address from the je instruction
-- Dishonored2.exe+3E7893 - 74 0D                 - je Dishonored2.exe+3E78A2
print(
  getNameFromAddress(
    extractRIPRelativeAddress(getAddress('Dishonored2.exe+3E7893'),01,01)
  )
)

-- Dishonored2.exe+3E78CC - F3 0F10 05 38548103   - movss xmm0,[Dishonored2.exe+3BFCD0C]
print(
  getNameFromAddress(
    extractRIPRelativeAddress(getAddress('"Dishonored2.exe"+3E78CC'),04,04)
  )
)


I can later make a wrapper to expose the function to the auto assembler using ``registerAutoAssemblerCommand``. I could not get this working using the ``$()`` syntax, as the script would not pass the syntax check.
Back to top
View user's profile Send private message
fakuivan
Newbie cheater
Reputation: 0

Joined: 27 Dec 2018
Posts: 17

PostPosted: Thu Jan 10, 2019 9:43 pm    Post subject: Reply with quote

This is the final script in case anyone needs something similar in the future (link in image description).
Back to top
View user's profile Send private message
fakuivan
Newbie cheater
Reputation: 0

Joined: 27 Dec 2018
Posts: 17

PostPosted: Thu Jan 24, 2019 12:43 am    Post subject: Reply with quote

The script I posted is having problems with negative offsets. How can I convert the offset to signed once I read it?
Back to top
View user's profile Send private message
TheyCallMeTim13
Wiki Contributor
Reputation: 50

Joined: 24 Feb 2017
Posts: 976
Location: Pluto

PostPosted: Thu Jan 24, 2019 3:32 pm    Post subject: Reply with quote

It's not on the wiki, but there is a second "signed" parameter for the read integer functions.

"celua.txt":
Quote:
readSmallInteger, readInteger, readSmallIntegerLocal, readIntegerLocal
can also have second boolean parameter. If true, value will be signed.

_________________
Back to top
View user's profile Send private message Visit poster's website
fakuivan
Newbie cheater
Reputation: 0

Joined: 27 Dec 2018
Posts: 17

PostPosted: Thu Jan 24, 2019 3:41 pm    Post subject: Reply with quote

TheyCallMeTim13 wrote:
It's not on the wiki, but there is a second "signed" parameter for the read integer functions.

"celua.txt":
Quote:
readSmallInteger, readInteger, readSmallIntegerLocal, readIntegerLocal
can also have second boolean parameter. If true, value will be signed.


Yes, that's an option but it won't work for small jumps, where I use readByes
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites