2011-12-17 27 views
8

こんにちはすべて、シェルコードをchar []配列として宣言するときとchar *を宣言するときの違いは?

私は基本的なシェルコーディングを学びたいと思っています。私は誰かが私に説明できることを好奇心を越えて走りました。私は、次のコードを2つの方法でコンパイルしました。シェルコードを配列として宣言し、char *として宣言します。シェルコードを配列として宣言すると、linuxはデータを実行しようとしていることを検出し、最初の命令でsegfaultを取得します。しかし、シェルコードをchar *として宣言すると、すべてのシェルコードが実行され、 "Hello world!"が得られます。コンパイラはこれらの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)(); 
} 

答えて

8

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

Linux上でmprotectを使用して、メモリ領域またはWindows上でVirtualProtectExの権限を設定できます。そうすれば、実行可能になるようにメモリのパーミッションを明示的に設定することができます。あなたの最初のケースで

3

char shellcode[] = 

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

char* shellcode = 

文字列は静的メモリに住んでいる - 実行可能である - 通常のプログラムのバイナリの他の部分と同じ領域に。

関連する問題