James Hoi's Blog

TSCTF-J 2020

Word count: 1.8kReading time: 9 min
2021/01/31 Share

前言

第一次参加CTF比赛,感觉自己好菜(我就学了一个月而已…菜也正常)。
(以后一定要记得每次做完就写wp… 不然最后一天很难受)
TSCTF-J比赛网址

easyXor.exe

这题没啥说的,标准的异或出flag

1
2
3
4
5
enflag = [62,58,41,57,44,84,54,28,58,99,34,60,98,9,20,56,78,31,32,52,74,13,27,48,37,36,29,97,101]
decode = "abcdefghijklmnopqrstuvwxyz!!!"

for i in range(len(enflag)):
print(chr((enflag[i]-9)^ord(decode[i])),end="")

得到flag: TSCTF-J{X0r_4nd_4dd_4re_ea5y}

welcome

用虚拟机运行一次,出现merak.png,扫描并关注公众号后回复TSCTF-J得到flag

得到flag: TSCTF-J{Welcome_to_TSCTF-J_2020}

PACMAN.zip

用dnSpy打开Assembly-CSharp.dll,找到关键语句,直接复制再运行一次就出来了
dnSpy下载地址

Exp脚本

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
74
75
76
77
78
79
80
81
82
83
84
85
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.IO;

namespace ConsoleApp1
{
class Program
{
public static string GenerateMd5(string text)
{
string result;
using (MD5 md = MD5.Create())
{
byte[] bytes = Encoding.Default.GetBytes(text);
byte[] array = md.ComputeHash(bytes);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < array.Length; i++)
{
stringBuilder.Append(array[i].ToString("x2"));
}
result = stringBuilder.ToString();
}
return result;
}

public static string DesDecrypt(string key, string iv)
{
byte[] bytes = Encoding.UTF8.GetBytes(key);
byte[] bytes2 = Encoding.UTF8.GetBytes(iv);
string s = "eqwLr9Qh7qNMVaNd78tRy1tUdJa4eG48C9vIB+FVPTcjDf+RKofGrA==";
DESCryptoServiceProvider descryptoServiceProvider = new DESCryptoServiceProvider();
string result;
using (MemoryStream memoryStream = new MemoryStream())
{
byte[] array = Convert.FromBase64String(s);
try
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, descryptoServiceProvider.CreateDecryptor(bytes, bytes2), CryptoStreamMode.Write))
{
cryptoStream.Write(array, 0, array.Length);
cryptoStream.FlushFinalBlock();
}
result = Encoding.UTF8.GetString(memoryStream.ToArray());
}
catch
{
result = "Oho!You are caught by me!";
}
}
return result;
}


static void Main(string[] args)
{
int Eat = 0;
string secret = "937d05a262a8a9efb9ceb2dac317fc2982e4d1bb";
while (true)
{
Eat++;
if (Eat % 100 == 0)
{
secret = GenerateMd5(secret) + secret;
Console.WriteLine("hello1");
}
else if (Eat == 574)
{
secret = GenerateMd5(secret);
secret = DesDecrypt(secret.Substring(0, 8),secret.Substring(24));
Console.WriteLine(secret);
if ((int)(secret[8] * secret[13] * secret[15]) != 486400)
{
Console.WriteLine(secret);
}
break;
}
}
Console.ReadKey();
}
}
}

得到flag: TSCTF-J{P4c_m@n_1s_s0_1nT3rested}

Go_1000_floors.zip

秒解了…直接Notepad++查找TSCTF-J就找到flag了

得到flag: TSCTF-J{Y0u_4re_a_rea1_man}

easyASM

这题让我好好的学了一次汇编,直接照着汇编自己手打一次python

原python脚本

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
import dis

def a(i):
return len(i)

def b(i):
if i[:8] != "TSCTF-J{": return False
if i[-1:] != "}": return False
return True

def c(i):
l = a(i)
b = []
for j in range(l):
print(i[j])
i[j] = (i[j] + 128) % 256
return bytes(i)


