 |
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
DodgeWolfy Newbie cheater
Reputation: 0
Joined: 13 May 2017 Posts: 19
|
Posted: Wed Aug 23, 2017 4:17 pm Post subject: Making scripts, using pointers and Stupid questions. |
|
|
Hey guys,
I'll start off by saying:
I am Sorry If i am posting this in the wrong section!
- Background info so you understand where i'm coming from -
I've been playing around with CE for quite a while now but only recently did i start getting into the more fun stuff like making scripts and not having to scan for values every damn time by finding static addresses / pointers and i will admit i am a complete newbie.
However i seem to misunderstand what exactly i can "DO" with a Static address, say you find the address for Health and it looks something like this P->XXXXXXXX and also the value is now in Hex (You can change it by right clicking on it), while that does help me stop searching for the value every time, i still need to edit it or freeze it pretty much every time...
I've only made some AOB Injection scripts so far and it's simple ones like infinite health that just replace the existing value at the point where you take damage etc.
- Cutting to the chase -
Q1: How can i make / assemble a script whose only purpose is to modify the value of the Pointer or freeze it, not one that necessarily injects and replaces code, or would it be better just to set keybinds as much as i don't like that. (Presumably i would do it in Table -> Show CT Lua Script but this is more about the actual code)
Q2: Is it possible to use a pointer in a normal AOB Injection script where you edit what happens after X game function is completed by using "What writes to this address" and "What accesses this address"
Q3: In general, what would be easier or a more convenient way for a newbie to hack, using the disassembler and writing injection codes or finding static addresses?
Q4: Where can i find information on "eax" "ebx" "al" and the commands like "jne" "sub" "add" etc, all i know is E means it's 32 bit and R 64 bit, and very few of the commands like jump if not equal, add, subtract.
Thanks in advance!!!
P.S. - I did look online before posting but searching these specific questions was not the easiest of things, i do apologize if it's been asked before, i hope i wrote the post in an easy to understand way, English is not my native language...
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4702
|
Posted: Wed Aug 23, 2017 5:16 pm Post subject: |
|
|
DodgeWolfy wrote: | Q1: How can i make / assemble a script whose only purpose is to modify the value of the Pointer or freeze it... | I don't see why you would want to do this in an AA script when you can already modify the value however you want as a memory record. You still need to click the "Active" box to activate the script, so that doesn't save any time over freezing the memory record and it only saves a few clicks over changing it manually. You could use Lua to automate the process slightly, but assigning hotkeys would be much faster and easier. Right click on a memory record and select "Set hotkeys" to do this.
DodgeWolfy wrote: | Q2: Is it possible to use a pointer in a normal AOB Injection script where you edit what happens after X game function is completed by using "What writes to this address" and "What accesses this address" | The last half of that sentence didn't make sense to me, but you can traverse a pointer path like this:
Code: | /* Pointer Information:
base: "Tutorial-i386.exe"+001FD660
offset 0: C
offset 1: 14
offset 2: 0
offset 3: 18
*/
code:
mov edx,[Tutorial-i386.exe+001FD660]
mov edx,[edx+C]
mov edx,[edx+14]
mov edx,[edx]
lea edx,[edx+18] // edx is now the address of the value being pointed to
mov [edx],#5000 |
DodgeWolfy wrote: | Q3: In general, what would be easier or a more convenient way for a newbie to hack, using the disassembler and writing injection codes or finding static addresses? | That depends on what you want to do. Modifying a game's code is obviously more versatile than modifying the values it uses. If you don't plan on using a table more than a few times, don't bother making it reusable in the first place. Otherwise, the pointer scanner requires the least effort and knowledge on the user's part.
DodgeWolfy wrote: | Q4: Where can i find information on "eax" "ebx" "al" and the commands like "jne" "sub" "add" etc, all i know is E means it's 32 bit and R 64 bit, and very few of the commands like jump if not equal, add, subtract. | With regards to the instructions (e.g. mov, add, sub, lea...), any good x86 / x86-64 instruction set reference will do.
If you want to learn about x86 and x86-64 architectures in general, you might be able to find some quick tutorials online, but most of the ones I've seen don't cover much and/or provide false information. You may need to sift through some crap, but they'll give you a basic overview- enough to make simple scripts.
If you want correct, complete, and formal information, look at Intel's software developer manuals. Specifically, V1 gives a good overview of most stuff, and V2 contains information about the instructions themselves. Only consult further volumes if you have a good reason to.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
FreeER Grandmaster Cheater Supreme
Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
Posted: Wed Aug 23, 2017 5:34 pm Post subject: |
|
|
Q1. like this Code: | [ENABLE]
["Tutorial-i386.exe"+1FD5D0]+480:
dd #100
// sizes:
// dd = 4 byte, dw = 2, db = 1, dq = 8
[DISABLE]
["Tutorial-i386.exe"+1FD5D0]+480:
dd #200
// (float) or (double) for floating point values
// eg. dd (float)100 or dq (double)200
// # is equivalent to (int) aka decimal values
// as $ is equivalent to 0x aka hexadecimal
// values default to hexadecimal if not specified (100 = 256 decimal)
// as OldCheatEngineUser mentioned this works for multiple offsets
// [[[[["module.exe"+offset]+off]+off]+off]+off]+off:
| Though you could also use lua eg. Code: | {$lua}
local addr = "[Tutorial-i386.exe+1FD5D0]+480"
[ENABLE]
-- prevent accidentally running important code when just creating/editing the script
if syntaxcheck then return end
writeInteger(addr,100)
--[[
size and type are determined by the function you use
copy/paste from celua.txt in CE install directory
writeBytes(address, x,x,x,x,...) : Write the given bytes to the given address from a table
writeBytes(address, table) : Write the given bytes to the given address from a table
writeSmallInteger(address,value) : Writes a 16-bit integer to the specified address. Returns true on success
writeInteger(address,value) : Writes a 32-bit integer to the specified address. Returns true on success
writeQword(address, value): Write a 64-bit integer to the specified address. Returns true on success
writeFloat(address,value) : Writes a single precision floating point to the specified address. Returns true on success
writeDouble(address,value) : Writes a double precision floating point to the specified address. Returns true on success
writeString(address,text, widechar OPTIONAL) : Write a string to the specified address. Returns true on success
]]--
[DISABLE]
-- values are decimal by default, use 0x for hexadecimal
writeInteger(addr,200) |
Freezing it without nopping all the code that changes it would require createThread or a timer in lua (or hooking some game function that runs very often)... easier to just have a memory record and freeze it manually.
Q2. sure, the simple way would be to use lua to determine the address when the script is enabled, but of course that only works if the address doesn't change while the script is enabled. Code: |
XGameFunctionHook:
...
{$lua}
local addr = '... pointer path ...'
addr = getAddress(addr) -- get numeric instead of string address
-- return assembly instruction to move 5 into the address
return ('mov [%x], 5'):format(addr)
{$asm}
...
| if it does change then you have to read the path manually eg
Code: |
// example for base address "Tutorial-i386.exe"+1FD5D0 with offsets 4,C,8 (probably not valid)
XGameFunctionHook:
...
push eax -- save a registers value to the stack or use one you know will be overwritten
mov eax, ["Tutorial-i386.exe"+1FD5D0] // read from base address
// add and dereference each offset, except the last
mov eax, [eax+4]
mov eax, [eax+C]
mov [eax+8], 5 // now set the value at the final address
pop eax -- restore saved value if you saved it to the stack
...
| A bit of a pain. Of course, it's much easier if you can hook someplace that already has the address in a register but that case is fairly obvious if you know basic assembly.
Q3. For a newbie, if you can find statics with a few searches, or pointers, then that's great and makes it pretty easy. But most modern games don't use statics anymore and pointers are getting a bit harder to find as well, beyond that you're mostly limited to hotkeys that set or freeze the value if you don't use scripts (either asm or lua) so you'll probably want to learn those at some point, might as well start now and fall back to static/pointers when you just can't get it working.
Q4. http://opensecuritytraining.info/IntroX86.html , http://ref.x86asm.net/index.html , and google (specific instructions along with "assembly" and maybe "x86" or "x64")
Last edited by FreeER on Thu Aug 24, 2017 6:29 am; edited 3 times in total |
|
Back to top |
|
 |
