web-dev-qa-db-ja.com

バッファオーバーフロースタック攻撃演習ヘルプ

だから私はバッファオーバーフローの演習を完了しようとしています。私が利用しようとしているコードは以下のとおりです。私ができることは、オーバーフロー攻撃によって自分の印刷ステートメントを挿入することです。私がやりたいのは、$ catファイルで攻撃を実行することです。 code.c

#include <stdio.h>
#include <string.h>
#define INPUT_BUFFER 256 /* maximum name size */
/*
* read input, copy into s
*/
void getl(char *s)
{
    int c;
    while ((c=getchar()) != EOF)
        *s++ = c;
        *s = '\0';
    }
void removenl(char *s)
{
    int l;
    l = strlen(s);
    while (l--)
        if (s[l] == '\n')
            s[l] = '\0';
}

int main()
{
    char target[INPUT_BUFFER];
    getl(target);
    if (strlen(target) < INPUT_BUFFER) {
        removenl(victim);
        printf("%s is the target\n", target);
    }
return 0;
}

「char target [INPUT_BUFFER];」で攻撃が行われることを知っています。ポイント。たとえば257 'a'とすると、BOFが生成されます。

現時点での分解はこんな感じ。

   0x0000000000400673 <+0>:     Push   %rbp
   0x0000000000400674 <+1>:     mov    %rsp,%rbp
   0x0000000000400677 <+4>:     sub    $0x100,%rsp
=> 0x000000000040067e <+11>:    lea    -0x100(%rbp),%rax
   0x0000000000400685 <+18>:    mov    %rax,%rdi
   0x0000000000400688 <+21>:    callq  0x4005ed <getline>
   0x000000000040068d <+26>:    lea    -0x100(%rbp),%rax
   0x0000000000400694 <+33>:    mov    %rax,%rdi
   0x0000000000400697 <+36>:    callq  0x4004b0 <strlen@plt>
   0x000000000040069c <+41>:    cmp    $0xff,%rax
   0x00000000004006a2 <+47>:    ja     0x4006cc <main+89>
   0x00000000004006a4 <+49>:    lea    -0x100(%rbp),%rax
   0x00000000004006ab <+56>:    mov    %rax,%rdi
   0x00000000004006ae <+59>:    callq  0x400623 <removenewlines>
   0x00000000004006b3 <+64>:    lea    -0x100(%rbp),%rax
   0x00000000004006ba <+71>:    mov    %rax,%rsi
   0x00000000004006bd <+74>:    mov    $0x400764,%edi
   0x00000000004006c2 <+79>:    mov    $0x0,%eax
   0x00000000004006c7 <+84>:    callq  0x4004c0 <printf@plt>
   0x00000000004006cc <+89>:    mov    $0x0,%eax
   0x00000000004006d1 <+94>:    leaveq 
   0x00000000004006d2 <+95>:    retq  

バッファが満たされていないスタックは次のようになります。

0x7fffffffded0: 0xf7ffe1c8      0x00007fff      0xf7de4961      0x00007fff
0x7fffffffdee0: 0x00000000      0x00000000      0xf7ff7a10      0x00007fff
0x7fffffffdef0: 0x00000001      0x00000000      0x00000000      0x00000000
0x7fffffffdf00: 0x00000001      0x00007fff      0xf7ffe1c8      0x00007fff
0x7fffffffdf10: 0x00000000      0x00000000      0x00000000      0x00000000
0x7fffffffdf20: 0x00000000      0x00000000      0x00000000      0x00000000
0x7fffffffdf30: 0x00000000      0x00000000      0xf7ffe520      0x00007fff
0x7fffffffdf40: 0xffffdf70      0x00007fff      0xffffdf60      0x00007fff
0x7fffffffdf50: 0xf63d4e2e      0x00000000      0x00400391      0x00000000
0x7fffffffdf60: 0xffffffff      0x00000000      0xffffe0c8      0x00007fff
0x7fffffffdf70: 0xf7a251f8      0x00007fff      0xf7ff74c0      0x00007fff
0x7fffffffdf80: 0xf7ffe1c8      0x00007fff      0x00000000      0x00000000
0x7fffffffdf90: 0x00000001      0x00000000      0x0040072d      0x00000000
0x7fffffffdfa0: 0xffffdfd0      0x00007fff      0x00000000      0x00000000
0x7fffffffdfb0: 0x004006e0      0x00000000      0x00400500      0x00000000
0x7fffffffdfc0: 0xffffe0b0      0x00007fff      0x00000000      0x00000000
0x7fffffffdfd0: 0x00000000      0x00000000      0xf7a36f45      0x00007fff
0x7fffffffdfe0: 0x00000000      0x00000000      0xffffe0b8      0x00007fff
0x7fffffffdff0: 0x00000000      0x00000001      0x00400673      0x00000000
0x7fffffffe000: 0x00000000      0x00000000      0x5f571179      0x81bce2d3
0x7fffffffe010: 0x00400500      0x00000000      0xffffe0b0      0x00007fff

