標籤:off 瞭解 檔案頭 iii cci read http env 位元組順序
前言
今天這篇博文有點意思,它是從一個例子出發,從而體現出在編程中的種種細節和一些知識點的運用。和從前一樣,我是人,離成神還有幾十萬裡,所以無可避免的出現不嚴謹的地方甚至錯誤,請酌情閱讀。
0x00
首先,題目是:讀取一個位元影像檔案(xxx.bmp),然後讀取前30個位元組,從這前三十個位元組中提取一些資訊。
這裡有一些知識要Crowdsourced Security Testing道:一個位元影像的前30位有什嗎?
BMP格式採用小端方式儲存資料,檔案頭的結構按順序如下:
- 前兩個位元組:‘BM‘表示Windows位元影像,‘BA‘表示OS/2位元影像;
- 一個4位元組整數:表示位元影像大小;
- 一個4位元組整數:保留位,始終為0;
- 一個4位元組整數:實際映像的位移量;
- 一個4位元組整數:Header的位元組數;
- 一個4位元組整數:映像寬度;
- 一個4位元組整數:映像高度;
- 一個2位元組整數:始終為1;
- 一個2位元組整數:顏色數。
你先要知道,讀取一個位元影像的前30位,那麼這前30位是什麼編碼呢?例如,某個位元影像的前30位:
b‘\x42\x4d\x38\x8c\x0a\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x80\x02\x00\x00\x68\x01\x00\x00\x01\x00\x18\x00‘
很容易看出,它們的單位是bytes
,也就是說,我們無法直接看懂它們,因此,我們得把它轉換成我們能看懂的東西。
python有趣的地方就在這裡了,Python提供了一個struct
模組來解決bytes
和資料類型的轉換。
例如,我想把一個整數10241024
轉換為以bytes
為單位的位元組怎麼辦?(如果你不懂位元組編碼,看這裡)很簡單:
>>> struct.pack(‘>I‘, 10241024)b‘\x00\x9cD\x00‘
稍微解釋一下:
>
表示位元組順序是big-endian,也就是網路序,I
表示4位元組不帶正負號的整數。
那麼我想把以bytes
為單位的位元組轉換回整型怎麼辦?,也很簡單:
>>> struct.unpack(‘>I‘, b‘\x00\x9cD\x00‘)(10241024,)
要注意的地方就是unpack
函數的第一個參數:‘>I‘
,解釋和pack
函數的一樣。
0x01
到了這裡,基本可以看例子了。說明:
- 我的執行環境是:python 3.6;
data.bmp
是我用Windows內建畫圖隨手畫的一個位元影像圖片;
- 我把這個程式儲存為:
struct1.py
;
data.bmp
和struct1.py
同在一個Windows目錄下,完整路徑:G:\newpython\data.bmp
和G:\newpython\struct1.py
例子:
#!/usr/bin/env python# -*- coding: utf-8 -*-import sysimport structfrom collections import namedtupledef bmg_info(weitu): with open(weitu, ‘rb‘) as f: data = f.read(30) info = BMGinfo(*struct.unpack(‘<ccIIIIIIHH‘, data)) if info.ch1 == b‘B‘ and (info.ch2 == b‘M‘ or info.ch2 == b‘A‘): return { ‘width‘: info.width, ‘height‘: info.height, ‘color‘: info.colornum } return Noneif __name__ == "__main__": BMGinfo = namedtuple(‘BMGinfo‘, (‘ch1‘,‘ch2‘,‘size‘,‘reserved‘,‘offset‘,‘headerbits‘,‘width‘,‘height‘,‘num‘,‘colornum‘)) weitu = sys.argv[1] print(bmg_info(weitu))
開啟cmd
,進入目錄G:\newpython
,執行命令:python struct1.py "G:\newpython\data.bmp"
即可看見驚喜。
這篇部落格說到這裡,終於到了重要的地方。其實在實踐這段代碼時,我遇見了幾個問題(錯誤):
- 遇到錯誤(AttributeError: module ‘struct‘ has no attribute ‘unpack‘),原來是我自己的py檔案不要和系統的模組名重名,解決辦法,把檔案名稱改掉(我這裡把
struct.py
改為struct1.py
);
- 靈活運用namedtuple。瞭解更多請看這裡
- 靈活運用可變參數技能(*struct.unpack(‘<ccIIIIIIHH‘, data)),關於可變參數,看這裡
0x10
感謝閱讀。
python中提取位元影像資訊(AttributeError: module 'struct' has no attribute 'unstack')