今天拿到一個(gè)png圖片隱寫的題疚俱。
對于這種windows下可以打開,linux下無法打開的png文件,當(dāng)然是第一時(shí)間懷疑寬和高做了手腳墓陈。
爆破crc校驗(yàn)所需要了解到的PNG文件頭知識(shí)
- (固定)八個(gè)字節(jié)89 50 4E 47 0D 0A 1A 0A為png的文件頭
- (固定)四個(gè)字節(jié)00 00 00 0D(即為十進(jìn)制的13)代表數(shù)據(jù)塊的長度為13
- (固定)四個(gè)字節(jié)49 48 44 52(即為ASCII碼的IHDR)是文件頭數(shù)據(jù)塊的標(biāo)示(IDCH)
- (可變)13位數(shù)據(jù)塊(IHDR)
- 前四個(gè)字節(jié)代表該圖片的寬
- 后四個(gè)字節(jié)代表該圖片的高
- 后五個(gè)字節(jié)依次為:
Bit depth、ColorType第献、Compression method贡必、Filter method、Interlace method
- (可變)剩余四字節(jié)為該png的CRC檢驗(yàn)碼庸毫,由從IDCH到IHDR的十七位字節(jié)進(jìn)行crc計(jì)算得到仔拟。
但我只有手頭抄的別人python2.7的腳本,放在python3下運(yùn)行不了(……)
在不斷的調(diào)試中發(fā)現(xiàn):
- 有數(shù)值超過了127岔绸,ascii不認(rèn)
- binascii在python3下不支持unicode編碼理逊,必須輸入字節(jié)碼,改成b''就能運(yùn)行了盒揉,但沒辦法payload拼接在一起爆破
- python3把文本和二進(jìn)制分開晋被,字節(jié)碼不能拼接
- 用string.encode('utf-8')倒是能運(yùn)行了,但是沒爆破出來刚盈,仔細(xì)一看發(fā)現(xiàn)編碼會(huì)把超過ascii范圍的譬如\xf4拆成b'\xc3\xb4'
- ……
搜了一圈又冷靜下來羡洛,覺得字節(jié)碼不能拼接就不拼接嘛……走別的路徑行不行?
行。
搜到bytearray()是個(gè)好東西欲侮,相比bytes字節(jié)串崭闲,bytearray是可修改的。是的我們知道在python2里可直接str拼接威蕉,但是我決定堅(jiān)守在python3里(其實(shí)就是懶得裝)刁俭,于是開始了數(shù)組賦值的過程。
python3.6下的代碼如下
import zlib
import struct
crc32key = 0xCBD6DF8A #補(bǔ)上0x韧涨,winhex下copy hex value牍戚。
data = bytearray(b'\x49\x48\x44\x52\x00\x00\x01\xF4\x00\x00\x01\xF1\x08\x06\x00\x00\x00') #winhex下copy grep hex。
n = 4095 #理論上0xffffffff,但考慮到屏幕實(shí)際/cpu虑粥,0x0fff就差不多了
for w in range(n):#高和寬一起爆破
width = bytearray(struct.pack('>i', w))#q為8字節(jié)如孝,i為4字節(jié),h為2字節(jié)
for h in range(n):
height = bytearray(struct.pack('>i', h))
for x in range(4):
data[x+4] = width[x]
data[x+8] = height[x]
crc32result = zlib.crc32(data)
if crc32result == crc32key:
print(width,height)
return None
一開始用的n是65535娩贷,感覺要花掉一生的時(shí)間第晰,自己手動(dòng)取消了()
就算這樣,本來也是沒有最后這行return的彬祖,我只是把65535換成了4095茁瘦。跑出結(jié)果我花了58s的時(shí)間,丟給老師涧至,他在虛擬機(jī)里只用了3s腹躁。
想要挽回自己的尊嚴(yán)()
想要買臺(tái)新電腦()
心得
- 今天為了做這道題把png啊struct啊crc啊bytes啊甚至py2到py3的知識(shí)全都過了一遍∧吓睿基礎(chǔ)知識(shí)還是要扎實(shí)啊纺非,或者出問題的時(shí)候再冷靜點(diǎn)()
- 其實(shí)寫到這里我覺得為什么不直接rb讀文件再slice一下而要手動(dòng)從winhex貼呢,如此的不neat赘方。但是好困了我要睡覺……
20170727更新:一鍵解決png圖片crc隱寫的代碼
import zlib
import struct
#讀文件
file = CommonFile+'2.png'
fr = open(file,'rb').read()
data = bytearray(fr[12:29])
crc32key = eval(str(fr[29:33]).replace('\\x','').replace("b'",'0x').replace("'",''))
#crc32key = 0xCBD6DF8A #補(bǔ)上0x烧颖,copy hex value
#data = bytearray(b'\x49\x48\x44\x52\x00\x00\x01\xF4\x00\x00\x01\xF1\x08\x06\x00\x00\x00') #hex下copy grep hex
n = 4095 #理論上0xffffffff,但考慮到屏幕實(shí)際,0x0fff就差不多了
for w in range(n):#高和寬一起爆破
width = bytearray(struct.pack('>i', w))#q為8字節(jié)窄陡,i為4字節(jié)炕淮,h為2字節(jié)
for h in range(n):
height = bytearray(struct.pack('>i', h))
for x in range(4):
data[x+4] = width[x]
data[x+8] = height[x]
#print(data)
crc32result = zlib.crc32(data)
if crc32result == crc32key:
print(width,height)
#寫文件
newpic = bytearray(fr)
for x in range(4):
newpic[x+16] = width[x]
newpic[x+20] = height[x]
fw = open(file+'.png','wb')#保存副本
fw.write(newpic)
fw.close
return None