不正行為のためのメモリエディタを無効にする戦略-デスクトップゲーム[終了]


35

私たちはデスクトップゲームについて話していると仮定しています-プレーヤーがローカルコンピューターでダウンロードして実行するものです。多くのプレーヤーは、プレーヤーの健康状態など、値を検出して凍結できるメモリエディターです。

メモリ変更による不正行為をどのように防止しますか?この種の不正行為と戦うにはどのような戦略が効果的ですか?

参考のために、プレイヤーができることを知っています:-値または範囲で何かを検索-値を変更したものを検索-メモリ値を設定-メモリ値を固定

良いものを探しています。私が使用している平凡な2つは次のとおりです。

  • 数値ではなくパーセンテージとして値を表示(例:46/50 = 92%ヘルス)
  • 配列内の値を保持し、変更のたびに値を移動する低レベルのクラス。(たとえば、intの代わりに、intの配列であるクラスがあり、値が変更されるたびに、ランダムに選択された別の配列項目を使用して値を保持します)

ゲームはオフラインで、無料でシングルプレイヤーです。

編集:後世のために、私は(C#で)これを解決し、私の解決策を掲載ここに私のブログ上で、。

回答:


21

別の可能性(整数値の場合)は、既存の変数のビット単位の補数を保持する2番目のメンバー変数を持つことです。

想像してみてくださいhealth、あなたも持っているでしょうhealthComplement。実装は次のようになります。

// 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;
}

チートしたい人は、ヘルスとhealthComplementを正しく設定する必要があります。そうしないと、ゲームがクラッシュします。

このようなことを防止しようとするのは無意味だと思います。人々ははるかに複雑なもののためのハック/チートを成功裏に作成し、コードを不必要に難読化したり、ゲームのパフォーマンスを悪化させたりしています。


12

誰かがずっと前にボードでそれを求めていたときに私が思いついた一つのスキームがあります。パーセンテージまたは2倍の変数を使用しても、「任意の」値を検索してフリーズできるため、実際には機能しません。

代わりに、データ型のモンスターを作成します。

基本的に、重要な値を以下の構造体として保存します。

  • ビットへの32ポインター
  • 読みやすくするために、構造体に現在の値を単純なintとして含めます

操作のために、個別に割り当てられたビット(true / false intの場合もあります)から現在の値を収集し、値を変更してから、それらを格納します。

ここに厄介なビットがあります:値を操作するたびに、ビットを解放して再度割り当てます。割り当てはランダムな順序で行われる必要があるため、データはメモリ内を飛び回り、簡単に凍結することはできません。

追加の保護手段は、値のチェックサム(および「プレーン」int)を保存し、操作呼び出し中にこれらを比較することです。不一致が見つかった場合は、ゲームを進めるためにドアのロックを解除するために必要なランダムキーを削除するなど、微妙なことを行います。

編集:さらにメモリを移動するには、古い「ビット」を解放する前に、必ず新しい「ビット」を割り当ててください。

編集:マルチプレイヤーゲームの場合、データ構造をシリアル化し、圧縮し、ネットワーク経由で送信することもできます。ネットワークを最も効率的に使用するわけではありませんが、パケットスニッフィングを通じて把握するのは間違いなく困難です。


9

保管するたびに生成されるランダムな値で補完されたヘルスを保管してください。これは、メモリ内の値の増加/減少を検索してヘルスを見つけるという単純なメカニズムを少なくとも無効にします。

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;
    }
  }
}

さらに、ヘルスが変化していなくても、フレームごとに値をリセットすることもできます。これにより、人々は、健康状態が変化したときに変更された住所を検索できなくなり、健康状態が同じでも同じ住所を維持できます。

ボーナス:変更するたびに新しいオブジェクトを作成して、メモリアドレスを変更し、ヘルスを設定して、読み取るたびにメモリ内の乱数、xored値、およびアドレスを変更します。

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;
    }
  }
}

8

最初のコメントでは、聴衆の一部の体験を明らかに見返りなく低下させるという点について疑問を投げかけましたが、それでも技術的な観点からは興味深い質問です。

私はちょうどこの考えを持っていました:詐欺師が行うことは、それらを変更し、凍結する値を見つけることです。検索は、死亡またはプレイヤーの健康を変えたイベントの間でのみ行われます。さらに、詐欺師は、「死なない」ときに変化したものを除外することにより、検索を改良できます。

「ヘルス」カウンターが常に変化している場合はどうなりますか?パフォーマンスヒットが大きすぎる場合は、ポインタにして、すべてのフレームまたはNフレームごとに再割り当てします。または、すべてのフレームを変更するランダムな値とXORします(新しいランダムな値で暗号化する前に、同じ値に対して復号化を再度XORします)。

他のゲーム内データが全体の時間(プレイヤーキャラクターのx位置とy位置、またはタイムカウンターを含む)も変更している場合、すべての変更データのどれがヘルスであるかを見つけるのが難しくなる可能性があります。そして、ゲーム全体の状態を凍結することは、詐欺師にとっては不必要です。

さらに誤解を招く可能性がある場合は、実際にハニーポットと呼ばれる単純な書き込み専用変数にヘルスを保存できます。

編集

それでも、不正行為者は、試行錯誤を繰り返すうちにフリーズするのは、全体的に変化している変数のどれかを見つけようとするかもしれません。考えられる解決策は、変数を結合することです。

例:

