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 and at the same time change _asm ?

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

Joined: 10 Apr 2020
Posts: 174

PostPosted: Wed Jun 10, 2020 5:04 pm    Post subject: Calling game function and at the same time change _asm ? Reply with quote

I mean calling a game function in c++. But the new _asm should be only specifically changed when im calling the function. I dont want the function to have its code permanently altered. Only when i call it i want it to have a specific _asm code.

This is my code that calls the game function, it works perfectly:

Code:
#include "Memory.h"

struct _Target
{
    typedef void(__thiscall* _Func)(int pThis, int astring, int bstring, int cstring, int dstring, int estring);
    _Func Func;
    int pThis = 0x14930358; //ECX
    int astring = 0x41; //STACK 1
    int bstring = 0x1E0001; //STACK 2
    int cstring = 0x0; //STACK 3
    int dstring = 0x0; //STACK 4
    int estring = 0x0; //STACK 5
}Target;



DWORD WINAPI MainThread(LPVOID param)
{

    uintptr_t base = (uintptr_t)GetModuleHandle(0);
    Target.Func = (_Target::_Func)(base + 0xB0820);

    while (!GetAsyncKeyState(VK_END))
    {
        if (GetAsyncKeyState(VK_NUMPAD3))
        {
            Target.Func(Target.pThis, Target.astring, Target.bstring, Target.cstring, Target.dstring, Target.estring); //Function called
        }
    }
    FreeLibraryAndExitThread((HMODULE)param, 0);
    return 0;
}

BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
{
    switch (dwReason)
    {
    case DLL_PROCESS_ATTACH:
        CreateThread(0, 0, MainThread, hModule, 0, 0);
        break;
    default:
        break;
    }
    return TRUE;
}


As you can see i call the function base + 0xB0820, and i write its arguments. Thats awesome. But now how can i change the value ESI inside that function?

In other words if it is possible to change the esi or other values inside the function as assembly code?

Like this:

_asm
{
mov esi, 0x20
}

Where do i put this?
If that even is allowed?
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 97

Joined: 14 Jul 2007
Posts: 3329

PostPosted: Thu Jun 11, 2020 2:16 am    Post subject: Reply with quote

Local variables in a function only exists while that function runs. Plus, there may be multiple instances.
Register are pretty volatile as all processing goes through them; you need to change them at the right moment else is might not even be holding the right variable.
So, I think you will want to inject a permanent piece of code (into the game) anyway that determines a) whether the change is required and if yes, b) get the value that should be loaded into ESI and lastly, c) load the value into ESI.
Back to top
View user's profile Send private message
LongBeardedLion
Expert Cheater
Reputation: 0

Joined: 10 Apr 2020
Posts: 174

PostPosted: Thu Jun 11, 2020 2:29 am    Post subject: Reply with quote

Thanks CSimba

That sounds like a good way to go. Could you please just give me an hint of how to alter a eventual ESI value in the midst of my function?

Where do i put it?
Cause i have no idea.

Also i was thinking, what if i do a 3 process method:

1- Hook/detour the function, change the code to something that i want. This i know how to do.

2- Call the function (will call the function but now it has the hook with my new code).

3- After the call is finished, hook again the function and overwrite it again with its original code.

All these three processes will run quickly one after the other. So basically it will change the code of the function, call function, and change back to what it was.

? IS this a good practice? Or its stupid and doesnt make any sense?
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 97

Joined: 14 Jul 2007
Posts: 3329

PostPosted: Thu Jun 11, 2020 2:59 am    Post subject: Reply with quote

In your hook, allocate space for two variables and register them both.
One is a flag, the second is the value.
In your hook you will do something like:
Code:
cmp [flag],1 // Are we to run?
jne short @f  // If not, skip past to the end
mov esi,[value] // Update ESI with our value
mov [flag],0 // Optional, to ensure ESI is updated only once. (i.e. auto off)
@@:

And in your function, you update these two values only.
The hook will take care of ESI updates whenever you want it.

Are you aware of a good reason to hook/unhook before/after each call?
If not, just hook once and forget about it and control the variables from the outside whenever you want to.
Unhook only on exit.
Back to top
View user's profile Send private message
LongBeardedLion
Expert Cheater
Reputation: 0

Joined: 10 Apr 2020
Posts: 174

