2018 巅峰极客CTF misc writeup

flows

拿到一个pcap包,用wireshark打开,发现是USB协议,尝试在kali下使用tshark提取,提取失败,发现异常。回到wireshark分析数据。在其中一个数据包中发现了tip

把字节分组以原始数据保存出来,得到两个tips

然后将数据包排序,把最大的两个数据导出为1.pcap和2.pcap,然后在kali下利用tshark将leftover capture data里的内容单独提取出来,命令如下:

tshark -r 1.pcap -T fields -e usb.capdata > 1.txttshark -r 2.pcap -T fields -e usb.capdata > 2.txt

参考:https://www.anquanke.com/post/id/85218 直接脚本将其中一个txt跑出来为: flag[u5b-key,Tips里提醒了shirt问题,则为: flag{u5b_key

附上脚本:(网站中给出的脚本有错误,定义mappings时\将后面的内容转义了,需要将”"转义一下”)

mappings = {0x04:"A",  0x05:"B",  0x06:"C", 0x07:"D", 0x08:"E", 0x09:"F", 0x0A:"G",  0x0B:"H", 0x0C:"I",  0x0D:"J", 0x0E:"K", 0x0F:"L", 0x10:"M", 0x11:"N",0x12:"O",  0x13:"P", 0x14:"Q", 0x15:"R", 0x16:"S", 0x17:"T", 0x18:"U",0x19:"V", 0x1A:"W", 0x1B:"X", 0x1C:"Y", 0x1D:"Z", 0x1E:"1", 0x1F:"2", 0x20:"3", 0x21:"4", 0x22:"5",  0x23:"6", 0x24:"7", 0x25:"8", 0x26:"9", 0x27:"0", 0x28:"n", 0x2a:"[DEL]",  0X2B:"    ", 0x2C:" ",  0x2D:"-", 0x2E:"=", 0x2F:"[",  0x30:"]",  0x31:"\\", 0x32:"~", 0x33:";"}
nums = []
keys = open('1.txt')
for line in keys:
    if line[0]!='0' or line[1]!='0' or line[3]!='0' or line[4]!='0' or line[9]!='0' or line[10]!='0' or line[12]!='0' or line[13]!='0' or line[15]!='0' or line[16]!='0' or line[18]!='0' or line[19]!='0' or line[21]!='0' or line[22]!='0':
         continue
    nums.append(int(line[6:8],16))
keys.close()
output = ""
for n in nums:
    if n == 0 :
        continue
    if n in mappings:
        output += mappings[n]
    else:
        output += '[unknown]'
print 'output :n' + output

第二个数据包为鼠标的数据,根据tips,只需要看第一个字节,将后面的字节删除,只保留第一字节,推测00为未点击,01为点击左键,02为点击右键。将txt整理好,去掉没有点击的00; 保留01和02,即左键与右键; 猜测应为左键为0,右键为1,所以将01替换为0,02替换为1,生成二进制字符串。

将两段flag拼接即可得到完整flag。

tips:第一个键盘数据包的脚本存在问题,根据tips应告示如果第一个字节为0x20就按下shift,但是脚本中无法识别第一个字节为0x20的字符,直接被忽略了,但是这里我们可以根据猜测货值直接打开txt文件手工判断也能得到flag。


warmup

注意看这张图一会会考脑洞。

拿到题目打开后是一张bmp格式的图片,由此想到LSB加密。LSB也就是最低有效位 (Least Significant Bit)。原理就是图片中的像数一般是由三种颜色组成,即三原色,由这三种原色可以组成其他各种颜色,例如在PNG图片的储存中,每个颜色会有8bit,LSB隐写就是修改了像数中的最低的1bit,在人眼看来是看不出来区别的,也把信息隐藏起来了。譬如我们想把’A’隐藏进来的话,如下图,就可以把A转成16进制的0×61再转成二进制的01100001,再修改为红色通道的最低位为这些二进制串。


既然是LSB加密,上神器stegsolve。下载地址: 密码: ckbb

打开之后,使用Stegsolve——Analyse——Frame Browser这个可以浏览三个颜色通道中的每一位,并没有发现什么有价值的信息。

之后,使用Stegsolve——Analyse——Data Extract分别提取三个颜色通道中的最低位,发现是brainfuck和Ook,在线解密:https://www.splitbrain.org/services/ook

将三段字符串拼接得到完整flag。


Loli

图片下载下来,根据题目hint,想到使用0xFF异或整个文件(这我也不知道怎么想到的。。看了wp才知道这样做),脚本如下:

#!/usr/bin/env python
# coding=utf-8

def xor():
    with open('./1.png', 'rb') as f, open('xor.png', 'wb') as wf:
        for each in f.read():
            wf.write(chr(ord(each) ^ 0xff))


if __name__ == '__main__':
    xor()

得到新的png文件

使用二进制编辑器观察尾部,看到提示“black and white”,以及“IEND”标识,这是png的文件尾部,暗示该文件中隐藏了一个png文件。

使用 foremost 命令直接提取或者直接手扣一个png

观察png文件,可以看到色块分为11列,每列隔行的色块永远是黑色,这说明应该横向读取图片,而列中的横长条由8个小色块组成,显然其代表的是一个字节的数据。

按上述思路使用脚本提取该信息:

import matplotlib.image as mpimg

res_str = []
res = []


def readpng():
    png = mpimg.imread('./out.png')
    yy, xx, depth = png.shape
    for y in range(yy):
        if y % 2 == 0:
            for x in range(1, xx - 1, 9):
                _str = "0b" + str(int(png[y][x][0])) + str(int(png[y][x + 1][0])) + str(int(png[y][x + 2][0])) + str(int(png[y][x + 3][0])) + str(int(png[y][x + 4][0])) + str(int(png[y][x + 5][0])) + str(int(png[y][x + 6][0])) + str(int(png[y][x + 7][0]))
                res_str.append(_str)
                res.append(bin2hex(_str))
    print res_str
    with open('res.bin', 'wb') as f:
        for each in res:
            f.write(chr(each))


def bin2hex(_bin="0b101"):
    return int(_bin, 2) ^ 0xFF


if __name__ == '__main__':
    readpng()

得到二进制文件,只用cat命令即可获取flag


总结

CTF脑洞是真的重要,有些东西根本想不到或者不知道怎么想到的。另外,这次misc题目让我更加了解了stegsolve的用法,以前一般都是一起整体提取三个颜色的最低位,没想到还可以分别提取。还有就是了解了USB数据包的方法以及一般做题步骤。还是要多积累。加油!!!

posted @ 2019-03-24 15:20  𝓢𝓷1𝓹𝓮𝓻/  阅读(472)  评论(0编辑  收藏  举报