Challenge-21-25

Twenty-one

image.png

1
2
3
4
5
if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password))
{
echo 'Wrong Format';
exit;
}

正则匹配

[:graph:]:是除空格符(空格键与[TAB]键)之外的所有按
^ :匹配你要用来查找的字符串的开头
$:匹配结尾
{12,} :匹配重复12次或多次–>长度大于12

所以可见字符超过12个

1
2
3
$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
if (6 > preg_match_all($reg, $password, $arr))
break;

字符串中,把连续的符合,数字,大写,小写作为一段,
至少分六段,例如a12SD+io8可以分成a 12 SD + io 8六段

1
2
3
4
5
6
$ps = array('punct', 'digit', 'upper', 'lower');
foreach ($ps as $pt)
{
if (preg_match("/[[:$pt:]]+/", $password))
$c += 1;
}

$ps = 数组//[[:punct:]] 任何标点符号 [[:digit:]] 任何数字 [[:upper:]] 任何大写字母 [[:lower:]] 任何小写字母
进行匹配 ,如果password 匹配到了 就进行 +1 操作 赋给$c

1
2
if ($c < 3) break;
if ("42" == $password) echo $flag;

在匹配次数里面 $c 要大于3
大写,小写,数字,符号这四种类型至少要出现三种
但是最后$password 还要等于 42 就有点困难了
42 转换
转换成16进制
image.png
已经符合了正则3 这里的a 可以写成大写 x是小写
让它符合正则1也很容易,在前面补0就可以
image.png
但是还没有满足正则二的条件 差符合
可以使用科学计数法
image.png
但是感觉输入进去只有
420.000000000000e-1
这样才成功 ,因为.点会破坏判断相等时进行的转换
所以有- 才满足正则二
image.png

Twenty-two

image.png
找到一个MD5等于自己的字符串
源代码:
image.png
md5加密后两者还是相等,php弱类型比较,php若比较会截取字符串的数字,直到遇到字符才会停止,比如‘12x34’会被读取为12,而‘ee123’就会被读取为0。而在以0x开头的字符串进行弱比较的时候,就总是被认为是相同的。在这里我们就需要找到一个是0x开头并且md5加密后还是0x开头的字符串

image.png

Twenty-three

image.png
大概意思是传入 key1 key2
key1 的数据要=== Hello hacker!
key2 输入的数据md5 要大于 666666>666666
key3 要等于 666,但是有 intval函数 默认转成10进制
key4 如果大于0 ,k3 + k4 要小于 666
看着逻辑不是很难
一步步来

