[Include] [INC]How to make an Anti Weaponhack using Callback Hooks
#1

Hello SA-MP Forum Community.
This is my first Tutorial on 'How to make an Anti Weaponhack using Callback Hooks'.

In this Tutorial you will learn:
- How to hook a Callback
- How to hook a Function
- How to protect your Server for Weapon Cheaters


Now let's get started.

First off all you will need an Texteditor or somethink you can make an .inc File

Now we are going to make our Include works so it cant included twice

pawn Код:
#if defined _AC_included
    #endinput
#endif
#define _AC_included
The next part is to make our Forwards so we can Script on it

pawn Код:
// Callback Hooks
forward AC_OnGameModeInit();
forward AC_OnGameModeExit();
forward AC_OnPlayerConnect(playerid);
forward AC_OnPlayerDisconnect(playerid, reason);
forward AC_OnPlayerSpawn(playerid);
forward AC_OnPlayerDeath(playerid, killerid, reason);
forward AC_OnPlayerKeyStateChange(playerid, newkeys, oldkeys);

//Function Hooks
forward AC_GivePlayerWeapon(playerid,weaponid,ammo);
forward AC_ResetPlayerWeapons(playerid);

forward OnPlayerWeaponHack(hackerid,weapon);
The only think we need is a bool which checks if he has the weapon or not

pawn Код:
new bool:Weapons[MAX_PLAYERS][47];
It's created a bool which holds the weapons which the player can use and return true, if he has the gun or false if he dont have the gun.
The MAX_PLAYERS stands for ALL Players so no-one can use the weapons from other players, the 47 stands for the weapons ( There are only 47 guns which the player can use ).

Now let's Hook all the publics:

pawn Код:
public OnGameModeInit()
{  
    for(new acplayer = 0; acplayer < MAX_PLAYERS; acplayer++)
    {
        if(!IsPlayerConnected(acplayer) && IsPlayerNPC(acplayer)) continue;
        {
            for(new aci=0;aci<47;aci++) Weapons[acplayer][aci] = false;
        }
    }
    return CallLocalFunction("AC_OnGameModeInit","");
}

public OnGameModeExit()
{
    for(new acplayer = 0; acplayer < MAX_PLAYERS; acplayer++)
    {
        if(!IsPlayerConnected(acplayer) && IsPlayerNPC(acplayer)) continue;
        {
            for(new aci=0;aci<47;aci++) Weapons[acplayer][aci] = false;
        }
    }
    return CallLocalFunction("AC_OnGameModeExit","");
}

public OnPlayerConnect(playerid)
{
    for(new aci=0;aci<47;aci++) Weapons[playerid][aci] = false;
    return CallLocalFunction("AC_OnPlayerConnect","i",playerid);
}

public OnPlayerDisconnect(playerid, reason)
{  
    for(new aci=0;aci<47;aci++) Weapons[playerid][aci] = false;
    return CallLocalFunction("AC_OnPlayerDisconnect","ii",playerid,reason);
}

public OnPlayerSpawn(playerid)
{
    for(new aci=0;aci<47;aci++) Weapons[playerid][aci] = false;
    return CallLocalFunction("AC_OnPlayerSpawn","i",playerid);
}

public OnPlayerDeath(playerid, killerid, reason)
{
    for(new aci=0;aci<47;aci++) Weapons[playerid][aci] = false;
    return CallLocalFunction("AC_OnPlayerDeath","iii",playerid, killerid, reason);
}

public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
    new ackey = GetPlayerState(playerid); // Get's the current state of the Player
    if(newkeys & KEY_FIRE) // if he shoot with the gun
    {
        if(ackey == PLAYER_STATE_DRIVER || ackey == PLAYER_STATE_ONFOOT) // if he's driver of a vehicle or if he on foot?
        {
            new acweapon = GetPlayerWeapon(playerid); // Get's the weapon the player is holding
            if(Weapons[playerid][acweapon] == false && acweapon !=0 && acweapon !=46) // if he isnt allowed to use this gun, and isnt it weap id 0 (hand or 46 prarshute)
            {
                OnPlayerWeaponHack(playerid,acweapon); // Call this Callback ( the player is hacking a gun )
                return 1;
            }
        }
    }
    return CallLocalFunction("AC_OnPlayerKeyStateChange","iii",playerid, newkeys, oldkeys);
}
Ok what did the Codes do ?

public OnGameModeInit() and public OnGameModeExit() resets the gun veriables on ServerRestart
OnPlayerConnect(playerid) and OnPlayerDisconnect(playerid) resets the gun veriables if he leave the server or connect to the server
OnPlayerSpawn resets the gun veriables if he is spawning
OnPlayerDeath is called if the player died and resets the gun veriables too

Now let's start hooking the Publics:

pawn Код:
/*=============== Public Hooking ===============*/

