超神之路之PWN训练之1之fd

环境搭建:拷的学长的ubuntu虚拟机,直接拿过来用了。

训练网址为http://pwnable.kr/play.php。

 点开fd,可以看到需通过SSH连接到远程终端做题,命令如下:ssh [email protected] -p2222,密码:guest,连接好以后如下图。

超神之路之PWN训练之1之fd超神之路之PWN训练之1之fd

通过ls命令可以看到有三个文件,再用ls -al查看文件权限,发现fd和fd.c文件都只有读的权限,fd为fd.c编译出来的C程序,而flag则是要运行的夺旗程序,但我们没有权限执行,需通过运行fd+参数来执行。

超神之路之PWN训练之1之fd

接下来看fd.c的代码,执行命令cat fd.c

超神之路之PWN训练之1之fd超神之路之PWN训练之1之fd

可以看到,要运行flag程序得到flag,必须使buf的值为“LETMEWIN\n”,而buf的值是通过read()函数从定义的fd复制来的。而fd的值就是传输给程序fd的参数转化为int值后再减去0x1234得来的。那么问题来了,最后得到fd的值为一个整型,复制给fd的也是一个整型,在if语句中整型和字符串比较是无论如何无法匹配的,那么该怎么通过if得到flag呢?

这个时候就需要知道一个点,read()函数的第一个参数是可以设置为某些特殊参数的,如下

超神之路之PWN训练之1之fd超神之路之PWN训练之1之fd

当fd为0时,要复制给buf的值就可以从键盘输入,bingo。

现在只要通过输入给程序fd的值来使参数fd=0,就可以再通过键盘输入“LETMEWIN\n”来进入if语句夺旗。

注意一点,atoi()函数是将字符串转化为十进制的字符串整型,与0x1234减的时候会先转化为16进制,所以需先将参数转为10进制再输入,0x1234的十进制为4660,故输入命令./fd 4660后再输入"LETMEWIN\n" 就可以获得flag。

超神之路之PWN训练之1之fd超神之路之PWN训练之1之fd

扩展:当输入值为4661和4662时,也能通过键盘输入"LETMEWIN"来获得flag。

原因是输入4661和4662,相应的fd值为1和2,对应了上表的Standard output和Standard error。Standard output是让你键入你想要程序输出的值,Standard error是键入程序出错时显示的异常值,而无论是设定的哪个值都会把键入值复制给buf,故输入4660-4662都能夺旗。