[原创]2023SCTF-Syclang-关于中间指令的分析
2023-7-9 20:9:30 Author: bbs.pediy.com(查看原文) 阅读量:17 收藏

[原创]2023SCTF-Syclang-关于中间指令的分析

2小时前 197

[原创]2023SCTF-Syclang-关于中间指令的分析

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 :=

  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 :=

  IF var15<+56> < temp4 GOTO label3  //一个循环结构

  GOTO label2

LABEL label3 :

  temp5 :=

  var12<+32> := temp5

  var16<+64> := var15<+56>

  var12<+32> ::= var11<+1><+tempa>  //var12 = input[i]

  temp6 :=

  temp7 := temp6 - var15<+56>

  var18<+80> := temp7

  var22(@exp.key[0])<+8><+488><+tempa> := var12<+32

      //var22(@exp.key[0])<+8><+488>获得exp结构体数组的起始地址,exp.key[23-i] = var12 = input[i]

  temp3 :=

  var15<+56> := var15<+56> + temp3

  GOTO label4

//第二个循环,运算2

LABEL label2 :

  temp8 :=

  var15<+56> := temp8

LABEL label11 :

  temp10 :=

  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 :=

  var15<+56> := temp8

LABEL label11 :

  temp10 :=

  IF var15<+56> > temp10 GOTO label10 //终止条件

  GOTO label9

LABEL label10 :

  var18<+80> := var15<+56>

  var19<+88> := var22(@exp.key[0])<+8><+488><+tempa>

  temp11 :=

  temp12 := var15<+56> - temp11  // i-1

  var16<+64> := temp12

  var17<+72> := var22(@exp.key[0])<+8><+488><+tempa>

  temp13 := var19<+88> - var17<+72>

  var21<+104> := temp13

  var22(@exp.key[0])<+8><+488><+tempa> := var21<+104// exp.key[i] =exp.key[i] - exp.key[i-1]

  temp9 :=

  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 :=

  var22(@exp.L[0])<+200><+488> := temp15

  temp17 :=

  var22(@exp.R[0])<+264><+488> := temp17

  temp19 :=

  var22(@exp.X[0])<+328><+488> := temp19

  temp21 :=

  var22(@exp.L[1])<+208><+488> := temp21

  temp23 :=

  var22(@exp.R[1])<+272><+488> := temp23

  temp25 :=

  temp26 :=

  temp27 := temp25 - temp26

  var22(@exp.X[1])<+336><+488> := temp27

  temp29 :=

  var22(@exp.L[2])<+216><+488> := temp29

  temp31 :=

  var22(@exp.R[2])<+280><+488> := temp31

  temp33 :=

  var22(@exp.X[2])<+344><+488> := temp33

  temp35 :=

  var22(@exp.L[3])<+224><+488> := temp35

  temp37 :=

  var22(@exp.R[3])<+288><+488> := temp37

  temp39 :=

  temp40 :=

  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;

}

Unicorn高级逆向与反混淆


文章来源: https://bbs.pediy.com/thread-277942.htm
如有侵权请联系:admin#unsafe.sh