I used Microsoft Visual C++ 2008. You can use a different compiler, you'd just have to change the assemblys syntax.
This "tutorial" is not intended to be used to "attack" or "make hacks" for other servers. It is intended to help other server developers/owners.
Don't ask me "what is an int?" or whatnot. If you want to understand this, go learn C++.
Note: I won't explain everything, I will not go into detail on a lot, and will be wrong. Just enough for you to get a kick-start on C++ developing for GunZ.
I may not be correct on everything, and my explanations are rather horrid.
@Phail and Guy, I know you will criticize me a lot what I typed. But try to keep it to a minimum please. :D
I've been up for 3 fucking days, but I'm positive you don't care. lol.
typedef: a keyword used to define another type. In this case, void.
__cdecl: __cdecl is a calling convention. (More information later)
*: is used as a pointer in this case, not to multiply. :p
The arguments:
const char*: The message to display
int: Where to place it
int: The type of color
DWORD: The color of the message
Usage of ZChatOutput:
Code:
ZChatOutput("Hello world!", 2, 0, 0xFFFFFF);
You might be asking, "How do I find the addresses?"
Using ollydbg, test.txt, and GunZOld.exe.
Fire up ollydbg, open GunZOld.exe in ollydbg.
Open test.txt, and find ZChatOutput: 427A40: ZChatOutput
The "427A40" is the address in GunZOld.exe. Copy that address, open the ollydbg window, and hit "CTRL + G" paste it in the text box, and hit OK.
It should be something like this:
Since the addresses have changed, we can NOT copy "Calls", "MOV + [address]", or anything with an address.
Open up a new ollydbg window, and open "theduel.exe"
Highlight from: "MOV ECX, DWORD PTR SS:[ESP+10]" - to "PUSH EDX"
right click -> binary -> binary copy
Open the "theduel.exe" ollydbg, press "CTRL + B" and paste it in the "HEX + 00" box.
NOTE: It may not look exactly like eachother, so search underneath/above it and compare between each runnable in ollydbg.
They appear to be the same, so scroll back up to 0042A230 - And we have ZChatOutput's address!!
(Their are more ways to find addresses, but I like this way.)
void MyThread()
{
for(;;Sleep(20)) //Infinite Loop
{
if(GetAsyncKeyState (VK_MENU) && GetAsyncKeyState ('L'))
// IF THE KEY ALT (was pressed) AND THE KEY L (was pressed)
{
ZChatOutput("Hello World!", 2, 0, 0xFFFFFF);
Sleep(250); //To make sure it doesn't run while them keys were pressed.
}
}
}
Compile, inject, fix any errors (if any) and test.
Congratulations.
Let's take a bigger step, using assembly's syntax inside of C++. ZGameClient::OnAnnounce
Looks different, that's because ZGameClient::OnAnnounce is used as a class, not a function.
So attempting to use the "__cdecl" will not work, we will need to use "__asm" keyword to call this.
/*
MOV ECX, ZGetGameClientAdd - COPY ZGetGameClientAdd into the ECX register
MOV EAX, OnAnnounceAdd - COPY OnAnnounceAdd into the EAX register
PUSH szMsg - PUSH'ing szMsg into the stack
PUSH nType - PUSH'ing nType into the stack
CALL EAX - CALL what's in the EAX register
So, when we call EAX, we also call what we push'd. (Learn ASM)
*/
How did I know the parameters? The GunZ PDB Dump, searching for the functions name.
Copy this: ZGameClient::OnAnnounce - and open GunZ PDB Dump.txt in wordpad.
Press "CTRL + F" and paste that, and search.
Gives us all we need, but hit F3 two more times.
You should see something like this:
Code:
Function : static, [0x000afd70][0x0001:0x000aed70], len = 00000030, protected: void __thiscall ZGameClient::OnAnnounce(unsigned int,char *)
FuncDebugStart : static, [0x000afd71][0x0001:0x000aed71]
FuncDebugEnd : static, [0x000afd9a][0x0001:0x000aed9a]
Data : enregistered edx, Object Ptr, Type: class ZGameClient * const, this
Data : ebp Relative, [0x00000004], Param, Type: unsigned int, nType
Data : ebp Relative, [0x00000008], Param, Type: char *, szMsg
Ok, we have a better view on what we should use as parameters for this function.
(Remember, my explanations are rather horrid. And I may not be correct on everything.)
Quote:
Originally Posted by Theoretical
Your definitions for calling conventions are incorrect my good sir.
The "__cdecl" - we can call, when the function is NOT apart in a class.
The "__thiscall" - we can call using ASM.
The "__stdcall" - used for calling functions that apart of graphics/winapi/directx/etc.
__cdecl -> Arguments are pushed from right to left, and the calling function cleans it up.
__thiscall -> Arguments are pushed from right to left, and the called function cleans the stack up. ECX = "this" aka class pointer.
__stdcall -> Arguments are pushed from right to left, and the called function cleans the stack up.
^ Thanks Phail.
=====
I'm done. Took me an hour or so to write this.
Enjoy what you i gave, please correct me if I am wrong. (I like critisizm, but keep it to a minimum please.)
13-10-09
alfredao
Re: Basic tut on using C++ for GunZ
Very Nice Tutorial, Thanks ;D
14-10-09
monckey100
Re: Basic tut on using C++ for GunZ
nice tutorial, i sadly got 3 errors, undefined identifier "ZChatOutput" is one of them
ZChatType ZChat = (ZChatType)0042A230;
they count the 2 as an illegal token O-o
MessageBox(NULL, L"Injected", L"HI", MB_OK);
apparently doesnt match something outside of the code O-o
i tried 2 different compilers, same errors, is it because im saving it as a .cpp?
14-10-09
PenguinGuys
Re: Basic tut on using C++ for GunZ
Thanks for that Monckey, you need to make it an offset. Just by adding
"0x" infront of the address.
I used Microsoft Visual C++ 2008. It will NOT compile on other compilers unless you change the ASM syntax.
I also used an "L" (wide char) due to the size of the message.
You don't need the messagebox, try
Code:
Beep(750, 750);
instead.
14-10-09
ThePhailure772
Re: Basic tut on using C++ for GunZ
Your definitions for calling conventions are incorrect my good sir.
The "__cdecl" - we can call, when the function is NOT apart in a class.
The "__thiscall" - we can call using ASM.
The "__stdcall" - used for calling functions that apart of graphics/winapi/directx/etc.
__cdecl -> Arguments are pushed from right to left, and the calling function cleans it up.
__thiscall -> Arguments are pushed from right to left, and the called function cleans the stack up. ECX = "this" aka class pointer.
__stdcall -> Arguments are pushed from right to left, and the called function cleans the stack up.
14-10-09
Guy
Re: Basic tut on using C++ for GunZ
Quote:
Originally Posted by Theoretical
Your definitions for calling conventions are incorrect my good sir.
The "__cdecl" - we can call, when the function is NOT apart in a class.
The "__thiscall" - we can call using ASM.
The "__stdcall" - used for calling functions that apart of graphics/winapi/directx/etc.
__cdecl -> Arguments are pushed from right to left, and the calling function cleans it up.
__thiscall -> Arguments are pushed from right to left, and the called function cleans the stack up. ECX = "this" aka class pointer.
__stdcall -> Arguments are pushed from right to left, and the called function cleans the stack up.
ECX/RCX is only "this" pointer with MSVS, when using thiscall.
And don't forget, x64-MSVS doesn't have any of these calling conventions.
Also, you forgot __fastcall.
15-10-09
Linear88
Re: Basic tut on using C++ for GunZ
Quote:
Originally Posted by Theoretical
Your definitions for calling conventions are incorrect my good sir.
The "__cdecl" - we can call, when the function is NOT apart in a class.
The "__thiscall" - we can call using ASM.
The "__stdcall" - used for calling functions that apart of graphics/winapi/directx/etc.
__cdecl -> Arguments are pushed from right to left, and the calling function cleans it up.
__thiscall -> Arguments are pushed from right to left, and the called function cleans the stack up. ECX = "this" aka class pointer.
__stdcall -> Arguments are pushed from right to left, and the called function cleans the stack up.
Thanks for explaining this, I never knew what those meant.
For PenguinGuy's tutorial, I knew the rest from the start. :)
15-10-09
Guy
Re: Basic tut on using C++ for GunZ
Quote:
typedef: a keyword used to define another type. In this case, void.
Wrong - you're defining a function with a return value of void (None).
Code:
for(;;Sleep(20)) //To make it run forever! OR while(1) OR while(true)
....
Sleep(20); //Without this, it'll hog CPU resources. It will cause it to lag extremely bad.
You're launching a call to Sleep with the same parameter twice; that's redundant.
Quote:
So attempting to use the "__cdecl" will not work, we will need to use "__asm" keyword to call this.
You don't have to use inline ASM; the ECX register can be modified using a statically linked .ASM file, the SetThreadContext function, VEH, etc etc.
Also, EAX did not have to modified.
15-10-09
PenguinGuys
Re: Basic tut on using C++ for GunZ
Quote:
Originally Posted by Guy
Wrong - you're defining a function with a return value of void (None).
I only know what I read from tutorials/documentations, snooping around the GunZ client/PDB dumps & hack source codes.
I do know void returns nothing, but I don't seem to understand what you mean.
Code:
typedef char* pntChar;
Am I correct?
15-10-09
Guy
Re: Basic tut on using C++ for GunZ
Quote:
Originally Posted by PenguinGuy
I only know what I read from tutorials/documentations, snooping around the GunZ client/PDB dumps & hack source codes.
I do know void returns nothing, but I don't seem to understand what you mean.
Code:
typedef char* pntChar;
Am I correct?
The above is a type definition for a pointer, yes. However, what you saw before was a function pointer - function type pointers, when defined using typedef, can be given specific parameters.
(Code not tested)
Edit: Forgot the ClearInput :P: If you forget to add the "ClearInput", you will not be able to input another command.
Edit2: I plan on updating this tutorial tonight or tomorrow night on finding an using pointers, adding/removing functions in "theduel.exe", and creating custom commands in C++ and ASM.
14-12-09
Linear88
Re: Basic tut on using C++ for GunZ
You might want to detour ZChat::Input instead.
14-12-09
PenguinGuys
Re: Basic tut on using C++ for GunZ
Quote:
Originally Posted by Linear88
You might want to detour ZChat::Input instead.
It's still pretty much the same out-come. Detouring ZChat::Input could be better.
Detouring is something I try to avoid. With little modification to ZChat::Input, you can complete your task without the use of the detours library. Or just use the above method.
16-12-09
gpadmin
Re: Basic tut on using C++ for GunZ
Hello. How change server port 7777 to 4545 and how change same port on client side? Thank you.
16-12-09
Linear88
Re: Basic tut on using C++ for GunZ
Quote:
Originally Posted by gpadmin
Hello. How change server port 7777 to 4545 and how change same port on client side? Thank you.
Make a separate topic, don't post it here.
22-12-09
00niels00
Re: Basic tut on using C++ for GunZ
Quote:
Originally Posted by PenguinGuy
Hook ZChat::Input or use 0x3A6 or 0x3A8 (I forget which offset) for chat input. Of course, return it as a char. E.X;
(Code not tested)
Edit: Forgot the ClearInput :P: If you forget to add the "ClearInput", you will not be able to input another command.
Edit2: I plan on updating this tutorial tonight or tomorrow night on finding an using pointers, adding/removing functions in "theduel.exe", and creating custom commands in C++ and ASM.
1>c:\documents and settings\administrator\mijn documenten\visual studio 2008\projects\chat2\chat2\main.cpp(13) : error C2601: 'ChatInput' : local function definitions are illegal
1> c:\documents and settings\administrator\mijn documenten\visual studio 2008\projects\chat2\chat2\main.cpp(11): this line contains a '{' which has not yet been matched
1>c:\documents and settings\administrator\mijn documenten\visual studio 2008\projects\chat2\chat2\main.cpp(14) : error C3861: 'ZGetGameInterface': identifier not found
1>Build log was saved at "file://c:\Documents and Settings\Administrator\Mijn documenten\Visual Studio 2008\Projects\Chat2\Chat2\Debug\BuildLog.htm"
1>Chat2 - 2 error(s), 0 warning(s)
It´s probaly because of the ZGetGameInterface.
How to make it load the interface of in-game(Not lobby or room)
I posted it here because I think it get faster a respond to it.
1>c:\documents and settings\administrator\mijn documenten\visual studio 2008\projects\chat2\chat2\main.cpp(13) : error C2601: 'ChatInput' : local function definitions are illegal
1> c:\documents and settings\administrator\mijn documenten\visual studio 2008\projects\chat2\chat2\main.cpp(11): this line contains a '{' which has not yet been matched
1>c:\documents and settings\administrator\mijn documenten\visual studio 2008\projects\chat2\chat2\main.cpp(14) : error C3861: 'ZGetGameInterface': identifier not found
1>Build log was saved at "file://c:\Documents and Settings\Administrator\Mijn documenten\Visual Studio 2008\Projects\Chat2\Chat2\Debug\BuildLog.htm"
1>Chat2 - 2 error(s), 0 warning(s)
It´s probaly because of the ZGetGameInterface.
How to make it load the interface of in-game(Not lobby or room)
I posted it here because I think it get faster a respond to it.
Check line 11.
Also your code needs indentation for readability.
And, you need to define the address of ZGetGameInterface.