Stratégies pour vaincre les éditeurs de mémoire pour tricherie - Jeux de bureau [fermé]

35

Je suppose que nous parlons de jeux de bureau - quelque chose que le joueur télécharge et exécute sur son ordinateur local. Nombreux sont les éditeurs de mémoire qui vous permettent de détecter et geler des valeurs, telles que la santé de votre lecteur.

Comment empêchez-vous de tricher via la modification de mémoire? Quelles stratégies sont efficaces pour lutter contre ce type de tricherie?

Pour référence, je sais que les joueurs peuvent: - Rechercher quelque chose par valeur ou par plage - Rechercher quelque chose qui a changé de valeur - Définir les valeurs de la mémoire - Figer les valeurs de la mémoire

Je cherche des bons. Deux que j'utilise et qui sont médiocres sont:

  • Affichage des valeurs sous forme de pourcentage au lieu du nombre (par ex. 46/50 = 92% de santé)
  • Une classe de bas niveau qui contient des valeurs dans un tableau et les déplace à chaque changement. (Par exemple, au lieu d'un int, j'ai une classe qui est un tableau d'ints, et chaque fois que la valeur change, j'utilise un élément de tableau différent, choisi au hasard pour contenir la valeur)

Le jeu est hors ligne, gratuit et solo.

Edit: pour la postérité, j'ai résolu ceci (en C #) et posté ma solution ici , sur mon blog.

cendres999
la source

Réponses:

21

Une autre possibilité (pour les valeurs entières) est d’avoir une deuxième variable membre qui contient le complément au niveau du bit d’une variable existante.

Alors imaginez que vous avez health, vous auriez aussi healthComplement. Votre implémentation pourrait ressembler à ceci:

// setter sets value and complement
void setHealth(int value){
    health = value;
    healthComplement = ~value;
}

// getter checks if value was changed outside of the setter
int getHealth(){
    if(value != ~healthComplement){
        // launch some cheat-counter-measure, like crashing the game?
        exit;
    }
    return health;
}

Quelqu'un qui veut tricher devrait mettre la santé et la santé Complément correctement, sinon le jeu planterait.

Je pense que c'est un peu inutile d'essayer d'empêcher des choses comme ça. Les gens ont créé avec succès des hacks / cheats pour des choses beaucoup plus complexes et cela obscurcit inutilement votre code ou rend votre jeu moins performant.

bummzack
la source
12

Voici un stratagème que j'ai imaginé quand quelqu'un le réclamait sur un tableau il y a longtemps. L'utilisation de pourcentages ou de variables doublées ne fonctionne pas vraiment, car vous pouvez rechercher des valeurs "quelconques" et les figer.

Au lieu de cela, créez un monstre d'un type de données.

En gros, stockez vos valeurs importantes en tant que structure avec:

  • 32 pointeurs en bits
  • Pour une lecture rapide, demandez à la structure d'inclure la valeur actuelle en tant que simple int

Pour la manipulation, collectez la valeur actuelle à partir des bits alloués séparément (qui peuvent être des entrées true / false), modifiez la valeur, puis enregistrez-les à nouveau.

Voici le bit méchant: chaque fois que vous manipulez la valeur, libérez et allouez les bits à nouveau. L'allocation doit se faire dans un ordre aléatoire , de sorte que les données sautent en mémoire et ne peuvent pas être gelées facilement.

