青岑CTF Web 入门 EZPHP系列 详解(write up)

1.EZPHP

代码审计

  • show_source(__FILE__):展示当前文件的源代码。

  • include("flag.php"):包含flag.php文件,其中可能定义了$flag变量。

  • $a = $_GET['a']$b = $_GET['b']:通过GET请求接收参数ab

逻辑判断

第一层判断

if($a and $a == 0)

注意:如果$a直接为0,0 and ...会短路返回假,导致条件不成立。

$a就得满足以下要求:

  • 数值上不等于0。

  • 在布尔判断中为真(非零、非空字符串等)。

  • 绕过方法:使用科学计数法表示,如0e0

当字符串与数字进行松散比较“==”时,PHP会尝试将字符串转换为数字。而强比较“===”时会先看字面量类型相不相同,再看值。所以不同类型 强比较 都为false                                       

第二层判断

if(is_numeric($b))

  • 如果$b数字或数字字符串(如123"123"),则执行exit("nono");退出并输出"nono"。

  • 因此,必须让$b不是数字或数字字符串,以绕过此判断。

 第三层判断

if($b > 2026)

  • 在绕过is_numeric()后,要求$b的值大于2026。

  • 这里利用了PHP的弱类型比较:当字符串与数字进行松散比较时,PHP会尝试将字符串转换为数字。转换规则为:从字符串起始位置读取数字部分,直到遇到非数字字符停止;如果起始不是数字,则转换为0。

  • 因此,可以传入$b=2027abc,在比较$b > 2026时,字符串"2027abc"会被转换为数字2027,满足大于2026的条件。

payload:?a=0e0&b=2027abc

最后即可得出flag

拓展(弱比较“==”)

字符串vs数组                                                                                             

数组会转换为字符串,结果固定为 "Array"
var_dump("string" == []);         // false
var_dump("" == []);               // false
var_dump("Array" == []);          // false 空数组不等于"Array"
var_dump("0" == []);              // false

var_dump("test" == ["a"]);        // false,"Array" == "test"
var_dump("Array" == ["a", "b"]);  // true!数组转字符串是"Array"
var_dump([1,2] == "Array");       // true!

字符串vsnull

"" == null    // true
其他都为false

数字vsnull

0 == null       // true 
0.0 == null     // true
-0 == null      // true
1 == null       // false
-1 == null      // false
3.14 == null    // false

字vs数组

空数组 []​ 在数字上下文中转换为 0
非空数组​ 不会简单地转换为数字,通常保持为数组
0 == []     // true
0.0 == []   // true
0 == [1]    // false
0 == [0]    // false
0 == ["a"]  // false

数组vsnull

null == []     // true
null == [1]       // false
null == [0]       // false
null == [""]      // false
null == ["a"]     // false
null == [[]]      // false(嵌套空数组也是非空数组)

2.EZPHP_2

代码审计

if (!isset($_GET['qc']) || $_GET['qc'] === '')

  • 要求get传参qc且不为空,不然就退出并返回no

$qc = (array)json_decode($_GET['qc'], true)

  • 对$qc进行数组化处理,(array)和json_decode作用一样,都是将其变为数组

json_decode()是 PHP 中用于解析 JSON 字符串并将其转换为 PHP 变量的内置函数。

mixed json_decode(
    string $json, 
    bool $associative = false, 
    int $depth = 512, 
    int $flags = 0
)
参数说明
$json:要解码的 JSON 格式字符串
$associative:
   false(默认):返回对象(stdClass)
   true:返回关联数组
$depth:最大递归深度(默认 512)
$flags:解码选项位掩码

$key = array_search("QCCTF", $qc)

  • 定义了一个新变量$key,其值等于从$qc数组中找出QCCTF的键

array_search()是 PHP 中用于在数组中搜索给定值并返回对应键名的函数


mixed array_search(
    mixed $needle, 
    array $haystack, 
    bool $strict = false
)
$needle:要搜索的值
$haystack:被搜索的数组
$strict:
false(默认):松散比较(==)
true:严格比较(===)

if($key === 1)

  • 要求键值为1不然不输出flag
  • 所以可以看出来$qc的QCCTF的序列为1

可以构建payload:/?qc=["anything", "QCCTF"] 得出flag

PHP中定义数组的方法1.基本定义2.特殊数组定义3.函数定义(2.3可跳过)

1.基本定义

array()语言结构:

// 索引数组
$arr1 = array("apple", "banana", "cherry");

// 关联数组
$arr2 = array("name" => "Alice", "age" => 25);

// 多维数组
$arr3 = array(
    "fruits" => array("apple", "banana"),
    "numbers" => array(1, 2, 3)
);

简短语法 []:
// 索引数组
$arr1 = ["apple", "banana", "cherry"];

// 关联数组
$arr2 = ["name" => "Alice", "age" => 25];

