先小小提一下下面涉及到的一些东西,玩Linux很溜的可以无视。主要照顾一些现在只接触过Windows的同学:
ls : 查看当前目录下的所有文件(这个命令让你你看见的都是文件名和目录名)
cat: 打开文件查看(这个命令让你看见的是文件“内容”,相当于在Windows下使用记事本的方式打开文件)
./文件名:这个命令可以执行Linux下的可执行文件
C语言:这东西博大精深,我搁着一两句也说不清,如果你不会的话,赶紧去找教程学吧。没这个下面的PWN你会看起来和天书一样。
题目源码:
#include
#include
#include
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;
}
解题步骤:
SSH连接成功后输入题目内对应的PassWorld
进入题目:
输入ls命令,查看当前路径下的文件:
可以看到,有三个文件,使用cat命令显示fd.c文件:
得到源码,从题目可知此题是为了让我们学习linux系统下的文件描述符。在windows系统下也有类似的东西,叫做文件句柄。 这里不多赘述。
我们现在开始分析源码...
Londoing.....
从main函数数起,第八行的if语句是关键的判断语句。因为它一旦判断通过,就可以输出flag了!
这里的strcmp("LETMEWIN\n",buf)是用于比较字符串的。如果"LETMEWIN\n"和buf一致
则返回0,如果不一致则返回正数。
buf是一个长度为32的字符型数组。
我们记住buf往上找,又一次看见了buf它出现在第七行的read(fd,buf,32)中。
read函数用来从文件中的读取内容,
fd这个参数的位置上会出现三种情况,
0:代表stdin(标准输入)
1:代表 stdout(标准输出)
2:代表 stderr(标准错误)
buf的位置是一个指向缓冲区的字符指针
32的位置是要取出的字节数
我们现在需要向buf里输入字符,所以我们需要让read函数的fd参数为0。
这条语句直接的向fd进行了赋值。atoi函数是把字符串转化从整型数的一个函数。
所以我们现在只要输入一个和十六进制的1234一样大小的十进制数(4660)即可。
现在我们就可以输入buf的字符了
出现了flag,我特意没有截全。留作练习。
最后整理一遍源码:
1 #include
2 #include
3 #include
4 char buf[32];
5 int main(int argc, char* argv[], char* envp[]) //程序入口
6 {
7 if(argc<2) //这是为了判断你有没有在执行程序的时候就输入了参数
8 {
9 printf("pass argv[1] a number\n");
/*这是提示信息,如果你直接调用了程序它就会提醒你要传进来一个数字*/
10 return 0;
11 }
12 int fd = atoi( argv[1] ) - 0x1234; //atoi()函数的功能是把字符串转化为数字
13 int len = 0;
14 len = read(fd, buf, 32);
/*在这里说一下,其实你想通过下面这个验证有三条路可以走
你输入的值为4660,4661,4662均可,简单来说就是只要让read()函数的参数合法
你就可以输入下面的密码了。(我也不太清楚作者为什么这样做,可能是为我这样的小白降低难度吧....)
*/
15 if(!strcmp("LETMEWIN\n", buf))
16 {
17 printf("good job :)\n");//能让程序执行到这就是胜利了!
18 system("/bin/cat flag");
19 exit(0);
20 }
21 printf("learn about Linux file IO\n");
22 return 0;
23 }