友情链接
前言
时隔一年,又迎来了一年一度的hacker game,不得不说的是,去年也为了写题解而建了博客,只不过一直在咕而已TT。
P.S.今年我的排名可以说比去年高了整整几百名,并且整场比赛打下来也对于网络安全意识方面有着不止一星半点的提高。并且能取得这样的成绩也是我所没有预想到的,很开心的hhhhhh。
那么切入正题,今年的hacker game在打的过程中我能明显地感受到和去年不同,有些题目有思路,而且知道往哪里去想 (虽然也不会做就是了) 具体的做题顺序已经忘了,先从签到题开始说起。
签到
正解:进入网页,观察到需要画文字经由识别成2022签下即可拿到flag,但画字时间逐渐减小,所以说明存在其他解法,点击提交发现Url上增加query参数 ?result=????
将????更改为2022提交Url即可拿到flag
歪解:查看题解之后发现原网页模型识别基于点落得位置进行数字的判断,所以尝试
也是可行的。
猫咪问答喵
第一问:
谷歌USTC Nebula即可查询到此页面点击查看,查看到最后一段
中国科学技术大学“星云战队(Nebula)”成立于2017年3月
得到答案2017-03
第二问:
谷歌LUG活动,查询到历史FSD数据
点击slides查看到相关pdf
发现到关键字 Configure Kdenlive
猜测是Kdenlive (注意首字母要大写)
尝试可得答案即为Kdenlive
第三问:
谷歌搜索firefox on windows 2000
上面写的是10,但是答案不对,尝试往上增加版本号,12即为正确版本号,其实帖子下面也说了,12是最后的版本)))但当时我没看见
第四问:
找到 torvalds/linux.git
的Github地址
转到commit尝试搜索argc无果后,搜索题中所给 CVE-2021-4034
关键字得到commit结果
复制即可得到答案 dcd46d897adb70d63e025f175a00a89797d31a43
第五问:
考察搜索引擎使用方法,直接搜肯定是不行的,引擎会自动拆分关键字,应该在引擎中搜索 "e4:ff:65:d7:be:5d:c8:44:1d:89:6b:50:f5:50:a0:ce"
字段,引号表示强匹配,得到链接
进入查看可得网址为sdf.org 吻合题目说明域名为1996年创建
p.s.:其实一开始想太多了,还想到有没有什么方法可以从md5算法逆向出来原url,还是经过别人提醒才想到的搜索就行了,惭愧惭愧hhhhh
第六问:
谷歌搜索 USTC 网络通 20元
发现啥都没有,进入官网搜索关键字网络通,经过一番查找定位到网字文件,尝试 2011-01-01
发现答案不对,查看文件发现2003年存在老的网字文件,尝试即可得到答案为 2003-03-01
家目录里的秘密
观察一通,发现flag可能藏在隐藏目录里,拿出everything,搜索到
存在两个可疑文件
rclone.conf 对应rclone
DUGV.c 对应vscode
打开DUGV.c,看到注释直接出现flag{finding_everything_through_vscode_config_file_932rjdakd}
打开rclone.conf,看到文本内容为
猜测从逆向密码入手
谷歌 how to reverse rclone password
慢慢搜索发现rclone forum有人提到
How to retrieve a 'crypt' password from a config file - Help and Support - rclone forum
应该是go写的,把代码稍作修改
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"errors"
"fmt"
"log"
)
// 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
}
// MustReveal reveals an obscured value, exiting with a fatal error if it failed
func MustReveal(x string) string {
out, err := Reveal(x)
if err != nil {
log.Fatalf("Reveal failed: %v", err)
}
return out
}
func main() {
fmt.Println(MustReveal("tqqTq4tmQRDZ0sT_leJr7-WtCiHVXSMrVN49dWELPH1uce-5DPiuDtjBUN3EI38zvewgN5JaZqAirNnLlsQ"))
}
扔到一个在线go后端跑一下,得到flag
HeiLang
作为一名理工男,不觉得这道题很酷吗,完全符合我对未来生活的想象,科技并带着趣味😎
点开发现酷炸了,一千多行
既然如此我也耍个酷,写个简短的c#程序处理一下文件(把文件的前面和后面多余代码全部去掉,只留下科技与狠活的位置)
static void Main(string[] args)
{
string text = "";
var lines = File.ReadLines("txt.txt");
foreach (var line in lines)
{
var ansandre = line.Split("=");
var anses = ansandre[0];
var re = ansandre[1];
var anss = anses.Replace("a[", "").Replace("]", "").Split("|");
foreach (var ans in anss)
{
text += $"a[{ans.Trim()}]={re.Trim()}\n";
}
}
File.WriteAllText("txt1.txt", text);
}
}
处理完后把科技与狠活粘贴回去
此时我们已经对helang的语言进行了全面的翻译,这时进行运行即可得到何同学赋予我们最终的答案。
Tha flag is: flag{6d9ad6e9a6268d96-add67fb6bea2f786}
Xcaptcha
进入题目
点击图片后出现如下题目,且停留时间只有一秒钟
解题思路是用c#请求页面,然后正则取出对应的值,用大整数类进行计算然后post回去,但是当时不论怎么尝试都显示已经超过1s,百思不得解,后来魏佬提醒每次新题都会下发新的session,需要进行session的替换,所以得到flag,代码如下:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Numerics;
using System.Text;
using System.Text.RegularExpressions;
namespace test
{
class Program
{
public static List<string> StartPos = new();
public static List<string> EndPos = new();
public static List<string> Flight = new();
public static string Session = "";
static void Main(string[] args)
{
var con = GetHttp("http://202.38.93.111:10047/xcaptcha");
var match1 = Regex.Match(con, @"(?<=( <label for=""captcha1"">)).*(?=( 的结果是?</label>))");
var match2 = Regex.Match(con, @"(?<=( <label for=""captcha2"">)).*(?=( 的结果是?</label>))");
var match3 = Regex.Match(con, @"(?<=( <label for=""captcha3"">)).*(?=( 的结果是?</label>))");
string num1, num2, num3, num4, num5, num6;
num1 = match1.Value.Split("+")[0];
num2 = match1.Value.Split("+")[1];
num3 = match2.Value.Split("+")[0];
num4 = match2.Value.Split("+")[1];
num5 = match3.Value.Split("+")[0];
num6 = match3.Value.Split("+")[1];
Console.WriteLine(PostHttp("http://202.38.93.111:10047/xcaptcha",
$"captcha1={BigInteger.Parse(num1) + BigInteger.Parse(num2)}&captcha2={BigInteger.Parse(num3) + BigInteger.Parse(num4)}&captcha3={BigInteger.Parse(num5) + BigInteger.Parse(num6)}"));
}
public static string GetHttp(string url)
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "text/html; charset=UTF-8";
request.Headers.Add("Cookie",
"DOKU_PREFS=list#rows#sort#name; session=.eJwVUMlOQlEM_Ze3fomdBxIXjAaeQkwkuFVAERRlUEiM_-5l0UV7eob2tzouz8eqVaGZAycoJSaFOmudiOgSxEnCaoJBEGASQBGWyEqeUVsIOKNbEjMHm6ISuCF4hCgpMCDWKeFg7KSFV7RUkpQQ1dQJIAiNhWtCAHQPJODwIh3JnGacWeYlH1qAa01paCmFqiAeZYNQSrGrkCIVZwvlOkAA1b0ku8CRfrktUVNY_CJ_Marq6vi5WW7LJ0qrrbv-fXfYhdVksu-s50t88nOzHTSLKc5uD_PhwTk-9DmaMXzvbmD30H5rb86jEze9_SI63psNBuNpu1ntOuv-y9do-_izf7866XQ1X2_Pr9fX1d8_HZBbKQ.Y1z_TA.Fhw3bYP9PAmTMnAvS2sTAg0ut3E");
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
Session = response.Headers.Get(name: "set-cookie");
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
string retString = myStreamReader.ReadToEnd();
myResponseStream.Close();
myResponseStream.Close();
return retString;
}
public static string PostHttp(string url, string postData)
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
request.Headers.Add("Cookie", Session);
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse) request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
string retString = myStreamReader.ReadToEnd();
myResponseStream.Close();
myResponseStream.Close();
return retString;
}
}
}
即可得到flag:flag{head1E55_br0w5er_and_ReQuEsTs_areallyour_FR1ENd_45339267b3}
旅行照片2.0
第一问
上传至exif信息网站即可获得
即可获得答案:
第二问
通过分析照片上远处建筑物牌子上的字即可发现信息
看出来是ZOZOXXXXXXX Staduim
谷歌得到是zozo marine stadium
题目上说是拍照人所在地点的邮政编码 (并非体育馆邮政编码)
得到附近酒店邮编为2610021 (体育馆邮编是2610020)
通过上一题juice sm6115+xiaomi可搜到是红米Note9,闪光灯位置也可以通过反光看出来很吻合。
所以答案为2340x1080
难点在于航班,首先看到是下午六点二十三分左右拍摄得到,是日本东京时间,所以搜索flightaware在时间点附近的航班逐一排除即可。根据飞机飞向可得是东北方向,所有离港航班均会经过此处,进港航班全部排除掉,所以暴力搜索可得
即可得到flag
Latex机器人
谷歌Latex inject得到
所以得到flag
第二问不会,当时想着是要执行shell的
\immediate\write18{}
结果试了好久也没尝试出来。
Flag的痕迹
这一题是随便尝试出来的,首先尝试了?rev=1666291980
因为发现规律是rev的赋值是修改的时间戳,结果发现
然后又尝试了
发现revision相关的功能都寄了
走投无路之下,尝试了http://202.38.93.111:15004/doku.php?id=start&rev=1666292040&do=diff
diff功能是比对两次文件的修改
拿到flag
线路板
用kicad打开ebaz_sdr-F_Cu.gbr
,打开显示边界可以看出来flag
Flag自动机
个人认为是这场比赛最满意的一题,因为是人生中第一次做出binary。
打开软件,发现点不到狠心读取。
用ida打开
经过分析可得exit函数引用如下
分析主要函数在sub_401510
考虑动态调试干掉前面判断
用x32附加进程
把401840之前的函数全部nop掉,让他进入执行即可得到flag
杯窗鹅影
第一问
很简单,写个读取文件的c就好了
#include <stdio.h>
int main(void)
{
int ch;
FILE *fp;
fp = fopen("/flag1", "r");
while ((ch = fgetc(fp)) != EOF)
{
putchar(ch);
}
return 0;
}
得到flag
第二问(NOT SOLVED)
当时考虑的是使用win32api的CreatProcess函数创建/readflag进程,结果不知道为什么在服务器端一直都无法调起进程,导致这问完全不会了)思路就这么僵死了
惜字如金
第一问
HS384脚本如下
#!/usr/bin/python3
# Th siz of th fil may reduc after XZRJification
from bas64 import urlsaf_b64encod
from hashlib import sha384
from hmac import digest
from sys import argv
def check_equals(left, right):
# check whether left == right or not
if left != right: exit(0x01)
def sign(fil: str):
with open(fil, 'rb') as f:
# import secret
secret = b'ustc.edu.cn'
check_equals(len(secret), 39)
# check secret hash
secret_sha384 = 'ec18f9dbc4aba825c7d4f9c726db1cb0d0babf47f' +\
'a170f33d53bc62074271866a4e4d1325dc27f644fdad'
check_equals(sha384(secret).hexdigest(), secret_sha384)
# generat th signatur
return digest(secret, f.read(), sha384)
if __nam__ == '__main__':
try:
# check som obvious things
check_equals('creat', 'cr' + 'at')
check_equals('referer', 'refer' + 'rer')
# generat th signatur
check_equals(len(argv), 2)
sign_b64 = urlsaf_b64encod(sign(argv[1]))
print('HS384 sign:', sign_b64.decod('utf-8'))
except (SystemExit, Exception):
print('Usag' + 'e: HS384.py <fil' + 'e>')
可以看出来这是一份被惜字如金过的脚本,观察secret应该是有39位的,且有供验证secret具体值的sha384,所以分析secret被惜字如金前的排列组合
首先分为两类:一类是辅音字母消除,一类是元音字母消除 元音字母分为两种:一类是原先就没有e的,另一种是e跟在c后面的,也就是ustce.edu.cn
,一类是e在n后面的,也就是ustc.edu.cne
,最后一种是包含两种状态ustce.edu.cne
。
辅音字母包含s,t,c,d,c,n重复的状态,也就是有可能为ussstttttcc.eduuuu.cccccccccn
这种组合,也就是说,可以循环遍历每一位上所有组合并叠加,符合总位数为39位,进行sha384和脚本中的验证值中的一串数字作为比较即可(选择数字是因为数字不会被惜字如金)。
以下是寻找secret值的脚本
// us |a| t |b| c |c|.ed |d| u.c |e| n |f|
//39
// ustc.edu.cn
using System.Security.Cryptography;
using System.Text;
using Utils.Encrypt;
namespace ConsoleApp1;
public static class Program
{
public static void Main()
{
string sa = "us";
string sb = "t";
string sc = "c";
string sd = ".ed";
string se = "u.c";
string sf = "n";
string result = "";
//no e
{
for (int a = 0; a <= 28; a++)//s
{
for (int b = 0; b <= 28; b++)//t
{
for (int c = 0; c <= 28; c++)//c
{
for (int d = 0; d <= 28; d++)//d
{
for (int e = 0; e <= 28; e++)//c
{
for (int f = 0; f <= 28; f++)//n
{
if (a + b + c + d + e + f == 28)
{
result += sa;
for (int i = 0; i < a; i++)
{
result += "s";
}
result += sb;
for (int i = 0; i < b; i++)
{
result += "t";
}
result += sc;
for (int i = 0; i < c; i++)
{
result += "c";
}
result += sd;
for (int i = 0; i < d; i++)
{
result += "d";
}
result += se;
for (int i = 0; i < e; i++)
{
result += "c";
}
result += sf;
for (int i = 0; i < f; i++)
{
result += "n";
}
if (Hash.SHA384(result).Contains("62074271866"))
{
Console.WriteLine(result);
}
result = "";
}
}
}
}
}
}
}
}
sa = "us";
sb = "t";
sc = "c";
sd = "e.ed";
se = "u.c";
sf = "n";
result = "";
//ustce.edu.cn
//e after c
{
for (int a = 0; a <= 27; a++)
{
for (int b = 0; b <= 27; b++)
{
for (int c = 0; c <= 27; c++)
{
for (int d = 0; d <= 27; d++)
{
for (int e = 0; e <= 27; e++)
{
for (int f = 0; f <= 27; f++)
{
if (a + b + c + d + e + f == 27)
{
result += sa;
for (int i = 0; i < a; i++)
{
result += "s";
}
result += sb;
for (int i = 0; i < b; i++)
{
result += "t";
}
result += sc;
for (int i = 0; i < c; i++)
{
result += "c";
}
result += sd;
for (int i = 0; i < d; i++)
{
result += "d";
}
result += se;
for (int i = 0; i < e; i++)
{
result += "c";
}
result += sf;
for (int i = 0; i < f; i++)
{
result += "n";
}
if (Hash.SHA384(result).Contains("62074271866"))
{
Console.WriteLine(result);
}
result = "";
}
}
}
}
}
}
}
}
sa = "us";
sb = "t";
sc = "c";
sd = ".ed";
se = "u.c";
sf = "n";
result = "";
//ustc.edu.cne
//e after n
{
for (int a = 0; a <= 27; a++)
{
for (int b = 0; b <= 27; b++)
{
for (int c = 0; c <= 27; c++)
{
for (int d = 0; d <= 27; d++)
{
for (int e = 0; e <= 27; e++)
{
for (int f = 0; f <= 27; f++)
{
if (a + b + c + d + e + f == 27)
{
result += sa;
for (int i = 0; i < a; i++)
{
result += "s";
}
result += sb;
for (int i = 0; i < b; i++)
{
result += "t";
}
result += sc;
for (int i = 0; i < c; i++)
{
result += "c";
}
result += sd;
for (int i = 0; i < d; i++)
{
result += "d";
}
result += se;
for (int i = 0; i < e; i++)
{
result += "c";
}
result += sf;
for (int i = 0; i < f; i++)
{
result += "n";
}
result += "e";
if (Hash.SHA384(result).Contains("62074271866"))
{
Console.WriteLine(result);
}
result = "";
}
}
}
}
}
}
}
}
sa = "us";
sb = "t";
sc = "c";
sd = "e.ed";
se = "u.c";
sf = "n";
result = "";
//ustce.edu.cne
//e after c and n
{
for (int a = 0; a <= 26; a++)
{
for (int b = 0; b <= 26; b++)
{
for (int c = 0; c <= 26; c++)
{
for (int d = 0; d <= 26; d++)
{
for (int e = 0; e <= 26; e++)
{
for (int f = 0; f <= 26; f++)
{
if (a + b + c + d + e + f == 26)
{
result += sa;
for (int i = 0; i < a; i++)
{
result += "s";
}
result += sb;
for (int i = 0; i < b; i++)
{
result += "t";
}
result += sc;
for (int i = 0; i < c; i++)
{
result += "c";
}
result += sd;
for (int i = 0; i < d; i++)
{
result += "d";
}
result += se;
for (int i = 0; i < e; i++)
{
result += "c";
}
result += sf;
for (int i = 0; i < f; i++)
{
result += "n";
}
result += "e";
if (SHA384Encrypt(result).Contains("a825c"))
{
Console.WriteLine(result);
}
result = "";
}
}
}
}
}
}
}
}
}
/// <summary>
/// SHA384加密,不可逆转
/// </summary>
/// <param name="str">string str:被加密的字符串</param>
/// <returns>返回加密后的字符串</returns>
public static string SHA384Encrypt(string str)
{
SHA384 sha384 = SHA384CryptoServiceProvider.Create();
return Convert.ToBase64String(sha384.ComputeHash(Encoding.Default.GetBytes(str)));
}
public static void Run()
{
}
}
是的,极其暴力的搜索,最终得到答案:usssttttttce.edddddu.ccccccnnnnnnnnnnnn
有了secret即可拿到flag
第二问(NOT SOLVED)
不会)))
光与影
打开之后分析render-main.js
发现主要调用的是fragment-shader.js的文件
打开文件发现是shader相关内容
定位分析到这个函数最可疑
经过写unity的经验,trans代表transform,pTO变量后面还有scale字样,猜测pTO可能是flag有关的参数。
修改scale的值发现flag被拉伸
调整trans的值发现flag有位移
修改如下,即可使flag偏移出来
得到flag
片上系统
第一问
朋友介绍了SDCARD_SPI模式的原理和信号特征,打开pulseview,打开文件并调整为SD Card(SPI Mode)
调整信道对应如下
得到扇区信号如下
FF FF FF FF FF FF 01 FF FF FF FF FF FF FF FF 00 FF FF FF FF FF FF FF FF 00 FF FF FF FF FF FF FF FF FF FF FF FE 37 01 10 20 13 01 C1 FF EF 00 00 01 37 15 00 20 67 00 05 00 6F 00 40 00 B7 07 00 20 83 A8 87 0B B7 07 00 20 83 A5 47 0A B7 07 00 20 03 AF 47 0B B7 07 00 20 83 AE 07 0B B7 07 00 20 03 A8 C7 09 13 05 10 00 13 86 08 20 13 0E 10 00 13 03 70 00 83 A7 05 00 E3 8E 07 FE 23 20 AF 00 23 A0 CE 01 83 A7 05 00 E3 8E 07 FE 93 87 08 00 13 07 08 00 83 A6 07 00 13 07 47 00 93 87 47 00 23 2E D7 FE E3 98 C7 FE 13 05 15 00 13 08 08 20 E3 12 65 FC B7 12 00 20 67 80 02 00 67 80 00 00 00 10 00 20 14 20 00 96 10 20 00 96 00 20 00 96 08 10 00 96 04 10 00 96 00 10 00 96 00 00 00 96 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 66 6C 61 67 7B 30 4B 5F 79 6F 75 5F 67 6F 54 5F 74 68 33 5F 62 34 73 49 63 5F 31 64 45 34 5F 63 61 52 52 79 5F 30 4E 7D B0 E5 FF
使用十六进制转文本即可查看到末尾flag
第二问(NOT SOLVED)
依旧不会)
企鹅拼盘
第一问
暴力尝试得出)
第二问第三问(NOT SOLVED)
不会)
火眼金睛的小 E
第一问
下载两个binary文件bindiff分析,软件使用不再展开详细讲解
ps:如果有找不到的match函数需要在unmatched列表里找大致相同的
第二问第三问(NOT SOLVED)
依旧不会)
后记
今年会做的题目也就只有这些了)有些题目是有思路的,但是碍于自身知识欠缺,并没有解出,直到看官方题解才恍然大悟,哦~ 原来是这样的。那么今年就到这里了,我们明年HackerGame再见w~
2 条评论
太强了!妹控聚聚教教
魏佬教教math🥺