RoarCTF-Misc-TankGame

  1. 引言
  2. 开始
    1. 考点介绍
    2. GetFlag

引言

web手硬生生的被逼成了野生re手。。。

虽然是没啥技术含量的re。。。

开始

考点介绍

Unity逆向

一般用dnspy(没错就是因为它界面好看所以用它)

用ILSpy、reflector8也可以

初级算法

GetFlag

使用dnspy打开Assembly-CSharp.dll

可以看到关键的几个地方:

胜利条件

简单来讲就是打掉指定砖块,然后计算sha1,与题中所给sha1相等即获胜,然后得到flag

flag中md5值的生成方式

即md5后取前十位

地图初始化数值

仅列出部分

地图的数值变化

通过分析地图数值,可知8为空地,墙(Wall,数值为1)被击毁后值会变为8,老家(Heart,数值为0)被击毁后值会变为9

综上,我们只需要变动老家和墙的值(变动4个或5个),之后计算sha1,比对成功后计算md5,取其前10位即得flag

脚本如下:

import hashlib
import copy
from itertools import combinations


class tankgame():
    def __init__(self):
        self.map_data = [
        [
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8
        ],
        [
            8,
            8,
            4,
            5,
            8,
            1,
            1,
            1,
            1,
            1,
            1,
            8,
            8,
            8,
            8,
            4,
            8
        ],
        [
            8,
            2,
            8,
            1,
            8,
            8,
            5,
            1,
            8,
            8,
            8,
            1,
            8,
            1,
            8,
            4,
            8
        ],
        [
            8,
            5,
            8,
            2,
            8,
            8,
            8,
            8,
            1,
            8,
            8,
            4,
            8,
            1,
            1,
            5,
            8
        ],
        [
            8,
            8,
            8,
            8,
            2,
            4,
            8,
            1,
            1,
            8,
            8,
            1,
            8,
            5,
            1,
            5,
            8
        ],
        [
            8,
            8,
            8,
            8,
            5,
            8,
            8,
            1,
            5,
            1,
            8,
            8,
            8,
            1,
            8,
            8,
            8
        ],
        [
            8,
            8,
            8,
            1,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            1,
            8,
            1,
            5,
            8
        ],
        [
            8,
            1,
            8,
            8,
            1,
            8,
            8,
            1,
            1,
            4,
            8,
            8,
            8,
            8,
            8,
            1,
            8
        ],
        [
            8,
            4,
            1,
            8,
            8,
            5,
            1,
            8,
            8,
            8,
            8,
            8,
            4,
            2,
            8,
            8,
            8
        ],
        [
            1,
            1,
            8,
            5,
            8,
            2,
            8,
            5,
            1,
            4,
            8,
            8,
            8,
            1,
            5,
            1,
            8
        ],
        [
            0,
            1,
            4,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8
        ],
        [
            1,
            1,
            8,
            1,
            8,
            8,
            2,
            1,
            8,
            8,
            5,
            2,
            1,
            8,
            8,
            8,
            8
        ],
        [
            8,
            8,
            8,
            8,
            4,
            8,
            8,
            2,
            1,
            1,
            8,
            2,
            1,
            8,
            1,
            8,
            8
        ],
        [
            8,
            1,
            1,
            8,
            8,
            4,
            4,
            1,
            8,
            4,
            2,
            4,
            8,
            4,
            8,
            8,
            8
        ],
        [
            8,
            4,
            8,
            8,
            1,
            2,
            8,
            8,
            8,
            8,
            1,
            8,
            8,
            1,
            8,
            1,
            8
        ],
        [
            8,
            1,
            1,
            5,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            1,
            8,
            8,
            8,
            8
        ],
        [
            8,
            8,
            1,
            1,
            5,
            2,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            2,
            8,
            8
        ],
        [
            8,
            8,
            4,
            8,
            1,
            8,
            2,
            8,
            1,
            5,
            8,
            8,
            4,
            8,
            8,
            8,
            8
        ],
        [
            8,
            8,
            2,
            8,
            1,
            8,
            8,
            1,
            8,
            8,
            1,
            8,
            2,
            2,
            5,
            8,
            8
        ],
        [
            8,
            2,
            1,
            8,
            8,
            8,
            8,
            2,
            8,
            4,
            5,
            8,
            1,
            1,
            2,
            5,
            8
        ],
        [
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8,
            8
        ]
    ]
        # Position of Wall and Heart.Format:[1,1,"wall"]
        self.position = []
        # Store Changed map
        self.current_map = []
        # All possibilities positions of destroyed things.(Is a index.Like 0,1,2,etc)
        self.destoryed_position = []
        self.find_position()
        self.calc_destoryed_position(length=4)

    @staticmethod
    def get_sha1(string):
        obj = hashlib.sha1(string.encode("utf-8"))
        return obj.hexdigest()

    @staticmethod
    def get_md5(string):
        obj = hashlib.md5(string.encode("utf-8"))
        return obj.hexdigest()

    def find_position(self):
        """
        Find position of changeable item
        :return:
        """
        wall = 1
        heart = 0
        for i in range(0, 21):
            for j in range(0, 17):
                if self.map_data[i][j] == wall:
                    self.position.append([i, j, "wall"])
                elif self.map_data[i][j] == heart:
                    self.position.append([i, j, "heart"])

    def change_point(self, position):
        """
        Change the value in map_data based on the data type(wall or heart)
        :param position: like [1,1,"wall"]
        """
        if position[2] == "wall":
            self.current_map[position[0]][position[1]] = 8
        if position[2] == "heart":
            self.current_map[position[0]][position[1]] = 9

    def calc_destoryed_position(self, length):
        seed = list(range(0, 66))
        obj = combinations(seed, length)
        if length == 4:
            for d1, d2, d3, d4 in obj:
                self.destoryed_position.append([d1, d2, d3, d4])
        elif length == 5:
            for d1, d2, d3, d4, d5 in obj:
                self.destoryed_position.append([d1, d2, d3, d4, d5])

    def get_flag(self):
        # To show progress
        schedule = 0
        for each_destoryed_positions in self.destoryed_position:
            self.current_map = copy.deepcopy(self.map_data)
            for position in each_destoryed_positions:
                self.change_point(self.position[position])
            # List to string
            map_string = "clearlove9"
            for items in self.current_map:
                for item in items:
                    map_string += str(item)
            current_sha1 = self.get_sha1(map_string)
            if current_sha1.upper() == "3F649F708AAFA7A0A94138DC3022F6EA611E8D01":
                print("Find! Flag is: {}".format("RoarCTF{wm-" + self.get_md5(map_string)[:10] + "}"))
                exit()
            schedule += 1
            if schedule % 10000 == 0:
                print("{:.2f}% Total: {}".format(schedule/len(self.destoryed_position)*100, len(self.destoryed_position)))


a = tankgame()
a.get_flag()

脚本逻辑:

1. 找出地图中墙和老家的位置(x,y),将其存入一个列表中

2. 生成0~65的列表,对其进行分组(4个一组/5个一组,进行组合即可)

3. 遍历生成的组合,更改墙和老家的值,计算sha1,进行比对

4. 比对成功后计算md5,取前十位,组合flag并输出

结果如下:

写这脚本简直要了我老命了。。。

不过也学到了一点东西,比如itertools这个库,简直就是我等算法渣的福音。


如果我的文章能帮到您的话我会很开心.如需转载记得注明出处:)
目录