题目:ssh fd@pwnable.kr -p2222 (pw:guest)
源码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
}
几个函数的说明:
1.atoi()
函数用来将字符串转换成整数(int),其原型为:int atoi (const char * str);
2.定义函数:ssize_t read(int fd, void * buf, size_t count);
,read()会把参数fd所指的文件传送count个字节到buf指针所指的内存中。若参数count为0,则read()不会有作用并返回0。返回值为实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动。
3.strcmp()如果返回值 = 0,则表示 str1 等于 str2。
4.局部变量fd表示文件描述符,为read所使用。
5.fd是由atoi(argv[1])-0x1234计算出来的,其中argv[1]可控,且程序没有做任何check。
6.read的dst buffer
是一个全局的数组buf,大小定义为32,且read的第三个参数限定了32,不存在溢出。
7.Linux下stdin的定义在/usr/include/unistd.h中
参考大佬的博客,得知fd为文件描述符,关于文件描述符可以参考这篇文章,liunx中一切都可以看做文件,这个题目要求buf
为LETMEWIN
才可以输出flag,所以我们要把fd
的文件描述符修改为0,那么我们就可以标准输入LETMEWIN
,在看int fd = atoi( argv[1] ) - 0x1234;
这行,他将我们的输入减了0x1234
,既然我们要他等于0,那么我们直接输入4660(0x1234)
就可以了。
https://api.superbed.cn/pic/5c18874fc4ff9e2b4e045009
flag:mommy! I think I know what a file descriptor is!!