

C言語でプログラムを書いた後、gccによって実行ファイルを作成し、それをバイナリ解析しようと思ったのですが、以下のプログラムであると、stringsコマンドによって"hoge"という文字列が出力されてしまいます。そこで、それが出力されないようにしたいのですが、どういった手法を用いれば良いのでしょうか。txtファイルに保存してということもできると思うのですが、これをバイナリ解析の問題としてダウンロードファイルにしたいため、それをするとtxtファイルまでダウンロードさせることになり、簡単に解かれてしまうと思い質問しました。

[code]

    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
      char buf[32];
      char key[] = "hoge";
    
      puts("Please input password.");
      fgets(buf, sizeof(buf), stdin);
      strtok(buf, "\n");
    
      if(!strcmp(buf, key)){
        puts("Congratulations!");
      }
      else{
        puts("Invalid input.");
      }
      return 0;
    }
    
[/code]


CC BY-SA 3.0
2018-01-03T16:17:50.653
40696
2018-01-06T07:48:35.647
2018-01-03T16:31:26.357
5288
20760
question
c
strings コマンドによる解析に対する対策


strings コマンドで簡単にバレてしまうことに対する対策であれば、  
簡単に以下のようにするのはいかがでしょう?

[code]

    char key[] = {'h', 'o', 'g', 'e', 0};
    
[/code]

手元で strings コマンドで確認したところ、`hoge` はなくなりました。

ただし、少なくとも gcc の場合、以下のようにオプションにもよるようです。

`cc -S test.c` の場合:

[code]

        movb    $104, -53(%rbp)
        movb    $111, -52(%rbp)
        movb    $103, -51(%rbp)
        movb    $101, -50(%rbp)
        movb    $0, -49(%rbp)
    
[/code]

↑これだと問題ありませんが、

`cc -O2 -S test.c` の場合:

[code]

        movl    $1701277544, 11(%rsp)
    
[/code]

↑最適化すると `hoge` が見えてしまいました。

[code]

    luna:~ % cc --version
    cc (GCC) 7.2.1 20171128
    Copyright (C) 2017 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
[/code]

コメントにもある通り、`-fno-store-merging` でこの挙動は抑制できますが、  
同じ `.c` ファイルの他の部分にも影響を与えてしまいますので、  
このオプションを使うなら、この部分だけ別の `.c` ファイルに分離するのが良い  
だろうと思います。


CC BY-SA 3.0
2018-01-03T16:39:09.853
40698
2018-01-06T04:24:22.483
2018-01-06T04:24:22.483
5288
5288
40696
answer


本当にやりたいのは実行形式ファイルの難読化であって `strings` に特化した話ではなさそうですが、質問タイトルに沿う形で話を続けることにします。

前提条件  
\- ソースコードを大きく変更しない  
\- `strings` で表示されない

案１．日本語にしてしまう  
`strings` は日本語文字列を表示しませんから `strcmp(buf, "ほげ")` でよさそうです。

案２．ワイド文字にしてしまう  
入力文字を `char` → `wchar_t` に変換して `wcscmp(buf, L"hoge")` とすると `strings a.exe` では
`hoge` は表示されなくなります。ただし `strings -el a.exe` では表示されてしまいます。知っている人には通用しなさそうです。

案３．難読化ツール・圧縮ツールを使う  
MS-DOS の時代には EXE ファイルを圧縮し、起動時に自己展開するようなツールが流行っていました。圧縮すれば `strings`
で見ても中身はぐちゃぐちゃです。今はあまり見かけないのでしょうか？ちょっと探しただけだと upx とか超古いものしか見つかりませんでした。  
難読化ツール Obfuscator は .NET の世界では広く使われていますが native
の世界ではあまり見かけないようです。とりあえずちょろっと検索して見つけた範囲では PELock とか <https://www.pelock.com>

案４．直接見られたくない文字列はコンパイル前に base64 や uuencode する  
ソースコード上例えば `strcmp(buf, unbase64(BASE64IZE("hoge")))` のように書きます。  
\- `BASE64IZE()` はコンパイル前に base64 変換するマクロっつかツールでソース置換する  
\- `unbase64()` は実行時に base64 逆変換する関数を自作

windows 特化であれば文字列リソースを base64/uuencode しておいて `LoadResource`
後に元に戻すとか。パスワードを含むテキストファイルを zip
圧縮してヘッダ取り除くとか。まあやろうと思えばいくらでもできます。あとはコストパフォーマンスの問題に過ぎないです。

\--- 以下追記 ---

パスワードの生文字列を見せたくないのであればパスワードシステムとしてすでに確立しているソルト＋暗号学的単方向ハッシュ（＋ストレッチング）を実装してみるとか。固定ソルト＋固定ハッシュを１回で十分（ソルトなしでも十分という話がちらほら聞こえてきそうです）


CC BY-SA 3.0
2018-01-04T04:57:09.830
40707
2018-01-04T23:03:23.110
2018-01-04T23:03:23.110
8589
8589
40696
answer


多少脱線しますが回答者も間違えているので重要なこととして補足しておきます。K&R 2nd 4.9 Initializationにも

> Character arrays are a special case of initialization; a string may be used
> instead of the braces and commas notation:
[code]

>     char pattern[] = "ould";
>  
[/code]

>
> is a shorthand for the longer but equivalent
[code]

>     char pattern[] = { 'o', 'u', 'l', 'd', '\0' };
>  
[/code]

と説明されているように、たとえソースコード中で１文字ずつ分割して記述したとしても言語仕様上は同じ意味となります。

* * *

さて回答ですが、ここから一歩発展させて各文字を`~`ビット反転させてみてはどうでしょうか？  
実行時にはもう一度ビット反転させることで値が復元できます。もちろん`~`でなくても特定のビットパターンでのXORでも可能です。

[code]

    char key[] = { ~'h', ~'o', ~'g', ~'e', '\0' };
    for (int i = 0; i < 4; i++) key[i] = ~key[i];
    
[/code]

これで質問にある「strings コマンドによる解析」に対してとりあえずの対策とはなります。

* * *

なお、有名ソフトウェアになりますと例えば[MS SQL
Serverで全ユーザーの生パスワード閲覧可能な脆弱性](https://news.mynavi.jp/article/20090909-a055/)のようにプログラム動作中のメモリを盗み見ることで漏洩する・その対策が求められることになります。  
実行ファイルの難読化も実行開始時に復号してプログラムスタートとなる実装の場合、復号完了した時点でプロセスを一時停止しメモリイメージをダンプされてしまうと簡単に難読化前の実行ファイルを取得できてしまいます。  
そういった事例も踏まえましてどこまで対策を試みるべきかから見直した方がいいかもしれません。


CC BY-SA 3.0
2018-01-05T06:03:33.173
40737
2018-01-06T07:48:35.647
2018-01-06T07:48:35.647
4236
4236
40696
answer