前言
极客少年挑战赛作为CCS成都网络安全大会的重磅赛事,自去年举办以来,已成为我国官方举办的面向未成年人规模最大、影响最盛、覆盖范围最广、参赛人数最多的网络攻防技能赛事之一。本届挑战赛在去年基础上进一步提升赛题设置合理性和专业性,以网络安全理论为基石,设置最前沿的CTF(夺旗赛)实战考察,既契合青少年知识储备,又强化网络安全专业技能,让参赛青少年在竞技中深度体验网络安全的趣味。
本次挑战赛将以“线上答题+线上交流”形式进行,参赛选手在线解题,内容涉及网络安全法律法规、数据安全、人工智能安全、二进制安全、Web漏洞与渗透(Web)、软件逆向(Reverse Engineering)、漏洞挖掘和利用(Pwn)等前沿网络安全知识。
目录:
一、Web
1.1 DSOS
二、Reverse
2.1 easy_re
2.2 Fllaa
三、Misc
3.1 1+1=all
Web
DSOS
1.访问网站发现DS_Store,.DS_Store 是 Desktop Services Store 的缩写,是 macOS 操作系统上的一个不可见文件。
2.访问.DS_Store,并下载txt文件
- 打开txt文件后发现 “flag here!c 4 f a 0 f 1 2 e 2 d 1 b c 0 a e 2 e e 2 4 d f 0 1 2 e 0 c b 7 . t x t”,将文件名去除空格后并访问此文件
3.访问后发现flag{1a0675f0ece1f96bd4d896862096134c}
FLAG:flag{1a0675f0ece1f96bd4d896862096134c}
Reverse
easy_re
1.打开文件并解压缩发现是一个pyc文件,应该是pyc逆向成py
- 将解压后的pyc文件放入在线网站进行反编译得到py脚本
- 分析后发现是一个异或的操作,直接写脚本,将操作逆序。
脚本如下:
import base64
def decode(message):
s = ''
message = base64.b64decode(message)
for i in message:
x = i-5
x = x ^ 50
s += chr(x)
return s
message = 'WWNYWk5cWEZQckdQVlQ='
flag = decode(message)
print(flag)
- 执行脚本得到flag
FLAG: flag{easy_pyc}
Fllaa
jeb静态分析
1.在程序的Mainactivity中我们发现他加载了fllaa.so文件,我们将原apk文件的后缀名改为zip并提取出来
2.接下来是获取输入部分
3.然后我们将字符串加密后使用安卓的反射机制调用函数对输入进行处理
4.最后就是check函数
ida动态调试
5.因为每次都要调用decode函数,特别特别麻烦,并且在so文件中RC4的密钥也是被加密过的
所以我们选择动态调试
反射机制调用的函数
6.通过动调可以知道在jeb中分析的反射机制调用的函数就是base64编码
魔改RC4
7.然后对base64编码后的部分进行魔改的RC4,魔改过程如下
将所有的密文异或0xC6
8.密钥流异或时多异或一个0x73
9.通过动调我们可以知道decode后的RC4_key为Hikari#a0344y3y#19301211
然后就是写脚本解密了
解密部分
#include<stdio.h>
#include <string.h>
void Rc4_init(unsigned char* S, unsigned char*K,unsigned char* key, unsigned long len)
{
unsigned char tmp = 0;
for (int i = 0; i < 256; ++i)
{
S[i] = i;
K[i] = key[i % len];
}
int j = 0;
for (int i = 0; i < 256; ++i)
{
j = (j + S[i] + K[i]) % 256;
tmp = S[i];
S[i] = S[j];
S[j] = tmp;
}
return;
}
void Rc4_encrypt(unsigned char* S, unsigned char* flag,char*flag1)
{
int len = strlen(flag1);
int i = 0, j = 0,t = 0 ;
unsigned char tmp = 0;
for (unsigned long k = 0; k < len; ++k)
{
i = (i + 1) % 256;
j = (j + S[i]) % 256;
tmp = S[i];
S[i] = S[j];
S[j] = tmp;
t = (S[i] + S[j]) % 256;
flag[k] ^= S[t];
}
}
int main()
{
unsigned char S[256] = { 0 };
unsigned char K[256] = { 0 };
char code[512] = { 0xF0, 0x90, 0x10, 0xB7, 0xD1, 0x6E, 0x1D, 0x9A, 0xF0, 0x6D, 0xD8, 0x86, 0x3C, 0xC1, 0xB5, 0x4F,
0x4D, 0x96, 0x9A, 0x85, 0xD9, 0xEC, 0x42, 0x5A, 0xCB, 0x16, 0x42, 0x9A, 0x4D, 0x32, 0x51, 0xD6,
0xC6, 0x71, 0x6D, 0xB6, 0xF3, 0x04, 0x48, 0x3A, 0xC2, 0x26, 0x2D, 0xE4, 0x4D, 0x27, 0xBC, 0x3C };
char decode[100] = { 0 };
char key[] = "Hikari#a0344y3y#19301211";
Rc4_init(S, K,(unsigned char*)key, strlen(key));
for (int i = 0; i < 48; ++i) {
code[i] ^= 0x73;
}
Rc4_encrypt(S, (unsigned char*)code, code);
for (int i = 0; i < 48; ++i) {
code[i] ^= 0xC6;
}
printf("%s", code);
return 0;
}
10.得到结果ZmxhZ3stZmxsQF9zMF9uQDF2ZSMjeW91X2ZpbmRfbWUhISF9后进行base64解码
FLAG: flag{-fll@s0n@1ve##youfindme!!!}
Misc
1+1=all
- 将附件解压后打开是一个txt文件和zip压缩包文件
- 将flag1.zip打开后发现是二进制,应该是二进制转图片,字数为16000个字符,因此可以判断图片大小应该是400x400
- 将字符串放入脚本转成图片,设定大小为400x400。
脚本如下:
from PIL import Image
MAX = 400
#二维码大小
pic = Image.new("RGB",(MAX, MAX))
str = """二进制文件太长了这里直接省略啦emmmmm"""
# str为获取的01片段
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("1.png")
- 打开跑出来的图片发现是一半的二维码,那么另一半应该在压缩包中。
- 打开压缩包发现存在密码
- 使用压缩包密码爆破工具ARCHPR,得到密码pp8
- 打开后竟然不是二维码,将flag2.png拖入winhex查看
- 通过以往刷题经验,应该是修改图片宽度和高度,要使图片能够拼合图片长宽应该和前面一半二维码的尺寸一样,因此,通过对比将flag2.png的图片大小改成和flag1一样。
修改前
修改后
得到图片
- 将图片进行拼合,扫码后得到flag
FLAG: flag{adca24b024aeaecc74ed901e2426486c}