0

使用#define:

#include <stdio.h>

#define CONSTANT "Constant"

int main(void)
{
    char buf[32];
    strcpy(buf, CONSTANT);

    return 0;
}

グローバルの使用const:

#include <stdio.h>

const char *constant = "Constant";

int main(void)
{
    char buf[32];
    strcpy(buf, constant);

    return 0;
}

ここで、誰かが生成されたバイナリ ファイルを何とか 16 進編集したとします。グローバル定数を編集してバッファ オーバーフローを引き起こし、任意のコードを実行する可能性があります。

私の質問は、この種の 16 進編集は#defines で可能ですか?

これらの16進値を解読する方法がまったくわからないため、自分で16進編集を試みたことはありません! 信頼できるチュートリアルも見つかりません。

4

4 に答える 4

2

どちらもより安全ではありません。ある時点で、とにかく両方の文字列を実行可能ファイルに格納する必要があります。

さらに、ユーザーがバイナリ ファイルを編集する場合、文字列をオーバーフローさせることさえ気にしないと思います。バイナリ コードを直接編集するだけです。

$ cat test.c
#include <stdio.h>

#if TEST == 0

#define str "Hello World\n"

int main() {
    puts(str);
    return 0;
}

#else

const char *str = "Hello World\n";

int main() {
    puts(str);
    return 0;
}

#endif
$ gcc test.c -Wall -DTEST=0 -o test0
$ gcc test.c -Wall -DTEST=1 -o test1
$ grep "Hello World" test0
Binary file test0 matches
$ grep "Hello World" test1
Binary file test1 matches
于 2013-07-03T06:44:42.717 に答える
1

まったく同じです。唯一の違いは、 #define を使用すると、文字列がコンパイラによって自動的に割り当てられる内部名を取得し、C プログラムからはアクセスできないことです。

オプション -save-temps -fverbose-asm を使用してプログラムをコンパイルすると、これを確認できます。これにより、プリプロセッサの結果とアセンブリ プログラムが残ります。どちらの場合も、文字列が宣言されていることがわかります。1 つは your のラベルで、もう 1 つはconst *生成された名前で宣言されます。

于 2013-07-03T06:52:09.047 に答える
1

名前が複数回使用される場合は、おそらくグローバル定数配列を使用する必要があります。

const char constant[] = "Constant";

占めるスペースが少なくなります — 配列名はポインタですが、メモリには保存されません。対照的に、const char *constant = "Constant";バージョンでは、格納されたポインター (変更可能) と文字列値の両方があります。名前が 1 回しか使用されない場合は、コード内で文字列をリテラルとして直接記述するか、配列または#defineメカニズムを使用することができます。

を使用しても#define、ユーザーは生成されたバイナリ ファイルを他のメカニズムと同じように「16 進編集」できます。使用される表記法によって提供される追加の保護はありません。

于 2013-07-03T06:41:22.893 に答える