web-dev-qa-db-ja.com

コードをスキップするようにバッファオーバーフローの脆弱性を含むCコードを変更する

次のソースコードのバッファオーバーフローの脆弱性を利用する方法を見つけようとしているので、printf( "x is 1")という行はスキップされます。

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

void func(char *str) {
     char buffer[24];
     int *ret;
     strcpy(buffer,str);
}

int main(int argc, char **argv) {
    int x;
    x = 0;
    func(argv[1]);
    x = 1;
    printf("x is 1");
    printf("x is 0");
    getchar();
}

これを行うために、「func」関数を変更します。リターンアドレスをスキップしたい行のすぐ後ろに変更するためにret変数を使用する必要があることはわかっていますが、実際にそれを行う方法がわかりません。

Gdbを使用することで、main関数で次の呼び出しを見つけることができました。

Temporary breakpoint 1, 0x00000000004005ec in main ()
(gdb) x/20i $pc
=> 0x4005ec <main+4>:   sub    $0x20,%rsp
   0x4005f0 <main+8>:   mov    %edi,-0x14(%rbp)
   0x4005f3 <main+11>:  mov    %rsi,-0x20(%rbp)
   0x4005f7 <main+15>:  movl   $0x0,-0x4(%rbp)
   0x4005fe <main+22>:  mov    -0x20(%rbp),%rax
   0x400602 <main+26>:  add    $0x8,%rax
   0x400606 <main+30>:  mov    (%rax),%rax
   0x400609 <main+33>:  mov    %rax,%rdi
   0x40060c <main+36>:  callq  0x4005ac <func>
   0x400611 <main+41>:  movl   $0x1,-0x4(%rbp)
   0x400618 <main+48>:  mov    $0x4006ec,%edi
   0x40061d <main+53>:  mov    $0x0,%eax
   0x400622 <main+58>:  callq  0x400470 <printf@plt>
   0x400627 <main+63>:  mov    $0x4006f3,%edi
   0x40062c <main+68>:  mov    $0x0,%eax
   0x400631 <main+73>:  callq  0x400470 <printf@plt>
   0x400636 <main+78>:  callq  0x400490 <getchar@plt>
   0x40063b <main+83>:  leaveq
   0x40063c <main+84>:  retq
   0x40063d:    nop

しかし、私はここからどこへ行くのか混乱しています。関数が0x400611の行に戻ることと、0x400631にジャンプさせる必要があることはわかっていますが、ジャンプするビット数を決定する方法がわかりません。私はinsecure.org/stf/smashstack.htmlからの例3に沿って試してみましたが、変数を調整するために何ビットを理解するかについて迷いました。何か助け?

7
user2276280

すでに確認したように、アドレス0x400631に戻る必要があります。引数を使ってスタックを破壊するときは、EIPを制御する必要があります。すなわち:

./a.out AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

EIP 0x41414141が表示されます。次に、AのスタックのどこにEIPになる4バイトが配置されているかを判別する必要があります。 metasploitのpattern_create.rb/pattern_offset.rbのようなツールを使用することができます。または、これは非常に小さなバッファーであるため、手動で実行できます。

./a.out AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTT

そして、EIPのアドレスに基づいて、A(x41)、B(x42)、C(x43)などであるかどうかを判別できます。これにより、\ x31\x06\x40\x00の前に配置する必要があるバイト数がわかります。戻りアドレスがハードコードされているため、これはもちろん信頼できるエクスプロイトではありませんが、学習例には十分です。

4
wireghoul