James Hoi's Blog

TSCTF-J 2021 Reverse Official WP

Word count: 1.7kReading time: 8 min
2022/01/11 Share

TSCTF-J 2021 Reverse Official WP

by James

easyXor

签到。题目就是题解,xor加密后验证,这里要提多一句,选手可以再仔细分析分析反编译出来的while流程。这里给出相对应的源码,希望选手理解为什么ida反编译后的结果等同于这句源码。

解题脚本

1
2
3
4
5
6
7
8
9
data = [
0x59,0x5f,0x4c,0x5a,0x4f,0x25,0x41,0x71,0x52,0x61,
0x4b,0x65,0x31,0x4d,0x66,0x5d,0x2f,0x43,0x4b,0x4d,
0x5a,0x4c,0x5d,0x37,0x5f,0x4b,0x4f,0x26,0x63,0x4f,
0x7f,0x61,0x72,0x7f,0x1f,0x71,0x6c,0x49,0x78,0x73,
0x04,0x05,0x06,0x5b
]
for i in range(44):
print(chr(data[i]^i^0xD),end="")

debugMe

送分题。可以发现判断了字符串长度与flag头是否为TSCTF-J,然后输入的字符串直接进行比较了,所以动态调试查看buffer变量可以找到flag。这题没用动调的选手可以再做一遍

maze

送分题,这题做出来的人这么少属于是没想到,选手可以再分析下迷宫变量类型和程序流程。下图可以看出是个10x10的数组,v9,v10是数组索引

程序漏写了最后终点的判断导致有多解,标准解如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
char map[10][10] = {
{0,1,1,1,0,0,0,0,0,2},
{0,1,1,1,0,1,1,1,1,1},
{0,0,1,1,0,0,0,0,1,1},
{1,0,1,1,1,1,1,0,0,1},
{1,0,1,0,0,0,1,1,0,1},
{1,0,0,0,1,0,1,0,0,1},
{1,1,1,1,1,0,1,0,1,1},
{1,0,0,0,0,0,1,0,1,1},
{1,0,1,1,1,1,0,0,1,1},
{1,0,0,0,0,0,0,1,1,1}
};
//SSDSSSDDWDDSSSAAAASSDDDDDWDWWWDWWAWAAAWWDDDDD
//TSCTF-J{f62f3965313148ebccaec0bcdb132957}

UpxRand

这题和去年的PaintUpx是一个意思。upx脱壳后ida分析发现有Sleep函数卡住了导致图片输出不全,patch掉即可,修改汇编方法如下图

把sleep改成nop,修改后再点击上图中的Apply patches to input file

再打开软件扫二维码得flag

tic-tac-toe

井字棋,用exeinfope可以发现是c#写的,用dnspy打开

可以发现经典c# Form入口,045X7ZYGMK是Form类型

进入后多在几个地方下断点看看变量信息,可以发现有个判断赢了多少次的函数

修改变量绕过判断或其他方法获取flag即可

Minecraft

exeinfope可以看出是pyinstaller打包的,github找到pyinstxtractor.py脚本提取exe内容,找到main.pyc进行反编译,当中要注意解包脚本需要和打包时的py版本一致,否则会导致pyc无法反编译。

反编译结果中的关键信息

1
2
3
4
5
6
7
8
9
10
11
12
def judge_flag(label_text):
flag = input('请输入flag进行验证:')
enflag = [81, 77, 13, 81, 25, 180, 41, 237, 21, 233, 125, 65, 229, 209, 161, 192, 161, 125, 25, 85, 57, 185, 229, 125, 181, 141, 125, 196, 205, 185, 209, 125, 165, 81, 245]

def encrypt(data):
return (data & 192) >> 6 | (data & 48) << 2 | (data & 12) << 2 | (data & 3) << 2

if enflag == [encrypt(ord(s)) for s in flag]:
label_text += ' flag是' + flag
else:
label_text += ' 输入flag错误'
return label_text

