oxo2 分析
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
| #include <stdio.h> #include <fcntl.h>
#define PW_LEN 10 #define XORKEY 1
void xor(char* s, int len){ int i; for(i=0; i<len; i++){ s[i] ^= XORKEY; } }
int main(int argc, char* argv[]){ int fd; if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0){ printf("can't open password %d\n", fd); return 0; }
printf("do not bruteforce...\n"); sleep(time(0)%20);
char pw_buf[PW_LEN+1]; int len; if(!(len=read(fd,pw_buf,PW_LEN) > 0)){ printf("read error\n"); close(fd); return 0; }
char pw_buf2[PW_LEN+1]; printf("input password : "); scanf("%10s", pw_buf2);
xor(pw_buf2, 10);
if(!strncmp(pw_buf, pw_buf2, PW_LEN)){ printf("Password OK\n"); system("/bin/cat flag\n"); } else{ printf("Wrong Password\n"); }
close(fd); return 0; }
|
从代码上看如果不是非常细心是很难看到漏洞在哪里的,但是可以从执行中看出一点端倪。首先执行的时候会先sleep一段时间然后发现需要我们输入一些东西才会执行printf("input password : ");
。所以要仔细分析printf("input password : ");
之前的代码,找到到底哪里需要输入数据。
fd=open("/home/mistake/password",O_RDONLY,0400) < 0
这句代码有一个问题,因为小于号<的优先级事实上是比赋值号=的优先级高的,也就是会先判断open返回的文件描述符是不是小于0(正常打开的话应该从最小的未分配的3开始),然后再赋值给fd,从而导致fd==0
。因此if(!(len=read(fd,pw_buf,PW_LEN) > 0))
就变成了从标准输入中读取数据,从而导致pw_buf
和pw_buf2
都是用户的输入;
pw_buf2
的每一个字符的最低位由于和1做异或操作,结果是每一个字符的最低位都被取反。比如从BBBBBBBBBB
变为CCCCCCCCCC
。
0x02 利用
1 2 3 4 5 6
| mistake@prowl:~$ ./mistake do not bruteforce... BBBBBBBBBB input password : CCCCCCCCCC Password OK Mommy, the operator priority always confuses me :(
|