def e(f):
o = []
l = a(f)
for i in range(l):
w = ord(f[i]) ^ ord(f[(i+4)%l])
o.append(w)
return c(o)


def main():
s = input("Guess\n>>")
o = b'\xa9\x9a\xbf\xb6\x90\xea\x9f\xb1\xd9\xec\x8a\xa0\x80\x9a\xa6\x8a\xd8\x89\xbe\xca\xbe\xb7\xab\x9e\x94\xaf\x89\xfe\x92'
if e(s) == o and b(s): print("Correct")
else: print("Wrong...")

解密原理

根据加密原理,加密第一位要用第四位,加密第二位要用第五位,加密最后一位;又因为已知flag头尾一定是TSCTF{},所以能直接反推得到flag

1
2
3
for i in range(24):
print((i+4)%l,end=" ")
#输出:4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 0 1 2 3

Exp脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enflag = b'\xa9\x9a\xbf\xb6\x90\xea\x9f\xb1\xd9\xec\x8a\xa0\x80\x9a\xa6\x8a\xd8\x89\xbe\xca\xbe\xb7\xab\x9e\x94\xaf\x89\xfe\x92'
key = []
flag = [84,83,67,84,70,45,74,123,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125] # TSCTF{}
l = len(enflag)

for i in range(l):
key.append(enflag[l-i-1] - 128)

for i in range(l):
k = ((l-i-1)+4)%l
flag[l-i-1] = key[l-i-1]^flag[k]

test_flag = []
for i in range(l):
test_flag.append(chr(flag[i]))
print(chr(flag[i]),end="")

得到flag: TSCTF-J{R3aLly_E4sy_4Ss3mblY}

PaintUpx.exe

运行一下发现flag是用命令行画出来的,但到后面就卡住不输出了(WOW!便秘的感觉~~)

分析

PaintUpx名如其名,用upx加壳了,脱壳后开始分析主函数

点进sub_4016CB函数发现Sleep函数,说不定nop掉就完事?(还真是这样)

Patch

点击Edit > Patch program > Assemble  编辑汇编

点击Edit > Patch program > Apply pathes to input file > OK  patch成功
patch后的exe: PaintUpx_crack.rar
运行得到flag: TSCTF-J{So_E@SY_paINt_GAmE!!?}

ZBR想要请客

分析js代码,设置断点,修改totalWrong使if命令不成立即可


得到flag: TSCTF-J{R1ch_Ric1n_ZBR_D1nn3r!}

EasyF12

没什么好说的,就普通js断点…
主页找到源码找到game1.html,进入game1.html找到game2.php,在game2.php下断点js

进入gethint.php?q=9999发现需要进入fina1.php,f12查看代码

经典md5碰撞问题,postman解决

得到flag: TSCTF-J{Welc0me_To_tHe_wor1d_0f_Web}

宣讲会

白嫖宣讲会 知乎链接
得到flag: TSCTF-J{消磨这一身魂也陪你闯}

EasyVerify

node.js运行调试即可获得flag

得到flag: TSCTF-J{Yoshino-s_want_1_girlfriend}

那你能帮帮我吗

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python3
from secret import flag, secret_number_you_never_know

print("Source code:")
with open("main.py") as f:
print(f.read())

print("")
try:
val = 0
inp = input("Input value: ")
count_digits = len(set(inp))
if count_digits <= 10:
val = eval(inp)
else:
raise

if val == secret_number_you_never_know: # I am very sure it is a int
print(flag)
else:
print("Nope. Better luck next time.")
except:
print("Nope. No hacking.")
exit(1)

print(vars())可得flag

得到flag: TSCTF-J{Y_laoshi_want_girl_pengyou_qq_1735439536}

奇特的解法

输入exec(input())可以无限构造长度,感觉这个方法以后可以经常用

资源小能手

题目文件
题目百度网盘 提取码2ser
百度网盘全选文件下载,发现密码是2815e9c7290f40897da2c359ccd5029e
解压后的压缩包flag.tar.gz用010 Editor打开,发现flag

