津门杯2021初赛wp

津门杯和红帽杯左右开弓,有点难受。

GoodRe

主要逻辑很简单,静态看不太容易看明白但是动态分析很容易。

前面一部分是把输入简单分割生成的数组,还有一个常量数组。

之后四个相同的函数不知道在干什么

进去看看

动调到sub_*8667的时候看到0x9e3779b9。加上后面的4,5,4,5。基本实锤tea加密。

明文是输入,密钥就是之前的常量,加密后比较,直接解密即可。

flag{7dea3f6d3b3d6c0c620864add2fa2ae1a61f2736f0060da0b97e8356d017ce59}

babydsp

玄学TMS320C6架构(ida认的

看strings找到

很像flag经过某种变换得到的,让我回想起之前做过的一个riscv架构的题。(后来发现两个题一模一样

然后后面有调试信息,大概手动恢复出来一部分的数据结构和函数调用关系:

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
g_stack
g_sp
g_weight
g_idx
tree_list
g_nodinfo_idx
fd
buf
pos
bufend
buff_stop
flags
FILE

struct Node{
left
right
c
}

struct NodeInfo{
node
depth
weight
}

init_statk() {
memset()
}
mynodecalloc() {
exit()
memset()
memset()
}
mynodeinfocalloc() {
exit()
memset()
memset()
}
build_tree(tree_list, node) {
mynodecalloc()
build_tree()
}
push_node(nodeinfo) {}
pop_node() {}
calc_weight(node) {

node.depth = i
node.node = B5
node.weight = 0x31*i + X

push_node()
mynodeinfocalloc()
push_node()
pop_node()
}
check_weight(weight, len) {
}
check_password(password, length) {
memset()
check_weight()
check_weight()
}
main() {
init_stack()
printf()
fgets()
build_tree()
build_tree()
calc_weight()
check_password()
}

有build_tree的操作,那一长串的字符就是一棵树的先序遍历。

然后github上找到一个dump_coff的工具,ida插件会爆炸,不过使用它的dump工具手动修复一下ida的偏移还是基本能认出来。

根据之前分析的函数调用关系找到check_weight函数

传入了一个数组和大量的常数进行比较。

再看calc_weight

image-20210514220710614

基本能看出来的是一个0x31或者0x30乘上节点的深度。大概就能脑补出来具体的加密流程了。

之前生成的树上每个节点对应唯一的weight,weight计算如下:

1
weight[i] = weight[i.parent] + i.depth * ([i是左儿子]?0x31:0x30)

根据比较的常量表到树上去取出来节点就是flag

flag{JUst_a_babyyyy_DsP_rEveRse}