#if defined _ALS_OnGameModeInit
    #undef OnGameModeInit
#else
    #define _ALS_OnGameModeInit
#endif

#define OnGameModeInit          AC_OnGameModeInit
/*==============================================*/

#if defined _ALS_OnGameModeExit
    #undef OnGameModeExit
#else
    #define _ALS_OnGameModeExit
#endif

#define OnGameModeExit          AC_OnGameModeExit
/*==============================================*/

#if defined _ALS_OnPlayerConnect
    #undef OnPlayerConnect
#else
    #define _ALS_OnPlayerConnect
#endif

#define OnPlayerConnect         AC_OnPlayerConnect
/*==============================================*/

#if defined _ALS_OnPlayerDisconnect
    #undef OnPlayerDisconnect
#else
    #define _ALS_OnPlayerDisconnect
#endif

#define OnPlayerDisconnect      AC_OnPlayerDisconnect
/*==============================================*/

#if defined _ALS_OnPlayerSpawn
    #undef OnPlayerSpawn
#else
    #define _ALS_OnPlayerSpawn
#endif

#define OnPlayerSpawn           AC_OnPlayerSpawn
/*==============================================*/

#if defined _ALS_OnPlayerDeath
    #undef OnPlayerDeath
#else
    #define _ALS_OnPlayerDeath
#endif

#define OnPlayerDeath           AC_OnPlayerDeath
/*==============================================*/
#if defined _ALS_OnPlayerKeyStateChange
    #undef OnPlayerKeyStateChange
#else
    #define _ALS_OnPlayerKeyStateChange
#endif

#define OnPlayerKeyStateChange  AC_OnPlayerKeyStateChange
it's checks if the callback is defined and undefine them, then it redefine the publics and hook it

What we have forgotten ? Yes!, the GivePlayerWeapon and ResetPlayerWeapon part.

pawn Код:
public AC_ResetPlayerWeapons(playerid)
{
    for(new aci=0;aci<47;aci++) Weapons[playerid][aci] = false;
    return ResetPlayerWeapons(playerid);
}

public AC_GivePlayerWeapon(playerid,weaponid,ammo)
{
    Weapons[playerid][weaponid] = true;
    return GivePlayerWeapon(playerid,weaponid,ammo);
}
Now if the Weapons will be resetted using ResetPlayerWeapons the gun veriables will be resseted
If we give a player a weapon using GivePlayerWeapon, the veriable from the weaponid will be activated, so it is true!

pawn Код:
#define GivePlayerWeapon AC_GivePlayerWeapon
#define ResetPlayerWeapons AC_ResetPlayerWeapons
Okay now you can use the OnPlayerWeaponHack(hackerid,weapon) in your GameMode if you have included your .inc file in ur script under samp inc!!

Warning: if you dont put OnPlayerWeaponHack in your Gamemode you'll get errors!

Sorry for my bad English i comes from Germany.
Hope you liked this Tutorial, please Comment and ye, have a nice day!
Reply
#2

Well done,i'm goint to test it.
Reply
#3

nice but your ALS code is kinda poor...
check here https://sampforum.blast.hk/showthread.php?tid=85907

you should make vars and hold if the next function really exist
if so call it,
your way your calling the function every time if it exists or not.


this is closer to what it should look like, (without the weapon code)

pawn Код:
static gAC_HasCB[6];

//--------------OnGameModeInit Hook-------------------

public OnGameModeInit()
{
    //your OnGameModeInit pre code here

    //function hook checks
    gAC_HasCB[0] = funcidx("AC_OnGameModeExit") != -1;
    gAC_HasCB[1] = funcidx("AC_OnPlayerConnect") != -1;
    gAC_HasCB[2] = funcidx("AC_OnPlayerDeath") != -1;
    gAC_HasCB[3] = funcidx("AC_OnPlayerDisconnect") != -1;
    gAC_HasCB[4] = funcidx("AC_OnPlayerKeyStateChange") != -1;
    gAC_HasCB[5] = funcidx("AC_OnPlayerSpawn") != -1;
    if (funcidx("AC_OnGameModeInit") != -1)
    {
        CallLocalFunction("AC_OnGameModeInit", "");
    }
    //your OnGameModeInit post code here

    return 1;
}

#if defined _ALS_OnGameModeInit
    #undef OnGameModeInit
#else
    #define _ALS_OnGameModeInit
#endif
#define OnGameModeInit AC_OnGameModeInit
forward AC_OnGameModeInit();



//--------------OnGameModeExit Hook-------------------

public OnGameModeExit()
{
    //your OnGameModeExit code here

    if (gAC_HasCB[0])
    {
        return CallLocalFunction("AC_OnGameModeExit", "");
    }
    return 1;
}
#if defined _ALS_OnGameModeExit
    #undef OnGameModeExit
#else
    #define _ALS_OnGameModeExit
#endif
#define OnGameModeExit AC_OnGameModeExit
forward AC_OnGameModeExit();



//--------------OnPlayerConnect Hook-------------------

public OnPlayerConnect(playerid)
{
    //your OnPlayerConnect code here

    if (gAC_HasCB[1])
    {
        return CallLocalFunction("AC_OnPlayerConnect", "i",playerid);
    }
    return 1;
}
#if defined _ALS_OnPlayerConnect
    #undef OnPlayerConnect
#else
    #define _ALS_OnPlayerConnect
#endif
#define OnPlayerConnect AC_OnPlayerConnect
forward AC_OnPlayerConnect(playerid);



//--------------OnPlayerDeath Hook-------------------

public OnPlayerDeath(playerid, killerid,  reason)
{
    //your OnPlayerDeath code here

    if (gAC_HasCB[2])
    {
        return CallLocalFunction("AC_OnPlayerDeath", "iii",playerid, killerid,  reason);
    }
    return 1;
}
#if defined _ALS_OnPlayerDeath
    #undef OnPlayerDeath
#else
    #define _ALS_OnPlayerDeath
#endif
#define OnPlayerDeath AC_OnPlayerDeath
forward AC_OnPlayerDeath(playerid, killerid,  reason);



//--------------OnPlayerDisconnect Hook-------------------

public OnPlayerDisconnect(playerid,  reason)
{
    //your OnPlayerDisconnect code here

    if (gAC_HasCB[3])
    {
        return CallLocalFunction("AC_OnPlayerDisconnect", "ii",playerid,  reason);
    }
    return 1;
}
#if defined _ALS_OnPlayerDisconnect
    #undef OnPlayerDisconnect
#else
    #define _ALS_OnPlayerDisconnect
#endif
#define OnPlayerDisconnect AC_OnPlayerDisconnect
forward AC_OnPlayerDisconnect(playerid,  reason);



//--------------OnPlayerKeyStateChange Hook-------------------

public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
    //your OnPlayerKeyStateChange code here

    if (gAC_HasCB[4])
    {
        return CallLocalFunction("AC_OnPlayerKeyStateChange", "iii",playerid, newkeys, oldkeys);
    }
    return 1;
}
#if defined _ALS_OnPlayerKeyStateChange
    #undef OnPlayerKeyStateChange
#else
    #define _ALS_OnPlayerKeyStateChange
#endif
#define OnPlayerKeyStateChange AC_OnPlayerKeyStateChange
forward AC_OnPlayerKeyStateChange(playerid, newkeys, oldkeys);



//--------------OnPlayerSpawn Hook-------------------

public OnPlayerSpawn(playerid)
{
    //your OnPlayerSpawn code here

    if (gAC_HasCB[5])
    {
        return CallLocalFunction("AC_OnPlayerSpawn", "i",playerid);
    }
    return 1;
}
#if defined _ALS_OnPlayerSpawn
    #undef OnPlayerSpawn
#else
    #define _ALS_OnPlayerSpawn
#endif
#define OnPlayerSpawn AC_OnPlayerSpawn
forward AC_OnPlayerSpawn(playerid);

also redefining native functions you should also be using some sort of ALS
because if some other include try to redefine then it will break the code.



regards, J5
Reply
#4

Hmm thanks for the tip but ye i have never usedthe funcidk
Reply
#5

You should ignore the parachute, fist (weapon id 0) and any other weapon wich is acquired without hacking or giving it script-side.
Reply
#6

Good tutorial, a lot more could be explained. You should go more in-depth on what callback hooking is, be very helpful for those who want to know.
Reply
#7

Quote:
Originally Posted by Tigerkiller
Посмотреть сообщение
Hmm thanks for the tip but ye i have never usedthe funcidk
well i just gave you the hole skeleton of what you need. You could in 5 mins fix this.
if your gonna teach you should try to teach the best practices,
This is why i dont write tutorials. Because I dont know enough on a unique subject
to write about it and teach others.

otherwise everyone who reads this and dont know any better
will think that's the best practice for using ALS code and will release their mods
with the same not so great ALS code.

just think about the
new str[256];

and how many STILL think its okay to use when their str is actually "hi"



I do like this tutorial though!!! so please dont take what i said as rude,
just like to see you improve your als code.


regards,
Reply
#8

Hmm but why hook the function on the same way as for example OnGameModeInit ?
why dont define it ? ex: #define Func My_Func ?
can this causes errors or bugs or somethink else ?
Reply
#9

yes, because if someone else hooks it also in their include it will break their code or your code.
this is the hole reason behind ALS hooking method


without als if they try to define this and yours is already done
they will get an error stating a redefinition has taken place.

with als, you can check if someone else has already hooked this function
if so undefine else just define.

hope that made sense,
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)