得到flag: MIXCTF{Y_la0sh1_1s_Old_driu3R}

fxxk

动调后发现加密规律,直接得到exp脚本

1
2
3
4
5
6
7
8
enflag = [
0x54, 0x52, 0x41, 0x57, 0x42, 0x28, 0x4C, 0x7C, 0x5E, 0x6C,
0x78, 0x72, 0x53, 0x68, 0x6F, 0x7C, 0x69, 0x4E, 0x54, 0x4B,
0x4C, 0x4C, 0x49, 0x45, 0x7D, 0x6F, 0x7F, 0x69, 0x6F, 0x78,
0x41, 0x2E, 0x11, 0x15, 0x17, 0x12, 0x10, 0x58
]
for i in range(38):
print(chr(i^enflag[i]),end="")

得到flag: TSCTF-J{Very_easy_FXXY_Reverse_114514}

playWithMe

分析

题目附件playWithMe.pyc,用uncompyle6得到python脚本

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
def a(i):
return len(i)


def c(i):
l = a(i)
for j in range(l):
i[j] = (ord(i[j]) + 128) % 256
else:
return bytes(i)[::-1]


def e(f):
l = a(f)
w = list(f)
for i in range(l):
w[i] = chr(ord(w[i]) ^ ord(w[((i + 4) % l)])) # 这里和easyAsm不同,把加密后的立刻赋值到第一位
else:
return c(w)


def main():
s = input('Guess?\n>> ')
o = b'\xd2\xa8\xba\xa2\x92\xe6\x9b\xe3\xc8\xb3\xeb\xbb\xf3\xd5\xc3\xd8\x83\xda\xbd\x9d\x91\xaf\x89\xfe\x92'
if e(s) == o:
print('Correct!')
else:
print('Wrong...')


if __name__ == '__main__':
main()

这题和easyAsm好像,我一直在找哪不同…(找了好久)

Exp脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
enflag = b'\xd2\xa8\xba\xa2\x92\xe6\x9b\xe3\xc8\xb3\xeb\xbb\xf3\xd5\xc3\xd8\x83\xda\xbd\x9d\x91\xaf\x89\xfe\x92'
key = []
flag = [84,83,67,84,70,45,74,123,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125]
l = len(enflag)

for i in range(l):
key.append(enflag[l-i-1] - 128)

# 只加了这个for,其他都没变
for i in range(4):
flag[i] ^= flag[i+4] # 因为是加密后直接复制给原字串,所以要先加密一次,不然反推会错

for i in range(l):
k = ((l-i-1)+4)%l
flag[l-i-1] = key[l-i-1]^flag[k]

test_flag = []
for i in range(l):
test_flag.append(chr(flag[i]))
print(chr(flag[i]),end="")

得到flag: TSCTF-J{W0w!Th4t’S_Go0D!}

whoami

附件是图片,binwalk -e解出文件,运行里面的js代码,出现TtS_C_T4F_-Jf{e1NSc_e?T?h?A}
栅栏加密,取每组字数15

得到flag: TSCTF-J{1SThAt4__feNce???}

总结

感觉re都不太难,但自己明显对很多原理上的东西还没理解透彻,有时间希望能多看看书

CATALOG
  1. 1. 前言
  • easyXor.exe
  • welcome
  • PACMAN.zip
    1. 1. Exp脚本
  • Go_1000_floors.zip
  • easyASM
    1. 1. 原python脚本
    2. 2. 解密原理
    3. 3. Exp脚本
  • PaintUpx.exe
    1. 1. 分析
    2. 2. Patch
  • ZBR想要请客
  • EasyF12
  • 宣讲会
  • EasyVerify
  • 那你能帮帮我吗
    1. 1. 奇特的解法
  • 资源小能手
  • fxxk
  • playWithMe
    1. 1. 分析
    2. 2. Exp脚本
  • whoami
  • 总结