0x0 背景
弃坑Arcaea
一年多了,周六还是偶然打开某arc群时还是发现几个大佬在发 Hackergame 2021
排名截图。真巧,今年也来玩一玩。不过现在变身成为打工人后空闲时间只顾着咸鱼了,花了一上午挑了一些简单的题目做完后直接摆烂了......
0x1 题目
签到
众所周知本题应该不难,上来是需要在限定时间内手写2022
并通过识别后提交。打开HTML
源码看到是Vue
写的,第一时间就是修改时间限制。但往下翻翻发现提交函数直接拼接了识别结果。果然还是想难了.....随便提交一个结果后将传参改为?result=2022
即可。
flag{HappyHacking2022-1a3d895fa6}
猫咪问答 Pro Max
参考历年题目,考察信息搜索能力。
中国科学技术大学 NEBULA 战队(USTC NEBULA)是于何时成立的喵?
直接Google搜索USTC NEBULA成立时间
得知为2017-03
。
2022 年 9 月,中国科学技术大学学生 Linux 用户协会(LUG @ USTC)在科大校内承办了软件自由日活动。除了专注于自由撸猫的主会场之外,还有一些和技术相关的分会场(如闪电演讲 Lightning Talk)。其中在第一个闪电演讲主题里,主讲人于 slides 中展示了一张在 GNOME Wayland 下使用 Wayland 后端会出现显示问题的 KDE 程序截图,请问这个 KDE 程序的名字是什么?
Google LUG @ USTC GNOME Wayland
可找到并下载Slides,截图在第15页,注意一条菜单项叫Configure Kdenlive
,那程序名就很明显了。
22 年坚持,小 C 仍然使用着一台他从小用到大的 Windows 2000 计算机。那么,在不变更系统配置和程序代码的前提下,Firefox 浏览器能在 Windows 2000 下运行的最后一个大版本号是多少?
Google Windows 2000
可得12
你知道 PwnKit(CVE-2021-4034)喵?据可靠谣传,出题组的某位同学本来想出这样一道类似的题,但是发现 Linux 内核更新之后居然不再允许 argc 为 0 了喵!那么,请找出在 Linux 内核 master 分支(torvalds/linux.git)下,首个变动此行为的 commit 的 hash 吧喵!
找到此仓库torvalds/linux: Linux kernel source tree (github.com)并搜索CVE-2021-4034
可得dcd46d897adb70d63e025f175a00a89797d31a43
通过监视猫咪在键盘上看似乱踩的故意行为,不出所料发现其秘密连上了一个 ssh 服务器,终端显示 ED25519 key fingerprint is MD5:e4:ff:65:d7:be:5d:c8:44:1d:89:6b:50:f5:50:a0:ce.,你知道猫咪在连接什么域名吗?
直接GoogleMD5:e4:ff:65:d7:be:5d:c8:44:1d:89:6b:50:f5:50:a0:ce
可以在第二页找到ssh.log — Book of Zeek (git/master)此页面。在#outbound-movement
中可发现连接的IP地址为205.166.94.16
。直接访问看邮箱域名可得sdf.org
。
中国科学技术大学可以出校访问国内国际网络从而允许云撸猫的“网络通”定价为 20 元一个月是从哪一天正式实行的?
Google中国科学技术大学 网络通 20元
可以找到关于实行新的网络费用分担办法的通知-中国科学技术大学 (ustc.edu.cn)此页面。得知旧的费用分担办法已经为20元一个月。使用关键词网络费用分担办法的通知 2003年
在Google没搜到结果,百度居然给了结果关于实行新的网络费用分担办法的通知 (ustc.edu.cn)。由文件可知2003-03-01
flag1:flag{meowexammeow_772b498346fe0925_1e02f422c8}
flag2:flag{meowexamfullymeowed!_6c159adddb7f171b_8f2fb889d9}
家目录里的秘密
用过rclone,知道配置文件默认在.config
下,翻了下发现Code
也在这个目录,一顿翻找找到user\.config\Code\User\History\2f23f721\DUGV.c
文件。这才知道原来VSCode
有保存历史文件。然后想到直接全文检索flag
其实更容易定位到......
说回rclone,此前尝试写世纪互联版OneDrive的实现时有研究过rclone。知道rclone将明文密码”加密“后保存。这次打开配置文件后可以看出ftp的各种配置都没啥用,只有pass
字段值的钻研下。rclone加密的方式在rclone/obscure.go at master · rclone/rclone (github.com)。最优解是调用此func Reveal(x string)
:
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"errors"
"fmt"
)
// crypt internals
var (
cryptKey = []byte{
0x9c, 0x93, 0x5b, 0x48, 0x73, 0x0a, 0x55, 0x4d,
0x6b, 0xfd, 0x7c, 0x63, 0xc8, 0x86, 0xa9, 0x2b,
0xd3, 0x90, 0x19, 0x8e, 0xb8, 0x12, 0x8a, 0xfb,
0xf4, 0xde, 0x16, 0x2b, 0x8b, 0x95, 0xf6, 0x38,
}
cryptBlock cipher.Block
cryptRand = rand.Reader
)
// crypt transforms in to out using iv under AES-CTR.
//
// in and out may be the same buffer.
//
// Note encryption and decryption are the same operation
func crypt(out, in, iv []byte) error {
if cryptBlock == nil {
var err error
cryptBlock, err = aes.NewCipher(cryptKey)
if err != nil {
return err
}
}
stream := cipher.NewCTR(cryptBlock, iv)
stream.XORKeyStream(out, in)
return nil
}
// Reveal an obscured value
func Reveal(x string) (string, error) {
ciphertext, err := base64.RawURLEncoding.DecodeString(x)
if err != nil {
return "", fmt.Errorf("base64 decode failed when revealing password - is it obscured?: %w", err)
}
if len(ciphertext) < aes.BlockSize {
return "", errors.New("input too short when revealing password - is it obscured?")
}
buf := ciphertext[aes.BlockSize:]
iv := ciphertext[:aes.BlockSize]
if err := crypt(buf, buf, iv); err != nil {
return "", fmt.Errorf("decrypt failed when revealing password - is it obscured?: %w", err)
}
return string(buf), nil
}
func main() {
out, _ := Reveal("tqqTq4tmQRDZ0sT_leJr7-WtCiHVXSMrVN49dWELPH1uce-5DPiuDtjBUN3EI38zvewgN5JaZqAirNnLlsQ")
fmt.Println(out)
}
跑一下就得到了结果。
整活解法:
- pip3 install pyftpdlib
- 修改site-packages
- 开启服务器
python -m pyftpdlib -D
成功打印出密码
VSCode:flag{finding_everything_through_vscode_config_file_932rjdakd}
Rclone: flag{get_rclone_password_from_config!_2oi3dz1}
HeiLang
来自 Heicore 社区的新一代编程语言 HeiLang,基于第三代大蟒蛇语言,但是抛弃了原有的难以理解的
|
运算,升级为了更加先进的语法,用A[x | y | z] = t
来表示之前复杂的A[x] = t; A[y] = t; A[z] = t
。作为一个编程爱好者,我觉得实在是太酷了,很符合我对未来编程语言的想象,科技并带着趣味。
这里描述很乐,根据描述的语法来修复代码即可。
with open('getflag.hei.py', 'r') as f:
lines = f.readlines()
for i in range(0, len(lines)):
if lines[i].startswith('a['):
indexs = lines[i].split('[')[1].split(']')[0].split('|')
result = lines[i].split('=')[1].strip()
lines[i] = ''
for index in indexs:
index = index.strip()
lines[i] += f'a[{index}] = {result};'
with open('getflag.hei.fixed.py', 'w') as f:
f.writelines(lines)
最后一下修复后的代码得到flag
flag{6d9ad6e9a6268d96-cb74a571dc764044}
Xcaptcha
拿到这题后发现是延时1秒自动提交结果,首先的想法是抓包再手动提交。抓包后用Python逐个计算了下结果提交后发现还是返回验证失败:超过 1 秒限制
。
搞不清楚后端是如何判断时间是否超时的,第一个怀疑是通过Cookie,奈何技术力低下看不懂如何解Cookie就跳过了,不过看起来Cookie像是JWT Token。接下来尝试了给请求Header加Date
,时间改到了2042年,未果。然后就没有头绪了,只能尝试硬解。拿出Tampermonkey
写了一段脚本后通过计算:
function cal(captcha){
let split = captcha.split('+');
let left = BigInt(split[0]);
split = split[1].split(' ');
let right = BigInt(split[0]);
let result = left + right;
return result;
}
(function() {
'use strict';
let captcha1 = document.querySelector("label[for=captcha1").textContent;
document.getElementById('captcha1').value=cal(captcha1);
let captcha2 = document.querySelector("label[for=captcha2").textContent;
document.getElementById('captcha2').value=cal(captcha2);
let captcha3 = document.querySelector("label[for=captcha3").textContent;
document.getElementById('captcha3').value=cal(captcha3);
document.getElementById('submit').click();
})();
拿到flag后看意思果然应该还是在header里做文章,等题解......
flag{head1E55_br0w5er_and_ReQuEsTs_areallyour_FR1ENd_c6c5697944}
旅行照片 2.0
今年的旅行照片居然没有隐去EXIF,第一题查看EXIF即可得到答案:
flag{1f_y0u_d0NT_w4nt_shOw_theSe_th3n_w1Pe_EXlF}
第二题未解完:
酒店:
- 放大图片观察建筑可以看到
WELCOME TO ZOZOMA***E STADIUM
,谷歌得知地点为日本千叶ZOZO海洋球场。查看对面大概位置酒店的邮编即可2610021
- 根据上题EXIF得知手机厂商为小米,CPU为sm6115,即高通骁龙662。那么对应的手机为红米Note 9。分辨率为
2340x1080
航班:
- 地图放大后看附近机场,再看飞行方向猜测很大可能是羽田机场起飞。但查航线回放时发现要会员,也懒得遍历就摆烂了......
Flag 自动机
这题用动态调试+patch过了。永远无法触及的狠心夺取
按钮直接不管,我们要做的是让放手离开
按钮按下后执行打印flag的逻辑。IDA打开后发现无法调试,找了找方法发现sub_4083AC
中检测了调试器,直接把call exit
nop掉即可。
查看sub_401510
伪代码:
LRESULT __stdcall sub_401510(HWND hWndParent, UINT Msg, WPARAM a3, LPARAM lParam)
{
size_t v4; // eax
FILE *Stream; // [esp+40h] [ebp-18h]
void *Block; // [esp+44h] [ebp-14h]
HFONT wParam; // [esp+48h] [ebp-10h]
unsigned int dwNewLong; // [esp+4Ch] [ebp-Ch]
switch ( Msg )
{
case 2u:
PostQuitMessage(0);
break;
case 0x111u:
if ( (_WORD)a3 == 2 )
PostQuitMessage(0);
if ( (_WORD)a3 == 3 )
{
if ( lParam == 114514 )
{
Block = (void *)sub_401F8A(hWndParent, 114514);
MessageBoxW(hWndParent, "m`淯`O穬梍 ", L"Congratulations", 0);
Stream = fopen("flag_machine.txt", "w");
if ( !Stream )
{
MessageBoxW(hWndParent, "噀鯪Sb", "E", 0);
free(Block);
exit(-1);
}
v4 = strlen((const char *)Block);
fwrite(Block, 1u, v4, Stream);
fclose(Stream);
free(Block);
}
else
{
MessageBoxW(hWndParent, "穬諷 ", "E", 0);
}
}
break;
case 1u:
hWnd = CreateWindowExW(0, "B", "鄏胈:Y諷", 0x50000000u, 85, 150, 80, 25, hWndParent, (HMENU)3, 0, 0);
dword_40B024 = CreateWindowExW(0, "B", ">eKb粂", 0x50000000u, 185, 150, 80, 25, hWndParent, (HMENU)2, 0, 0);
dword_40B028 = CreateWindowExW(
0,
&word_40A04A,
lpWindowName,
0x50000000u,
85,
100,
300,
20,
hWndParent,
(HMENU)1,
0,
0);
dwNewLong = GetWindowLongA(hWndParent, -16) & 0xFFFEFFFF;
SetWindowLongA(hWndParent, -16, dwNewLong);
wParam = CreateFontW(12, 0, 0, 0, 400, 0, 0, 0, 0x86u, 0, 0, 2u, 0x12u, "媅SO");
SendMessageA(hWndParent, 0x30u, (WPARAM)wParam, 1);
SendMessageA(hWnd, 0x30u, (WPARAM)wParam, 1);
SendMessageA(dword_40B024, 0x30u, (WPARAM)wParam, 1);
SendMessageA(dword_40B028, 0x30u, (WPARAM)wParam, 1);
break;
}
return DefWindowProcW(hWndParent, Msg, a3, lParam);
}
可以发现重要的判断有if ( (_WORD)a3 == 3 )
和if ( lParam == 114514 )
,而动调sub_401510
时可发现当按下放手离开
按钮,a3 = 2
,那么只需patch程序,调换下条件即可。另外需要保证[ebp+lParam]
为114514 mov [ebp+lParam], 114514
。
flag{Y0u_rea1ly_kn0w_Win32API_89ab91ac0c}
Flag 的痕迹
(题目 Dokuwiki 版本基于 2022-07-31a "Igor")
看到题目强调版本,我感觉可能有些问题,故而翻了翻官方的commit历史,然后翻到了这条SECURITY fix difftype handling. #3761
SECURITY fix difftype handling. #3761 · splitbrain/dokuwiki@63e9a24 (github.com)。
进去看了下,没用到这个XSS,但发现原来?do=diff
即便在revisions
关掉后也可以查看历史。那往前翻翻到这就发现flag啦/doku.php?id=start&do=diff&rev2[0]=1665224461&rev2[1]=1666320802&difftype=sidebyside
flag{d1gandFInD_d0kuw1k1_unexpectEd_API}
微积分计算小练习
看了看网页源码后可以发现直接将query丢到了innerHTML
。摆明了就是要XSS,而”后台“也是拿面页里的数据来用。拿注入一下打印cookie
就好了。
100:<img src=x onerror="document.querySelector('#greeting').innerText=document.cookie">
flag{xS5_1OI_is_N0t_SOHARD_d94d8efdc1}
0x2 尾巴
怎么说呢,感觉近期动力不充足。白天工作完了晚上也有项目,一周到了末尾只想咸鱼,逛逛B站、打打游戏,其它什么都不想动。这一年也没什么目标基本没有再钻研过逆向,没有掌握新逆向知识。感觉这个状态不对,但不知道怎么走出来......
最后分数: