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 


Calling game function & thread local storage

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

Joined: 25 Jan 2009
Posts: 186

PostPosted: Thu Dec 13, 2012 2:00 pm    Post subject: Calling game function & thread local storage Reply with quote

So I'm trying to call a game function. However this particular one is causing the game to crash.

I used the "Break and trace instructions" to see why.

Comparing a call from the game by doing the required action, and calling the function with the Auto Assemble.

And this is where it seems to go wrong. (several functions deep)

Code:

mov eax, fs:[00000018] // Linear address of TIB
mov ecx, [ebp+08]
and dword ptr [eax+34], 00 // Last error number (?)
cmp ecx, 40
jae 7575F4A6 // Doesn't jump from either AA call or normal call

// EAX = 7FFDF000 (game call), EAX = 7FFA6000 (AA call)
// ECX = 8

mov eax, [eax+ecx*4+00000E10]

// EAX is now 0 when calling with AA, and then it is later dereferenced causing an exception. It was 0x002350B0 when the game called it.


So from what i understand: the last instruction in the above code block is accessing the Thread Information Block with the offset of 0xE30 (8*4+E10).

I believe this would be thread local storage (TLS)?

What would be the best way to call the function without it crashing?
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25804
Location: The netherlands

PostPosted: Thu Dec 13, 2012 2:18 pm    Post subject: Reply with quote

I've never used this method so not sure if it works, but suspend the process and look for a thread that isn't waiting for some kind of event (might take several tries), then store the state and change eip to your injected code that calls the function , upon return restore the state to the original
_________________
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
View user's profile Send private message MSN Messenger
661089799107
Expert Cheater
Reputation: 3

Joined: 25 Jan 2009
Posts: 186

PostPosted: Thu Dec 13, 2012 2:45 pm    Post subject: Reply with quote

Thanks for the quick response.

Sorry. I should of been more clear.

While that sounds like it should work: I'd like to do this without having to do it manually. As I am doing this from within the game process, and using my injected DLL to automate my character. I was using the Auto Assembly to see why it wasn't working.
Back to top
View user's profile Send private message
n0 m3rcY
Cheater
Reputation: 0

Joined: 18 Jun 2012
Posts: 42

PostPosted: Thu Dec 13, 2012 5:12 pm    Post subject: Reply with quote

What was ebp earlier in the proc?
Back to top
View user's profile Send private message
661089799107
Expert Cheater
Reputation: 3

Joined: 25 Jan 2009
Posts: 186

PostPosted: Thu Dec 13, 2012 7:32 pm    Post subject: Reply with quote

n0 m3rcY wrote:
What was ebp earlier in the proc?


The function was set up with a standard stack frame.

Edit: I guess I should be able to find where the thread that accesses this function is created. Then I can store the thread handle, and use the method Dark Byte mentioned.

- DebugActiveProcess
- SuspendThread
- GetThreadContext (backup registers)
- SetThreadContext (modify EIP to my code, ending with a 0xCC BP?)
- ResumeThread
- WaitForDebugEvent
- SetThreadContext (restore registers)
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25804
Location: The netherlands

PostPosted: Fri Dec 14, 2012 3:59 am    Post subject: Reply with quote

If you're doing it from inside a dll then DebugActiveProcess won't work.

Anyhow, you only need SetThreadContext once.
1: SuspendThread
2: GetThreadContext.
3: Check if thread was in waiting state. If Yes, ResumeThread and goto 1 (perhaps send it a message to awaken it as well)
4: Save context to a static/hardcoded location
5: SetThreadContext to new eip

Your code:
1: Do stuff
2: When done, read the state from the known location
3: Setup the registers to what they should be (do not use registers to store the address, use direct addresses only)
4: Jump to the eip address store in the context at the known location (jmp [AddressOfStoredContextEIP] )

_________________
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
View user's profile Send private message MSN Messenger
661089799107
Expert Cheater
Reputation: 3

Joined: 25 Jan 2009
Posts: 186

PostPosted: Fri Dec 14, 2012 11:31 am    Post subject: Reply with quote

Thank you. I got it working Smile

Code:

_declspec(naked) void mainThread_useItem()
{
   __asm
   {
      PUSHAD
      push [selectedItem_addr]
      call [useItem_addr]
      POPAD
      JMP [contextBackup.Eip]
   };
}


Code:

void useItem(int pos)
{
   *pSelectedItem = pos;

   callFunctionFromMainThread(reinterpret_cast<DWORD>(&mainThread_useItem));
}


Code:

void callFunctionFromMainThread(DWORD newEIP)
{
   HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, mainThreadID);

   if(!hThread)
   {
      std::cout << "[Error] OpenThread\n";
      return;
   }

   // Suspend thread so we can change the EIP
   if(SuspendThread(hThread) == -1)
   {
      std::cout << "[Error] SuspendThread\n";
      return;
   }

   contextBackup.ContextFlags = CONTEXT_FULL;

   // Backup registers
   if(!GetThreadContext(hThread, &contextBackup))
   {
      std::cout << "[Error] GetThreadContext\n";

      if(ResumeThread(hThread) == -1)
      {
         std::cout << "[Error] ResumeThread\n";
      }

      return;
   }
   
   DWORD oldEIP = contextBackup.Eip;
   
   // Set new EIP
   contextBackup.Eip = newEIP;
   if(!SetThreadContext(hThread, &contextBackup))
   {
      std::cout << "[Error] SetThreadContext\n";

      if(ResumeThread(hThread) == -1)
      {
         std::cout << "[Error] ResumeThread\n";
      }
   }

   contextBackup.Eip = oldEIP;

   // Resume execution (in our code)
   ResumeThread(hThread);
}
Back to top
View user's profile Send private message
TsTg
Master Cheater
Reputation: 5

Joined: 12 Dec 2012
Posts: 340
Location: Somewhere....

PostPosted: Fri Dec 14, 2012 9:52 pm    Post subject: Reply with quote

Would a technique like this work with a game that uses integrity checks on its executable code ??

I would like to program a DLL that can inject any custom code in a certain location in game code, here's my idea:

1- Create my watching thread in the target process(via DLL inject or CreateRemoteThread)
2- Constantly Susupend the target thread and get the Thread context
3- compare if EIP is my taget address, then redirect it if euqal(SetThreadContext)
4- in my custom code i put JMP DWORD [Original EIP+next command offset]
5- Resume the thread

But my question is would that affect the game speed as am constantly suspending and resuming it's thread ??
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25804
Location: The netherlands

PostPosted: Sat Dec 15, 2012 4:16 am    Post subject: Reply with quote

No, that will not work.
The time between resuming the process and suspending it again is too big, it may have already executed that function 10 times, or 0 times if no context switch had happened inbetween

If it worked it wouldn't slow down the game too much (as suspending and resuming it happens in the running context of another thread so that thread was most likely not even running at that time)
But yeah, it won't work because this is too inaccurate.

One method that does work is set the trap flag and capture every single step exception. This will of course make the game run at 0.00000001 frames per day

Blecknight:
You might want to do a pushfd/popfd as well, in case you break right after a compare and before a conditional jump

_________________
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
View user's profile Send private message MSN Messenger
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