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 


Need help replacing mov [edx-1B], bl with mov [edx-1B], 3

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
rain-13
Expert Cheater
Reputation: 0

Joined: 18 Mar 2009
Posts: 106

PostPosted: Tue Jan 16, 2024 6:20 pm    Post subject: Need help replacing mov [edx-1B], bl with mov [edx-1B], 3 Reply with quote

Hi!

I have mov [edx-1B], bl

Code:
Warcraft II BNE.exe+54248 - 88 5A E5              - mov [edx-1B],bl
Warcraft II BNE.exe+5424B - 8B 44 24 14           - mov eax,[esp+14]
Warcraft II BNE.exe+5424F - 81 C2 98000000        - add edx,00000098 { 152 }
Warcraft II BNE.exe+54255 - 48                    - dec eax
Warcraft II BNE.exe+54256 - 89 54 24 10           - mov [esp+10],edx
Warcraft II BNE.exe+5425A - 89 44 24 14           - mov [esp+14],eax
Warcraft II BNE.exe+5425E - 0F85 65FEFFFF         - jne "Warcraft II BNE.exe"+540C9 { ->Warcraft II BNE.exe+540C9 }
Warcraft II BNE.exe+54264 - 5F                    - pop edi
Warcraft II BNE.exe+54265 - 5E                    - pop esi
Warcraft II BNE.exe+54266 - 5D                    - pop ebp
Warcraft II BNE.exe+54267 - 5B                    - pop ebx
Warcraft II BNE.exe+54268 - 83 C4 18              - add esp,18 { 24 }
Warcraft II BNE.exe+5426B - C3                    - ret
Warcraft II BNE.exe+5426C - 90                    - nop
Warcraft II BNE.exe+5426D - 90                    - nop
Warcraft II BNE.exe+5426E - 90                    - nop
Warcraft II BNE.exe+5426F - 90                    - nop


But I want to mov [edx-1B], 3 instead. How do I do that?

At first I thought I could make use of nops at the end to get those extra bytes that I need.

So I replaced
88 5A E5 8B 44 24 14 81 C2 98 00 00 00 48 89 54 24 10 89 44 24 14 0F 85 65 FE FF FF 5F 5E 5D 5B 83 C4 18 C3 90 90 90 90
with
C7 42 E5 03 00 00 00 8B 44 24 14 81 C2 98 00 00 00 48 89 54 24 10 89 44 24 14 0F 85 65 FE FF FF 5F 5E 5D 5B 83 C4 18 C3

But it causes game to crash. Any suggestions?
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4289

PostPosted: Tue Jan 16, 2024 6:39 pm    Post subject: Reply with quote

`0F 85 ?? ?? ?? ?? - jne rel32` takes a displacement relative to EIP. What this instruction does changes depending on the address it's located at.
There might also be a jmp/jcc above that which jumps into that section of code.

You probably want `mov byte ptr[edx-1B],3` instead.

Make sure that instruction only writes to the address(es) you want to modify. See the right click menu in the disassembler.

Why can't you just inject code? See the CE tutorial. Use the AOB injection or Full injection template.

_________________
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
rain-13
Expert Cheater
Reputation: 0

Joined: 18 Mar 2009
Posts: 106

PostPosted: Thu Jan 18, 2024 3:42 pm    Post subject: Reply with quote

Thanks!

I didn't use code injection before because I had not learned it and and it seemed scary at first. I looked up few tutorials from youtube and I think I get the idea but seems like in my case the devil lies in details. I tried the following code but game crashed when I injected it. What is wrong there?



Game crashes immediately after injection. On next attempt I even set a breakpoint before that line so that if injected code looks wrong then at least I could see what's wrong before game crashes. The breakpoint never triggered before crash so it seems like the memory allocation itself crashed it?

I even get message that tells that injection was successful even though it wasn't.

Quote:
The code injection was successfull
newmem=02150000
Go to 02150000?




Quote:
What this instruction does changes depending on the address it's located at.

I suspected it might be so but could you explain a bit more why and how? Doesn't it have hardcoded address 65FEFFFF?
Anyways I tryed byte ptr as you suggested but it still messed it up this jump because now 3 byte code was replaced with 4 byte.

