【pwnable.kr】Toddler‘s Bottle-[fd]


打开题目审题


image-20211106222529367

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)

Linux中的文件描述符是什么。如果你是完全的初学者,可以去youtube链接看视频。

解释下 SSH:

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

SSH 是Linux系统的登录工具,现广泛用于服务器登录和各种加密通信。其实在这里就是一个终端连接工具。

所以,打开CMD

image-20211106223448388

输入命令回车,输入密码:guest 。即可登录服务器。

登录上就可以开始找flag了。


找到突破口


照例先 ls -la

fd@pwnable:~$ ls -la
total 40
drwxr-x---   5 root   fd   4096 Oct 26  2016 .
drwxr-xr-x 115 root   root 4096 Dec 22  2020 ..
d---------   2 root   root 4096 Jun 12  2014 .bash_history
-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
-rw-------   1 root   root  128 Oct 26  2016 .gdb_history
dr-xr-xr-x   2 root   root 4096 Dec 19  2016 .irssi
drwxr-xr-x   2 root   root 4096 Oct 23  2016 .pwntools-cache

发现flag文件,尝试查看(肯定看不了

fd@pwnable:~$ cat flag
cat: flag: Permission denied
fd@pwnable:~$

果然不能看。

看下别的,文件flag肯定是最后的答案,所以需要看看其他文件找寻突破口。

还有一个c语言源文件fd.c和可执行文件fd

那没什么说的,看看fd.c。

fd@pwnable:~$ cat 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;

}

找到重点 system("/bin/cat flag");

看到源码大概已经明白了,我们没有查看文件的权限,但是fd有,所以只要分析如何让代码执行system("/bin/cat flag");即可。


相关c语言知识


int main( int argc , char * argv[ ] ,char * envp[ ])

main函数的参数列表保存了输入参数的信息:

第一个参数argc记录了输入参数的个数。且argc是包括程序本身在内的参数个数。如本题目,直接./fd运行,该参数实际上是1,而不是0。

第二个参数是字符串数组的,字符串数组的每个单元是char*类型的,指向一个c风格字符串,arg[ ]指向的数组中至少有一个字符指针,即arg[0].他通常指向程序中的可执行文件的文件名。

第三个参数是用来取得系统的环境变量,如:在DOS下,有一个PATH变量。当你在DOS提示符下输入一个命令的时候,DOS会首先在当前目录下找这个命令的执行文件。如果找不到,则到PATH定义的路径下去找,找到则执行,找不到返回Bad command or file name 。在DOS命令提示符下键入set可查看系统的环境变量。

int atoi(const char * str)

**函数说明:**C 库函数 int atoi(const char *str) 把参数 str 所指向的字符串转换为一个整数(类型为 int 型)。

ssize_t read(int fd, void * buf, size_t count);

函数说明:read()会把参数fd 所指的文件传送count 个字节到buf 指针所指的内存中. 若参数count 为0, 则read()不会有作用并返回0. 返回值为实际读取到的字节数, 如果返回0, 表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动。

fd所指文件指的是什么

每一个进程在进程控制块中都保存着一分文件描述符表,文件描述符就是这个表的索引,文件描述符表中每个表项都有一个指向已打开文件的指针

fd: 为打开文件的文件描述符,而每个进程都有一张文件描述符表,fd文件描述符就是这张表的索引。

Linux下 文件描述符(fd)与 文件指针(FILE*) 想了解更多可以看该链接。

简言之,在linux中,值为0、1、2的fd,分别代表标准输入标准输出标准错误输出


源代码分析


char buf[32];
int main(int argc, char* argv[], char* envp[]){
    	// 输入参数不能少于2 接一个参数就可以
        if(argc<2){
                printf("pass argv[1] a number\n");
                return 0;
        }
    	// 将 argv[1] - 0x1234 赋值给fd 
        int fd = atoi( argv[1] ) - 0x1234;
        int len = 0;
    	// 读取32字节到buf中,那么fd 必须为标准输入 即为0
        len = read(fd, buf, 32);
    	// buf 中32字节一定是 LETMEWIN 这样就能得到flag
        if(!strcmp("LETMEWIN\n", buf)){
                printf("good job :)\n");
                system("/bin/cat flag");
                exit(0);
        }
        printf("learn about Linux file IO\n");
        return 0;
}

代码看完了,想必如何做出来也都心里有数了。

参数一定要满足 fd=0 那么 参数 argv[1] = 0x1234 = 4660。

image-20211106231831401
最后在输入“LETMEWIN” 即可。


找到FLAG


执行可执行文件fd。./fd 4660 回车。

fd@pwnable:~$ ./fd 4660

此时开始执行len = read(fd, buf, 32); 输入“LETMEWIN” 回车即可得到flag。

fd@pwnable:~$ ./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!!

image-20211106231454694

输入验证即可。


参考:

https://www.cnblogs.com/ftl1012/p/ssh.html

https://blog.csdn.net/qq_40657299/article/details/78332875

http://c.biancheng.net/cpp/html/239.html

https://blog.csdn.net/qq_31967569/article/details/81145309

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值