担忧有人不知道pwnable.kr是什么,因此以为有必要简单介绍一下它。编程
pwnable.kr是一个非商业性的Wargame网站
,它提供有关系统开发的各类pwn挑战。pwnable.kr的主要目的是'有趣'。并把每一个挑战视为游戏。地址:http://pwnable.kr/数组
每一个挑战都有对应的标记文件(相似于CTF),您须要阅读该文件并提交给pwnable.kr以得到相应的分数。为了读取标志文件,您须要一些有关编程,逆向工程,漏洞利用,系统知识,密码学的技能。每一个挑战都有做者的预期解决方案,可是,还有许多意外的解决方案。服务器
挑战分为四类:ssh
Mommy! what is a file descriptor in Linux?函数
https://youtu.be/971eZhMHQQw源码分析
ssh fd@pwnable.kr -p2222 (pw:guest)网站
这道题名为fd(file descriptor,翻译过来就是文件描述符),顾名思义,其实考察的就是 Linux 的文件描述符的知识。this
链接到服务器上后,当前目录存放了几个文件:fd.c fd flag
经过ls -l
,咱们能够查看文件权限,发现当前用户没有权限查看flag
文件,而后咱们就分析fd.c
文件,是一段代码,内容以下:命令行
//fd.c #include <stdio.h> #include <stdlib.h> #include <string.h> char buf[32]; int main(int argc, char* argv[], char* envp[]){ if(argc<2){ printf("pass argv[1] a number\n"); return 0; } int fd = atoi( argv[1] ) - 0x1234; int len = 0; len = read(fd, buf, 32); if(!strcmp("LETMEWIN\n", buf)){ printf("good job :)\n"); system("/bin/cat flag"); exit(0); } printf("learn about Linux file IO\n"); return 0; }
从源代码中,咱们能够看到关键一句在于经过第 2 个 if 语句的检查,若是 buf 变量的值为 LETMEWIN
字符串,那么就能够顺利打开 flag 文件。buf 是从哪里来呢?向上溯源,能够看到,buf 的值来源于 read 函数读进来的内容。翻译
C 语言中 read 函数的原型是:ssize_t read(int fd, void*buf, size_t count)。其中 fd 表明文件描述符,buf 为读出数据的缓冲区,count 是读取的字节数。也就是说,这句代码表示程序从文件描述符中读入数据并放到 buf 中。
fd 的值应该是什么呢?经过搜索,查到以下描述:Linux 系统将全部设备都看成文件来处理,而 Linux 用文件描述符来标识每一个文件对象。好比说,咱们用键盘输入数据,用显示器阅读显示的数据,那么键盘输入就是一个文件对象,显示器输出也是一个文件对象。对于每一个不一样的文件对象,Linux 会用不一样数字标识并加以区分。
Linux 标准文件描述符是这样规定的:
数字 0 表示 STDIN,即标准输入,也就是咱们经过运行程序以后,在命令行输入的数据。
数字 1 表示 STDOUT,即标准输出,也就是程序运行过程当中,在终端显示的数据。
数字 2 表示 STDERR,即标准错误输入,也就是程序运行时若是发生错误,致使不能正常退出时,终端上会显示的信息。
在了解了这些知识之后,这道题就能够很顺利的解出了:咱们只须要让 fd 的值等于 0,再经过终端命令行输入 LETMEWIN,就可让 buf 的值等于咱们输入的字符串,从而顺利经过 if 语句的检查。
对着代码,向上溯源,能够看到另一个关键语句:
int fd = atoi( argv[1] ) - 0x1234;
这一句定义了 fd 的值,其中 argv 是 main 函数的一个参数,再加上 argc 和 envp,表示程序运行时在命令行输入的命令参数。argc 是一个整型,表示参数的个数(程序文件名也算在内,因此 argc 至少值应该大于等于 1),argv 是一个指针数组,其元素个数是 argc,存放的是指向每个参数的指针,因此 argv[1] 就表示程序运行的第二个命令参数(第一个命令参数是 argv[0],也就是程序名)。envp 是一个指针数组,指向系统的环境变量字符串,这里没有用到。
因此,咱们只须要让程序运行的第一个命令参数等于 0x1234 便可,转换成 10 进制的值是 4660。
至此,解题思路就很明确了,终端输入以下:
$ ./fd 4660 LETMEWIN good job :) mommy! I think I know what a file descriptor is!!
本题考察了三个知识点:
本文首发于BigYoung小站