CTFHub題解-歷年真題-Crypto篇
2020-BJDCTF-Crypto
(一)編碼與調制
本題要點:binascii進制轉換、曼徹斯特編碼
下載附件看一下:
有一張圖,I· m hint,上面有一串二進制01001100011,暫時還不知道是什么意義......
先了解一下曼徹斯特編碼和差分曼徹斯特編碼
曼徹斯特編碼:每一位的中間有一跳變,位中間的跳變既作時鍾信號,又作數據信號;從高到低跳變表示"1",從低到高跳變表示"0"。

差分曼徹斯特編碼:每位中間的跳變僅提供時鍾定時,而用每位開始時有無跳變表示"0"或"1",有跳變為"0",無跳變為"1"。
一:標准曼徹斯特編碼波形圖1代表從高到低,0代表從低到高
二:差分曼徹斯特編碼波形圖1代表沒有跳變(也就是說上一個波形圖在高現在繼續在高開始,上一波形圖在低繼續在低開始)開始畫0代表有跳變(也就是說上一個波形圖在高位現在必須改在低開始,上一波形圖在高位必須改在從低開始)
注:第一個是0的從低到高,第一個是1的從高到低,后面的就看有沒有跳變來決定了(差分曼徹斯特編碼)
emmmm,看懂了兩種編碼的原理,感覺那一串二進制好像沒什么解題思路呢....還是先看看密文吧.....
密文:2559659965656A9A65656996696965A6695669A9695A699569666A5A6A6569666A59695A69AA696569666AA6
密文看起來像是16進制,但是解轉字符串出來是亂碼....
參考了一些大佬的wp,發現還有這個16進制轉2進制和曼徹斯特編碼的轉碼工具~
為什么選標准曼徹斯特,因為筆者用小工具試了一下 802.3曼徹斯特和差分曼徹斯特,轉出來的16進制轉字符都是亂碼(捂臉)...
曼徹斯特解碼之后的16進制我們再轉一下字符串~
16進制:024A447B4469664D616E63686573746572636F64657D
咦,第一位沒有顯示出來誒........當然,比賽的時候,猜的話肯定能猜到是BJD{}......
試試用python轉一下呢~
補充一點py的語法~
python內置函數: hex(): #把10進制轉整形換成16進制 #內置函數hex和binascii.hexlify()的區別就在於, #hex只能接受整形不能接受字符串
import binascii x=0x024A447B4469664D616E63686573746572636F64657D x=binascii.unhexlify(hex(x)[2:]) print(x)
binascii模塊是python的一個用於進制轉換的模塊,關於binascii.unhexlify感興趣的小伙伴可以參考這篇博客:
python binascii 二進制轉換實例【b2a_hex、a2b_hex、hexlify、unhexlify】
由於筆者的py學的比較差,好多語法都還不會,起初沒太明白這個地方的hex(x)[2:]是什么意思.....網上找了半天資料,也沒有解釋...
后來筆者經過測試和猜測:
x=binascii.unhexlify(hex(x)[2:]) 此處的[2:]應該是讀取x的0x這兩個字節,因為我發現當把[2:]中的2改成4的時候,輸出結果就變成了JD{DifManchestercode};依次變成6/8/10的時候,輸出的字符串的開頭就會少一位。
因為如果刪去[2:],運行會報錯binascii.Error: Non-hexadecimal digit found,不識別十六進制數。
啊哦,發現報錯~
因為hexstr必須包含偶數個十六進制數字,所以奇數長度會報錯。
參考很多大佬的wp都是讓添加‘0’,而且我也沒有懂為什么要加‘0’,其實只要補一個字節就可以了。
而且之所以會變成奇數長度,主要是因為hex在轉換16進制的時候,把x=0x024A...36F64657D開頭的024A直接轉換成了24A;
所以你其實在x=0x ?24A...36F64657D這里改成任何一個非零的數字就可以。
import binascii x=0x024A447B4469664D616E63686573746572636F64657D x=binascii.unhexlify('0'+hex(x)[2:]) print(x)
運行是正常了,但是結果似乎不太對呢~
難道是轉碼轉錯了?但是其他的轉出來就更離譜.....
思索了半天,其實報錯是因為字符串是一個奇數字符串,所以要加一個字節變成偶數,B的16進制應該是42。
按理說
x=424A447B4469664D616E63686573746572636F64657D 就是正確的flag了
(筆者這屬於沒事干瞎想,比賽的時候,直接猜就完事了!)
有可能是出題人出錯了,也有可能暗含其他玄機,懂得小伙伴可以給我評論,指點一下迷津~
import binascii x=0x424A447B4469664D616E63686573746572636F64657D #此處改成0x42才能運行出正確結果 x=binascii.unhexlify(hex(x)[2:]) print(x)
BJD{DifManchestercode}
完成!
(二)base??
本題要點:base64編解碼原理、python基礎編程
題目是這樣:
emmm....給出了字典,給出了密文,有可能是讓我們根據base64編碼原理,解明文
先學習一下base64的編碼原理:
Base64是一種基於64個可打印字符來表示二進制數據的表示方法
Base64是一種編碼方式,提及編碼方式,必然有其對應的字符集合。在Base64編碼中,相互映射的兩個集合是:
二進制數據{0, 1}
{A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +, /}
Base64編碼方式可使得信息在這兩種字符集表示法之間相互等價轉換。
因為Base64的編碼方式是公開的,所以base64也可以算是公開算法的加密方法;但是只能簡單的“加密”保護某些數據,決不能在需要安全等級較高的場景中使用,因為可以使用公開的編碼方法輕易從base64字符表示的數據解碼二進制數據。
base64編碼過程
由於base64的字符集大小為64,那么,需要6個比特的二進制數作為一個基本單元表示一個base64字符集中的字符。因為6個比特有2^6=64種排列組合。
具體來說,編碼過程如下:
將每三個字節作為一組,共24bit,若不足24bit在其后補充0;
將這24個bit分為4組,每一組6個bit;
在每組前加00擴展為8個bit,形成4個字節,每個字節表示base64字符集索引;
擴展后的8bit表示的整數作為索引,對應base64字符集的一個字符,這就是base64編碼值;在處理最后的不足3字節時,缺一個字節索引字節取3個,最后填充一個=,;缺兩個字節取2個索引字節,最后填充==。
解碼時將過程逆向即可。
# -*- coding: UTF-8 -*- import base64 dict={0: 'J', 1: 'K', 2: 'L', 3: 'M', 4: 'N', 5: 'O', 6: 'x', 7: 'y', 8: 'U', 9: 'V', 10: 'z', 11: 'A', 12: 'B', 13: 'C', 14: 'D', 15: 'E', 16: 'F', 17: 'G', 18: 'H', 19: '7', 20: '8', 21: '9', 22: 'P', 23: 'Q', 24: 'I', 25: 'a', 26: 'b', 27: 'c', 28: 'd', 29: 'e', 30: 'f', 31: 'g', 32: 'h',33: 'i', 34: 'j', 35: 'k', 36: 'l', 37: 'm', 38: 'W', 39: 'X', 40: 'Y', 41: 'Z', 42: '0', 43: '1', 44: '2', 45: '3', 46: '4', 47: '5', 48: '6', 49: 'R', 50: 'S', 51: 'T', 52: 'n', 53: 'o', 54: 'p', 55: 'q', 56: 'r', 57: 's', 58: 't', 59: 'u', 60: 'v', 61: 'w', 62: '+', 63: '/', 64: '='} base64_list = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P','Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f','g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v','w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'] cipher='FlZNfnF6Qol6e9w17WwQQoGYBQCgIkGTa9w3IQKw' res='' for i in range(len(cipher)): for j in range(64): if(dict[j]==cipher[i]): res+=base64_list[j] print(res) flag=base64.b64decode(res) print(flag)
在線的python環境可以運行出來:
BJD{D0_Y0u_kNoW_Th1s_b4se_map}
完成!
參考資料
https://www.soinside.com/question/JpjZizLwHTBaXKVn3ZzM5g
https://www.cnblogs.com/yinsjun/p/6951588.html
https://www.cnblogs.com/hushaojun/p/7552138.html