C6 42 E5 03 8B 44 24 14 81 C2 98 00 00 00 48 89 54 24 10 89 44 24 14 0F 85 65 FE FF FF 5F 5E 5D 5B 83 C4 18 C3 90 90 90

Is there way to fix this method too or is code injection the only way?
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4289

PostPosted: Thu Jan 18, 2024 4:36 pm    Post subject: Reply with quote

I didn't mention `byte ptr` because of the number of bytes the instruction takes up. Without that, CE assumes you're moving a 4-byte value. The original code is only moving a 1-byte value. Explicitly specifying `byte ptr` indicates the `3` immediate operand is a 1-byte value and not a 4-byte value.

Again, I'd use the full injection template. In the [ENABLE] section, replace everything between `newmem:` (your code) and `address:` (injection point) with this:
Code:
...
newmem:
  mov byte ptr[edx-1B],3
  mov eax,[esp+14]
  jmp return

address:
...
Delete `label(code)` too

Assign it to the cheat table ("File" menu in the AA script) and click the box on the left to enable / disable it

If it still doesn't work, then again, check and make sure that instruction is only accessing the address(es) you want it to access. This should be one of the first things you do before you start modifying code. If your code writes 3 to a bunch of random addresses, weird things can happen.
Maybe there's some instruction that jumps to the second instruction at game.exe+5424B. That would jump to garbage when the script is enabled and crash the game. You could try injecting at game.exe+5424F instead since that instruction takes up at least 5 bytes. Make sure you write to edx-1B before the original code modifies edx, not after.
Maybe the game has some kind of protection against modifying code in the exe.

`0F 85 ?? ?? ?? ?? - jne rel32` - those 4 bytes, 65 FE FF FF, are a signed 32-bit displacement relative to EIP- the address of the next instruction to execute. "65 FE FF FF" is -411 or -0x19B (see "little endian" and "two's complement"). EIP is game.exe+54264. EIP + rel32 is game.exe+54264-19B = game.exe+540C9.
Change where the instruction is located, and EIP will change too when the instruction is executed. This changes where the instruction jumps to.
You could account for this manually, but that's annoying. Code injection is easier.

_________________
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
rain-13
Expert Cheater
Reputation: 0

Joined: 18 Mar 2009
Posts: 106

PostPosted: Fri Jan 19, 2024 4:10 pm    Post subject: Reply with quote

Yes, you were correct. Something else keeps jumping the very next line and therefore gets garbage code.

But how do I correctly inject in that case?
I added jmp at game.exe+5424B as you suggested. Now the good thing is that game no longer crashes but the bad thing is that mov [edx-1B], 3 also gets executed in cases where only mov eax,[esp+14] was intended to be executed but not mov [edx-1B], 3. This created created some fun bug where I can control enemy units as if they were mine but it's not what I intended.

Right now I have the following code template:
Code:
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)

newmem:
mov [edx-1B], 3
mov eax,[esp+14]
add edx,00000098
jmp returnhere

originalcode:
mov eax,[esp+14]
add edx,00000098

exit:
jmp returnhere

"Warcraft II BNE.exe"+5424B:
jmp newmem
nop
nop
nop
nop
nop
returnhere:


And after the injection code looks like this:
Code:
Warcraft II BNE.exe+54248 - 88 5A E5              - mov [edx-1B],bl
Warcraft II BNE.exe+5424B - E9 B0BDF101           - jmp 02370000
Warcraft II BNE.exe+54250 - 90                    - nop
Warcraft II BNE.exe+54251 - 90                    - nop
Warcraft II BNE.exe+54252 - 90                    - nop
Warcraft II BNE.exe+54253 - 90                    - nop
Warcraft II BNE.exe+54254 - 90                    - nop
Warcraft II BNE.exe+54255 - 48                    - dec eax
Warcraft II BNE.exe+54256 - 89 54 24 10           - mov [esp+10],edx
Warcraft II BNE.exe+5425A - 89 44 24 14           - mov [esp+14],eax
Warcraft II BNE.exe+5425E - 0F85 65FEFFFF         - jne "Warcraft II BNE.exe"+540C9 { ->Warcraft II BNE.exe+540C9 }
Warcraft II BNE.exe+54264 - 5F                    - pop edi
Warcraft II BNE.exe+54265 - 5E                    - pop esi
Warcraft II BNE.exe+54266 - 5D                    - pop ebp
Warcraft II BNE.exe+54267 - 5B                    - pop ebx
Warcraft II BNE.exe+54268 - 83 C4 18              - add esp,18 { 24 }
Warcraft II BNE.exe+5426B - C3                    - ret
Warcraft II BNE.exe+5426C - 90                    - nop
Warcraft II BNE.exe+5426D - 90                    - nop
Warcraft II BNE.exe+5426E - 90                    - nop
Warcraft II BNE.exe+5426F - 90                    - nop



