20190919pwnable的第二题[collision]详解writeup

这里题目提示是哈希碰撞。然后是利用ssh工具连接pwnable.kr 端口2222,用户名为col,密码为guest。


这里我们可以看到含有col、col.c、flag三个文件,显然flag我们不能直接读取。这里正常的ssh工具是通过执行ls命令来查看该文件夹下的文件及文件夹。


先让我们cat col.c来看看这个源文件。

#include<...>是调用头文件。

unsigned long hashcode = 0x21DD09EC;        这里是定义了一个hashcode为无符号长整型变量,大小为0x21DD09EC这里的0x代表是十六进制,要是不习惯可以用计算器的程序员模式看看十进制数。

unsigned long check_password(const char* p)    这里是定义了check_passwprd为无符号长整型变量,const char* p意味着定义一个指向字符常量的指针,const意味着这个指针不可修改。

int* ip = (int*)p;    这里是将char*p强制转换成int*p,这里要将4个char类型字符强制转换成1个int类型,因为这是一个32位程序,一个int 4个字节,一个char 1个字节。这里就是定义一个int类型变量ip,将p转化为int型的值赋给ip。

        int i;

        int res=0;

        for(i=0; i<5; i++){

                res += ip[i];

        }

        return res;

这里定义了一个i,用于做循环。还定义了一个整型数res(result的简写),这里用的是一个for循环,i初始为0,循环条件i<5,i++每次循环+1。循环体是res+=ip[i],意思是res=res+ip[i],就是把我们的输入累加到一起,最后返回一个res。

int main(int argc, char* argv[]) 这个的详细描述在我们上一篇文档中有呈现。本文我也简单阐述一下,int main(int argc, char* argv[])这里意味着定义一个main函数,第一个参数argc的值表示程序运行时,命令行参数的个数。第二个参数*argv[]的值表示指向字符串数组的指针,每个字符串对应一个参数。argv[0]是输入的路径,argv[1]、argv[2]......就是我们的第一个、第二个....个输入。

        if(argc<2){

                printf("usage : %s [passcode]\n", argv[0]);

                return 0;

        }

这里argc<2,将会输出usage : ./col [passcode],因为这里做了个判断,是否有两个输入,./col就是一个输入,第二个输入是我们应该赋的值。

        if(strlen(argv[1]) != 20){

                printf("passcode length should be 20 bytes\n");

                return 0;

        }

这里strlen是判断我们输入的字符长度,!=20意味着不等于而是就会输出passcode length should be 20 bytes。所以我们这里一定要输入20个字符。

        if(hashcode == check_password( argv[1] )){

                system("/bin/cat flag");

                return 0;

        }

        else

                printf("wrong passcode.\n");

        return 0;

这里就是把argv[1]我们的输入放进check_password里,最后来判断是否等于hashcode,如果等于则cat flag。否则则输出wrong passcode。

这边我们就把这几十行C的代码看完了,那接下来我们就想一下如何构造吧。这里要输入的字符最后累加为0x21DD09EC。我们先看看它对应十进制的多少。

这个最后一位为4,我们可以把他整除5。ps这里的方法很多,我只是推荐一种我使用的,各位见仁见智吧,只要最后配出来的是0x21DD09EC即可。

这里我整除了五,发现它的十六进制数为0x06C5CEC8,然后不知道大家知不知道我们的计算机是小端机,小端机的输入应该反过来,我们应该输入C8 CE C5 06这样往里输入。由于这里整除的时候有个余数4,所以我们最后一位要构造成0x06C5CECC,输入应为CC CE C5 06。然后由于ASCII码只包含128位,所以有些是不可显示字符,我们无法直接输入进去,在这边我们就需要使用python大法了。./col `python -c "print '\xC8\xCE\xC5\x06' * 4 + '\xCC\xCE\xC5\x06'"`


flag:daddy! I just managed to create a hash collision :)

这题拿下!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容