PostPosted: Thu Jun 11, 2020 2:13 pm    Post subject: Reply with quote

Thanks Csimbi,
Quote:

In your hook, allocate space for two variables and register them both.


But this is not a hook? This just calls a game function. Yes it can change the function parameters, as you can see in Astring = 0x41 ; and Bstring = 0x.. etc... Those are function parameters.

But thats about all i can do here.

I have no idea how can i make _asm code in this situation inside the function called. That is the key. As soon as i can do that, i have the problem solved.

I do know however how to hook and make detours inside functions, although its a different code than what i have above.

Where would i throw the:

Quote:

cmp [flag],1 // Are we to run?
jne short @f // If not, skip past to the end
mov esi,[value] // Update ESI with our value
mov [flag],0 // Optional, to ensure ESI is updated only once. (i.e. auto off)
@@:


Is there a way to do this with the code i have or i have to mix my function call with another function that hooks? Because so far my code does not hook it only calls a function. It seems thats the approach i should take?

This is the code i use for hooking/detour, its a different thing, even the address is defined differently, previously i defined it as B0820, but here its defined as 4B0820:

Code:
#include <Windows.h>

bool Hook(void * toHook, void * ourFunct, int len) {
   if (len < 5) {
      return false;
   }

   DWORD curProtection;
   VirtualProtect(toHook, len, PAGE_EXECUTE_READWRITE, &curProtection);

   memset(toHook, 0x90, len);

   DWORD relativeAddress = ((DWORD)ourFunct - (DWORD)toHook) - 5;

   *(BYTE*)toHook = 0xE9;
   *(DWORD*)((DWORD)toHook + 1) = relativeAddress;

   DWORD temp;
   VirtualProtect(toHook, len, curProtection, &temp);

   return true;
}

DWORD jmpBackAddy;
void __declspec(naked) ourFunct() {
   __asm {
      push esi
      mov esi, ecx
      cmp [flag],1 // Are we to run?
                jne short @f  // If not, skip past to the end
                mov esi,[value] // Update ESI with our value
                mov [flag],0 // Optional, to ensure ESI is updated only once.
   }
}

DWORD WINAPI MainThread(LPVOID param) {
   int hookLength = 7;
   DWORD hookAddress = 0x4B0820;
   jmpBackAddy = hookAddress + hookLength;

   Hook((void*)hookAddress, ourFunct, hookLength);

   while (true) {
      if (GetAsyncKeyState(VK_ESCAPE)) break;
      Sleep(50);
   }

   FreeLibraryAndExitThread((HMODULE)param, 0);

   return 0;
}

BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved) {
   switch (dwReason) {
   case DLL_PROCESS_ATTACH:
      CreateThread(0, 0, MainThread, hModule, 0, 0);
      break;
   }

   return TRUE;
}



