第一题

一个ctf的web的题,包括了php方面知识。


下面我们就对其进行分析
1
show_source() 函数对文件进行语法高亮显示。

然后下面有一个include,这里说一下,引用文件的方法有两种:require 及 include。两种方式提供不同的使用弹性。
这里的include也就是引用
require 的使用方法如 require(“MyRequireFile.php”); 。这个函数通常放在 PHP 程序的最前面,PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部份。常用的函数,亦可以这个方法将它引入网页中。
include 使用方法如 include(“MyIncludeFile.php”); 。这个函数一般是放在流程控制的处理部分中。PHP 程序网页在读到 include 的文件时,才将它读进来。这种方式,可以把程序执行时的流程简单化。
他们两个的用途是完全一样的,不一定非得哪个放在最前面哪个放在中间。他们最根本的区别在于错误处理的方式不一样。
require一个文件存在错误的话,那么程序就会中断执行了,并显示致命错误
include一个文件存在错误的话,那么程序不会中端,而是继续执行,并显示一个警告错误。
这个题是传参get 提交,满足条件就有 flag1 flag2
首先创建了两个GET变量a和b,然后进行了三次判断,
第一次判断,同时满足a=0和a为真才能显示出flag1这个变量。
因为php语言中“==”为弱类型判断,会自动把判断转为同类型再比较,
故php中可以得到“ab” == 0 为真,所以我们在URL栏手动传参a=ab:
此时就只出了一半

然后进行b的构造
第二次进行判断 使用is_numeric函数,is_numeric() 函数用于检测变量是否为数字或数字字符串。
因此我们要返回false,避免退出程序。从而进行第三步if判断
如果b> 1234输出$falg 我们构造“ ?a=a&b=1244m“ 这个后面的字母是防止第二步数字或者生成数字字符串。然后就返回$falg

第二题

原题代码:

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
<?php
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;

$a = $_GET['a'];
$b = $_GET['b'];

if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
$key1 = 1;
}else{
die("Emmm...再想想");
}
}else{
die("Emmm...");
}

$c=(array)json_decode(@$_GET['c']);
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL;
foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL;
}
$key2 = 1;
}else{
die("no hack");
}
}else{
die("no");
}

if($key1 && $key2){
include "Hgfks.php";
echo "You're right"."\n";
echo $flag;
}

?> Emmm...

枯燥的同时也是学习的积累,每个函数都有独特的用处,大致意思以下:
从 $_GET中获取名为c的参数值,并将其解码为php数组。这里使用了(array)强制类型转换和 json_decode() 函数来实现。
1
$c=(array)json_decode(@$_GET['c']);

检查$c是否为数组,$c[“m”] 是否为一个大于2022的数值,以及$c[“n”]是否为一个包含两个元素且第一个元素为数组的数组,如果这些条件都满足,就将$key1和$key2设置为true,否则将结束脚本,并输出相应的错误信息。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL;
foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL;
}
$key2 = 1;
}else{
die("no hack");
}
}else{
die("no");
}

如果$key1和$key2都为真,则包含一个名为Hgfks.php的文件,并输出一个$flag变量的消息。我们要的就是这个
1
2
3
4
5
if($key1 && $key2){
include "Hgfks.php";
echo "You're right"."\n";
echo $flag;
}

根据这段代码的分析,它的主要作用是验证用户提交的参数值,并且只有在这些参数符合一定的条件时才会输出一个包含$flag变量的消息。具体来说,如果c参数为一个非空数组,m值为一个大于2022的数值,n值为一个包含两个元素且第一个元素为数组的数组,同时$c[“n”]不包含字符串”DGGJ”,那么将输出一个包含$falg变量的消息。否则将输出一些错误信息并结束脚本的执行。
开头还是一个highlight_file()函数,是php当中的一个内置函数,他表示输出一个突出显示PHP语法的文件。
找到flag ,还是include函数(程序不会中断,而是继续执行,并显示一个警告错误。)
前面调用die:(die是一种用于输出一条消息并退出当前脚本的函数,该函数是exit()函数的别名,die函数的语法是“die(status)”,其参数status规定在退出脚本之前写入的消息或状态号)
if….else 语句在条件为 true 时执行代码,在条件为 false 时执行另一段代码。
符合条件输出,不符合die函数执行一条“Emmm…再想想“消息。

分析第一个条件
1
(isset($a) && intval($a) > 6000000 && strlen($a) <= 3)

Isset: 检测变量是否已设置并且非 NULL. 大于6000000 Intval: 强制类型转换,转换为整数类型 ; strlen:计算字符串的长度; 这句话判断a是非空的,转换为整数类型,且满足小于等于3
/?a=1e9
第二个

还是判断b非空, 有个函数是substr()函数;它用于返回字符串的一部分,但是应该返回多少呢,(-6,6) 真的无语,是后六位,还是MD5值,为8b184b,使用脚本,使用工具他不香吗,得到b的值为53724


脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import hashlib

n = 0

while True:

    m = hashlib.md5(str(n).encode('utf-8')).hexdigest()

    if m[-6:] == '8b184b':

        print(f"n = {n}, md5(n) = {m}")

        break

    n += 1

?a=1e9&b=53724
第三个
构造c,这确定是新手?
第一个判断
1
(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022)

json_decode:该函数主要用来将数组和对象,转换为json格式,
PHP is_array() 函数用来判断一个变量是否是数组,其语法格式如下:
如果参数是数组,就返回 true,否则返回 false。
is_numeric:检测字符串是否只由数字组成,如果字符串中只包括数字,就返回Ture,否则返回False
综上c是个json格式的参数,非空且不是数值类型(前面有个感叹号),且m键对应的值不为数字的同时需要满足大于2022
c的m键值后面还要做比较,因此不能直接简单构造一个is_numreric为false的字符串。例如,’123a’和一个整数作比较时,它会转换成123;’a123’和整数作比较时,由于第一个位置是a,非整数,php则规定其值为0,即变成了0和123比较
m:2023a
接下来是n:

有且仅有两个元素的数组,第一个值为数组,此处易于实现;第二个值要满足array_search(“DGGJ”, $c[“n”])返回为真,同时c[“n”]中又不能出现”DGGJ”。此处利用array_search函数在比较两者是否相等时是使用的弱类型比较。又由于”DGGJ”是既非数字字符串又非先导数字字符串的字符串,其在与数字进行比较时会转化为数字0。从而令c[‘n’]的第二个值为0。
n:[[6
综上