Crypto
利用下班时间打了下这个比赛,挑了部分解出的有趣题目记录下来供参考。
Echo Chamber
pwntools的简单使用,将获取到的数据重复一遍发送过去
脚本如下:
1 2 3 4 5 6 7 8 9 10 11
| from pwn import *
c = remote('echo.tghack.no',5555) i = 0 while i <= 50: s = c.recvline() print s c.sendline(s.strip()) i += 1 print i print c.recvline()
|
得到flag
TG19{behold_the_echo_chamber_of_secrets}
Exclusive Magic Club
上图的二进制代码摘录如下:
00111001 00101000 01000101 01010001 00011110 00010000 00110000 00011100
00110001 00001011 00011000 00000100 00110001 00111101 00010001 00011100
00101011 00011001 00000111 00010001 00110111 00100100 00111011 00000000
00000100 00011000 00001010 00000101 00011111 00110000 00010000 00000001
00000000 00001001
直接Binary转Ascii是乱码,查看本题的分值和相关信息,才发现是XOR运算,也就是和mother_knows_best做异或运算,在此之前,做了诸如对二进制代码按位取反等操作,在下面的脚本也有体现。
注意需要将mother_knows_best转换为二进制,因为原文是34个二进制,所以mother_knows_best,也就是xorkey需要补全。
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
|
secret = "00111001 00101000 01000101 01010001 00011110 00010000 00110000 00011100 00110001 00001011 00011000 00000100 00110001 00111101 00010001 00011100 00101011 00011001 00000111 00010001 00110111 00100100 00111011 00000000 00000100 00011000 00001010 00000101 00011111 00110000 00010000 00000001 00000000 00001001" step1 = secret.split(" ") print step1
step2 = [] for i in step1: print i for j in i: step2.append(str(int(j)^1))
print step2 step3 = "".join(step2) print step3 step4 = "" for l in range(len(step3)//8): print int(step3[l*8:l*8+8],2) step4 += step3[l*8:l*8+8] + " " print step4
step5 = step4.strip().split(" ")
print step5
xorkey = "01101101 01101111 01110100 01101000 01100101 01110010 01011111 01101011 01101110 01101111 01110111 01110011 01011111 01100010 01100101 01110011 01110100 01101101 01101111 01110100 01101000 01100101 01110010 01011111 01101011 01101110 01101111 01110111 01110011 01011111 01100010 01100101 01110011 01110100" xorkey2 = xorkey.split(" ") print len(step1) print len(xorkey2) flag = "" for x in range(34): flag += chr(int(step1[x],2)^int(xorkey2[x],2))
print flag
|
最终得到flag
Josefssons Final Exam
有了上题的经验,第一部分明显是使用good_luck作为xorkey,与二进制异或。
使用类似的脚本处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
secret = "00100011 00100010 00000100 00000010 00001000 00101010 00010111 00001011 00000001 01010101 01010110 00001100 00100010 01101100 00011000 00010001 00001111 00101111 01011110 00011111 00000100 00010001 00011011 00000010 00011001 00101100 00011011 00010011 00101001 01011101 00110010 00111000 00000001 00110011 00101001 01011011 00001101 01011110 01010110 00000110 00011000 00101010 00100011 01010011 00100011 00100001 00111101 01010110"
step1 = secret.split(" ") print step1
xorkey = "01100111 01101111 01101111 01100100 01011111 01101100 01110101 01100011 01101011 01100111 01101111 01101111 01100100 01011111 01101100 01110101 01100011 01101011 01100111 01101111 01101111 01100100 01011111 01101100 01110101 01100011 01101011 01100111 01101111 01101111 01100100 01011111 01101100 01110101 01100011 01101011 01100111 01101111 01101111 01100100 01011111 01101100 01110101 01100011 01101011 01100111 01101111 01101111" xorkey2 = xorkey.split(" ") print len(step1) print len(xorkey2) flag = "" for x in range(48): flag += chr(int(step1[x],2)^int(xorkey2[x],2))
print flag
|
运行后的输出效果如下:
输出了下面的内容:
DMkfWFbhj29cF3tdlD9pkuDnlOptF2VgmFJ0j19bGFV0HFR9
到这里思路断了,因为使用base64去解密是乱码。
后来考虑是不是使用了移位密码把一段base64字符串做了处理,于是验证了一下
>>> import base64
>>> base64.b64encode("TG19{blablabla}")
'VEcxOXtibGFibGFibGF9'
再看看移位处理后的字符串,前面的字符果然是相同的。
最后就是按照输出的内容修改字符大小写
VEcxOXtzb29uX3lvdV9hcmVfdGhlX2NyeXB0b19tYXN0ZXJ9
得到flag
>>> base64.b64decode("VEcxOXtzb29uX3lvdV9hcmVfdGhlX2NyeXB0b19tYXN0ZXJ9")
'TG19{soon_you_are_the_crypto_master}'
Passing Notes
题目首先给了一段AES的密文
vyLlwWSY1PCK5ELNTPUVdpl8z0rIXiB2+Ybcu/BeXidR3MEiym852HCkS6wHVCr+CdpP6Moe9VQUeFcyq3vZDpVK/orl+8vREYMRrnQR9O4=
然后给出了一段hash
bbb2c5e63d2ef893106fdd0d797aa97a
这段hash可以经过md5解密,解密后的内容为supersecretpassword
最后给出了一段加密代码,告诉我们使用的是AES加密
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import base64 from Crypto.Cipher import AES from Crypto import Random from Crypto.Hash import SHA256 from struct import pack
BS = 16 secret = b'not_the_secret' key = SHA256.new() key.update(secret)
def encrypt(key, message): iv = Random.new().read(BS) pad_len = BS - divmod(len(message), BS)[1] padding = [pad_len]*pad_len padding = pack('b'*pad_len, *padding) cipher = AES.new(key, AES.MODE_CBC, iv) return base64.b64encode(iv + cipher.encrypt(message + padding))
|
这里有个坑,就是上面的代码里key.update(secret)得到的不是可用的key
修改代码,再加载正确的密码就可以解出原文。
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
| import base64 from Crypto.Cipher import AES from Crypto import Random from struct import pack import hashlib
BS = 16 secret = b'supersecretpassword' key = hashlib.sha256(secret.encode('utf-8')).digest()
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
def encrypt(key, message): iv = Random.new().read(BS) pad_len = BS - divmod(len(message), BS)[1] padding = [pad_len]*pad_len padding = pack('b'*pad_len, *padding) cipher = AES.new(key, AES.MODE_CBC, iv) return base64.b64encode(iv + cipher.encrypt(message + padding))
def decrypt(key, cipher): enc = base64.b64decode(cipher) iv = enc[:16] cipher = AES.new(key, AES.MODE_CBC, iv) return unpad(cipher.decrypt(enc[16:])).decode('utf8')
if __name__ == '__main__': cipher = 'vyLlwWSY1PCK5ELNTPUVdpl8z0rIXiB2+Ybcu/BeXidR3MEiym852HCkS6wHVCr+CdpP6Moe9VQUeFcyq3vZDpVK/orl+8vREYMRrnQR9O4=' print decrypt(key,cipher)
|
运行
Superb Owlput
superb-owlput.pcap
提供了一个流量包文件供我们分析,使用wireshark分析,发现主要是DNS流量
从上图就可以看到Info信息里的域名长串有点东西
转一下就发现是JPEG的文件头,那么这题的思路就很清楚了,把所有的域名字串拼起来得到一张图片。
这里使用tshark和awk脚本可以很方便的处理,注意-Y是做过滤的
tshark -r superb-owlput.pcap -Y "ip.src == 172.19.1.50 && dns" -T fields -e dns.qry.name | awk '{if ($1~/.dw.tghekk.local/) print $1}' | awk -F '.' '{print $1}' | tr -d '\n' > dns
得到dns后,再使用xxd转换为图片文件,命令如下:
xxd -p -r dns flagdns
然而打开图片后并没有flag,使用exiftool看一下文件头
明显是一段base64字符串
加入=之后就可以解密了。
>>> base64.b64decode("VEcxOXtUSEVfV0FMTFNfQVJFX0NPVkVSRURfV0lUSF9NQUdJQ0FMX1NBTFR9Cg==")
'TG19{THE_WALLS_ARE_COVERED_WITH_MAGICAL_SALT}\n'