第七题 input

远程连接之后看到代码的我是一脸懵逼:

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(int argc, char* argv[], char* envp[]){
printf("Welcome to pwnable.kr\n");
printf("Let's see if you know how to give input to program\n");
printf("Just give me correct inputs then you will get the flag :)\n");

// argv
if(argc != 100) return 0;
if(strcmp(argv['A'],"\x00")) return 0;
if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0;
printf("Stage 1 clear!\n");

// stdio
char buf[4];
read(0, buf, 4);
if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0;
read(2, buf, 4);
if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0;
printf("Stage 2 clear!\n");

// env
if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0;
printf("Stage 3 clear!\n");

// file
FILE* fp = fopen("\x0a", "r");
if(!fp) return 0;
if( fread(buf, 4, 1, fp)!=1 ) return 0;
if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0;
fclose(fp);
printf("Stage 4 clear!\n");
<!--more-->
// network
int sd, cd;
struct sockaddr_in saddr, caddr;
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd == -1){
printf("socket error, tell admin\n");
return 0;
}
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
saddr.sin_port = htons( atoi(argv['C']) );
if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){
printf("bind error, use another port\n");
return 1;
}
listen(sd, 1);
int c = sizeof(struct sockaddr_in);
cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c);
if(cd < 0){
printf("accept error, tell admin\n");
return 0;
}
if( recv(cd, buf, 4, 0) != 4 ) return 0;
if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0;
printf("Stage 5 clear!\n");

// here's your flag
system("/bin/cat flag");
return 0;
}

我对linux变成本来就不太熟,来设了5个关卡来卡我。。。。

看了下youtube上大神的讲解,大概思路是生成一个exe程序去调用他。。。关键是权限问题,
/tmp 目录是有读写权限的,所以去该目录先创建个文件夹

编写一下代码过掉了第一关 ,对Linux编程,我也不是很懂。

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
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main( int argc, char *argv[], char *envp[]){
char* argv1[101]={"/home/input2/input" ,[1 ... 99]="A",NULL };
for (int i =0;i<100;i++){argv1[i]="";};
argv1['A']="\x00";
argv1['B']="\x20\x0a\x0d";
printf("asd\n");
int q = execve("/home/input2/input",argv1,envp);
printf("%d\n",q);
return 0;
}//关键点还是execve函数,把我们构造好的参数交给input程序

看看第二关的检测,从标准输入缓冲区获取数据,和标准错误输出缓冲区获取数据,我们只需要将数据写进去就好了,代码如下:

int a = open("./1.txt",O_CREAT|O_RDWR,00700);
write(a,"\x00\x0a\x00\xff",4);
int b = open("./2.txt",O_CREAT|O_RDWR,00700);
write(b,"\x00\x0a\x02\xff",4);
lseek(a,SEEK_SET,0);
lseek(b,SEEK_SET,0);
dup2(a,0);
dup2(b,2);

通过该代码可以往标准输入输出等地方写数据。

执行之后过了第二关,下面要分析第三关,第三关是判断环境变量的。。。传参之前设置下就好

1
2
envp1[0]="\xde\xad\xbe\xef=\xca\xfe\xba\xbe";
envp1[1]=NULL;

把这个作为参数传递给环境变量参数,第三关就过了

第四关参考第二关,也比较简单

1
2
3
FILE* fp = fopen("\x0a","w");
fwrite("\x00\x00\x00\x00",4,1,fp);
fclose(fp);

第五通过 nc 命令来完成 相当于开2个连接,一个开启监听,一个发生送:

1
python -c "print '\xde\xad\xbe\xef'" | nc localhost 19001

最后直接得到flag

跌跌撞撞的做完这题,感觉自己linux基础相对比较薄弱,在做题的过程中,不断的学习到了各种linux知识,很多东西没理解的时候就一直搜,到最后大概能理解整个程序的流程,以及部分linux的运作方式了。
1