可见是单字节加密,爆破即可(也可以根据加密推翻),脚本如下

1
2
3
4
5
6
enflag = [81, 77, 13, 81, 25, 180, 41, 237, 21, 233, 125, 65, 229, 209, 161, 192, 161, 125, 25, 85, 57, 185, 229, 125, 181, 141, 125, 196, 205, 185, 209, 125, 165, 81, 245]
def encrypt(data):
return (data & 192) >> 6 | (data & 48) << 2 | (data & 12) << 2 | (data & 3) << 2
for s in enflag:
for d in range(32,127):
if s == encrypt(d): print(chr(d),end="")

crackme

原题是有壳的,而且题目没有问题,有人说脱不出后就干脆不加壳。
main函数里的sub_401C50可以看出是检测进程名称,方法五花八门,总之绕过就行。

sub_401DB0是个SEH异常反调试,详情请百度

直接查看汇编,参考刚刚上⾯的源码,反调试的E9刚好起到了花指令的作⽤,patch一下发现了dword_408160有运算

再返回主函数汇编,发现藏了个函数sub_402870,基本所有常量字符串都加了异或加密,防止定位到这个函数,而且当中接收了输入字符串进行加密验证。

先看_Initialize_parallel_init_info函数,发现了NtSetInformationThread,这整个函数是隐藏线程防⽌调试⽤的,绕过就⾏(留意下dword_408160)

这个是smc,动态运行函数,当中有用到dword_408160这个变量进行解密


当反调试函数都过了,让dword_408160+=21,21,14,即dword_408160为56时才解密成功,从⽽调⽤函数,每个加密函数都有固定的花指令。函数分别是异或的变形,加减乘除取余


过了一层验证后还有md5限制多解,md5字符串也用异或加密了一下校验md5前控制台会输出提示正在做md5


提取md5字符串得到d57d1bc45d6f044959e2e796930a301e,脚本如下

1
2
3
4
5
6
7
8
9
s = [
0x5C, 0x0D, 0x0F, 0x5C, 0x09, 0x5A, 0x5B, 0x0C, 0x0D, 0x5C,
0x0E, 0x5E, 0x08, 0x0C, 0x0C, 0x01, 0x0D, 0x01, 0x5D, 0x0A,
0x5D, 0x0F, 0x01, 0x0E, 0x01, 0x0B, 0x08, 0x59, 0x0B, 0x08,
0x09, 0x5D
]

for i in range(32):
print(chr(s[i]^56),end="")

可以看出可以单字节爆破,写脚本即可,由于限制md5再写脚本遍历比较md5即可

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
#include<iostream>

#define rand100 rand()%10+1

const char enflag[] = {
0x6B, 0x6F, 0x80, 0x3E, 0x81, 0x85, 0x68, 0x29, 0x28, 0xA1,
0x3A, 0xE3, 0xE2, 0x1D, 0x28, 0x40, 0xD3, 0xD6, 0xD1, 0x06,
0x5B, 0x69, 0x5A, 0x27, 0xF6, 0x03, 0x52, 0x3E, 0x7F, 0x26,
0x66, 0x7E, 0x9F, 0xFD, 0x88, 0x18, 0x46, 0xCC, 0xBC, 0x82,
0x43, 0x82, 0xA6, 0xA5, 0x94, 0x15, 0x1E, 0xED, 0x29, 0x93,
0x87, 0x3F, 0x9A, 0x3C, 0x15, 0x61, 0xA4, 0x3D, 0x5C, 0x00
};

