 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
LongBeardedLion Expert Cheater
Reputation: 0
Joined: 10 Apr 2020 Posts: 174
|
Posted: Wed Jul 01, 2020 10:19 am Post subject: C++ Hook without assembly? |
|
|
I have been playing around with hooks using assembly. It helped me understand a little more assembly.
But now i need to hook functions using C++ code inside the hooked function. So basically instead of usin __asm . I will hook the function and throw my c++ code inside.
But i could not find videos about this on youtube. Most are with assembly.
Can anyone help me? Or give me an hint of what i should look for?
|
|
| Back to top |
|
 |
atom0s Moderator
Reputation: 205
Joined: 25 Jan 2006 Posts: 8587 Location: 127.0.0.1
|
|
| Back to top |
|
 |
LongBeardedLion Expert Cheater
Reputation: 0
Joined: 10 Apr 2020 Posts: 174
|
Posted: Thu Jul 02, 2020 7:33 am Post subject: |
|
|
Thank you atomOs,
Thats awesome .
Just one question.
I have this impression that using _asm instead of a detour that uses C++, is faster and more code efficient. Or am i wrong, or is it irrelevant? Seems like _asm is going straight to the code, and its cleaner and faster?
But anyways. Its very confusing to use _asm only. And in C++ i can simply write a small program inside the injection.
Im trying to make an injection that logs all the registers that go through a certain function into a .txt in my desktop. Dont know if thats the best practice. Or if thats fast enough. But i was told that i can print to the console. However i have no idea where the console is in Age of Empires 2 or if i must create a console.
|
|
| Back to top |
|
 |
Csimbi I post too much
Reputation: 98
Joined: 14 Jul 2007 Posts: 3340
|
Posted: Thu Jul 02, 2020 3:19 pm Post subject: |
|
|
| I think they meant the LUA console.
|
|
| Back to top |
|
 |
atom0s Moderator
Reputation: 205
Joined: 25 Jan 2006 Posts: 8587 Location: 127.0.0.1
|
Posted: Fri Jul 03, 2020 2:10 pm Post subject: |
|
|
| LongBeardedLion wrote: | Thank you atomOs,
Thats awesome .
Just one question.
I have this impression that using _asm instead of a detour that uses C++, is faster and more code efficient. Or am i wrong, or is it irrelevant? Seems like _asm is going straight to the code, and its cleaner and faster?
But anyways. Its very confusing to use _asm only. And in C++ i can simply write a small program inside the injection.
Im trying to make an injection that logs all the registers that go through a certain function into a .txt in my desktop. Dont know if thats the best practice. Or if thats fast enough. But i was told that i can print to the console. However i have no idea where the console is in Age of Empires 2 or if i must create a console. |
If you are not someone who has coded in ASM for years on end and are extremely efficient in optimizations and best practices, I would suggest avoiding naked code caves (using raw _asm blocks) whenever possible. The compiler will optimize your C++ code as needed and when possible that will more than likely generate better results, especially if your blocks of asm are large.
Doing simple small caves and such is fine, or if you know exactly what you are working to make, it's fine as well. But if you are doing things that are in-depth, it's usually not worth the hassle.
Console wise, you would need to make your own if you are injecting a DLL into the game and want to print information. You can use things like OutputDebugStringA/OutputDebugStringW which will write to the systems debug output. (You can use a tool like DbgView or DbgView++) Making your own and outputting to it is not hard though. Look into the 'AllocConsole' API to do that and how to set things up to make it work with "printf" and similar functions.
_________________
- Retired. |
|
| Back to top |
|
 |
