34

ハードコーディングされた文字列をバイナリから抽出できることを発見しました。
たとえば、Process Explorerのプロパティ ビューには、3 文字を超えるすべての文字列が表示されます。

これは、単純にテストするために作成した単純な実行可能ファイルのコードです。

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
    _TCHAR* hiddenString1 =_T("4537774B-CC80-4eda-B3E4-7A9EE77991F5");
    _TCHAR* hiddenString2 =_T("hidden_password_or_whatever");
    for (int i= 0; i<argc; i++) {
        if (0 == _tcscmp(argv[i],hiddenString1)) {
            _tprintf (_T("The guid argument is correct.\n")); }
        else if (0 == _tcscmp(argv[i],hiddenString2)) {
            _tprintf (_T("Do something here.\n")); }
    }

    _tprintf (_T("This is a visible string.\n"));
    //Keep Running
    Sleep(60000);
    return 0;
}

文字列は、対応する実行可能ファイルから明確に抽出できます。
代替テキスト

文字列を見つけるのは少し簡単すぎると思います。

私の質問は次のとおりです。

  1. 実行可能ファイルでhiddenString1またはhiddenString2単純に非表示にする方法は?
  2. あいまいな隠し入力よりも「チートコード」を使用する安全な方法はありますか?
4

9 に答える 9

32

防御的プログラミングのより広い世界へようこそ。

いくつかのオプションがありますが、それらはすべて何らかの形式の難読化に依存していると思います。これは完璧ではありませんが、少なくとも何かです。

  1. ストレートな文字列値の代わりに、テキストを他のバイナリ形式 (16 進数?) で格納できます。

  2. アプリに保存されている文字列を暗号化し、実行時に復号化できます。

  3. コード内のさまざまなポイントに分割して、後で再構成できます。

またはそれらのいくつかの組み合わせ。

一部の攻撃は、実際のバイナリを見るよりもさらに進んでいることに注意してください。プログラムの実行中に、プログラムのメモリアドレス空間を調査することがあります。MS は、.Net 2.0 で SecureStringと呼ばれるものを考え出しました。アプリの実行中に文字列を暗号化しておくことが目的です。

4 つ目のアイデアは、文字列をアプリ自体に保存するのではなく、制御するサーバーに送信される検証コードに依存することです。サーバー上で、それが正当な「チート コード」であるかどうかを確認できます。

于 2009-05-29T14:14:12.390 に答える
20

実行可能ファイル内のデータを隠す方法は多数あります。ここに他の人が良い解決策を投稿しています - いくつかは他よりも強力です。そのリストには追加しません。

ただ気をつけてください: これはすべていたちごっこです:あなたの「秘密」が誰にも知られないと保証することは不可能です。

暗号化やその他のトリックをどれだけ使用しても。どれだけの労力やお金を投入しても。それを隠すために「NASA​​/MIT/CIA/NSA」タイプがいくつ関与していても。

それはすべて単純な物理学に帰着します。ユーザーが実行可能ファイルから秘密を引き出して「再表示」する
ことが不可能である場合、コンピューターもそれを再表示できず、プログラムもそれを実行できません。これを使って。十分なインセンティブを備えた中程度のスキルを持つ開発者であれば、秘密を明らかにする方法を見つけるでしょう。

実行可能ファイルをユーザーに渡した時点で、ユーザーは秘密を見つけるために必要なものをすべて手に入れています。

あなたが望むことができる最善の方法は、秘密を明らかにすることを非常に難しくして、秘密を知ることから得られる利益が面倒なことに値しないようにすることです.

したがって、データを公開することが単に「好ましくない」場合、または公開することの結果が単に「不便」である場合は、データを不明瞭にしようとしても問題ありません。ただし、「マスター クライアント データベースへのパスワード」、秘密鍵、またはその他の重要な秘密をプログラムに隠すことは考えないでください。あなたはできません。

