10

こんにちは、みんな、

私は基本的なシェルコーディングを学ぼうとしていますが、誰かが私に説明してくれることを願っている何か不思議なことに出くわしました。次のコードを2つの方法でコンパイルしました。シェルコードを配列として宣言する方法とchar*として宣言する方法です。シェルコードを配列として宣言すると、Linuxはデータを実行しようとしていることを検出し、最初の命令でセグメンテーション違反が発生します。ただし、シェルコードをchar *として宣言すると、すべてのシェルコードが実行され、「Helloworld!」が表示されます。コンパイラはこれら2つの宣言をどのように異なる方法で処理し、一方が保護されていないメモリに存在するシェルコードで終わるのはなぜですか?前もって感謝します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* This declaration ends in a segfault */
//char shellcode[] =

/* This declaration ends in successful execution */
char* shellcode = 

/* Shellcode prints "Hello world!" and exits */    
"\xeb\x1f\x48\x31\xc0\x48\x31\xdb\x48\x31\xc9\x48\x31\xd2\xb0\x04\xb3\x01\x59\xb2\x0c\xcd\x80\x48\x31\xc0\xb0\x01\x48\x31\xdb\xcd\x80\xe8\xdc\xff\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21";

int main()
{
    void (*f)();
    f = (void (*)())shellcode;
    (void)(*f)();
}
4

2 に答える 2

10

として宣言するとchar[]、メモリはスタック上にあります。として宣言しchar*、文字列リテラルを割り当てると、メモリは実行可能イメージ自体にあります。Linuxは、スタックでコードを実行することを好みませんが、実行可能イメージのその部分でメモリを実行することは問題ありません。これは、特定の種類のスタックオーバーフロー攻撃を回避しようとしているためです。この攻撃では、ユーザーが任意の命令でスタックをオーバーフローさせてから実行する可能性があります。

Linuxで使用mprotectして、メモリ領域またはVirtualProtectExWindowsのアクセス許可を設定できます。このようにして、メモリのアクセス許可を実行可能に明示的に設定できます。

于 2011-12-17T05:53:26.867 に答える
3

最初のケースでは:

char shellcode[] =

これにより、文字列リテラルがローカル配列としてスタックに配置されます。スタックおよびヒープメモリには通常、実行権限がありません(セキュリティ上の明らかな理由から)。

2番目のケース:

char* shellcode = 

文字列は、実行可能な静的メモリ(通常はプログラムバイナリの残りの部分と同じ領域)に存在します。

于 2011-12-17T05:54:08.723 に答える