2023SYCTF的Syclang这道题还怪有意思的,作者写了一个简单的反编译器,将源代码输出中间指令、asm等格式
然后,我们今天要来头铁分析一下IR中间代码(个人感觉像Go语言hhh)
主要调出几个典型的指令进行一个分析,然后就可以逆出这段程序的大致意思了
感觉分析完这个中间指令,对程序的理解又更进了一步
程序的逻辑很简单,就是多个循环,加减加密,然后与密文比较。
在文章的结束,将会把附件上传,大家也可以下载下来分析
(作者水平有限,如有错误,请大佬指出)
调了几个很典型的指令,CTF题给了800多行代码,都是由这些指令组成的。
1
2
3
4
5
6
|
/
/
声明一个结构体
STRUCT exp :
ARRAY .key(
int
)[
24
]<
+
0
>
/
/
int
类型,这里占
8
个字节,
8
*
24
=
192
ARRAY .L(
int
)[
8
]<
+
192
>
ARRAY .R(
int
)[
8
]<
+
256
>
ARRAY .X(
int
)[
8
]<
+
320
>
|
定义函数
1
2
3
4
5
6
7
8
9
10
11
12
|
FUNCTION read
-
8
:
PARAM var2<
+
8
>
LABEL Flabelread :
FUNCTION writes
-
0
:
LABEL Flabelwrites :
FUNCTION writef
-
0
:
LABEL Flabelwritef :
FUNCTION exit
-
0
:
LABEL Flabelexit :
|
入口main函数
char类型在这里占一个字节,int类型占了8字节
<+n>这个表示偏移,理解一下就可以
1
2
3
4
5
6
7
8
9
10
|
FUNCTION main
-
1640
:
ARRAY var11(char)[
24
]<
+
0
>
/
/
char类型占一个字节
STRUCT var22(exp)<
+
488
>
STRUCT var23(exp)<
+
872
>
STRUCT var24(exp)<
+
1256
>
STRUCT var25(exp)<
+
1640
>
ARG var11<
+
24
>
temp1 :
=
CALL read
/
/
调用函数,获取我们的flag
temp2 :
=
#0
var15<
+
56
> :
=
temp2
|
分析第一个循环结构,其他的循环结构都是类似的
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
|
/
/
第一个循环,运算
1
LABEL label4 :
temp4 :
=
#24 //temp4=24 类似go语言的匿名变量
IF var15<
+
56
> < temp4 GOTO label3
/
/
一个循环结构
GOTO label2
LABEL label3 :
temp5 :
=
#0
var12<
+
32
> :
=
temp5
var16<
+
64
> :
=
var15<
+
56
>
#!tempa := {#1}*{var16<+64>} //这句就是将 某个变化的值赋值给一个临时的变量,理解为:tempa = var16 + 1 char类型就是一个字节
var12<
+
32
> ::
=
var11<
+
1
><
+
tempa>
/
/
var12
=
input
[i]
temp6 :
=
#23
temp7 :
=
temp6
-
var15<
+
56
>
var18<
+
80
> :
=
temp7
#!tempa := {#8}*{var18<+80>} //创建临时变量
var22(@exp.key[
0
])<
+
8
><
+
488
><
+
tempa> :
=
var12<
+
32
>
/
/
var22(@exp.key[
0
])<
+
8
><
+
488
>获得exp结构体数组的起始地址,exp.key[
23
-
i]
=
var12
=
input
[i]
temp3 :
=
#1
var15<
+
56
> :
=
var15<
+
56
>
+
temp3
GOTO label4
/
/
第二个循环,运算
2
LABEL label2 :
temp8 :
=
#23
var15<
+
56
> :
=
temp8
LABEL label11 :
temp10 :
=
#0
IF var15<
+
56
> > temp10 GOTO label10
GOTO label9
.......
/
/
其他代码
|
一个循环可以提取出来C代码:
1
2
3
|
for
(
int
i
=
0
; i <
24
; i
+
+
) {
var22.key[
23
-
i]
=
inputflag[i];
}
|
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
|
/
/
第二个循环,运算
2
LABEL label2 :
temp8 :
=
#23
var15<
+
56
> :
=
temp8
LABEL label11 :
temp10 :
=
#0
IF var15<
+
56
> > temp10 GOTO label10
/
/
终止条件
GOTO label9
LABEL label10 :
var18<
+
80
> :
=
var15<
+
56
>
#!tempa := {#8}*{var18<+80>}
var19<
+
88
> :
=
var22(@exp.key[
0
])<
+
8
><
+
488
><
+
tempa>
temp11 :
=
#1
temp12 :
=
var15<
+
56
>
-
temp11
/
/
i
-
1
var16<
+
64
> :
=
temp12
#!tempa := {#8}*{var16<+64>}
var17<
+
72
> :
=
var22(@exp.key[
0
])<
+
8
><
+
488
><
+
tempa>
temp13 :
=
var19<
+
88
>
-
var17<
+
72
>
var21<
+
104
> :
=
temp13
#!tempa := {#8}*{var15<+56>} //i
var22(@exp.key[
0
])<
+
8
><
+
488
><
+
tempa> :
=
var21<
+
104
>
/
/
exp.key[i]
=
exp.key[i]
-
exp.key[i
-
1
]
temp9 :
=
#1
var15<
+
56
> :
=
var15<
+
56
>
-
temp9
GOTO label11
/
/
初始化数组区
LABEL label9 :
|
第二个循环转换为c代码如下:
1
2
3
|
for
(
int
i
=
23
; i >
0
; i
-
-
) {
var22.key[i]
=
var22.key[i]
-
var22.key[i
-
1
];
}
|
初始化数组区,就是很常见的赋值
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
|
LABEL label9 :
temp15 :
=
#0
var22(@exp.L[
0
])<
+
200
><
+
488
> :
=
temp15
temp17 :
=
#8
var22(@exp.R[
0
])<
+
264
><
+
488
> :
=
temp17
temp19 :
=
#11
var22(@exp.X[
0
])<
+
328
><
+
488
> :
=
temp19
temp21 :
=
#15
var22(@exp.L[
1
])<
+
208
><
+
488
> :
=
temp21
temp23 :
=
#23
var22(@exp.R[
1
])<
+
272
><
+
488
> :
=
temp23
temp25 :
=
#0
temp26 :
=
#13
temp27 :
=
temp25
-
temp26
var22(@exp.X[
1
])<
+
336
><
+
488
> :
=
temp27
temp29 :
=
#2
var22(@exp.L[
2
])<
+
216
><
+
488
> :
=
temp29
temp31 :
=
#11
var22(@exp.R[
2
])<
+
280
><
+
488
> :
=
temp31
temp33 :
=
#17
var22(@exp.X[
2
])<
+
344
><
+
488
> :
=
temp33
temp35 :
=
#10
var22(@exp.L[
3
])<
+
224
><
+
488
> :
=
temp35
temp37 :
=
#20
var22(@exp.R[
3
])<
+
288
><
+
488
> :
=
temp37
temp39 :
=
#0
temp40 :
=
#19
temp41 :
=
temp39
-
temp40
var22(@exp.X[
3
])<
+
352
><
+
488
> :
=
temp41
......
|
其它的循环和赋值都是类似了,这里不在详细分析了
这里贴一下,翻译后的大致伪代码
感谢s0rry师傅的帮助~
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
typedef struct {
long
long
int
key[
24
];
long
long
int
L[
8
];
long
long
int
R[
8
];
long
long
int
X[
8
];
} exp;
int
main() {
exp var22;
exp var23;
exp var24;
exp var25;
var22.L[
0
]
=
0
;
var22.R[
0
]
=
8
;
var22.X[
0
]
=
11
;
var22.L[
1
]
=
15
;
var22.R[
1
]
=
23
;
var22.X[
1
]
=
-
13
;
var22.L[
2
]
=
2
;
var22.R[
2
]
=
11
;
var22.X[
2
]
=
17
;
var22.L[
3
]
=
10
;
var22.R[
3
]
=
20
;
var22.X[
3
]
=
-
19
;
var22.L[
4
]
=
6
;
var22.R[
4
]
=
13
;
var22.X[
4
]
=
23
;
var22.L[
5
]
=
9
;
var22.R[
5
]
=
21
;
var22.X[
5
]
=
-
29
;
var22.L[
6
]
=
1
;
var22.R[
6
]
=
19
;
var22.X[
6
]
=
31
;
var22.L[
7
]
=
4
;
var22.R[
7
]
=
17
;
var22.X[
7
]
=
-
37
;
var23.key[
0
]
=
252
;
var23.key[
1
]
=
352
;
var23.key[
2
]
=
484
;
var23.key[
3
]
=
470
;
var23.key[
4
]
=
496
;
var23.key[
5
]
=
487
;
var23.key[
6
]
=
539
;
var23.key[
7
]
=
585
;
var23.key[
8
]
=
447
;
var23.key[
9
]
=
474
;
var23.key[
10
]
=
577
;
var23.key[
11
]
=
454
;
var23.key[
12
]
=
466
;
var23.key[
13
]
=
345
;
var23.key[
14
]
=
344
;
var23.key[
15
]
=
486
;
var23.key[
16
]
=
501
;
var23.key[
17
]
=
423
;
var23.key[
18
]
=
490
;
var23.key[
19
]
=
375
;
var23.key[
20
]
=
257
;
var23.key[
21
]
=
203
;
var23.key[
22
]
=
265
;
var23.key[
23
]
=
125
;
/
/
初始化
for
(
int
i
=
0
; i <
24
; i
+
+
) {
var22.key[
23
-
i]
=
input
[i];
}
for
(
int
i
=
23
; i >
0
; i
-
-
) {
var22.key[i]
=
var22.key[i]
-
var22.key[i
-
1
];
}
/
/
对flag加密
for
(
int
i
=
0
; i <
8
; i
+
+
) {
var22.key[var22.L[i]]
+
=
var22.X[i];
var22.key[var22.R[i]]
-
=
var22.X[i];
}
for
(
int
i
=
1
; i <
24
; i
+
+
) {
var22.key[i]
+
=
var22.key[i
-
1
];
}
/
/
对var23密文进行运算
for
(
int
i
=
23
; i >
0
; i
-
-
) {
var23.key[i]
-
=
var23.key[i
-
1
];
}
for
(
int
i
=
0
; i <
8
; i
+
+
) {
var23.key[var22.L[i]]
-
=
var22.key[i
*
3
];
var23.key[var22.R[i]]
+
=
var22.key[i
*
3
];
}
for
(
int
i
=
1
; i <
24
; i
+
+
) {
var23.key[i]
+
=
var23.key[i
-
1
];
}
/
/
比较密文和输入flag的密文
for
(
int
i
=
0
; i <
24
; i
+
+
) {
if
(var22.key[i] !
=
var23.key[i]) {
exit;
/
/
不相等则退出
}
}
return
0
;
}
|
更多【2023SCTF-Syclang-关于中间指令的分析】相关视频教程:www.yxfzedu.com