bugku嵌入(IOT):easyIOT个人解题writeup

写在前面

我很后悔在最后的阶段没有愿意多进行尝试, 不然一血应该属于从看到题目发布时就开始解题的我.

文件分析

这次的代码是一个Arduino程序,用于控制七段显示器的亮灭。代码中定义了一个名为data的数组,其中存储了每个LED灯对应的引脚编号(A-G和DP)。COM引脚被设置为5V。

// Set A-G, DP as OUTPUT pins, COM is 5V
int data[] = {0, 0, 0,2,4,5,6,7,8,0,2,3,5,6,8,0,2,3,4,0,2,4,5,7,8,0,2,4,5,6,7,8,0,2,3,4,0,2,4,5,6,7,8,0,4,5,6,7,8,0,2,3,4,0,2,4,5,7,8,0,2,3,4,0,4,5,6,7,8,0,2,4,5,6,7,8,0,2,3,4,5,6,7,8,0,2,4,5,6,7,8,0,3,4,0,2,3,4,0,2,3,5,6,8,0,2,4,5,6,7,8,0,3,4,7,8,0,2,3,4,0,2,3,4,0,2,4,5,6,7,8,0,3,4,0,2,3,4,0,2,3,5,6,8,0,2,4,5,6,7,8,0,2,4,5,7,8,0,2,4,5,7,8,0,2,6,7,8,0,2,4,5,6,7,8,0,2,3,4,5,7,8,0,2,3,4,0,2,3,4,5,8,0,2,4,5,7,8,0,2,6,7,8,0,2,3,4,0,2,3,4,5,8,0,2,4,5,6,7,8,0,2,6,7,8,0,2,4,5,7,8,0,2,6,7,8,0,2,4,5,6,7,8,0,2,4,5,7,8,0,2,4,5,6,7,8,0,3,4,0,2,3,4,0,2,3,4,5,8,0,2,3,4,0,2,3,4,5,7,8,0,2,3,4,0,3,4,5,6,8};

在setup()函数中,使用for循环将2到9号引脚设置为输出模式。

void setup() {
        for(int i=2; i<=9;i++) pinMode(i, OUTPUT);
}

在loop()函数中,使用for循环遍历data数组中的每个元素。如果data[i]等于0,则调用clear()函数使对应的LED灯熄灭;否则,将对应的LED灯设置为低电平(LOW)。

void loop() {
        for (int i=0; i<sizeof(data) / 2; i++) data[i] == 0 ? clear() : digitalWrite(data[i], LOW);
}

clear()函数的作用是使指定的LED灯熄灭一段时间(1秒),然后将其设置为高电平(HIGH)。

void clear() {
        delay(1000);
        for(int i=2; i<=9;i++) digitalWrite(i, HIGH);
        delay(1000);
}

编写代码

用python可以快速模拟以上内容

test = open("test","a")
the_main = ["■","■","■","■","■","■","■","■"]
light = the_main.copy()
word = ""
loop_num = 0
data = [0, 0, 0,2,4,5,6,7,8,0,2,3,5,6,8,0,2,3,4,0,2,4,5,7,8,0,2,4,5,6,7,8,0,2,3,4,0,2,4,5,6,7,8,0,4,5,6,7,8,0,2,3,4,0,2,4,5,7,8,0,2,3,4,0,4,5,6,7,8,0,2,4,5,6,7,8,0,2,3,4,5,6,7,8,0,2,4,5,6,7,8,0,3,4,0,2,3,4,0,2,3,5,6,8,0,2,4,5,6,7,8,0,3,4,7,8,0,2,3,4,0,2,3,4,0,2,4,5,6,7,8,0,3,4,0,2,3,4,0,2,3,5,6,8,0,2,4,5,6,7,8,0,2,4,5,7,8,0,2,4,5,7,8,0,2,6,7,8,0,2,4,5,6,7,8,0,2,3,4,5,7,8,0,2,3,4,0,2,3,4,5,8,0,2,4,5,7,8,0,2,6,7,8,0,2,3,4,0,2,3,4,5,8,0,2,4,5,6,7,8,0,2,6,7,8,0,2,4,5,7,8,0,2,6,7,8,0,2,4,5,6,7,8,0,2,4,5,7,8,0,2,4,5,6,7,8,0,3,4,0,2,3,4,0,2,3,4,5,8,0,2,3,4,0,2,3,4,5,7,8,0,2,3,4,0,3,4,5,6,8][2:]
for i in data:
    if i == 0:
        loop_num += 1
        b = "".join(light)#.replace("▢","1").replace("■","0")[::-1]
        print(b)
        if b == "▢■▢▢▢▢▢■":
            a = 6
        elif b == "▢▢■▢▢■▢■":
            a = 2
        elif b == "▢■▢▢■▢▢■":
            a = 5
        elif b == "▢▢▢■■■■■":
            a = 7
        elif b == "■■▢▢▢▢▢■":
            a = "b"
        elif b == "▢▢▢▢▢▢▢■":
            a = 8
        elif b == "▢■■■▢▢▢■":
            a = "f"
        elif b == "■▢▢■■■■■":
            a = 1
        elif b == "▢▢▢▢■■▢■":
            a = 3
        elif b == "▢▢▢▢■▢▢■":
            a = 9
        elif b == "■▢▢■■▢▢■":
            a = 4
        else:
            a = ""
        #a = int(a,2)
        #a = chr(a)
        #test.write(a)
        light = the_main.copy()
        if loop_num == 2:
            loop_num = 0
            test.write("\\x")
        a = str(a)
        word += a
        test.write(a)
    else:
        light[i-2] = "▢"
        #print(light)
    #print("".join(light))
test.write("d")
word += "d"
test.close()
print(word)

将得到的文件test复制进python为字符串,可以得到flag.

原理解析

七段显示器服从指令SEG, 通过对给出数组data进行for循环, 将2-9电位信息以■▢形式进行输出. 当data指向0时执行源代码的clear()函数的暂停重置指令, 故在python中使用if判别输出当前结果, 并通过if-elif-else进行SEG转换, 得到数据word, 并以"\xXX"形式储存为test文件, python中"\xXX"格式用于转换数据十六进制数据. 最后是结尾的"d", 我们可以在tinkercad进行Arduino的仿真模拟进行测试, 将一个Arduino与7段显示器如下所示进行连接, 并输入代码(为提升效率, 以下将delay暂停时长缩短为1/10). 开始模拟后, 我们可以发现在结尾多出了一个在python模拟中未出现的新字符"d", 这是因为python代码中以for循环中的data指向0为结束获取数据, 而题目的程序中在结尾并未添加0, 导致出现了数据丢失, 当时我拿着51个字符表示非常疑惑, 再加上flag头的bugku{}没能成功对应上"flag{}"字符的各种编码形式, 导致我陷入过很长一段时间的错误思考, 痛失一血. 将缺少的"d"进行补全, 在字符串中便可以轻松找到特殊字符组合"7b"和"7d", 即十六进制编码的"{}"符号, 进行解码, 成功拿下flag

ctf·arduino
202 views
Comments
登录后评论
Sign In
·

首发!