But i understood your asm code.
Basically what you are doing is everytime the function is called you will assign 1 to the flag? (must be assigned in the function called by VK_NUMPAD3 Right? So then when it compares, it will do our code, move the value to esi, and reset the flag value, or if the cmp is not equal it jumps to the end.

And my doubt here is. If i inject a dll with that code. How will the code inside my game know what [Flag] is? Since Flag is a variable defined in my C++ that i inject and that i change each time i fire the key VK_NUMPAD3? OR maybe, maybe you attributed [Flag] to an address inside the game? And then you will use writeto memory to overwrite the Flag value, so that it is 1 when you call the function and 0 all other times?


Pls help.
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 97

Joined: 14 Jul 2007
Posts: 3329

PostPosted: Thu Jun 11, 2020 2:40 pm    Post subject: Reply with quote

That seems to redirect code from 0x4B0820 to ourFunct just tine.
At least, by reading the code above, that's the impression I get.
Note: you did not save the original instructions - you should restore it after ESC is hit in MainThread.
Declare and initialize a DWORD for flag, make it a global var.
Declare and initialize a DWORD for value, make it a global var.

Add this to the loop in MainThread:
if (GetAsyncKeyState(VK_MENU)) flag = 1 else flag = 0;
Make sure value takes an input somewhere (another hotkey)?

What's with mov esi,ecx?
I thought your value was in ESI.
- the conditional jump has no label to jump to.
- it seems you don't pop the stack at the end of ourFunct.

Replace everything in ourFunct with a single NOP just to test that it the jump is actually correct (it does step into ourFunct).
Then, put the contents back and fixed those two things I mentioned above and then it should work.
Back to top
View user's profile Send private message
LongBeardedLion
Expert Cheater
Reputation: 0

Joined: 10 Apr 2020
Posts: 174

PostPosted: Thu Jun 11, 2020 4:54 pm    Post subject: Reply with quote

Sorry i think there is a bit of a confusion here. I shouldnt have not posted the code for hook, i distracted you from the problem and the real code. I think you confused it with the original function for calling. They are completely different things.

The last code i posted that you commented on your last answer is not the function im using, that is just an example that i used to show you my code for a hook/detour, so that i can show what i have done in the past when i wanted to change _asm, that i cant use right now because im calling a function, not injecting code. So that is different than the first code i showed you, that is used to calling the function (and that im trying to somehow use it and at the same time change the _asm of the function that is called by it).

The 1st code in the original post, is used solely to call a function, and the problem is there is no way, that i know, to alter _asm code in there.

The 2nd code i posted is a detour/hook, and that alone does not ever call the function. It simply overwrites the code and makes it jump, when the function is called by the game (not by user artificially).

In other words the difference between 1 and 2, is that 1 is calling the function externally/indirectly/artificially. While 2 is not calling the function just altering its code that sits there waiting for the game to call it.

I know this is confusing, and i dont know what else i can do to explain it better. Sorry if this is a mess.

So the same problem persists.

If i use the 1st code that calls the function, i have no way to alter its _asm, that i know. I dont know where in the 1st solution should i write the _asm. Whereas in the 2nd code the function is never called, because its just a detour, it was just an example, because i wanted to say that maybe i should somehow combine both, and try to alter the _asm first, and then call the function?

This can be solved if i know where in my 1st code, in the original post, can i insert _asm code that alters the instructions.

In my 2nd code whatever i do with the flags and _asm will not call the function.

However your idea to make a [flag] in my still beginner notions, would maybe solve the problem. If only i could assign the [flag] to a random address in memory, that is checked everytime the function is called. So that when i call the function artificially, i write to that address in [flag] the value of 1, so when the function is called (artificially), it will check the value in [flag], and it will know it is an artificial call, meaning its a call from the dll, and not any other calls made by the game, so it will then execute our code, and in this case change our ESI to the value that we need, and then set the flag again back to 0, so that when the function is called by the game in the natural circumstances, the ESI will get its natural values not our artificial value.
Does this make any sense?
What do you think?
Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 97

Joined: 14 Jul 2007
Posts: 3329

PostPosted: Fri Jun 12, 2020 1:55 am    Post subject: Reply with quote

Well, yes, in principle, the code changing ESI has to run as part of the original function, whenever it's called - and that's only possible if you hook it and redirect it to your won cave.
As for what happens in there, yes, you need to be able to control the variables from the outside.

Here's an idea: do it in CE's AA first and see what actually happens there.
Then, try to do the same with your own code.
Back to top
View user's profile Send private message
LongBeardedLion
Expert Cheater
Reputation: 0

Joined: 10 Apr 2020
Posts: 174

PostPosted: Fri Jun 12, 2020 7:30 am    Post subject: Reply with quote

I made a huge progress. Image below.

I was able to make an injection and write to a specific empty address the number 1, so thats the flag.

But the problem is, in my _asm im not being able to type the address where i make the flag. So it never makes the comparison. I tried editing the code and writting the address manually and then it works. So now i only need to figure out how to make the address pass into that _asm function.

chunk of the code that matters:

Code:

   __asm {
      mov esi, ecx
      cmp[valueSwitch], 0x01 // value switch always passes as 0x5EEAA480 instead of 0x775200 . so it cant make the comparison.
      je label
      mov cl, byte ptr [esp + 0x8]
      jmp[jmpBackAddy]
      label:
      mov cl, 0x03
      mov[valueSwitch], 0x00
      jmp[jmpBackAddy]
   }


It seems the variable valueSwitch as well as the jmpBackAddy adapts to the detour somehow and it does not maintain its original value, in this case valueSwitch should be 0x775200. But its 0x5EEAA480. I also tried writting literally 0x775200, but it does not let me compile. So it must work through variables. thats strange.

The funny thing is that my address is stored in 0x5EEAA480 as 00 52 77 but i have no idea how should i get it out of there?

Any idea how can i solve this? Im so close. Pls help me.

Full code:


Code:
#include <Windows.h>

bool Hook(void* toHook, void* ourFunct, int len) {
   if (len < 5) {
      return false;
   }

   DWORD curProtection;
   VirtualProtect(toHook, len, PAGE_EXECUTE_READWRITE, &curProtection);

   memset(toHook, 0x90, len);

   DWORD relativeAddress = ((DWORD)ourFunct - (DWORD)toHook) - 5;

   *(BYTE*)toHook = 0xE9;
   *(DWORD*)((DWORD)toHook + 1) = relativeAddress;

   DWORD temp;
   VirtualProtect(toHook, len, curProtection, &temp);

   return true;
}
void* switchAddress = (void*)0x775200; //Switch address change maybe wont work because of protection
DWORD jmpBackAddy;
DWORD valueSwitch;
void __declspec(naked) ourFunct() {
   __asm {
      mov esi, ecx
      cmp[valueSwitch], 0x01 // value switch always passes as 0x5EEAA480 instead of 0x775200
      je label
      mov cl, byte ptr [esp + 0x8]
      jmp[jmpBackAddy]
      label:
      mov cl, 0x03
      mov[valueSwitch], 0x00
      jmp[jmpBackAddy]
   }
}

DWORD WINAPI MainThread(LPVOID param) {
   int hookLength = 6;
   DWORD hookAddress = 0x4174A1;
   jmpBackAddy = hookAddress + hookLength;
   valueSwitch = 0x775200;
   DWORD switchProtection;
   VirtualProtect(switchAddress, 1, PAGE_EXECUTE_READWRITE, &switchProtection);
   memset(switchAddress, 0x01, 1);
   DWORD switchTemp;
   VirtualProtect(switchAddress, 1, switchProtection, &switchTemp);

   Hook((void*)hookAddress, ourFunct, hookLength);

   //memset(switchAddress, 0x00, 1);

   while (true) {
      if (GetAsyncKeyState(VK_ESCAPE)) break;
      Sleep(50);
   }

   FreeLibraryAndExitThread((HMODULE)param, 0);

   return 0;
}

BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved) {
   switch (dwReason) {
   case DLL_PROCESS_ATTACH:
      CreateThread(0, 0, MainThread, hModule, 0, 0);
      break;
   }

   return TRUE;
}



