cmd1 - pwnable
题目
运行程序,提示段错误程序停止。
分析
运行程序无提示信息,分析源码。
#include <stdio.h>
#include <string.h>
int filter(char* cmd){
int r=0;
r += strstr(cmd, "flag")!=0;
r += strstr(cmd, "sh")!=0;
r += strstr(cmd, "tmp")!=0;
return r;
}
int main(int argc, char* argv[], char** envp){
putenv("PATH=/thankyouverymuch");
if(filter(argv[1])) return 0;
system( argv[1] );
return 0;
}
main 函数首先写入一个环境变量:PATH =/thankyouverymuch
。(这部分不影响最后解题,就放到最后再补充getenv()&putenv()知识)。
13行调用filter并传入第一个参数。
我们来看一下filter对整个程序运行的影响:
//main
if(filter(argv[1])) return 0;
system( argv[1] );
//filter
int filter(char* cmd){
int r=0;
r += strstr(cmd, "flag")!=0;
r += strstr(cmd, "sh")!=0;
r += strstr(cmd, "tmp")!=0;
return r;
}
strstr(cmd,“flag”):查找子串"flag",在cmd的位置。
返回值:
成功:返回子串第一次在cmd中出现的位置
未找到:返回NULL
这里实现效果是:如果传入的参数中含有"flag"、“sh”、“tmp"中的一个,r就会累加。假如r返回值不为零(参数中含有"flag”、“sh”、"tmp"中的任意一个),main函数中的if条件成立,将会退出程序。
接着向下看,调用system执行我们输入的第一个参数。那么有没有可能执行cat flag
的操作?
system( argv[1] );
那么问题来了,我们输入的参数中不能含有flag,如果直接输cat flag
,则会跳出程序。
这就要介绍linux下的通配符。通配符是shell在做PathnameExpansion时用到的。说白了一般只用于文件名匹配,它是由shell解析的,比如find,ls,cp,mv等。更多介绍
这里我们需要用到的是*
:匹配0或多个字符。使用通配符实现效果:
/bin/cat flag
== /bin/cat fla*
这样参数中就不存在flag,不会使程序退出。
// 双引号括起来,一个字符串的形式当做第一个参数
cmd1@prowl:~$ ./cmd1 "/bin/cat fla*"
mommy now I get what PATH environment is for :)
cmd1@prowl:~$
getenv() & putenv()
getenv():取得环境变量内容
putenv():改变或增加环境变量
#include<stdio.h>
#include<stdlib.h>
// putenv()需要头文件stdlib.h
int main(){
char *p;// 定义字符指针,因为查询成功返回的是子串的位置
if((p=getenv("USER")))// 取得环境变量USER的内容
printf("USER=%s\n",p);
putenv("USER=test");// 改变变量值为test
printf("USER=%s\n",getenv("USER"));
return 0;
}
>>>USER=root
>>>USER=test