// 多维数组
$arr3 = [
    "fruits" => ["apple", "banana"],
    "numbers" => [1, 2, 3]
];
2.特殊数组定义

空数组
$empty1 = array();
$empty2 = [];

自动索引数组
$arr = [];
$arr[] = "first";   // 索引 0
$arr[] = "second";  // 索引 1
$arr[10] = "jump";  // 索引 10
$arr[] = "next";    // 索引 11(自动递增)

混合键类型
$arr = [
    0 => "zero",      // 整数键
    "1" => "one",     // 字符串"1"自动转为整数1
    1.5 => "float",   // 浮点数1.5转为整数1
    true => "bool",   // true转为1
    false => "bool2", // false转为0
    null => "null"    // null转为空字符串""
];
// 结果:最后写入的覆盖前面的相同键

list()解构赋值
// 从数组解构到变量
$info = ["Alice", 25, "USA"];
list($name, $age, $country) = $info;

// 简短语法
[$name, $age, $country] = ["Alice", 25, "USA"];

// 跳过来些元素
[, $age,] = ["Alice", 25, "USA"];  // 只获取年龄
3.通过函数创建数组

range()创建数值范围
$numbers = range(1, 5);        // [1, 2, 3, 4, 5]
$letters = range('a', 'd');    // ['a', 'b', 'c', 'd']
$steps = range(0, 10, 2);      // [0, 2, 4, 6, 8, 10]

explode()字符串转数组
$str = "apple,banana,cherry";
$arr = explode(",", $str);     // ["apple", "banana", "cherry"]

str_split()字符串分割
$str = "Hello";
$arr = str_split($str);        // ["H", "e", "l", "l", "o"]
$arr = str_split($str, 2);     // ["He", "ll", "o"]

array_fill()填充数组
$arr = array_fill(0, 5, 'test');  // [0=>'test', 1=>'test', ... 4=>'test']
$arr = array_fill(5, 3, 'xyz');   // [5=>'xyz', 6=>'xyz', 7=>'xyz']

array_combine()合并键值
$keys = ["name", "age", "city"];
$values = ["Alice", 25, "NY"];
$arr = array_combine($keys, $values);
// 结果:["name"=>"Alice", "age"=>25, "city"=>"NY"]

3.EZPHP_2

代码审计

if (!isset($_GET['qc']) || $_GET['qc'] === '') exit("no");
$qc = (array)json_decode($_GET['qc'], true);

  • 同上文一样,就不赘述了

if (!isset($qc["n"]) || !is_array($qc["n"]) || empty($qc["n"]))

  • 检查$qc中是否有n这个键,且其值为一个数组,且其不为空

if (array_search("QCCTF", $qc) === false) die("no...");
if (array_search("QCyyds", $qc["n"]) === false) die("no...")

  • 从$qc中查找是否有QCCTF这个值,没有则false
  • 检查n对于的数组值是否为等于QCyyds,但array_search()函数为弱类型比较,相当于“==”
  • 所以若n对应的数组的值为0,注意不是字符串,则0=“QCyyds'”为true

foreach ($qc["n"] as $val) {
    if ($val === "QCyyds") die("no......")

  • 遍历n对应的值有没有QCyyds,有就die
  • 所以综上可以构造payload?qc={"n":[0],"0":"QCCTF"}

得到flag

内容概要:本文详细介绍了作者在青岑靶场完成“OhNativeEnc”逆向挑战题的解题思路与过程。首先通过分析提供的APK文件,发现关键验证逻辑位于原生so库中,随后利用Ghidra工具对lib目录下的so文件进行逆向分析,定位到核心校验函数Java_work_pangbai_ohnativeenc_FirstFragment_checkFlag。进一步分析发现该函数使用XXTEA算法对输入进行加密,并与预设密文(DAT_00102ec9)比对;已知密钥为“ThisIsAXXteaKey”,结合密文数据并通过逆向脚本还原出原始flag为flag{Ur_G00d_@_n@tive_Func},最终成功提交。整个过程涵盖了APK结构解析、动态提示分析、so文件逆向、加密算法识别与解密还原等关键技术环节。; 适合人群:对移动安全、逆向工程感兴趣的网络安全初学者或有一定基础的研发人员,尤其是希望提升Android native层分析能力的学习者。; 使用场景及目标:①学习如何使用Ghidra等逆向工具分析APK中的so文件;②掌握XXTEA加密算法的识别与逆向解密方法;③理解JNI函数命名规则及native层校验逻辑的常见实现方式;④实战演练从提示信息入手逐步深入分析CTF逆向题目的完整流程。; 阅读建议:建议读者结合文中提到的工具(如Ghidra)和参考资料动手实践,尝试复现每一步操作,尤其应重点关注加密函数的识别与解密脚本的编写过程,以加深对native层保护机制的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值