7

私はいくつかのセキュリティ関連の実験を行っており、特に ret2ret エクスプロイトを理解しようとしていました。私が実験していたコード:

void foo(char * val){
        char buffer[64];
        int i;
        for (i=0; val[i]!=0; i++) buffer[i]=val[i];
        return;
}

int main(int argc, char ** argv) {
        foo(argv[1]);
        return 0;
} 

テスト中、ASLR、N^X、およびスタック カナリアはオフでした。そして、gccで32ビットにコンパイルしました。なぜだかわかりませんが、$eip を上書きしたといういつもの "0x41414141 in ?? ()" を取得できませんでした。そこで、gdb を使用してデバッグし、関数「cop」の ret にブレークポイントを設定することにしました。不思議なことに、300 個を超える「A」を書き込んだ後でも、スタックは次のようになりました。

 0xbffff46c:    0xb7ee2290  0xbffff496  0xb7e8f5f5  0x41414141
 0xbffff47c:    0x41414141  0x41414141  0x41414141  0x41414141
 0xbffff48c:    0x41414141  0x41414141  0x41414141  0x41414141
 0xbffff49c:    0x41414141  0x41414141  0x41414141  0x41414141
 0xbffff4ac:    0x41414141  0x41414141  0x41414141  0x00410043

バッファに対応する 64 文字はここにありますが、残りは書き込まれませんでした..理由はわかりません。何らかのアップデートによるものですか?

編集: バフの GDB ログ [64]

Dump of assembler code for function main:
   0x08048415 <+0>: push   %ebp
   0x08048416 <+1>: mov    %esp,%ebp
   0x08048418 <+3>: sub    $0x4,%esp
   0x0804841b <+6>: mov    0xc(%ebp),%eax
   0x0804841e <+9>: add    $0x4,%eax
   0x08048421 <+12>:    mov    (%eax),%eax
   0x08048423 <+14>:    mov    %eax,(%esp)
   0x08048426 <+17>:    call   0x80483dc <foo>
   0x0804842b <+22>:    mov    $0x0,%eax
   0x08048430 <+27>:    leave  
   0x08048431 <+28>:    ret 

Dump of assembler code for function foo:
   0x080483dc <+0>: push   %ebp
   0x080483dd <+1>: mov    %esp,%ebp
   0x080483df <+3>: sub    $0x44,%esp
   0x080483e2 <+6>: movl   $0x0,-0x4(%ebp)
   0x080483e9 <+13>:    jmp    0x8048404 <foo+40>
   0x080483eb <+15>:    mov    -0x4(%ebp),%edx
   0x080483ee <+18>:    mov    0x8(%ebp),%eax
   0x080483f1 <+21>:    add    %edx,%eax
   0x080483f3 <+23>:    movzbl (%eax),%eax
   0x080483f6 <+26>:    lea    -0x44(%ebp),%ecx
   0x080483f9 <+29>:    mov    -0x4(%ebp),%edx
   0x080483fc <+32>:    add    %ecx,%edx
   0x080483fe <+34>:    mov    %al,(%edx)
   0x08048400 <+36>:    addl   $0x1,-0x4(%ebp)
   0x08048404 <+40>:    mov    -0x4(%ebp),%edx
   0x08048407 <+43>:    mov    0x8(%ebp),%eax
   0x0804840a <+46>:    add    %edx,%eax
   0x0804840c <+48>:    movzbl (%eax),%eax
   0x0804840f <+51>:    test   %al,%al
   0x08048411 <+53>:    jne    0x80483eb <foo+15>
   0x08048413 <+55>:    leave  
   0x08048414 <+56>:    ret   

(gdb) b *foo+56
 Breakpoint 1 at 0x8048414: file exploit.c, line 9.

(gdb) r `python -c 'print "A"*64'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/prog `python -c 'print "A"*64'`

Breakpoint 1, 0x08048414 in foo (arg=0xbffff6da 'A' <repeats 64 times>) at exploit.c:9
9   }
(gdb) r `python -c 'print "A"*65'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/prog `python -c 'print "A"*65'`

Program received signal SIGSEGV, Segmentation fault.
0x0804840c in foo (arg=0xbffff6d9 'A' <repeats 65 times>) at exploit.c:6
6       for(i = 0; arg[i] != 0; i++) buff[i] = arg[i];

編集 2: バフの GDB ログ [20]

(gdb) disas foo
Dump of assembler code for function foo:
   0x080483dc <+0>: push   %ebp
   0x080483dd <+1>: mov    %esp,%ebp
   0x080483df <+3>: sub    $0x18,%esp
   0x080483e2 <+6>: movl   $0x0,-0x4(%ebp)
   0x080483e9 <+13>:    jmp    0x8048404 <foo+40>
   0x080483eb <+15>:    mov    -0x4(%ebp),%edx
   0x080483ee <+18>:    mov    0x8(%ebp),%eax
   0x080483f1 <+21>:    add    %edx,%eax
   0x080483f3 <+23>:    movzbl (%eax),%eax
   0x080483f6 <+26>:    lea    -0x18(%ebp),%ecx
   0x080483f9 <+29>:    mov    -0x4(%ebp),%edx
   0x080483fc <+32>:    add    %ecx,%edx
   0x080483fe <+34>:    mov    %al,(%edx)
   0x08048400 <+36>:    addl   $0x1,-0x4(%ebp)
   0x08048404 <+40>:    mov    -0x4(%ebp),%edx
   0x08048407 <+43>:    mov    0x8(%ebp),%eax
   0x0804840a <+46>:    add    %edx,%eax
   0x0804840c <+48>:    movzbl (%eax),%eax
   0x0804840f <+51>:    test   %al,%al
   0x08048411 <+53>:    jne    0x80483eb <foo+15>
   0x08048413 <+55>:    leave  
   0x08048414 <+56>:    ret    
End of assembler dump.
(gdb) b *foo+56
Breakpoint 1 at 0x8048414: file exploit.c, line 9.
(gdb) r `python -c 'print "A"*200'`
Starting program: /root/prog `python -c 'print "A"*200'`

Breakpoint 1, 0x08048414 in foo (arg=0xbffff652 'A' <repeats 200 times>) at exploit.c:9
9   }
(gdb) c
Continuing.
[Inferior 1 (process 3474) exited normally]
4

1 に答える 1

3

少なくとも64バッファについては、私はそれを理解したと思います。カウント変数 i は、(逆アセンブリごとに) バッファーよりもスタック上にあります。つまり、65 番目のストアが i の値を変更します。おそらく 4 バイトの整数であるため、i の値全体ではないことに注意してください。下位バイト (リトルエンディアン) のみです。いずれにせよ、その後、次の書き込み (66) が環境変数 (past ret) によって設定された領域を指し示すのに十分なだけ i を数えたかのようになります。これは無害であり、eip を汚染しません。

私のバットはほぼ完成しており、これを厳密に仕上げることはできません。しかし、これらの線に沿って考えてください。

バットフィンガーの編集/交差: また、両側が i の汚染の影響を受けているため、66 番目の書き込みで既に 0 が取り込まれている可能性があります (&buffer; に対して相対的に保存する場所、argv[1][0 に対して相対的に読み取ります)。 ]。

于 2014-02-01T23:33:34.937 に答える