Untitled.jpg
 Description:
 Filesize:  483.98 KB
 Viewed:  4330 Time(s)

Untitled.jpg


Back to top
View user's profile Send private message
Csimbi
I post too much
Reputation: 97

Joined: 14 Jul 2007
Posts: 3329

PostPosted: Fri Jun 12, 2020 8:14 am    Post subject: This post has 1 review(s) Reply with quote

You could pass the flag and the value as a parameter, yes.
But be sure you pass the pointers, not the current values of these.
(You will check/use the current values at the pointer every time the function runs.)
Back to top
View user's profile Send private message
LongBeardedLion
Expert Cheater
Reputation: 0

Joined: 10 Apr 2020
Posts: 174

PostPosted: Fri Jun 12, 2020 9:23 am    Post subject: Reply with quote

Thanks CSIMBI

I made it work finally.
With a lot of stubborness and with your help i was able to make it.
Is there anyway i can upvote you?
This is what i wrote in the assembly to make it work:

Code:

      mov esi, ecx
      push eax
      push [valueSwitch]
      mov eax, [esp]
      cmp[eax], 0x01
      jne label
      add esp, 0x4
      mov eax, [esp]
      add esp, 0x4
      mov cl, byte ptr [esp + 0x8]
      jmp[jmpBackAddy]
      label:
      add esp, 0x4
      mov[eax], 0x00
      mov eax, [esp]
      add esp, 0x4
      mov cl, 0x03
      mov[valueSwitch], 0x00
      jmp[jmpBackAddy]


I pushed one register into the stack. Then pushed the value of my address that is in a random address into the stack. Then pushed the value in the stack into EAX. Then made the comparison using EAX. Then restored back the previous values and restore the stack to where it was Very Happy Very Happy Very Happy . I have no idea if this is the right thing to do. But it works.

Thanks so much.
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