Portal SAMP
[Tutorial] Ant-Money e Ant-Hack - Versão de Impressão

+- Portal SAMP (https://portalsamp.com)
+-- Fórum: SA-MP (https://portalsamp.com/forumdisplay.php?fid=5)
+--- Fórum: Guias e Tutoriais (https://portalsamp.com/forumdisplay.php?fid=7)
+--- Tópico: [Tutorial] Ant-Money e Ant-Hack (/showthread.php?tid=3008)



Ant-Money e Ant-Hack - DuduPlay16 - 19/11/2022

Bom, irei deixar um tutorial bem básico, porém pode ser útil para alguém, não sei se já tem algum tutorial ensinando a fazer, mas irei deixar o meu abaixo.
O sistema é um Anti-Money (Hack de grana) e um Anti-Hack (Aqueles que tentar usar por exemplo um JetPack dentro do Servidor, esse é bem útil para Servidores RPG).

O sistema nada mais é que uma verificação, começando pelo sistema de Anti-Money.

Primeiramente seu sistema de grana precisa ser armazenado em uma variável (Creio que todos já usam dessa forma).

Mais como assim em uma variável? - Ao invés de usarmos a função nativa do samp ( GivePlayerMoney(playerid, money): ou GetPlayerMoney(playerid) )
Iremos usar a variável da sua enum PlayerInfo ( Exemplo de uma - Player[playerid][pDinheiro] ) isso é de acordo com sua enum, mas creio que todos já sabem essa parte.

Tendo esse requisito acima rsrs vamos partir para o sistema.

Vá no seu sistema de spawn, aquele que carrega os dados da sua conta e spawna o jogador no servidor após digitar sua senha corretamente, e crie um SetTimerEx
Código:
SetTimerEx("TimerHack", 1000, false, "i", playerid);

Criamos um timer, que será chamado em 1 segundo.

Uma explicação básica.
TimerHack - Nome dado a função que vai ser chamada, quando criarmos a public ela irá se chamar TimerHack ( public TimerHack(playerid) )
1000 - Isso é o tempo em milissegundos (1 segundo é igual a 1000 em milissegundos), porém irei deixar uma forma mais fácil de fazer isso mais abaixo
false - Repetição, false irá chamar a função apenas 1 vez, enquanto true ficará chamando sem parar de 1 em 1 segundo, ou o tempo que você definir. 

Ah mais o correto não seria ela ficar repetindo para identificar aquele que tá usando o hack dentro do Servidor? 
Sim, porém irei ensinar uma forma mais fácil.

Se ao invés de false fosse true, teríamos que criar o SetTimer dentro de uma variável, para quando o jogador saísse do Servidor nos darmos um KillTimer (Finalizar a execução do SetTimerEx).

Como assim criar o SetTimer dentro de uma variável?

Exemplo
Código:
// Topo do gm
new THack[MAX_PLAYERS];
THack[playerid] = SetTimerEx("TimerHack", 1000, false, "i", playerid);

Mais para quer fazer isso? - Para quando o jogador deslogar do Servidor a timer ser encerrada, e a função KillTimer(id) identifica qual timer você quer encerrar através do ID dela, que no caso seria KillTimer(THack[playerid]);

E o que acontece seu criar dessa forma
Código:
THack[playerid] = SetTimerEx("TimerHack", 1000, true, "i", playerid);
Ou dessa forma
Código:
SetTimerEx("TimerHack", 1000, true, "i", playerid);

Na primeira opção você a criou para repetir de 1 em 1 segundo sem parar, porém, você criou a mesma dentro de uma variável, e tem a possibilidade de dar um KillTimer quando o jogador desconectar o Servidor
Código:
public OnPlayerDisconnect(playerid, reason)
{
     KillTimer(THack[playerid]);
     return true;
}

Já na segunda opção você não a criou dentro de uma variável, por isso não poderá encerrar a mesma, e agora ela ficará repetindo mesmo se o jogador deslogar, e quando alguém conectar novamente usando o mesmo id que você estava dentro do Servidor, esse timer vai dobrar e vai ficar sendo chamado 2 vezes em seguida, e assim continuará caso deslogue novamente do Servidor e conecte com o mesmo id, ele vai só duplicando pois está sendo iniciado, porém não está sendo encerrado.

Por isso ao invés de true eu usei false e você já vão entender o porquê

Após ter criado o timer no seu sistema de spawn vamos criar a public onde irá conter nossas funções

Código:
forward TimerHack(playerid);
public TimerHack(playerid)
{
     if(!IsPlayerConnected(playerid))
          return true;

     ResetPlayerMoney(playerid);
     GivePlayerMoney(playerid, Sua variável do dinheiro);
     SetTimerEx("TimerHack", 1000, false, "i", playerid);
     return true;
}

Oque fizemos?
Criamos a public acima com o mesmo nome do timer para ser chamado, e colocamos nosso sistema abaixo

if(!IsPlayerConnected(playerid)); isso checa se o jogador ainda está conectado, aí que está nossa jogada. > ! < no início, significa não conectado, ou seja - Se o jogador não estiver conectado oq acontecerá? e a função resposta digitada abaixo foi return true; - ou seja, se o jogador for igual a desconectado não deixamos executar a função abaixo, que no caso é nosso sistema de anti-money

ResetPlayerMoney - Resetamos o dinheiro dele da função nativa do samp
GivePlayerMoney = Setamos o valor correto que ele tem de dinheiro salvo na variavel da grana

Após finalizar o sistema de hack que somente é essas duas funções kkkk vocês viram que eu executei o timer outra vez? Sim, lembra que quando criamos o timer lá em cima no sistema de spawn, definimos a repetição dele como false (Repetir somente uma vez) ou seja, quando o código foi chamado, era pra o timer ter finalizado, mais como eu coloquei o timer novamente no sistema, assim que ele executou o código, ele chamou o timer novamente, e assim tornando um loop, e o !IsPlayerConnected está  para pôr um fim no loop, pois se a função for chamada e o jogador estiver desconectado do Servidor, ele não deixará executar o código abaixo, e assim evitará o timer ser chamado mais uma vez.

Esse é um macete que uso para timer curtos, não aconselho usar dessa forma em timers grandes, pois 1 segundo como é rápido, dá tempo de ser executado antes de um jogador logar novamente usando o id do jogador anterior, e assim evitar do timer ficar duplicado

Agora vamos para o anti-hack, vou usar um exemplo de hack puxando um JetPack

Na mesma public que criamos para o antimoney

Código:
forward TimerHack(playerid);
public TimerHack(playerid)
{
     if(!IsPlayerConnected(playerid))
          return true;

     ResetPlayerMoney(playerid);
     GivePlayerMoney(playerid, Sua variável do dinheiro);

     // Sistema anti-hack
     if(GetPlayerSpecialAction(playerid) == SPECIAL_ACTION_USEJETPACK)
     {
          if(VariavelAdmin[playerid] == 0 && VariavelVip[playerid] == 0)
          {
               Ban(playerid);
               return true;
          }
     }
     SetTimerEx("TimerHack", 1000, false, "i", playerid);
     return true;
}

Oq fizemos? 
if(GetPlayerSpecialAction(playerid) == SPECIAL_ACTION_USEJETPACK) - Aqui checamos se o jogador está usando jetpack ( [b]SPECIAL_ACTION_USEJETPACK significa que sim )
if(VariavelAdmin[playerid] == 0 && VariavelVip[playerid] == 0) - Aqui fizemos uma outra checagem, verificamos se o jogador é VIP ou Admin ( Como vocês podem ver a variavel do Admin e VIP estão com igual == 0 > igual a 0, isso significa que se o jogador não for vip e nem admin o sistema abaixo será executado, que no caso é o BAN, você poderá alterar para KICK ou colocar seu sistema de banimento abaixo

[/b]
Ahh, e deixando a forma fácil de definir segundos no settimer

Código:
//Topo do GM
#define Minutos(%0) (1000 * %0 * 60)
#define Horas(%0) (1000 * %0 * 60 * 60)
#define Segundos(%0) (1000 * %0)
#define Dias(%0) (1000 * %0 * 60 * 60  * 24)


Pronto, agora ao invés de colocar 1000 (1 segundo e milissegundos), é só usar
Código:
SetTimerEx("SeuTimer", Segundos(1), false, "i", playerid");[/size][size=medium][/size]
SetTimerEx("SeuTimer", Minutos(2), false, "i", playerid");

Espero que gostem do tutorial, é meu primeiro tutorial aqui na comunidade, e peço perdão se deixei a desejar em alguma coisa, Deus Abençoe a todos!


RE: Ant-Money e Ant-Hack - White_Blue - 22/11/2022

+REP! Poderia ser mais completo sobre anti-money hack, o tutorial fala mais sobre timers para ser sincero. Mas a intenção é boa.



RE: Ant-Money e Ant-Hack - Mateus Lima - 22/11/2022

(19/11/2022 03:10)DuduPlay16 Escreveu: Bom, irei deixar um tutorial bem básico, porém pode ser útil para alguém, não sei se já tem algum tutorial ensinando a fazer, mas irei deixar o meu abaixo.
O sistema é um Anti-Money (Hack de grana) e um Anti-Hack (Aqueles que tentar usar por exemplo um JetPack dentro do Servidor, esse é bem útil para Servidores RPG).

O sistema nada mais é que uma verificação, começando pelo sistema de Anti-Money.

Primeiramente seu sistema de grana precisa ser armazenado em uma variável (Creio que todos já usam dessa forma).

Mais como assim em uma variável? - Ao invés de usarmos a função nativa do samp ( GivePlayerMoney(playerid, money): ou GetPlayerMoney(playerid) )
Iremos usar a variável da sua enum PlayerInfo ( Exemplo de uma - Player[playerid][pDinheiro] ) isso é de acordo com sua enum, mas creio que todos já sabem essa parte.

Tendo esse requisito acima rsrs vamos partir para o sistema.

Vá no seu sistema de spawn, aquele que carrega os dados da sua conta e spawna o jogador no servidor após digitar sua senha corretamente, e crie um SetTimerEx
Código:
SetTimerEx("TimerHack", 1000, false, "i", playerid);

Criamos um timer, que será chamado em 1 segundo.

Uma explicação básica.
TimerHack - Nome dado a função que vai ser chamada, quando criarmos a public ela irá se chamar TimerHack ( public TimerHack(playerid) )
1000 - Isso é o tempo em milissegundos (1 segundo é igual a 1000 em milissegundos), porém irei deixar uma forma mais fácil de fazer isso mais abaixo
false - Repetição, false irá chamar a função apenas 1 vez, enquanto true ficará chamando sem parar de 1 em 1 segundo, ou o tempo que você definir. 

Ah mais o correto não seria ela ficar repetindo para identificar aquele que tá usando o hack dentro do Servidor? 
Sim, porém irei ensinar uma forma mais fácil.

Se ao invés de false fosse true, teríamos que criar o SetTimer dentro de uma variável, para quando o jogador saísse do Servidor nos darmos um KillTimer (Finalizar a execução do SetTimerEx).

Como assim criar o SetTimer dentro de uma variável?

Exemplo
Código:
// Topo do gm
new THack[MAX_PLAYERS];
THack[playerid] = SetTimerEx("TimerHack", 1000, false, "i", playerid);

Mais para quer fazer isso? - Para quando o jogador deslogar do Servidor a timer ser encerrada, e a função KillTimer(id) identifica qual timer você quer encerrar através do ID dela, que no caso seria KillTimer(THack[playerid]);

E o que acontece seu criar dessa forma
Código:
THack[playerid] = SetTimerEx("TimerHack", 1000, true, "i", playerid);
Ou dessa forma
Código:
SetTimerEx("TimerHack", 1000, true, "i", playerid);

Na primeira opção você a criou para repetir de 1 em 1 segundo sem parar, porém, você criou a mesma dentro de uma variável, e tem a possibilidade de dar um KillTimer quando o jogador desconectar o Servidor
Código:
public OnPlayerDisconnect(playerid, reason)
{
     KillTimer(THack[playerid]);
     return true;
}

Já na segunda opção você não a criou dentro de uma variável, por isso não poderá encerrar a mesma, e agora ela ficará repetindo mesmo se o jogador deslogar, e quando alguém conectar novamente usando o mesmo id que você estava dentro do Servidor, esse timer vai dobrar e vai ficar sendo chamado 2 vezes em seguida, e assim continuará caso deslogue novamente do Servidor e conecte com o mesmo id, ele vai só duplicando pois está sendo iniciado, porém não está sendo encerrado.

Por isso ao invés de true eu usei false e você já vão entender o porquê

Após ter criado o timer no seu sistema de spawn vamos criar a public onde irá conter nossas funções

Código:
forward TimerHack(playerid);
public TimerHack(playerid)
{
     if(!IsPlayerConnected(playerid))
          return true;

     ResetPlayerMoney(playerid);
     GivePlayerMoney(playerid, Sua variável do dinheiro);
     SetTimerEx("TimerHack", 1000, false, "i", playerid);
     return true;
}

Oque fizemos?
Criamos a public acima com o mesmo nome do timer para ser chamado, e colocamos nosso sistema abaixo

if(!IsPlayerConnected(playerid)); isso checa se o jogador ainda está conectado, aí que está nossa jogada. > ! < no início, significa não conectado, ou seja - Se o jogador não estiver conectado oq acontecerá? e a função resposta digitada abaixo foi return true; - ou seja, se o jogador for igual a desconectado não deixamos executar a função abaixo, que no caso é nosso sistema de anti-money

ResetPlayerMoney - Resetamos o dinheiro dele da função nativa do samp
GivePlayerMoney = Setamos o valor correto que ele tem de dinheiro salvo na variavel da grana

Após finalizar o sistema de hack que somente é essas duas funções kkkk vocês viram que eu executei o timer outra vez? Sim, lembra que quando criamos o timer lá em cima no sistema de spawn, definimos a repetição dele como false (Repetir somente uma vez) ou seja, quando o código foi chamado, era pra o timer ter finalizado, mais como eu coloquei o timer novamente no sistema, assim que ele executou o código, ele chamou o timer novamente, e assim tornando um loop, e o !IsPlayerConnected está  para pôr um fim no loop, pois se a função for chamada e o jogador estiver desconectado do Servidor, ele não deixará executar o código abaixo, e assim evitará o timer ser chamado mais uma vez.

Esse é um macete que uso para timer curtos, não aconselho usar dessa forma em timers grandes, pois 1 segundo como é rápido, dá tempo de ser executado antes de um jogador logar novamente usando o id do jogador anterior, e assim evitar do timer ficar duplicado

Agora vamos para o anti-hack, vou usar um exemplo de hack puxando um JetPack

Na mesma public que criamos para o antimoney

Código:
forward TimerHack(playerid);
public TimerHack(playerid)
{
     if(!IsPlayerConnected(playerid))
          return true;

     ResetPlayerMoney(playerid);
     GivePlayerMoney(playerid, Sua variável do dinheiro);

     // Sistema anti-hack
     if(GetPlayerSpecialAction(playerid) == SPECIAL_ACTION_USEJETPACK)
     {
          if(VariavelAdmin[playerid] == 0 && VariavelVip[playerid] == 0)
          {
               Ban(playerid);
               return true;
          }
     }
     SetTimerEx("TimerHack", 1000, false, "i", playerid);
     return true;
}

Oq fizemos? 
if(GetPlayerSpecialAction(playerid) == SPECIAL_ACTION_USEJETPACK) - Aqui checamos se o jogador está usando jetpack ( [b]SPECIAL_ACTION_USEJETPACK significa que sim )
if(VariavelAdmin[playerid] == 0 && VariavelVip[playerid] == 0) - Aqui fizemos uma outra checagem, verificamos se o jogador é VIP ou Admin ( Como vocês podem ver a variavel do Admin e VIP estão com igual == 0 > igual a 0, isso significa que se o jogador não for vip e nem admin o sistema abaixo será executado, que no caso é o BAN, você poderá alterar para KICK ou colocar seu sistema de banimento abaixo

[/b]
Ahh, e deixando a forma fácil de definir segundos no settimer

Código:
//Topo do GM
#define Minutos(%0) (1000 * %0 * 60)
#define Horas(%0) (1000 * %0 * 60 * 60)
#define Segundos(%0) (1000 * %0)
#define Dias(%0) (1000 * %0 * 60 * 60  * 24)


Pronto, agora ao invés de colocar 1000 (1 segundo e milissegundos), é só usar
Código:
SetTimerEx("SeuTimer", Segundos(1), false, "i", playerid");[/size][size=medium][/size]
SetTimerEx("SeuTimer", Minutos(2), false, "i", playerid");

Espero que gostem do tutorial, é meu primeiro tutorial aqui na comunidade, e peço perdão se deixei a desejar em alguma coisa, Deus Abençoe a todos!

Olá maninho, parabéns pela contribuição! Eu particularmente não vejo necessidade de ficar resetando o money do coitado a cada 1 segundo, acho mais pratico você apenas verificar se o dinheiro em game condiz com o valor da variável "Dinheiro" e caso não tenha plena confiança nessa técnica aconselho que adminstre o movimento do dinheiro do jogador, sendo assim tendo controle sobre funções e usando de forma plena a variável.

Exemplo 1:
Código:
stock IsPlayerSuspectMoney(playerid)
{
    if(GetPlayerMoney(playerid) != PlayerInfo[playerid][pDinheiro])return true;
    return false;
}



Exemplo bem pratico (SERVER:: = macro de forward e public):

SERVER::ANTCHEAT_GetPlayerMoney(playerid)return PlayerInfo[playerid][pDinheiro];
SERVER::ANTCHEAT_ResetPlayerMoney(playerid)return PlayerInfo[playerid][pDinheiro] = 0;
SERVER::ANTCHEAT_GivePlayerMoney(playerid, money)return GivePlayerMoney(playerid, (PlayerInfo[playerid][pDinheiro]+=money)); 

#define GetPlayerMoney ANTCHEAT_GetPlayerMoney
#define ResetPlayerMoney ANTCHEAT_ResetPlayerMoney
#define GivePlayerMoney ANTCHEAT_GivePlayerMoney

(22/11/2022 14:46)White_Blue Escreveu:
+REP! Poderia ser mais completo sobre anti-money hack, o tutorial fala mais sobre timers para ser sincero. Mas a intenção é boa.

Pior que sim, enfim oque importa é a intenção.


RE: Ant-Money e Ant-Hack - DuduPlay16 - 26/11/2022

(22/11/2022 14:46)White_Blue Escreveu:
+REP! Poderia ser mais completo sobre anti-money hack, o tutorial fala mais sobre timers para ser sincero. Mas a intenção é boa.

Obg mano, vou tentar fazer melhor na próxima, como falei foi meu primeiro tutorial, mais vou tentar melhorar nos próximos!


RE: Ant-Money e Ant-Hack - Carlos Victor - 19/12/2022

Legal a iniciativa, portanto cria timer para cada jogador, dependendo do tanto de jogadores tem em um servidor, vai ocasionar em um uso de processamento alto, causando lag no servidor.

Você poderia simplesmente criar um timer global e fazer um loop dentro dessa timer, de forma simples, fácil e rápido.
Código:
public OnGameModeInit()
{
    SetTimer("OnVerifyMoneyHack", 1000, true);
    return 1;
}

forward OnVerifyMoneyHack();
public OnVerifyMoneyHack()
{
    for(new i = 0; i < MAX_PLAYERS; i++) if(IsPlayerConnected(i)) {

        if(GetPlayerMoney(i) != PlayerInfo[i][pMoney])
        {
            ResetPlayerMoney(i);
            GivePlayerMoney(i, PlayerInfo[i][pMoney]);
        }

    }
    return 1;
}

Dessa forma, além de diminuir o processamento, vai pegar todos os jogadores conectados, você pode também adicionar novas verificações, novos métodos, e também usar um looping mais otimizado, usar um foreach por exemplo.


RE: Ant-Money e Ant-Hack - White_Blue - 19/12/2022

(19/12/2022 21:23)Carlos Victor Escreveu: Legal a iniciativa, portanto cria timer para cada jogador, dependendo do tanto de jogadores tem em um servidor, vai ocasionar em um uso de processamento alto, causando lag no servidor.

Você poderia simplesmente criar um timer global e fazer um loop dentro dessa timer, de forma simples, fácil e rápido.
Código:
public OnGameModeInit()
{
    SetTimer("OnVerifyMoneyHack", 1000, true);
    return 1;
}

forward OnVerifyMoneyHack();
public OnVerifyMoneyHack()
{
    for(new i = 0; i < MAX_PLAYERS; i++) if(IsPlayerConnected(i)) {

        if(GetPlayerMoney(i) != PlayerInfo[i][pMoney])
        {
            ResetPlayerMoney(i);
            GivePlayerMoney(i, PlayerInfo[i][pMoney]);
        }

    }
    return 1;
}

Dessa forma, além de diminuir o processamento, vai pegar todos os jogadores conectados, você pode também adicionar novas verificações, novos métodos, e também usar um looping mais otimizado, usar um foreach por exemplo.

Funcionaria em teoria, entretanto, é mais otimizado como dito acima você usar `foreach` ao invés do loop `for` comum e também é mais otimizado você não chamar o timer na OnGameModeInit, mas sim criar um playertimer e chamar na OnPlayerConnect e depois executar um KillTimer na OnPlayerDisconnect.