当前位置: 代码迷 >> 综合 >> 看雪CTF.TSRC 2018 团队赛-第六题 追凶者也--拼图游戏
  详细解决方案

看雪CTF.TSRC 2018 团队赛-第六题 追凶者也--拼图游戏

热度:80   发布时间:2023-10-19 20:38:12.0

1.思路

       先看下前面大佬答题的时间,

看雪CTF.TSRC 2018 团队赛-第六题 追凶者也--拼图游戏

有点变态的,不到一个小时就弄完了!说明可能有点希望 0.0 !!!!!

2.正文

刚开始那道题目的时候!

先运行下看下情况!

发现是个窗体程序

直接拖到IDA里面!

看雪CTF.TSRC 2018 团队赛-第六题 追凶者也--拼图游戏

找到GetDlgItemTextA

 

然后由它的找到单击事件

看雪CTF.TSRC 2018 团队赛-第六题 追凶者也--拼图游戏

看雪CTF.TSRC 2018 团队赛-第六题 追凶者也--拼图游戏

咋一看,懵了!怎么没有判断序列号成功的地方!

刚开始怀疑类似于第二题,初始化一个全局或者静态的类对象,将验证算法藏在析构函数里面!奈何太菜没有找到!

然后又怀疑是不是栈溢出,但是输入的时候给定了最大长度!而且string的缓冲区也符合最大。

然后一点点想法,一点点否定。

最后将程序拖入study_pe的时候 ,

看雪CTF.TSRC 2018 团队赛-第六题 追凶者也--拼图游戏

发现这么一个东西。。。TLS表!

这东西注册回调函数的时候,一般先于入口点运行!

算了一下偏移值!

base+0x122FC

因为程序有重定向

所以在IDA中我把base值设成0x1340000(实际情况,由你来定)

0x1340000 +0x122FC=0x13522FC

由它找到回调函数

一路跟下来找到主要调用的地方,

看雪CTF.TSRC 2018 团队赛-第六题 追凶者也--拼图游戏

实际上每次调用GetDlgItemTextA之后,紧接着就会 调用这个函数(ps:藏的可真深啊!)

实际情况这样

看着很难看!

简单的定义了一个结构,让结果好看点

看雪CTF.TSRC 2018 团队赛-第六题 追凶者也--拼图游戏

这里有一些地方没定义就是,是为了让ida识别的好看点,没有什么lowbyte的恶心人(ps:可能我是强迫症吧,嘻嘻)

看雪CTF.TSRC 2018 团队赛-第六题 追凶者也--拼图游戏

从上图中逻辑中可以看出主要有两个检测点!

check1

check2

实际情况中,我过了一个答案就出来了!

看雪CTF.TSRC 2018 团队赛-第六题 追凶者也--拼图游戏

初始化一个3x3的表。

1

2

3

4 1 3

7 2 5

8 6 0

 

因为结果需返回1,所以可知最后的表结构

1

2

3

1 2 3

4 5 6

7 8 0

不用想也知道上图中move,改变了表。

而且对传入的序列号进行了判断输入w -> 0 , d -> 1 , s -> 2 a -> 3

 经常 玩游戏的可能一下就反应过来了,这是方向键!

可能我太菜了,一下没有反应过来,哈哈!

进去move看一看。

看雪CTF.TSRC 2018 团队赛-第六题 追凶者也--拼图游戏

看着很乱,但是用心分析很快也能分析出来

这是我粗略整理了一下

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

char __cdecl move(int s1, int s2)

{

    if(!s2)

        return 0;

    int j=0,i=0;

    for(j=0;j<3;j++){

        for(i=0;i<3;i++){

            if(table[j][i]==s2){

                switch ( s1 )

                {

                case 0:

                    if ( j )

                    {

                        if ( table1[j - 1][i] )

                        {

                            result = 0;

                        }

                        else

                        {

                            table1[j - 1][i] = table1[j][i];

                            table1[j][i] = 0;

                            result = 1;

                        }

                    }

                    else

                    {

                        result = 0;

                    }

                    return result;

                case 1:

                    if ( i == 2 )

                    {

                        result = 0;

                    }

                    else if ( table1[j][i+1] )

                    {

                        result = 0;

                    }

                    else

                    {

                        table1[j][i+1] = table1[j][i];

                        table1[j][i] = 0;

                        result = 1;

                    }

                    return result;

                    //break;

                case 2:

                    if ( j == 2 )

                    {

                        result = 0;

                    }

                    else if ( table1[j + 1][i] )

                    {

                        result = 0;

                    }

                    else

                    {

                        table1[j + 1][i] = table1[j][i];

                        table1[j][i] = 0;

                        result = 1;

                    }

                    return result;

                case 3:

                    if ( i )

                    {

                        if ( table1[j][i-1] )

                        {

                            result = 0;

                        }

                        else

                        {

                            table1[j][i-1] = table1[j][i];

                            table1[j][i] = 0;

                            result = 1;

                        }

                    }

                    else

                    {

                        result = 0;

                    }

                    return result;

                default:

                    ;

                }

            }

        }

         

    }

}  

由此可以看出!对传入的参数在0 1 2 3中进行了判断,有w a s d 我们就就可以初步的推断是对表中的元素进行了移动。

结果正是如此,由上面化简的代码可知,实际上移动后的位置会被置为0,而后面判断的元素,每个都是初始化的内容!

所以可知移动的地方只能为0。

最后的表结构为

1

2

3

1 2 3

4 5 6

7 8 0

因此我们就可以大胆的猜测这是一个拼图游戏。

1

2

3

4 1 3          1 2 3

7 2 5   -- ->  4 5 6

8 6 0          7 8 0

下面就是写算法求解了

可能我太菜了,于是乎上网随便搜了一个。。。。。。。。。。。

3.结果

看雪CTF.TSRC 2018 团队赛-第六题 追凶者也--拼图游戏

1

2

3

4

5

6

7

8

6 d

8 d

7 s

4 s

1 a

2 w

5 a

6 w

最后的序列号就为:d6d8s7s4a1w2a5w6

4.总结

       前面的大佬太强了,估计一下就看出算法了,学逆向一年左右了还是经验太少!还需学习啊,幸好有看雪这么好的论坛在(舔狗,哈哈 ^.^),看雪万岁!!

有空自己实现下拼图算法再发出来!先发网上的....... 

  相关解决方案