|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
giniyat202 How do I cheat? Reputation: 0
Joined: 17 Aug 2014 Posts: 1
|
Posted: Sun Aug 17, 2014 10:41 am Post subject: destroying a thread created using createthread() |
|
|
i had a problem while using createthread in a cheat table,
the thread was supposed to increase a specific value by 1 every second
and it was supposed to keep running until killed under [DISABLE]
but cheat engine has no destroythread so it was a problem,
until i came up with this solution and decided to post it here
Code: | [ENABLE]
alloc(mythread,$1000)
label(mythread_loop)
label(mythread_req_end)
createthread(mythread)
registersymbol(mythread_req_end)
mythread:
//some initialization
mythread_loop:
//whatever
cmp byte ptr [mythread_req_end], 0
je mythread_loop
//the thread is going to exit
//do any cleanup here
//free the memory and exit thread
push 0 //dwExitCode = 0
call GetCurrentThread
push eax //hThread = GetCurrentThread()
push 0 //return address = NULL
push 8000 //dwFreeType = MEM_RELEASE
push 0 //dwSize = 0
push mythread //dwAddress = mythread
push TerminateThread //return address = TerminateThread
jmp VirtualFree
mythread_req_end:
db 0
[DISABLE]
mythread_req_end:
dd 1
unregistersymbol(mythread_req_end)
|
note that you must not free the memory used by the thread under disable, and the thread free its own memory itself
i have tested only on 32 bit, if anyone can port it to 64 bit
please tell me since i have no knowledge of x64 assembly.
|
|
Back to top |
|
|
Nemexia55 Expert Cheater Reputation: 0
Joined: 28 Jan 2014 Posts: 160
|
Posted: Sat Dec 20, 2014 1:51 pm Post subject: |
|
|
excuse me, i couldn't find my answer anywhere,
what is a thread?
_________________
|
|
Back to top |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25295 Location: The netherlands
|
Posted: Sat Dec 20, 2014 2:29 pm Post subject: |
|
|
You can see a thread as something the cpu is currently executing, separate from the main code
As for the original poster, if you leave the stack intact (restore it) when you call ret it will automatically call the TerminateThread function, as that function is stored at the top of the stack when the thread starts
_________________
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 |
|
|
ZxPwds Advanced Cheater Reputation: 0
Joined: 27 Oct 2015 Posts: 59
|
Posted: Thu Oct 29, 2015 8:45 pm Post subject: |
|
|
Thank you Dark Byte I was looking for this!
|
|
Back to top |
|
|
mgr.inz.Player I post too much Reputation: 218
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Sun Nov 29, 2015 10:48 am Post subject: |
|
|
My 64bit implementation (kind of alpha version):
Code: | [ENABLE]
createThread(selfFreeingThread)
alloc(selfFreeingThread,2048)
label(mainLoop)
label(exitMyThread)
label(freeTheThread)
label(havetoquit)
registersymbol(havetoquit)
label(counter)
registersymbol(counter)
selfFreeingThread:
mov rax,selfFreeingThread
push rax //push base address of the region of pages to be freed
mov rax,VirtualFree
push rax //push VirtualFree address
sub rsp,28
mainLoop:
mov rcx,#500
call Sleep
and byte ptr [havetoquit],01
jnz exitMyThread
inc [counter]
jmp mainLoop
exitMyThread:
add rsp,28
jmp freeTheThread
havetoquit:
db 00
counter:
dd 0
selfFreeingThread+800:
freeTheThread:
mov rbp,rsp
sub rsp,40 // room for code and calls (remember pushes at the very beginning)
lea rcx,[rsp+20]
mov rdx,00000020
mov r8d,40
lea r9,[rsp+18]
mov rax,VirtualProtect // make stack executable
call rax
// place the rest on stack
mov [rsp+20],084D8B48 // mov rcx,[rbp+08] // address
mov [rsp+24],41D23148 // xor rdx,rdx // size
mov [rsp+28],008000B8 // mov r8d,00008000 // MEM_RELEASE
mov [rsp+2c],0055FF00 // call [rbp+00] // VirtualFree
mov [rsp+30],50C48348 // add rsp,50 //
mov [rsp+34],000000C3 // ret
lea rcx,[rsp+20]
jmp rcx
[DISABLE]
havetoquit:
db 01
unregistersymbol(havetoquit)
unregistersymbol(counter) |
My 32bit implementation (also alpha version):
Code: | [ENABLE]
createThread(selfFreeingThread)
alloc(selfFreeingThread,2048)
label(mainLoop)
label(exitMyThread)
label(freeTheThread)
label(havetoquit)
registersymbol(havetoquit)
label(counter)
registersymbol(counter)
selfFreeingThread:
push selfFreeingThread // base address of the region of pages to be freed
mainLoop:
push #500
call Sleep
and byte ptr [havetoquit],01
jnz exitMyThread
inc [counter]
jmp mainLoop
exitMyThread:
jmp freeTheThread
havetoquit:
db 00
counter:
dd 0
freeTheThread:
mov ebp,esp
sub esp,04
push esp
push 40
push 8
push esp
call VirtualProtect // make stack executable
// place "add esp,08 ; ret" code in stack
mov [esp],C308C483
push 00008000 //MEM_RELEASE
push 0 //size
push [ebp+00] //address
lea eax,[ebp-04]
push eax
jmp VirtualFree
[DISABLE]
havetoquit:
db 01
unregistersymbol(havetoquit)
unregistersymbol(counter) |
Description: |
demo,
attach 64bit CE to any 64bit process, then enable/disable the script.
counter should increase every 0.5s |
|
Download |
Filename: |
selfFreeingThread.CT |
Filesize: |
2.22 KB |
Downloaded: |
1483 Time(s) |
_________________
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4299
|
Posted: Thu Dec 24, 2015 6:35 pm Post subject: |
|
|
I'm guessing using ret is the correct way of terminating the thread, but what's the difference between calling TerminateThread yourself and letting the script ret on its own?
_________________
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: 458
Joined: 09 May 2003 Posts: 25295 Location: The netherlands
|
Posted: Thu Dec 24, 2015 7:18 pm Post subject: |
|
|
a thread's ret will bring it's instruction pointer to a "call RtlExitUserThread" (with eax being it's parameter)
TerminateThread is a bit more forceful but has basically the same effect
_________________
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 |
|
|
mgr.inz.Player I post too much Reputation: 218
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Thu Dec 24, 2015 7:36 pm Post subject: |
|
|
I'm guessing that there's no big difference.
giniyat202 called TerminateThread (and GetCurrentThread ) and probably he didn't want to go back to the original caller.
Lets analyse his code:
Code: | push 0 //dwExitCode = 0
call GetCurrentThread
push eax //hThread = GetCurrentThread()
push 0 //return address = NULL
push 8000 //dwFreeType = MEM_RELEASE
push 0 //dwSize = 0
push mythread //dwAddress = mythread
push TerminateThread //return address = TerminateThread
jmp VirtualFree |
When we stop at jmp, the stack will be:
Code: | retA | TerminateThreadAddress
| ourThreadAddress
| 0
| MEM_RELEASE
| 0
| hOurThread
| 0 |
Then we jump to the VirtualFree function. Jump instead of call. (CPU stack not changed)
So, VirtualFree function will take arguments (ourThreadAddress,0,MEM_RELEASE) and free memory at address ourThreadAddress.
Because it was a jump, it will RET to TerminateThread. Note, RET is also a jump, it just pops one value (ret address) from the stack. Callee also removes arguments from the stack.
At the very beginning of TerminateThread, the stack will be
Code: | retA | 0
| hOurThread
| 0 |
TerminateThread will take (hOurThread, 0), handle and ExitCode. And from what I see it doesn't ret to the original caller. Ret address is zero, but, it doesn't crash. So, TerminateThread doesn't have RET at the end. It will call other function and pass ExitCode value.
My approach is slightly different. Some tricks won't work in 64bit application. So, I move code execution to the stack, free the memory, and ret to the original caller. I made it for 64bit first, and I converted that code to 32bit version too.
_________________
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4299
|
Posted: Thu Dec 24, 2015 8:46 pm Post subject: |
|
|
Thank you both very much.
I tried to do a bit of research on RtlExitUserThread and found the parameter is an NTSTATUS. Should I make sure eax is 0 just before the ret, or does it really matter what parameter I pass it?
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
mgr.inz.Player I post too much Reputation: 218
Joined: 07 Nov 2008 Posts: 4438 Location: W kraju nad Wisla. UTC+01:00
|
Posted: Thu Dec 24, 2015 9:53 pm Post subject: |
|
|
part of CE code:
Code: | try
threadhandle:=createremotethread(processhandle,nil,0,pointer(testptr),nil,0,bw);
ok2:=threadhandle>0;
if ok2 then
closehandle(threadhandle);
finally
end; |
I don't see getexitcodethread there. Looks like it doesn't matter.
_________________
|
|
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
|
|