这个周末参加了一堆比赛。。。
HBCTF
听说是新手向的游戏,所以决定所有题目都尝试做一下看看:
Web 50
首先进去就能看到源码
1 |
|
大概就是我们需要设置user,而且user还要是一个文件。于是我们这里的想法就是利用网页的data协议,也就是利用data:text协议让其解析一段文本并且作为内容:
1 | http://123.206.66.106/?user=data:text/html;base64,dGhlIHVzZXIgaXMgYWRtaW4= |
此时user就算是作为一个【文件】传输进去了。
然后就没思路了。。。。参考官方wp得知,此时要利用php的特殊协议:php://
php:// — 访问各个输入/输出流(I/O streams)
查到的传输方式为:
php://filter/resource=class.php
然而此时并不能读到字符串。。。后来查到说,都是要先base64处理一下,于是这里写成
http://123.206.66.106/?file=php://filter/convert.base64-encode/resource=class.php&user=data:text/html;base64,dGhlIHVzZXIgaXMgYWRtaW4=
发现就能够文件数据读到了:
读到的内容base64解密一下得到:
1 |
|
这个的意思就是说,这个php文件要设置了$file,但是我已经完全不会玩了。。。
查了以后知道,我们的关键就是找到f1a9.php,然后关键的是,我们需要【让一个Read对象中的file被赋值。】,__toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。所以我们利用最后的参数pass,将我们自己实例化的对象先序列化处理,在顺着url传输后,在解析的时候会被解析成实例对象,从而实现file的赋值。
1 |
|
将其作为pass参数的时候,发现用原来的url并不能成功,后来发现是以为我们按照原来的传输方法,会进入到class.php里面,导致我们不能够进入f1ag.php文件中。最后我们把url改成:
1 | http://123.206.66.106/?file=class.php&user=data:text/html;base64,dGhlIHVzZXIgaXMgYWRtaW4=&pass=O:4:%22Read%22:1:{s:4:%22file%22;s:10:%22./f1a9.php%22;} |
终于过了。。。
flag6.zip(Misc)
这个打开发现zip里面的文件要密码:
但是我们注意到CRC,CRC其实就是把整个文件进行了CRC处理然后作为文件的校验。加上文件的题目,我们知道此事的文件中的内容并不是很长,所以我们可以尝试可以尝试暴力破解得到文件中的内容。
方法二
从网上找了一份zip格式的文件结构:
压缩源文件数据区:
50 4B 03 04:这是头文件标记(0x04034b50)
14 00:解压文件所需 pkware 版本
00 00:全局方式位标记(有无加密)
08 00:压缩方式
5A 7E:最后修改文件时间
F7 46:最后修改文件日期
16 B5 80 14:CRC-32校验(1480B516)
19 00 00 00:压缩后尺寸(25)
17 00 00 00:未压缩尺寸(23)
07 00:文件名长度
00 00:扩展记录长度
6B65792E7478740BCECC750E71ABCE48CDC9C95728CECC2DC849AD284DAD0500
压缩源文件目录区:
50 4B 01 02:目录中文件文件头标记(0x02014b50)
3F 00:压缩使用的 pkware 版本
14 00:解压文件所需 pkware 版本
00 00:全局方式位标记(有无加密,这个更改这里进行伪加密,改为09 00打开就会提示有密码了)
08 00:压缩方式
5A 7E:最后修改文件时间
F7 46:最后修改文件日期
16 B5 80 14:CRC-32校验(1480B516)
19 00 00 00:压缩后尺寸(25)
17 00 00 00:未压缩尺寸(23)
07 00:文件名长度
24 00:扩展字段长度
00 00:文件注释长度
00 00:磁盘开始号
00 00:内部文件属性
20 00 00 00:外部文件属性
00 00 00 00:局部头部偏移量
6B65792E7478740A00200000000000010018006558F04A1CC5D001BDEBDD3B1CC5D001BDEBDD3B1CC5D001
压缩源文件目录结束标志:
50 4B 05 06:目录结束标记
00 00:当前磁盘编号
00 00:目录区开始磁盘编号
01 00:本磁盘上纪录总数
01 00:目录区中纪录总数
59 00 00 00:目录区尺寸大小
3E 00 00 00:目录区对第一张磁盘的偏移量
00 00:ZIP 文件注释长度
我们用winhex打开看一下:
指定位置果然有个01表示是否加密,我们尝试改成00:
果然是伪加密。。。。。
just do it(Crypto)
一个C++的代码,结果我强行爆破做了。。。
1 |
|
后来仔细观察,发现自己的算法都看懂一半了为啥要爆破。。。。
解释一下:
1 | // a:输入字符串 b:空字符串 b[0] = a[0]^0x1 |
首先我们观察上面的算法:
b[i] = a[i]^b[i - 1]
b当前的字符只于上一个字符有关系,然后加上后面的那段:
b[i] = b[i] ^ b[i + 1] ^ 0x53
这里我们b[i + 1]不和b[i]相关,所以我们可以写出递推式:
b[i] = b[i] ^ a[i + 1] ^ b[i] ^0x53 = a[i + 1] ^ 0x53
相当于b[i] 只与a[i + 1]相关
然后后面的算法:
1 | // a 至少18位 |
虽然看着麻烦,但是注意到,这个key它本身就是个固定的值,在前7个数据中自己和自己异或,完全和a无关,而从第8个开始,之和前9个a相关,然而此时的a[7]以后的值早就算出来了,所以此时就完全不影响后续。。。然后我们知道通过e和b的异或,就能够把此时的a求出来.这里贴一段大佬的代码:
1 | # -*- coding:utf8 -*- |
whatiscanary(pwn 100)
这一题完全是自己做出来的。。找到函数的描述,发现一开始就把flag读到了一个全局变量里面:
然后再下面的函数中找到了如图所示的漏洞:
于是思路变为绕过cananry。
绕了半天都绕不过去啊。。。然后发现,当让这个___stack_chk_fail触发的时候,会产生字符串:
1 | *** stack smashing detected ***: ./whatiscanary terminated |
这个函数的名字肯定是我们argv[0]里面的参数,所以这里我们不用绕过canary,而是通过覆盖我们argv的第一个参数的位置,从而将这段内容里面的./whatiscanary的字符串变量地址覆盖成flag的地址即可。
1 | 函数名字所在的栈的地址为: |
所以需要的字符串长度为:232个字符
在这之后将其覆盖成全局变量的地址即可。
难得成功了一回。。。代码如下:
1 | from pwn import * |
pwn200 infoless
这种题目已经不是第一次见了,这种涉及到.plt的花式操作之前只知道修改.plt然后通过libc.so.6来对比查找,然而这个题目并没有相关的数据泄露。。。难道要开始leak了?这个题目知道最后放了wp,学习了一波无需libc进行system调用的一种花式操作 – ret2dl-resolve
逻辑很简单,就是一个read函数的溢出
然而这个文件实在是太简单了,只有一点可以用的函数:
导致我们完全没有什么利用的思路啊。。。连泄露地址的write都没有。。所以最后完全不会做,学习了一波ret2dl-resolve
然后我们这里就利用将伪造的dynstr写入.bss,然后替换掉对应的.dynstr的方法。
我们这里的思路是将fflush替换掉
然后/bin/sh传入,从而起到利用的作用。
代码参考了hook大佬:
1 | # -*- coding:utf-8 -*- |
参考博客:
http://blog.xmsec.cc/blog/2016/06/27/ZIP%E4%BC%AA%E5%8A%A0%E5%AF%86/
http://www.moonsos.com/post/256.html