DodgeWolfy Newbie cheater
Reputation: 0
Joined: 13 May 2017 Posts: 19
|
Posted: Wed Aug 23, 2017 5:48 pm Post subject: |
|
|
ParkourPenguin wrote: |
Code: |
Code:
/* Pointer Information:
base: "Tutorial-i386.exe"+001FD660
offset 0: C
offset 1: 14
offset 2: 0
offset 3: 18
*/
code:
mov edx,[Tutorial-i386.exe+001FD660]
mov edx,[edx+C]
mov edx,[edx+14]
mov edx,[edx]
lea edx,[edx+18] // edx is now the address of the value being pointed to
mov [edx],#5000
|
|
That code will be a really good reference to follow, Thanks!!
ParkourPenguin wrote: |
The last half of that sentence didn't make sense to me...
|
To clarify what i meant - Is it possible to have the code be standalone, without the need of putting it in between functions, so for example instead of doing an AOB injection to have it completely separate from the game and not rely on a function to run.
For example:
Let's say you have a code that sets your infinite money but relies on AOB injection that happens only when you purchase an item. Can you instead have the code run on its' own, completely separate from all game functions / code.
(I think i saw somewhere a video where a guy made a blank script, allocated memory and a thread and did it that way but i'm not completely sure on that one.)
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4702
|
Posted: Wed Aug 23, 2017 6:49 pm Post subject: |
|
|
DodgeWolfy wrote: | Is it possible to have the code be standalone, without the need of putting it in between functions, so for example instead of doing an AOB injection to have it completely separate from the game and not rely on a function to run.
...
(I think i saw somewhere a video where a guy made a blank script, allocated memory and a thread and did it that way but i'm not completely sure on that one.) |
Sure, that's possible. It's significantly more convoluted than changing it yourself, but if you'd like an example:
Code: | [ENABLE]
alloc(newmem,$1000)
label(shouldExit)
registersymbol(shouldExit)
createthread(newmem)
newmem:
// your code here
mov [address],#50 // freezes an address to the 4-byte value 50
// sleep & check if it should exit
push #50
call kernel32.Sleep
cmp [shouldExit],0
je newmem
// free memory, return
pop eax
push 8000
push 0
push newmem
push eax
jmp kernel32.VirtualFree
newmem+800:
shouldExit:
dd 0
[DISABLE]
unregistersymbol(shouldExit)
shouldExit:
dd 1 |
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
OldCheatEngineUser Whateven rank
Reputation: 20
Joined: 01 Feb 2016 Posts: 1586
|
Posted: Thu Aug 24, 2017 3:02 am Post subject: |
|
|
you can also use this syntax:
Code: | [[[[["module.exe"+offset]+off]+off]+off]+off]+off: |
_________________
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 |
|
 |
DodgeWolfy Newbie cheater
Reputation: 0
Joined: 13 May 2017 Posts: 19
|
Posted: Fri Aug 25, 2017 12:53 am Post subject: |
|
|
OldCheatEngineUser wrote: |
you can also use this syntax:
Code: |
[[[[["module.exe"+offset]+off]+off]+off]+off]+off:
|
|
Oh wow, that one's new, may i ask how exactly it differs from the other examples like copying into edx and exactly would i use it to modify something, would it be something along these lines, or how exactly do i implement it.
Code: |
push edx
lea edx,[[[["Tutorial-i386.exe"+001FD660]+C]+14]+0]+18:
mov [edx],#5000
pop edx
|
ParkourPenguin wrote: |
Sure, that's possible. It's significantly more convoluted than changing it yourself, but if you'd like an example:
Code: | [ENABLE]
alloc(newmem,$1000)
label(shouldExit)
registersymbol(shouldExit)
createthread(newmem)
newmem:
// your code here
mov [address],#50 // freezes an address to the 4-byte value 50
// sleep & check if it should exit
push #50
call kernel32.Sleep
cmp [shouldExit],0
je newmem
// free memory, return
pop eax
push 8000
push 0
push newmem
push eax
jmp kernel32.VirtualFree
newmem+800:
shouldExit:
dd 0
[DISABLE]
unregistersymbol(shouldExit)
shouldExit:
dd 1 |
|
The idea of doing it that way is not to complicate things for myself but to make it into a trainer, i'm sure there's better ways but still want to try out simple things even if they are less efficient!
I don't seem to understand why use "pop eax" before it's even pushed and also i think cheat engine recognizes "call Sleep" directly, no need for the kernel bit also why there is newmem+800 and what exactly that achieves, i tried making one on my own, but haven't tested it, feel free to tell me how bad it is, anyways, here's the code:
Code: | [ENABLE]
globalalloc(hackingcode,500)
createthread(hackingcode)
label(stopcode)
registersymbol(stopcode)
stopcode:
db 00
hackingcode:
//Code stuffs here
push #1000
call sleep //Calls sleep using number above in Ms from my understanding
cmp [stopcode],01
jne hackingcode
ret
[DISABLE]
stopcode:
db 01
|
I'm not 100% if the db 00 and db 01 would be needed
|
|
Back to top |
|
 |
OldCheatEngineUser Whateven rank
Reputation: 20
Joined: 01 Feb 2016 Posts: 1586
|
Posted: Fri Aug 25, 2017 1:17 am Post subject: |
|
|
DodgeWolfy wrote: | Oh wow, that one's new, may i ask how exactly it differs from the other examples like copying into edx and exactly would i use it to modify something, would it be something along these lines, or how exactly do i implement it.
|
you can use it as a label, or load it into a register
_________________
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 |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4702
|
Posted: Fri Aug 25, 2017 8:38 am Post subject: |
|
|
DodgeWolfy wrote: | Oh wow, that one's new, may i ask how exactly it differs from the other examples like copying into edx and exactly would i use it to modify something, would it be something along these lines, or how exactly do i implement it.
Code: | push edx
lea edx,[[[["Tutorial-i386.exe"+001FD660]+C]+14]+0]+18:
mov [edx],#5000
pop edx
|
| The colon isn't needed and you need square brackets around that pointer path for lea.
The difference is that CE traverses the pointer path once on assembly. If the game changes any node in the pointer path for whatever reason (e.g. level transition), this would probably crash the game.
DodgeWolfy wrote: | I don't seem to understand why use "pop eax" before it's even pushed | The pop eax / push eax instructions are to make VirtualFree return to the return address of whatever called newmem. Since VirtualFree deallocated newmem's memory, trying to return to newmem would crash.
DodgeWolfy wrote: | i think cheat engine recognizes "call Sleep" directly, no need for the kernel bit | True. It's just more descriptive, prevents name collisions, and I prefer it.
DodgeWolfy wrote: | why there is newmem+800 and what exactly that achieves | It makes sure the dword shouldExit is aligned properly. It's not necessary since Intel can address unaligned memory, but again, I prefer it.
DodgeWolfy wrote: | Code: | [ENABLE]
globalalloc(hackingcode,500)
createthread(hackingcode)
label(stopcode)
registersymbol(stopcode)
stopcode:
db 00
hackingcode:
//Code stuffs here
push #1000
call sleep //Calls sleep using number above in Ms from my understanding
cmp [stopcode],01
jne hackingcode
ret
[DISABLE]
stopcode:
db 01 |
|
- Using globalalloc means the memory will only be allocated once and never freed. This also simplifies things because you don't have to worry about freeing the memory, but it's still a one-time memory leak.
- stopcode is a label. It needs to be defined relative to another address. Either put it after ret, or put something like "hackingcode+100:" before it.
- You're registering the symbol stopcode in [ENABLE] but not unregistering it in [DISABLE].
- Since you're using db, put byte ptr behind [stopcode] so CE addresses that memory location as a byte and not as a dword.
- This is again just my preference, but I'd test [stopcode] against 0 and jump if equal back to the top.
DodgeWolfy wrote: | I'm not 100% if the db 00 and db 01 would be needed | If you want your code to run forever, then replace jne with jmp and remove stopcode, cmp, and ret.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
|
|
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
|
|