ヘルス(h)と位置(x)を保存する代わりに、それらを2つの変数aとbに保存し、そこから後で値を取得できます。

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

このように、詐欺師がそのうちの1つだけをフリーズしてからキャラクターを移動すると、位置が影響を受け、どちらがフリーズしたかに応じて、hが負になります(即時死)。上記の数式と次の数式を切り替えることができます。

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

連続したフレームで、変数のいずれかが凍結された後の最大2フレームで、xが変化したときにヘルスが0になることを保証します。aとbのみを保存していることに注意してください。これを上記の連続XORと組み合わせます。結果は、すべてのフレームを一見ランダムな値に変更する変数のコレクションです。また、単一またはそれらのサブセットをフリーズすると、ゲーム内で望ましくない副作用のみが発生します。


7

動作する可能性があると思われるオプションの1つ(これらのチートツールにあまり詳しくない):隠さないでください。操作を実行し、特定の結果を期待します。操作(おそらく次のフレーム)の後、結果が期待どおりであることを確認します。健全性を差し引いてから確認すると、決して変わらない健全性を見つけるために、それがロックされていることをかなりはっきりさせることができます(不明瞭なバグがなければ)。

不正行為を検出した場合、それがあなたの意図である場合、最大の悲嘆にふさわしいと思うように、ゲームのルールを自由に変更できるようになりました。不正行為を無視してゲームを継続させる場合は、メモリ内の別の場所にヘルスを再割り当てし、新しい値が使用され、古い値が無視されるようにポインターを変更します。広告を無限に繰り返します。


6

単なる難読化の試みは理論的には失敗するはずですが、実際には、ゲームで成功するよりも挑戦が楽しくなくなるように、破壊するのに十分なだけハードにする必要があります。私はあなたのゲームが何なのかわからないので、データ難読化の方法を提案するリスクはありません。

とはいえ、おそらくあなたはそれを好まないでしょう、私はあなたがトラステッドコンピューティングのコンセプトであるメモリカーテンを探していると思います。


3

一部のローグライク(DoomRL、Brogue)で使用される非常に効果的な手法の1つは、実際の変数マスクすることです。つまり、ヘルスを「2/10」と表示する代わりに、「20%」と表示します。

ほとんどのメモリエディタは、特定の値の検索/フィルタリングに適しています。特定の値がわからない場合でも、それを追跡することができます(たとえば、プレーヤーのヘルスが低下した後、変更された値または減少した値を検索します)。

また、反チートバックラッシュを提案します。たとえば、プレイヤーが正のダメージを負わず、体力が低下しないゲームがある場合、これを簡単かつ正確に確認し、プレイヤーがチートすることを確認できます。何か面白いことをしてください。例えば、彼の周りにいくつかの超敵を産みます:)


2

ReadProcessMemory / WriteProcessMemoryがアプリケーションで呼び出されたときにSSDTをフックし、ログ/ブロックするリング0ドライバーを作成します。単にクラッシュするのではなく、時間の経過とともにゆっくりとゲームの動作を変更できるように、ログを記録する方が良いでしょう。


低レベルの実装の詳細について話しているようです(Windows API?)一般的な高レベルの戦略について尋ねています。
ashes999

2

プレイヤーが自分自身をだますのを防ぐのはなぜですか(シングルプレイヤーゲームでのだましの量)。マルチプレイヤー環境では、不自然な変更を検出してそれらに対抗することはサーバーのタスクです(通常、入力を無視するか、犯人をサーバーから完全にブロックすることにより)ひどい。

IOW、マルチプレイヤーゲームを作成していない限り、それはお金の無駄です。あなたがそうであれば、間違った場所を強化することを考えています。


2

既知の不正行為ツールを調査し、最も一般的な不正行為のいずれかが実行中に検出されているかどうかを頻繁に確認します(プロセス名を確認しますか?)

何かが検出されたら、プレーヤーにチートをさせます(オフラインの場合は無害です)が、スコア/実績がオンラインリーダーボード/実績システムに投稿されないようにします-黙って失敗させますか?

決意を固めたハッカーを止めることはできませんが、よりカジュアルなチートがリーダーボードを台無しにする可能性を減らします。

(正当な目的のために開発ツールを開いて最小化し、ゲームの休憩を取っているコーダーを困らせるかもしれません...)


7
私は配信プラットフォームとしてSteamの大ファンであり、数年前に多くのTeam Fortress IIをプレイしました。ある晩、私は長いコーディングセッションを中断し、プレイ中にVisual Studioとデバッガーを開いたままにしました。「不正行為」のためにTF2から禁止されていることがわかりました。訴えもなく、解禁の枠組みもありません。1つの「オフェンス」であり、アカウントに対して永続的です。ゲームのプレイ中に「メモリエディタ」を開くことは不正行為であり、禁止されていたというFAQの奥深くに埋もれていることを除いて、なぜだか、そして私は発言していたと信じていますが、私はまだ考えがありません。ワオ。

1

これに対する最も簡単な解決策は、チートオプションを実装することだと思います。チートオプションの使用中にスコアリングを無効にします。

もう1つの良いアイデアは、どのように実装するかわからないということです。凍結されたメモリ変数またはそのようなものがあるときにゲームを停止することです:)

幸運(Y)


3
チートを実装することは良いオプションです。ゲームを終了するのはそれほどではありません...(これを間違えたら、想像して、正当なプレイヤーをシャットダウンします。)
ashes999
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.