You can do that by searching for the player position
and find out what writes to it.
Find out if the instruction is writing to all entities, not only the player.
Step 2: Find the flag that saperates player/enemy.
You can do that by dissecting the entity structures.
As you can see, in my case, offset entity+44 works fine.
0xC5 is the player and 0x81 is the enemy
Note those values down.
Step 3: Doing the injection.
Auto assemble at the start of the instructions that write the entity positions (posX)
and add the remaining instructions for posY and potential posZ if you are in 3D.
We need to add two functionalities now.
1. save the player position
2. load the enemy position to the saved player position.
I think this part is best shown by commenting my code as an example. (copy into CE editor to get syntax highlighting)
Code: Select all
[ENABLE]
aobscanmodule(INJECT_opk,Engine.dll,F2 0F 10 44 24 40 F2 0F 11 46)
alloc(newmem,$1000,"Engine.dll"+24E3ED)
alloc(container,256) // allocate some memory so we can store data there
label(code)
label(return)
label(save_flag)
label(load_flag)
label(x_pos)
label(y_pos)
registersymbol(save_flag)
registersymbol(load_flag)
registersymbol(x_pos)
registersymbol(y_pos)
container: //this is our container to store flags/player_pos
save_flag:
dd 0
load_flag:
dd 0
x_pos:
dd 0
y_pos:
dd 0
newmem:
cmp [save_flag],1
je save // jmp to save if save_flag is set
cmp [load_flag],1
je load // jmp to load if load_flag is set
jmp code
save: //here we save to current player pos to our container
cmp byte [rsi+44],0xC5 // cmp if instruction is trying to write to
// entity with player flag (step 2)
// (rsi == entitybase)
jne code // jmp to the original code if not
mov [save_flag],(int)0 //reset save flag
movsd xmm0,[rsp+40] // copy this part from the original code but write pos to
movsd [x_pos],xmm0 // our container instead
mov eax,[rsp+48]
mov [y_pos],eax
jmp code // jump back to the original code
load: //here we load the saved player pos to enemies
cmp byte [rsi+44],0x81 // cmp if instruction is trying to write to
// entity with enemy flag (step 2)
// (rsi == entitybase)
jne code // jmp to the original code if not
push rax // push rax on stack so we can work with it
mov rax,[x_pos] // move the player x_pos on rax
mov [rsi+48],rax // and into enemy
mov rax,[y_pos] // move the player y_pos on rax
mov [rsi+50],rax // and into enemy
pop rax // pop rax from stack
jmp return
code:
movsd xmm0,[rsp+40] //X
movsd [rsi+48],xmm0 //X
mov eax,[rsp+48] //Y
mov [rsi+50],eax //Y
jmp return
INJECT_opk:
jmp newmem
db 90 90 90 90 90 90 90 90 90 90 90 90 90
return:
registersymbol(INJECT_opk)
[DISABLE]
INJECT_opk:
db F2 0F 10 44 24 40 F2 0F 11 46 48 8B 44 24 48 89 46 50
unregistersymbol(INJECT_opk)
unregistersymbol(x_pos)
unregistersymbol(y_pos)
unregistersymbol(save_flag)
unregistersymbol(load_flag)
dealloc(container)
dealloc(newmem)
{
// ---------- INJECTING HERE ----------
"Engine.dll"+24A07D: F2 0F 10 44 24 40 - movsd xmm0,[rsp+40]
"Engine.dll"+24A083: F2 0F 11 46 48 - movsd [rsi+48],xmm0
"Engine.dll"+24A088: 8B 44 24 48 - mov eax,[rsp+48]
"Engine.dll"+24A08C: 89 46 50 - mov [rsi+50],eax
// ---------- DONE INJECTING ----------
}
Step 4: Adding hotkeys to save_flag and load_flag.
save:
just add the address "save_flag" to the cheat table and
add hotkey "Set value to: 1"
cause in the script we reset this flag to 0 once player position is saved.
load:
add following auto assemble script so we can toggle the load manually
Code: Select all
[ENABLE]
load_flag:
dd 1
[DISABLE]
load_flag:
dd 0
Step 5: Enjoy