View previous topic :: View next topic |
Author |
Message |
BigCrock5 How do I cheat?
Reputation: 0
Joined: 26 Apr 2022 Posts: 9
|
Posted: Wed Apr 27, 2022 2:11 pm Post subject: CREATETHREAD just crashes unity game |
|
|
I'm trying to inject code into a unity game and run it using CREATETHREAD.
If I run the same code using a code injection hook, it runs fine.
If I run it using CREATETHREAD, the game crashes instantly.
Is there something I'm missing?
Code: |
alloc(mycode,4096)
CREATETHREAD(mycode);
mycode:
mov rcx,(PlayerOffset) // Move player offset into rcx
mov rcx,[rcx] // Dereference player offset
mov eax,(float)100 // Move 100f into register
movd xmm1,eax // Transfer to xmm1 as per calling convention
call "GameAssembly.dll"+75DB30 // Call the heal function
ret
|
Edit: The crash code is a C0000005
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 150
Joined: 06 Jul 2014 Posts: 4656
|
Posted: Wed Apr 27, 2022 5:00 pm Post subject: |
|
|
A quick search tells you C0000005 is an access violation.
You aren't passing the right arguments, globals aren't in the correct state, and/or there's a pointer path from some argument or global to some value that isn't in the correct state. Step into the code and figure it out. (a break-and-trace might help)
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
BigCrock5 How do I cheat?
Reputation: 0
Joined: 26 Apr 2022 Posts: 9
|
Posted: Wed Apr 27, 2022 5:14 pm Post subject: |
|
|
I was thinking it may be related to some registers not being available because it's running a new thread or something like that.
If I call the code from a hook it works perfectly, if I call the exact same code from a thread, it does not work.
I created a small test app and hooked into it and called it on that and it worked, so I'm guessing there is some global state that cannot be accessed.
Or unity has a certain time window where you can make these updates.
But a buffer overflow sounds odd.
EDIT:
So I did some debugging, it fails on a piece of code:
Code: | movaps [rsp+30],xmm6 |
So it's either RSP or XMM6 that are the issue.
Upon comparing the registers at this point, xmm6 in the main thread has a value, whereas it is 0 in my thread, I don't know if this could cause an error with the movaps op.
So that leaves RSP, it has a value in both, so I'm not sure if this is the issue.
Is it possible to copy the registers from the main game thread into my newly created thread? I hope this may help the consistency issues.
EDIT AGAIN:
It seems RSP is the issue, RSP+30 doesn't seem to be aligned to 32 bits like it says it should be in the docs. Not sure what the solution to this is
FINAL UPDATE:
I actually got something working?!
It seems subbing 0x28 (#40) from RSP before calling will allow the function to work. NO IDEA WHY OR HOW.
If anyone could enlighten me that would be much appreciated.
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 150
Joined: 06 Jul 2014 Posts: 4656
|
Posted: Wed Apr 27, 2022 7:18 pm Post subject: |
|
|
Oh, right, my bad. In windows x64 ABI the stack must have a shadow store for the four register parameters (0x20 bytes) prior to a call as well as 16-byte alignment most of the time.
https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
The 16-byte alignment is what's causing movaps ("move aligned packed singles") to fail. If you fixed that, it might still fail if the return address was corrupted.
Allocating 0x28 bytes on the stack w/ `sub rsp,28` will give 0x20 bytes for the shadow store and align the stack to 0x10 bytes (the other 8 were from the return address of the call that called "mycode")
I think you could also just do a tail call and everything will work:
Code: | mycode:
mov rcx,(PlayerOffset)
mov rcx,[rcx]
mov eax,(float)100
movd xmm1,eax
jmp "GameAssembly.dll"+75DB30 | The stack is already aligned, and this re-uses the shadow store from the caller of "mycode".
It also has the added benefit that you can disable the script and deallocate memory even if the thread is still executing the call.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
BigCrock5 How do I cheat?
Reputation: 0
Joined: 26 Apr 2022 Posts: 9
|
Posted: Wed Apr 27, 2022 7:20 pm Post subject: |
|
|
So `jmp` instead of `call` will work?
Just curious, how would this work if I wanted to call multiple functions? Once I've used jmp, I cannot get back?
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 150
Joined: 06 Jul 2014 Posts: 4656
|
Posted: Wed Apr 27, 2022 7:35 pm Post subject: |
|
|
`call` works by pushing the return address (next instruction) on the stack. `ret` uses that to return to the caller.
`jmp` simply branches to the target address. In general, there's no way to get back to where you started from.
Look up "tail call" for more information.
If you want to call several functions, then you can't generally do that with a single jmp. You'll have to allocate space on the stack to adhere to windows x64 calling conventions.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 468
Joined: 09 May 2003 Posts: 25709 Location: The netherlands
|
Posted: Thu Apr 28, 2022 1:43 am Post subject: |
|
|
Also, since it's unity, likely il2cpp? you'll often have to call il2cpp_thread_attach to setup the TLS information for the current thread in case the routine you're calling wants to call something .net specific
_________________
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 |
|
 |
BigCrock5 How do I cheat?
Reputation: 0
Joined: 26 Apr 2022 Posts: 9
|
Posted: Thu Apr 28, 2022 5:59 am Post subject: |
|
|
How can I observe the return value of a function if I’m using jmp?
I’d originally planned to mov output,rax after the call but it seems that wont be possible with jmp.
|
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 468
Joined: 09 May 2003 Posts: 25709 Location: The netherlands
|
Posted: Thu Apr 28, 2022 6:40 am Post subject: |
|
|
don't use jmp, use call
_________________
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 |
|
 |
BigCrock5 How do I cheat?
Reputation: 0
Joined: 26 Apr 2022 Posts: 9
|
Posted: Thu Apr 28, 2022 6:57 am Post subject: |
|
|
And in that case, what should I sub from rsp?
|
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 468
Joined: 09 May 2003 Posts: 25709 Location: The netherlands
|
Posted: Thu Apr 28, 2022 7:10 am Post subject: |
|
|
28
8 to align and 20 for scratchspace
_________________
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 |
|
 |
BigCrock5 How do I cheat?
Reputation: 0
Joined: 26 Apr 2022 Posts: 9
|
Posted: Sat Apr 30, 2022 9:18 am Post subject: |
|
|
I've made a lot of progress, but some functions don't seem to work, and others do.
For example, I can call the set_position function on a Unity Transform, but get_position just crashes the game.
Seems to be an access violation again, this approach works for
Component->get_gameObject
GameObject -> get_transform
but not
Transform -> get_position
Not really sure what to do next.
I'm trying to run the following:
Code: |
mov rcx,(PlayerOffset)
mov rcx,[rcx]
call GameAssembly.dll+D852B0 // Get the GameObject
mov rcx,rax
call GameAssembly.dll+D89E70 // Get transform
mov rcx,rax
call GameAssembly.dll+1466C10 // Get position
|
The last call completely crashes the game.
|
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 468
Joined: 09 May 2003 Posts: 25709 Location: The netherlands
|
Posted: Mon May 02, 2022 5:46 am Post subject: |
|
|
you're sure they take no parameters ?
_________________
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 |
|
 |
BigCrock5 How do I cheat?
Reputation: 0
Joined: 26 Apr 2022 Posts: 9
|
Posted: Mon May 02, 2022 6:49 am Post subject: |
|
|
It's a C# property, so I'm assuming it just takes the thisPtr and nothing else.
Code: | [Token(Token = "0x170001AB")]
public Vector3 position
{
[Token(Token = "0x6000788")]
[Address(RVA = "0x1466C10", Offset = "0x1465E10", VA = "0x181466C10")]
get
{
return default(Vector3);
}
[Token(Token = "0x6000789")]
[Address(RVA = "0x1467380", Offset = "0x1466580", VA = "0x181467380")]
set
{
}
} |
|
|
Back to top |
|
 |
Bloodybone Newbie cheater
Reputation: 0
Joined: 07 Dec 2016 Posts: 21 Location: Germany
|
Posted: Mon May 02, 2022 1:25 pm Post subject: |
|
|
When you have a funtion that returns a Vector3, the first parameter should be a memory location that can hold 3 Floats.
So using your code, you'll have to change it like so:
Code: | sub rsp,30 // 0x20 for Callees and the other 0x10 for the returned position later on. You'll have to sub rsp,38 if the stack isn't aligned yet
mov rcx,(PlayerOffset)
mov rcx,[rcx]
call GameAssembly.dll+D852B0 // Get the GameObject
mov rcx,rax
call GameAssembly.dll+D89E70 // Get transform
lea rcx,[rsp+20] // Space for returned postion
mov rdx,rax
call GameAssembly.dll+1466C10 // Get position
// [rax] // [rsp+20] = X
// [rax+4] // [rsp+24] = Y
// [rax+8] // [rsp+28] = Z
add rsp,30 // Free space |
|
|
Back to top |
|
 |
|