Des sauvegardes supplémentaires consisteraient à stocker des sommes de contrôle des valeurs (ainsi que l'int "plaine" int) et à les comparer également lors des appels de manipulation. Si une incompatibilité est trouvée, faites quelque chose de subtil, tel que supprimer une clé aléatoire nécessaire pour déverrouiller les portes afin de progresser dans le jeu.

Edit: pour que la mémoire continue de bouger, assurez-vous d’allouer les nouveaux "bits" avant de libérer les anciens.

Edit: pour les jeux multijoueurs, il est également possible de sérialiser la structure de données, de la compresser et de l'envoyer sur le réseau. Ce n’est pas l’utilisation la plus efficace du réseau, mais bien plus difficile à comprendre grâce au reniflement de paquets.

Jari Komppa
la source
9

Que diriez-vous de stocker la santé complétée par une valeur aléatoire générée chaque fois que vous la stockez. Cela vaincrait au moins le mécanisme simple consistant à rechercher des valeurs croissantes / décroissantes en mémoire pour retrouver la santé.

class Player
{
  int m_Health;
  int m_RandomHealth;
  Random m_Rnd = new Random();

  public int Health {
    get
    {
      return m_Health ^ m_RandomHealth;
    }

    set
    {
      m_RandomHealth = m_Rnd.Next();
      m_Health = value ^ m_RandomHealth;
    }
  }
}

En outre, vous souhaiterez peut-être réinitialiser la valeur de chaque image, même si l'intégrité ne change pas. Cela empêchera les personnes de rechercher des adresses modifiées lorsque leur état de santé change et qui restent inchangées lorsque leur état de santé reste identique.

Bonus: créez un nouvel objet chaque fois qu'il change afin que l'adresse mémoire change, et définissez la santé pour modifier le nombre aléatoire, la valeur mémorisée et l'adresse en mémoire à chaque lecture :

class Player
{
  int [] m_HealthArray; // [0] is random int, [1] is xored health
  Random m_Rnd = new Random();

  public Player() {
    this.Health = 100;
  }

  public int Health {
    get
    {
      int health = m_HealthArray[0] ^ m_HealthArray[1];
      Health = health; // reset to move in memory and change xor value
      return health;
    }

    set
    {
      m_HealthArray = new int[2];
      m_HealthArray[0] = m_Rnd.Next();
      m_HealthArray[1] = m_HealthArray[0] ^ value;
    }
  }
}
Jason Goemaat
la source
8

Bien que j'aie fait le premier commentaire en questionnant le point de dégrader l'expérience d'une partie de votre auditoire sans aucun gain apparent, je la trouve quand même intéressante du point de vue technique.

Je viens juste d'avoir cette idée: ce que les tricheurs font, c'est trouver des valeurs qui changent et les figer. La recherche n'aurait alors lieu qu'entre des morts ou des événements qui ont changé la santé du joueur. De plus, le tricheur pourrait affiner la recherche en filtrant ce qui a changé quand il "ne mourait pas".

Que se passe-t-il si le compteur "santé" change tout le temps? Faites-en un pointeur et réaffectez-le toutes les images ou toutes les N images si les performances sont trop importantes. Ou bien XOR avec une valeur aléatoire qui change chaque image (XORing à nouveau avec la même valeur pour le déchiffrement avant le chiffrement avec une nouvelle valeur aléatoire).

Si vous avez d'autres données dans le jeu qui changent également tout le temps (y compris les positions x et y du personnage du joueur ou le compteur de temps), il pourrait être plus difficile de déterminer laquelle des données changeantes correspond à la santé. Et geler l’ensemble de l’état du jeu n’est pas une solution pour le tricheur.

Pour tromper davantage, vous pouvez réellement stocker la santé dans une variable en écriture seule appelée un pot à miel.

Modifier :

Néanmoins, le tricheur peut essayer de trouver laquelle des variables qui change tout le temps est celle qui doit être figée par essais et erreurs. Une solution possible serait de coupler les variables ensemble.

Un exemple:

Au lieu de stocker la santé (h) et la position (x), vous les stockez dans deux variables a et b, à partir desquelles vous pourrez récupérer les valeurs ultérieurement:

a = x+h; b = x-h
x = (a+b)/2; h = (a-b)/2

De cette façon, si le tricheur ne gèle qu'un seul d'entre eux et déplace le personnage, la position est affectée et, en fonction de celui qui a été gelé, h devient négatif (mort instantanée). Vous pouvez basculer entre les formules ci-dessus et:

a = x-h; b = x+h
x = (a+b)/2; h = (b-a)/2

Dans des images consécutives, et vous garantissez que dans au plus 2 images après que l’une ou l’autre des variables ait été gelée, l’intégrité passera à 0 au moment où x change. Rappelez-vous que vous ne stockez que a et b. Combinez cela avec le XOR continu comme mentionné ci-dessus. Le résultat est un ensemble de variables qui modifient chaque image en valeurs apparemment aléatoires, et geler une seule d'entre elles ou un sous-ensemble de celles-ci ne produit que des effets secondaires indésirables dans le jeu, dont la mort instantanée.

CeeJay
la source
7

Je pense qu'une option possible pourrait fonctionner (je ne connais pas trop ces outils de triche): ne le cachez pas. Effectuez vos opérations et attendez certains résultats. Après l’opération (éventuellement l’image suivante), vérifiez que les résultats sont conformes à vos attentes. Si vous soustrayez la santé et que vous la vérifiez, alors que la santé n’a jamais changé, vous pouvez être à peu près sûr (à condition de ne pas avoir un bogue obscur) qu’elle était verrouillée.

Si vous détectez une fraude, vous êtes maintenant libre de modifier les règles du jeu à votre guise, si tel est votre intention. Si votre intention est d'ignorer la triche et de laisser le jeu continuer à fonctionner, réaffectez la santé ailleurs dans la mémoire et modifiez vos pointeurs de sorte que la nouvelle valeur soit utilisée et que l'ancienne soit ignorée. Répétez ad infinitum.

James
la source
6

Toute tentative de simple obscurcissement est vouée à l'échec en théorie, mais en pratique, il suffit de rendre suffisamment difficile la résolution du défi pour que le défi devienne moins amusant que de réussir le match. Je ne sais pas quel est votre jeu, je ne risquerai donc pas de suggérer des méthodes d’obscurcissement des données, encore moins parce que je pense qu’elles sont inutiles.

Cela dit, et vous ne l'aimerez probablement pas, je crois que vous recherchez une mémoire de rideau , qui est un concept de Trusted Computing .

sam hocevar
la source
3

Une technique très efficace utilisée par certains roguelikes (DoomRL, Brogue) consiste à masquer les variables réelles. Cela signifie qu'au lieu de montrer la santé comme "2/10", montrez-la comme "20%".

N'oubliez pas que la plupart des éditeurs de mémoire fonctionnent bien avec la recherche / filtrage de valeurs spécifiques. Si vous ne connaissez pas la valeur spécifique, vous pouvez toujours la retrouver (par exemple, rechercher des valeurs modifiées / diminuées après que l'état de santé du joueur ait baissé), bien que cela prenne beaucoup plus de temps.