1
2
3
if(@file_get_contents($k1)==="Hello hacker!"){
echo 'welcome! Hacker!<br>';

k1 要强等于 Hello hacker!
一开始想到用php://input 去写 但是发现没有用 ,php://input 是要传post 数据的 (放弃)
又想到数据流 data 可以写入数据 ,
data://text/plain,base64,....
key1=data://test/plain;base64,SGVsbG8gaGFja2VyIQ==
image.png
绕过第一步 key1

1
if(md5($k2)>666666*666666)

传入key2 的md5 值要大于 他们相乘的值
使用作者的值 :1518375
他的md5 值全是数字
93240121540327474319550261818423
然后也可以使用弱类型
字符串为: skwerl11
MD5值为 :1e21ff98693770b768e4a1a4a704811b
1e 是科学计数法 ,然后后面的字符会当成数字来比较,直到没有数字为止
然后就是ke3了

1
2
3
4
5
if(intval($k3)<666)
{
if($k3==666)
{
echo 'Come on, flag is coming<br>';

k3 小于666 又要等于 666
采用 16进制
image.png
成功绕过 image.png
来到 key4

1
2
3
4
5
if($k4>0)
{
if(intval($k3+$k4)<666)
echo $flag;
}

小于 0 然后 相加还要小于 666
。。。。。
看了wp ,才了解到intval的表达范围是有限制的,取决于操作系统
可以使用溢出,
image.png

image.png
使用这个去绕过
999999999999999999999999999999999999999999999999996666
image.png
完整的payload :
key1=data://test/plain;base64,SGVsbG8gaGFja2VyIQ==&key2=skwerl11&key3=0x29a&key4=999999999999999999999999999999999999999999999999996666

Twenty-four

image.png

1
$a=(array)json_decode(@$_GET['foo']);

传入 foo 参数json格式的 数组

1
2
3
4
5
if(is_array($a)){
is_numeric(@$a["bar1"])?die("nope"):NULL;
if(@$a["bar1"]){
($a["bar1"]>2016)?$v1=1:NULL;
}

判断 $a[“bar1”] 是否满足 is_numeric,若满足则die掉。接下来又判断 $a[“bar1”] 是否大于 2016 。
使用弱类型绕过
bar1=2017a
这样is_numeric时会判断其为字符串而不是数字,而在与2016的比较中,会直接转换成2017,满足大于2016。这样 v1 就被设置为 1 了。

1
2
3
4
5
6
7
8
if(is_array(@$a["bar2"])){
if(count($a["bar2"])!==5 OR !is_array($a["bar2"][0])) die("nope");
$pos = array_search("nudt", $a["a2"]);
$pos===false?die("nope"):NULL;
foreach($a["bar2"] as $key=>$val){
$val==="nudt"?die("nope"):NULL;
}
$v2=1;

要求$a["bar2"]是个数组,其中元素的个数为5个(count($a["bar2"])!==5)
同时要求$a["bar2"][0]是数组。所以我们设置:$a["bar2"] = [[],2,3,4,5]
对于 $pos = array_search("nudt", $a["a2"]);,它搜索字符串“nudt”$a["a2"]中的位置。若没有找到,array_search返回false,会通过严格比较导致die掉。所以这里要设置$a["a2"] = “nudt”
注意这里因为用了$pos===false?的严格比较,所以0不===false
之后就能设置 v2 = 1
结合$a是由json_decode得来,所以第一个payload为:

foo={"bar1":"2017a","bar2":[[],2,3,4,5],"a2":["nudt"]}

1
2
3
4
5
6
7
8
$c=@$_GET['cat'];
$d=@$_GET['dog'];
if(@$c[1]){
if(!strcmp($c[1],$d) && $c[1]!==$d){
eregi("3|1|c",$d.$c[0])?die("nope"):NULL;
strpos(($c[0].$d), "htctf2016")?$v3=1:NULL;
}
}

先会用strcmp进行比较,利用数组array和字符串进行strcmp比较会返回null,而且数组array也不会等于字符串,我们可以设置cat[1]为一个数组。

接下来用eregi对拼接后的字符串$d.$c[0]进行正则匹配,若匹配到则die掉。而下一步又要求拼接字符串$c[0].$d中要有字符串“htctf2016”。这里利用%00eregi的截断功能,则在正则匹配eregi时在开头时就匹配结束掉。
strpos(($c[0].$d), "htctf2016")中,还要求“htctf2016”不能出现在开头。

payload:
?foo={"bar1":"2017e","bar2":[[],2,3,4,5],"a2":["nudt"]}&cat[0]=ahtctf2016&cat[1][]=&dog=%00

image.png

Twenty-five

image.png

1
2
3
if(strpos($key, "do_you_want_flag") !== false || strpos($value, "yes") !== false){
die("no hack");
}

这里不能使用 do_you_want_flag
然后这里和题目又很矛盾。。。。
image.png

查看师傅的wp 知道

在函数parse_url内部,如果url是以//开始,就认为它是相对url
而后认为url的部件从url+2开始。若p-s < 1也就是如果url为///x.php,则p = e = s = s + 2,函数将返回 NULL。
再看PHP_FUNCTION,line 351:
存在版本 :存在于php5.4.7以前

我这里和wp 又不太一样
image.png