const char random_list[] = {
0x27,0x14,0x27,0x26,0x38,0x62,0x42,0x56,0x33,0x0D,
0x36,0x01,0x2B,0x52,0x26,0x16,0x2E,0x56,0x62,0x51,
0x4D,0x5C,0x38,0x07,0x3A,0x18,0x52,0x29,0x1A,0x4F,
0x2F,0x5B,0x29,0x58,0x08,0x26,0x0C,0x12,0x39,0x44,
0x22,0x4F,0x18,0x58,0x62,0x55,0x0D,0x0C,0x4F,0x43,
0x1E,0x05,0x50,0x06,0x59,0x32,0x1E,0x4D,0x20,0x41,
0x0F,0x25,0x1D,0x03,0x35,0x05,0x26,0x39,0x63,0x49,
0x62,0x0E,0x54,0x04,0x3D,0x2B,0x30,0x4C,0x48,0x05,
0x4A,0x35,0x14,0x05,0x28,0x57,0x05,0x26,0x18,0x24,
0x22,0x5E,0x15,0x4B,0x54,0x3E,0x19,0x42,0x46,0x1F,
0x44,0x25,0x32,0x25,0x14,0x1C,0x01,0x18,0x17,0x4B,
0x0C,0x3F,0x42,0x5C,0x14,0x30,0x33,0x15,0x23,0x45,
0x19,0x4E,0x2F,0x20,0x3B,0x49,0x1F,0x23,0x52,0x24,
0x44,0x3D,0x0F,0x2B,0x4D,0x1C,0x18,0x5F,0x45,0x2D,
0x19,0x16,0x08,0x61,0x1B,0x40,0x29,0x3F,0x30,0x51,
0x30,0x1D,0x0E,0x54,0x3C,0x2C,0x5C,0x5F,0x3E,0x22,
0x49,0x34,0x37,0x47,0x14,0x4B,0x16,0x17,0x0B,0x35,
0x31,0x39,0x0C,0x4C,0x25,0x14,0x59,0x38,0x30,0x29,
0x37,0x5E,0x38,0x2A,0x05,0x44,0x11,0x39,0x02,0x1C,
0x0F,0x34,0x54,0x50,0x4B,0x2F,0x0F,0x64,0x42,0x26,
0x3D,0x35,0x4C,0x3D,0x57,0x33,0x17,0x22,0x38,0x3A,
0x45,0x62,0x4C,0x2A,0x29,0x4E,0x2C,0x52,0x11,0x17,
0x30,0x0D,0x5C,0x18,0x21,0x60,0x42,0x07,0x4C,0x50,
0x1C,0x22,0x36,0x30,0x53,0x3F,0x02,0x2D,0x39,0x2E,
0x5C,0x3C,0x0F,0x0E,0x5F,0x37,0x42,0x13,0x4E,0x54,
0x59,0x5F,0x09,0x06,0x4D,0x62,0x23,0x4E,0x15,0x1A,
0x1F,0x35,0x49,0x2E,0x43,0x3E,0x3A,0x5A,0x3C,0x0B,
0x4C,0x29,0x41,0x1B,0x5E,0x62,0x10,0x5A,0x5D,0x3D,
0x52,0x61,0x0C,0x50,0x4F,0x37,0x3B,0x63,0x25,0x04,
0x3B,0x2C,0x18,0x54,0x04
};

char encode(int input, int i) {
input ^= random_list[i * 5];
input += random_list[i * 5 + 1];
input *= random_list[i * 5 + 2];
input -= random_list[i * 5 + 3];
input %= 66666;
return input & 0xFF;
}

void brute() {
for (int i = 0; i < 59; i++) {
for (int j = 32; j < 133; j++) {
if (encode(j, i) == enflag[i]) {
std::cout << (char)j ;
//break;
}
}
std::cout << "\n";
}
}

int main() {
brute();
}

flag是TSCTF-J{cRaCK_sMC_ls_S0_eA2Y_AnD_i_B3iLeVE_y0u_CAN_ALLKILL}

CATALOG
  1. 1. TSCTF-J 2021 Reverse Official WP
    1. 1.1. easyXor
    2. 1.2. debugMe
    3. 1.3. maze
    4. 1.4. UpxRand
    5. 1.5. tic-tac-toe
    6. 1.6. Minecraft
    7. 1.7. crackme