LongBeardedLion Expert Cheater
Reputation: 0
Joined: 10 Apr 2020 Posts: 174
|
Posted: Fri Jul 03, 2020 8:53 pm Post subject: |
|
|
Ok so i have this dll injection that works except i cant make it run my C++ code in the middle of it.
So im hooking a function, writing back its stolen bytes. And then mov ECX to whiskas. Then i want to save the value in whiskas, that was in ECX. To a txt in the desktop. But its not even allowing me to compile because it says:
C2489 'whiskas': initialized auto or register variable not allowed at function scope in 'naked' function
And also:
Error C3068 'ourFunct': a 'naked' function cannot contain objects that would require unwinding if a C++ exception occurred
So this is my hook :
| Code: |
void __declspec(naked) ourFunct() {
int whiskas = 0x0;
__asm {
mov esi, ecx
mov cl, byte ptr[esp + 0x8]
mov whiskas, ecx
}
//Beep(1000, 1000);
std::ofstream file;
file.open("C:/Users/j/Desktop/Test.txt");
file << whiskas;
file.close();
__asm {
jmp[jmpBackAddy]
}
} |
However if i remove all the txt file code, and just leave the Beep(1000,1000); that i commented out, then it compiles, and it injects and it works perfectly. But i wanted the code to work with writting for the txt
This is the full code:
| Code: |
#include <Windows.h>
#include <iostream>
#include <fstream>
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() {
int whiskas = 0x0;
__asm {
mov esi, ecx
mov cl, byte ptr[esp + 0x8]
mov whiskas, ecx
}
//Beep(1000, 1000);
std::ofstream file;
file.open("C:/Users/j/Desktop/Test.txt");
file << whiskas;
file.close()
__asm {
jmp[jmpBackAddy]
}
}
DWORD WINAPI MainThread(LPVOID param) {
int hookLength = 6;
DWORD hookAddress = 0x4174A1;
jmpBackAddy = hookAddress + hookLength;
Hook((void*)hookAddress, ourFunct, hookLength);
while (true) {
Sleep(40);
if (GetAsyncKeyState(VK_NUMPAD3)) {
Sleep(40);
Beep(500, 500); //just to know that my whiskas injection is in place
}
}
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;
} |
|
|
| Back to top |
|
 |
atom0s Moderator
Reputation: 205
Joined: 25 Jan 2006 Posts: 8587 Location: 127.0.0.1
|
Posted: Sat Jul 04, 2020 3:19 pm Post subject: |
|
|
Naked functions are literally just that, they are blocks of code that have no automatic stack handling. There is no epilogue or prologue to deal with any local variables, stack cleanup, or calling convention handling. So it has no means of holding local variables or dealing with stack unwinds in the event of an exception.
To fix those errors, you can move 'whiskas' out of the function and make it a global. You can also take the file code and move it to a separate function, then call that function in your naked function.
_________________
- Retired. |
|
| Back to top |
|
 |
LongBeardedLion Expert Cheater
Reputation: 0
Joined: 10 Apr 2020 Posts: 174
|
Posted: Sat Jul 04, 2020 5:36 pm Post subject: |
|
|
Thank you atomos that solve the problem for now. It compiled.
I didnt expect it to work. Just wanted it to compile.
But then i injected it and its actually exporting my value in ECX to the txt in my desktop. How awesome.
But it also bugged some things in the game even though it didnt crash and it was functional. Now i need to make sure that the function where im doing the injection, stays with the proper registers intact after the function that you told me to create ends. Right? Is that the right thing to do? Or i dont know what im talking about? How should i proceed? Because it seems like im just a monkey writting code blindly and hoping it works . Im not sure if this is actually ruining all the code inside the game.
From what i saw in the debugger, the detour assembly looks like a mess. And it goes around doing some weird stuff
This is what i did:
I put whiskas in the global as you said.
And made a void function outside of the naked function.
Then called it inside.
Here it is:
| Code: | #include <Windows.h>
#include <iostream>
#include <fstream>
int whiskas;
void writeFileJ() {
std::ofstream file;
file.open("C:/Users/j/Desktop/Test.txt");
file << whiskas;
file.close();
}
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(std::ofstream& file)
{
__asm {
mov esi, ecx
mov cl, byte ptr[esp + 0x8]
mov whiskas, ecx
}
writeFileJ();
__asm {
jmp[jmpBackAddy]
}
}
DWORD WINAPI MainThread(LPVOID param) {
int hookLength = 6;
DWORD hookAddress = 0x4174A1;
jmpBackAddy = hookAddress + hookLength;
Hook((void*)hookAddress, ourFunct, hookLength);
while (true) {
Sleep(40);
if (GetAsyncKeyState(VK_NUMPAD3)) {
Sleep(40);
Beep(500, 500); //just to know that my whiskas injection is in place
}
}
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;
} |
|
|
| 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
|
|