How do I make it so that if jump was made to Warcraft II BNE.exe+54248 only then mov [edx-1B], 3 was executed and if it was made to Warcraft II BNE.exe+5424B then mov [edx-1B], 3 would be skipped? Right now since my jmp is at 5424B both cases get sent to newmem section meaning that mov [edx-1B], 3 will get executed even if it wasn't originally intended to. And code before it seems to be one big jump hell.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4289

PostPosted: Sat Jan 20, 2024 2:55 am    Post subject: Reply with quote

So that injection point is only 3 bytes long huh? That sucks.

The easiest thing to do is to use the 1-byte exception jump: enable it in the "Template" menu, then generate a new script at game.exe+54248. It'll probably work, unless that instruction is in a really busy section of code or the game has some kind of protection that dislikes int3 breakpoints.

You could look at the function in more detail and figure out what conditions are being checked, what code is run and when, etc. Maybe check the same condition, or even get the same behaviour as you want by changing a jcc to either NOPs or an unconditional jump.
If you aren't good at reading assembly, this would be difficult.

_________________
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
rain-13
Expert Cheater
Reputation: 0

Joined: 18 Mar 2009
Posts: 106

PostPosted: Sat Jan 20, 2024 10:32 am    Post subject: Reply with quote

Yes, it seems like 3 byte injection poin.

How do I enable 1-byte exception jump it in the "Template" menu?

The code itself has a ton of if statements within loop together with some bitshift magic. So if I can't come up with easy solution then I will leave it for future when I have better asm understanding.

In cheat engine I also found option called "Change register at this location". How does this option work exactly?

If for example I want to write my own trainer and I want to add there function changeRegisterAtLocation(processHandle, address, registerName, newRegisterValue) then what Win API functions would I have to know and how would it work in big picture?
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4289

PostPosted: Sat Jan 20, 2024 11:31 am    Post subject: Reply with quote

Go to "Memory Viewer -> View -> Auto Assemble" to open a new auto assembler window
Click on "Template -> 1 Byte Exception JMP"
Click on a template. For the third time now, I'd use "Full Injection" if you don't want to do an aob scan.

I haven't looked at CE's source, but I'm pretty sure "Change register at this location" just sets a breakpoint (probably int3) and changes the thread context in CE.

_________________
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
rain-13
Expert Cheater
Reputation: 0

Joined: 18 Mar 2009
Posts: 106

PostPosted: Sat Jan 20, 2024 11:35 am    Post subject: Reply with quote

I don't have 1 Byte Exception JMP" there. But can I go straight to the "Full Injection" ?
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4289

PostPosted: Sat Jan 20, 2024 12:05 pm    Post subject: Reply with quote

That won't fix what's wrong- it'll still use a 5 byte jump. Update to Cheat Engine 7.5.

Alternatively, you can use Lua to the same effect.
Code:
{$lua}
if syntaxcheck then return end
local addr = getAddress'game.exe+54248'

debug_removeBreakpoint(addr)

[ENABLE]
assert(readInteger(addr) == 0x8BE55A88)

debug_setBreakpoint(addr, function()
  EBX = (EBX & 0xFFFFFF00) | 3
end)

[DISABLE]
(this is an AA script you can put in the address list)
_________________
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
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking All times are GMT - 6 Hours
Page 1 of 1

 
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