-
序言
- pwnable.kr详细介绍
- 该咋玩
-
儿童瓶第一道题:fd
- 0x00 难题叙述
- 0x01 源代码剖析
- 0x02 答题方式
- 0x03 知识点总结
序言
担忧有些人不清楚pwnable.kr是啥 ,因此感觉必须简易介绍一下它。
pwnable.kr详细介绍
pwnable.kr是一个非商业性的
Wargame网址,它出示相关系统软件开发的各种各样pwn挑战 。pwnable.kr的关键目地是'有意思'。并把每一个挑战视作手机游戏。详细地址:http://pwnable.kr/
该咋玩
每一个挑战都是有相匹配的标识文件(类似CTF),您必须阅读文章该文件强调指出交到pwnable.kr以得到相对的成绩 。为了更好地载入标示文件 ,您必须一些相关程序编写,反向工程,漏洞利用 ,系统软件专业知识,密码算法的专业技能。每一个挑战都是有创作者的预期解决方案,可是 ,也有很多出现意外的解决方案。
挑战分成四类:
- 儿童瓶:比较简单的挑战 ,全是一些简易的不正确 。
- Rookiss:初学者必须把握的典型性漏洞利用。
- 怪异:这种挑战是怪异的,处理起來很痛楚,但得到Flag后 ,满足感满满的。
- 网络黑客的密秘:对于这种挑战的预期解决方案涉及到独特的网站渗透 。
儿童瓶第一道题:fd
0x00 难题叙述
Mommy! what is a file descriptor in Linux?
- try to play the wargame your self but if you are ABSOLUTE beginner, follow this tutorial link:
https://youtu.be/971eZhMHw
ssh [email protected] -p2222 (pw:guest)
这道题名叫fd(file descriptor,汉语翻译回来便是文件描述符),说白了 ,实际上调查的便是 Linux 的文件描述符的专业知识 。
0x01 源代码剖析
联接到网络服务器之后,当前目录储放了好多个文件:
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 ,即规范键入,也就是大家根据运作程序流程以后,在cmd键入的数据信息 。
数据 1 表明 STDOUT ,即规范輸出 ,也就是程序执行全过程中,在终端设备表明的数据信息。
数据 2 表明 STDERR,即规范不正确键入 ,也就是程序执行时假如产生不正确,造成不可以一切正常撤出时,终端设备上面表明的信息内容。
在了解了这种专业知识之后 ,这道题就可以很成功的解出了:大家只必须让 fd 的值相当于 0,再根据终端设备cmd键入 LETMEWIN,就可以让 buf 的值相当于大家键入的字符串数组 ,进而成功根据 if 句子的查验 。
冲着编码,往上追溯,能够见到此外一个重要句子:
int fd = atoi( argv[1] ) - 0x1234;
这一句界定了 fd 的值 ,在其中 argv 是 main 涵数的一个主要参数,再再加上 argc 和 envp,表明程序执行时在cmd键入的指令主要参数。argc 是一个整形 ,表明主要参数的数量(程序流程文件名也算进去 ,因此 argc 最少值应当高于或等于 1),argv 是一个指针数组,其原素数量是 argc ,储放的是偏向每一个主要参数的表针,因此 argv[1] 就表明程序执行的第二个指令主要参数(第一个指令主要参数是 argv[0],也就是程序流程名)。envp 是一个指针数组 ,偏向系统软件的环境变量字符串数组,这儿沒有采用 。
因此,大家只必须让程序执行的第一个指令主要参数相当于 0x1234 就可以 ,转化成 10 进制的值是 4660 。
0x02 答题方式
到此,解题思路就很确立了,终端设备键入以下:
$ ./fd 4660 LETMEWIN good job :) mommy! I think I know what a file descriptor is!!
0x03 知识点总结
题中调查了三个知识要点:
- Linux 下的文件描述符 fd 的界定和使用方法;
- C 语言表达中 read 涵数的原形和操作方法;
- main 涵数三个主要参数 argc, argv 和 envp 的含意。
文中先发于BigYoung华明镇