26

私はCで楽しみと利益のためにスタックを破壊するの例を実行しようとしていますが、コードは次のとおりです(私はUbuntu 64ビットの64ビットマシンを持っています):

int main()
{
    int x;

    x = 0;
    func(1,2,3);
    x = 1;
    printf("x is : %d\n", x);
}

void func(int a, int b, int c)
{
    char buffer[1];
    int *ret;

    ret = buffer + 17;
    (*ret) += 7;
}

上記のコードは正常に動作し、返されたx=1行は実行されませんが、背後にあるロジックを理解できません。つまり、バッファーに 8 バイト、スタックに保存されたベース ポインターに 8 バイトでret = buffer + 17;ある必要があります。ret = buffer + 16;

第二に、私の理解では、char buffer[1](64 ビット アーキテクチャにより) 8 バイトを使用しており、このバッファを増やしてbuffer[2].

よろしく、ヌマン

4

5 に答える 5

13

私が使用したすべてのアーキテクチャの 'char' は、それが 8 ビット マイクロ、16 ビット マイクロ、32 ビット PC、または 64 ビットの新しい PC であるかどうかに関係なく、8 ビット幅です。一方、int は単語サイズになる傾向があります。

ローカルがスタックに置かれる順序は、実装によって異なります。私の推測では、コンパイラが「int *ret」を「char buffer 1 」の前にスタックに置いていると思います。したがって、戻りアドレスに到達するには、「char buffer 1」(1 バイト)、「int *ret」(8 バイト)、および保存されたベース ポインター (8 バイト) の合計 17 バイトを通過する必要があります。

x86 64 ビットでのスタック フレームの説明は次のとおり です。 /x86-64

于 2009-01-29T08:36:54.960 に答える
9

gdb で逆アセンブルを実行し (逆アセンブル、stepi、nexti)、各ステップでレジスターを調べます (info レジスター)。

ここでは、逆アセンブルをステップ実行する方法を示します。

gdb ./myprogram
break main
run
display/4i $eip
stepi
stepi
...
info registers
...

また、多くのディストリビューションでは、gcc でスタック プロテクターがデフォルトで有効になっていることも知っておく必要があります (一部が機能していることを考えると、おそらく既に知っているはずです)。で手動で無効にすることができます-fno-stack-protector

于 2009-01-29T08:25:25.123 に答える
3

このスタック破壊的なものがたくさんあるので、あなたの親友はgdbです。あなたはすでにセグメンテーション違反をしているので、本来あるべきではないメモリをすでに書き込んでいます(良い兆候です)。正しく行うためのより効果的な方法は、戻りアドレスを有効なアドレス (たとえば、funcのアドレスまたは取得したシェルコード) に変更することです。私がお勧めする優れたリソースはShellcoder's Handbookですが、64 ビット アーキテクチャを使用しているため、多くの例を実行するには少し作業が必要です。

于 2009-01-29T08:22:34.737 に答える
0

x64バッファオーバーフローの悪用に関心がある場合は、ステルスの借用コードチャンク手法を検討してください。

于 2010-02-04T02:17:12.453 に答える