プログラムがなんらかの形で必要とするが、絶対に公開情報にはならない (秘密鍵のような) 非常に重要な機密情報がある場合は、プログラムが制御下にあるリモート サーバーと通信し、適切な認証と承認の制御を適用する必要があります (つまり、承認された人またはコンピューターのみがサーバーに要求できることを確認し、そのサーバーに秘密を保持させて使用させます。

于 2009-05-29T21:04:22.933 に答える
10

最も簡単な方法は、xor や rot-13 などの簡単な方法で暗号化し、使用時にその場で復号化することです。これにより、それらを何気なく見ることはなくなりますが、逆転の経験が豊富な人なら誰でも止めることはできません。

于 2009-05-29T14:19:47.120 に答える
6

Chris が言及しているこれらの方法に加えて、ハッシュ アルゴリズムを使用することもできます。正しい ID が指定されているかどうかを確認するだけであれば、実際に ID 全体をプログラムに格納する必要はありません。

  • 比較したい文字列/パスワード/ID のハッシュ (MD5、SHA など) を作成し、おそらく「ソルト」値を追加します。これをプログラムに保存します
  • プログラムの実行時に、入力文字列/パスワード/ID に対して同じアルゴリズムを実行し、2 つのハッシュを比較して一致するかどうかを確認します。

この方法では、実際のテキストがプログラムに保存されることはなく、ハッシュ アルゴリズムは一方向のみであるため、プログラムをリバース エンジニアリングして元のテキストが何であったかを調べることはできません。

于 2009-05-29T14:18:30.010 に答える
2

最善の方法は、パスワードまたは非表示にするその他の文字列をchar配列としてコーディングすることです。例えば:

std::string s1 = "Hello";   // This will show up in exe in hex editor
char* s2 = "World";   // this will show up in exe in hex editor
char s3[] = {'G', 'O', 'D'}; // this will not show up in exe in hex editor.
于 2009-06-12T13:14:23.913 に答える
2

秘密のコードはすべて GUID になりますか、それとも単なる例ですか?

おそらく、シークレットをバイナリ GUID として保存します。

const GUID SecretGuid =
    { 0x4537774B, 0xCC80, 0x4eda, { 0x7A, 0x9E, 0xE7, 0x79, 0x91, 0xF5 } };

次に、指定した GUID を文字列からバイナリ形式に変換し、2 つのバイナリ GUID を比較します。

于 2009-05-29T15:24:14.247 に答える
2

人に見られたくない特定の文字列がある場合は、それを暗号化し、実行時に復号化します。

GUID を他人に見られたくない場合は、文字列から構築するのではなく、バイトから構築します。

const GUID SecretGuid = 
      { 0x4537774B, 0xCC80, 0x4eda, { 0x7A, 0x9E, 0xE7, 0x79, 0x91, 0xF5 } };
于 2009-05-29T14:23:39.203 に答える
2

これが私がこの目的のために使用する方法です。まず、SysinternalsのStringsツールを使用して、EXE または DLL 内の文字列を表示します。次に、次の小さなツール(記事を参照) を使用して、これらの文字列を、算術式として保存された文字のスクランブル配列に置き換えます。たとえば、文字列の代わりに、 「this is a test」 というコードを配置します。このツールによって自動的に生成されます)

WCHAR T1[28];
 T1[22] = 69;
 T1[15] = 121 - 17;
 T1[9] = L':' + -26;
 T1[12] = L't' - 1;
 T1[6] = 116 - 1;
 T1[17] = 117 - 12;
 T1[3] = 116 - 1;
 T1[14] = L'' - 3;
 T1[13] = L'w' - 3;
 T1[23] = 69;
 T1[26] = L'Y' + 3;
 T1[19] = 111 + 0;
 T1[21] = L'k' - 34;
 T1[27] = L'\\' - 8;
 T1[20] = L'B' + 32;
 T1[4] = 42 + -10;
 T1[25] = L'm' - 17;
 T1[16] = L'H' + 18;
 T1[18] = L'A' + 56;
 T1[24] = 68;
 T1[1] = 105 - 1;
 T1[11] = L'k' - 6;
 T1[10] = 66 + 50;
 T1[2] = 105;
 T1[0] = 117 - 1;
 T1[5] = L'k' - 2;
 T1[8] = 89 + 8;
 T1[7] = 32;

この問題には多くの解決策があり、(私のものも含めて) 完璧な解決策はありませんが、機密性の高い文字列をごちゃまぜにしたり、偽装したり、隠したりする方法はいくつかあります。もちろん、これらを暗号化して実行時に復号化することもできます (この記事を参照) が、これらの文字列を実行可能ファイルのビットとバイトの間で非表示にし、機能させることがより重要であることがわかりました。私のツールを実行した後、実行可能ファイルに「this is a test」が見つかりません。

于 2018-08-07T12:42:12.477 に答える