Je suggère également une réaction anti-triche. Par exemple, si vous avez un jeu dans lequel le joueur subit des dégâts non positifs et que son état de santé ne baisse pas, vous pouvez le vérifier facilement et avec précision, en sachant que le joueur triche. Faites quelque chose d’intéressant, comme créer d’énormes ennemis autour de lui :)

cendres999
la source
2

Ecrivez un pilote en anneau 0 qui relie SSDT et les journaux / blocs lorsque ReadProcessMemory / WriteProcessMemory est appelé sur votre application. Il serait préférable de simplement vous connecter afin de pouvoir changer progressivement leur comportement de jeu au fil du temps plutôt que de simplement planter.

Doug-W
la source
On dirait que vous parlez de détails de mise en œuvre de bas niveau (API Windows?). Je vous pose des questions sur les stratégies générales de haut niveau.
ashes999
2

Pourquoi voudriez-vous empêcher les joueurs de se tromper (ce qui revient à tricher dans un jeu à joueur unique)? Dans un environnement multijoueur, il incombe au serveur de détecter les modifications non naturelles et de les contrer (généralement en ignorant l’entrée ou en bloquant complètement le coupable du serveur), mais dans un environnement à un seul joueur, rien ne se passe sauf que le tricheur se mauvais service.

IOW, à moins de créer un jeu multijoueur, c'est un gaspillage d'argent, et si vous envisagez de durcir le mauvais endroit.

jwenting
la source
2

Recherchez les outils de triche connus - et vérifiez fréquemment si l'un des plus courants est détecté en cours d'exécution (vérifiez les noms de processus?)

Si vous en détectez, laissez le joueur tricher (s'il est hors ligne, c'est sans danger), mais assurez-vous qu'aucun score / résultat ne sera publié sur un système de classement / résultat en ligne - faites-le simplement échouer en silence?

N'arrêtera pas les pirates plus déterminés, mais réduira le risque que des tricheurs plus occasionnels gâchent vos classements.

(Peut gêner les développeurs qui ont des outils de développement ouverts et minimisés à des fins légitimes et qui prennent une pause de jeu, cependant ...)

bluescrn
la source
7
J'étais un grand fan de Steam en tant que plate-forme de distribution et j'ai beaucoup joué à Team Fortress II il y a quelques années. Un soir, j'ai fait une pause dans une longue session de codage et laissé Visual Studio ouvert et un débogueur pendant que je jouais. Je me suis retrouvé banni de TF2 pour "triche". Pas d'appel, pas de cadre en place pour faire lever l'interdiction. Une "infraction" et il est permanent pour le compte. Je ne savais toujours pas pourquoi - et croyez-moi, j'étais furieux - si ce n'est que j'ai été plongé dans une FAQ qui disait qu'avoir un "éditeur de mémoire" ouvert pendant le jeu constituait une fraude et était ban-faisable. Sensationnel.
1

Je pense que la solution la plus simple consiste à implémenter une option de triche. Désactiver la notation en mode triche.

Une autre bonne idée, c'est que je ne sache pas comment vous allez mettre en œuvre. C’est d’arrêter le jeu quand il ya une variable de mémoire gelée ou quelque chose comme ça :)

Bonne chance)

HgMerk
la source
3
La mise en œuvre des astuces est une bonne option. Arrêter le jeu, pas tant que ça ... (imaginez si vous vous trompez et
arrêtez