1

次の簡単なコードを使用して、libc トリックに戻ろうとしています。

#define SYSTEM_CALL_ADDR 0xb7ec5e50  /*my system call addr*/
#define EXIT_CALL_ADDR  0xb7ebbb80   /*my exit call addr*/
char shell[] = "/bin/sh";

int main(){
 int* p; 
 p = (int*)&p + 2;
 *p = SYSTEM_CALL_ADDR;

 p = (int*)&p + 3;
 *p = EXIT_CALL_ADDR;

 p = (int*)&p + 4;
 *p = shell;

 return 1;
}

興味深いことに、このプログラムを実行すると「セグメンテーション エラー」で終了しますが、gdb を使用してデバッグし、段階的に実行すると、まったく問題なく、シェルが生成されてからプログラムが終了します。誰でもこの状況に遭遇しますか?または、誰かがこれを修正する方法を教えてもらえますか? まず感謝します。私は ArchLinux カーネル:2.6.33、gcc 4.5.0 を使用しています。

4

3 に答える 3

3

gdb は、ProPolice やアドレス空間レイアウトのランダム化 (ASLR) などのバッファー オーバーフロー エクスプロイト軽減技術の一部を無効にします。

于 2010-11-14T16:28:41.810 に答える
1

gdb は、デバッグを容易にするためにADDR_NO_RANDOMIZE パーソナリティ (2)を設定します。

于 2010-11-14T17:03:59.487 に答える
0

クラッシュは、変数 'p' の宣言が単一の (int *) ポインターに対してスタックに十分なスペースしか割り当てないために発生しますが、(&p + 2) などに値を詰め込むため、who-knows- を上書きしてしまいます。何。誰が何を知っているかという部分は、ある環境では重要ではなく、別の環境では重要であるため、gdb がある場合とない場合では動作が異なります。

ゴミ箱に入れようとしているスペースが重要なものではないことを確認することで、プログラムを「修正」できる場合があります。

int main(){
 int* p;
 char junk[100];    /* ADD THIS */

これで、「p」に割り当てられたストレージに続くスペースは (ほとんどの場合) ジャンク文字配列になり、上書きで回避できます。(少なくとも、「gcc -O0 -g」でコンパイルすると、特定のLinuxシステムでプログラムが「修正」されます)。

とはいえ、そこで使用している方法は、移植可能でも安全でもありません。コンパイラは、宣言した特定の順序でストレージ割り当てを配置することを約束しません。また、異なる最適化スイッチでコンパイルすると、動作が変わる場合があります。したがって、これは興味深い演習かもしれませんが、この種の方法が一貫して機能することを期待するべきではありません。

このように C スタックを手動で操作するのは悪い考えです!

于 2010-11-14T16:05:52.713 に答える