由于开学事情比较多,没时间写wp,现在补一补

分析

首先照常连上shell,

1
ls -al

跟fd一样,能看到的只有源代码,看一看代码:

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
col@ubuntu:~$ cat col.c
#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC;
unsigned long check_password(const char* p){
int* ip = (int*)p;
int i;
int res=0;
for(i=0; i<5; i++){
res += ip[i];
}
return res;
}

int main(int argc, char* argv[]){
if(argc<2){
printf("usage : %s [passcode]\n", argv[0]);
return 0;
}
if(strlen(argv[1]) != 20){
printf("passcode length should be 20 bytes\n");
return 0;
}

if(hashcode == check_password( argv[1] )){
system("/bin/cat flag");
return 0;
}
else
printf("wrong passcode.\n");
return 0;
}

有两个点,第一个是password长度只能是20位,
第二个点是check_password( argv[1] )需要等于0x21DD09EC,
先来看看这个函数,将传入的字符分为5个部分进行累加,结果必须为0x21DD09EC,
所以方法就是将0x21DD09EC拆分成5个int型的数,
因为不会做16进制的除法,所以先转为10进制:568134124然后除5等于1136268244
最后得到:

1
0x06C5CEC8*4+0x06C5CECC

这里先说下0x06C5CEC8长度问题,自己不太明白所以问了大佬,大佬给出的解释是:

1
2
3
4
一个字节是八位,
八位也就是八个二进制位,
而四个二进制位就是一个十六进制位,
所以两个十六进制位就代表一个字节

所以0x06C5CEC8占用的是4个字节,5个就是20个字节
(这里其实不太重要,大家应该都懂,只是因为自己这块知识比较薄弱,所以就当写笔记了)

又因为标准输入中是输入不了我们刚刚算出的字符串的,因为他的值超过了ascll的范围
所以这里借助python:

1
python -c "print '\xc8\xce\xc5\x06'*4 + '\xcc\xce\xc5\x06'"

\x代表的是16进制,并且目标机器用的小端序,所以payload需要些变化

pwn

payload:

1
./col `python -c "print '\xc8\xce\xc5\x06'*4 + '\xcc\xce\xc5\x06'"`