バッファがいっぱいになると、次のようになります。

0x7fffffffded0: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdee0: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdef0: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdf00: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdf10: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdf20: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdf30: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdf40: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdf50: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdf60: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdf70: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdf80: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdf90: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdfa0: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdfb0: 0x61616161      0x61616161      0x61616161      0x61616161
0x7fffffffdfc0: 0x61616161      0x61616161      0x61616161      0x37636161
0x7fffffffdfd0: 0x30343630      0x00003030      0xf7a36f45      0x00007fff
0x7fffffffdfe0: 0x00000000      0x00000000      0xffffe0b8      0x00007fff
0x7fffffffdff0: 0x00000000      0x00000001      0x00400673      0x00000000
0x7fffffffe000: 0x00000000      0x00000000      0x5f571179      0x81bce2d3
0x7fffffffe010: 0x00400500      0x00000000      0xffffe0b0      0x00007fff

私はこの攻撃を機能させるために知っている、戻りアドレスを上書きするために動作する必要があり、そこに自分のシェルコードを配置する。

シェルコードのペイロードと思われるものをGDBに入れて、それのシェルコード表現を取得しました。

#include <stdio.h>
void main() {
    printf("Now i've pwn your computer");
    return 0;
}



\xff\x25\x12\x0c\x20\x00\x68\x00\x00\x00\x00\xe9\xe0\xff\xff\xff\x55\x48\x89\xe5\xbf\xa4\x05\x40\x00\xb8\x00\x00\x00\x00\xe8\xe6\xfe\xff\xff\x90\x5d\xc3\x0f\x1f\x00

実際にこのシェルコードを取得して悪用するにはどうすればよいですか?入力する場所と、プログラムを自然に実行させる方法に戸惑っていると思います。何か見えたら、または正しい方向に役立つヒントを教えていただけませんか。

ありがとう。

1
Joe Hopper

これは一般にかなり広範な質問ですが、一般的なアプローチで回答してみます。

通常の容疑者(スタックカナリア、ASLR、no-exec-bitなど)を無効にした場合の一般的なアプローチは次のとおりです。

バッファがオーバーランする前に埋める必要があるスペースの量を確認し、そのスペースを任意の入力で埋めます(念のため、私は個人的にNOPを使用してNOPスライドを作成します)。

NOPスライドの最後で、戻りアドレスを上書きする前に、必ずペイロードを用意してください。

たとえば、戻りアドレスが1000バイトの最後の4バイトで、ペイロードが100バイトの場合、896 NOPの後にペイロードを置き、その後にNOPスライド内のアドレスを置きます。

オンラインで使用しているアーキテクチャの16進数値を調べることができます。

私は個人的に次のいずれかを好みます:

  • pythonを使用して必要な入力を生成するか、
  • 16進値をテキストファイルに手動で書き込み、catとパイプを使用して説明したように入力としてフィードできるバイナリを生成します。

あなたが尋ねたように2番目のオプションを使用するには、次を使用して必要なバイナリファイルを生成できます

xxd -r -p textfile > file

ここで、textfileは、次のような16進値の文字列を含むファイルです。

 aaaaaaaaaaaaaaaff25…
0
Tobi Nary

バッファオーバーフローの実行を考えるときは常に、最初に実行ポインタ(EIP/RIP)を制御する方法を考える必要があります。

関数が実行されるたびに、実行ポインタがスタックフレームに保存されます。関数が戻ると、スタックから実行ポインタを取得して実行を再開します(さらに多くの機能がありますが、私は単純化しすぎているため、一般的なアイデアを得ることができます)。

スタックだけを調べることはできません。スタックポインタ、ベースポインタ、命令ポインタのレジスタを調べる必要があります。これにより、EIPが正常に上書きされたかどうか、および期待される値で通知されます。

また、EIPをペイロードのアドレスでオーバーライドする必要がありますが、そのためには、ペイロードの場所を知る必要があります。この場合、それは単純なバッファオーバーフローであるため、スタックにあります。ただし、事前にスタックのアドレスを知っている必要がありますOR JMPを検索するESPコードで命令をそこに置く。

要約すると:

  • EIPの制御
  • スタックするEIPポイントを作成する
  • 残りのペイロードをスタックに追加する
0