2012-05-14 52 views
4

我一直在努力學習python最近,並遇到了一些我很難理解它是如何工作的。首先,它是一個列表的設計。Python幫助理解示例代碼

有問題的列表是從這個安全文章談論的是一個簡單的模糊工具:http://blog.securestate.com/post/2009/10/06/How-a-simple-python-fuzzer-brought-down-SMBv2-in-2-seconds.aspx

有問題的實際列表是:

#Negotiate Protocol Request 
packet = [chr(int(a, 16)) for a in """ 
00 00 00 90 
ff 53 4d 42 72 00 00 00 00 18 53 c8 00 00 00 00 
00 00 00 00 00 00 00 00 ff ff ff fe 00 00 00 00 
00 6d 00 02 50 43 20 4e 45 54 57 4f 52 4b 20 50 
52 4f 47 52 41 4d 20 31 2e 30 00 02 4c 41 4e 4d 
41 4e 31 2e 30 00 02 57 69 6e 64 6f 77 73 20 66 
6f 72 20 57 6f 72 6b 67 72 6f 75 70 73 20 33 2e 
31 61 00 02 4c 4d 31 2e 32 58 30 30 32 00 02 4c 
41 4e 4d 41 4e 32 2e 31 00 02 4e 54 20 4c 4d 20 
30 2e 31 32 00 02 53 4d 42 20 32 2e 30 30 32 00 
""".split()] 

他翻出一個字節(我認爲?)從它使用以下行:

what = packet[:] 
where = choice(range(len(packet))) 
which = chr(choice(range(256))) 
what[where] = which 

我從來沒有見過這樣設計的一個列表,似乎並不能按照它是如何選擇不管它。最令我困惑的是packet = [chr(int(a, 16)) for a in """,他將所有這些東西都放在了看起來像是評論區的地方......然後是.split()。 0_o

我知道這是一個模糊的問題,但如果任何人都可以向我解釋這一點,或者指向一些解釋列表構建風格的文檔,我會非常高興。這看起來像是一種非常有效的方式來存儲/提取大量字節。

+0

這是一個字符串,而不是註釋。 – Marcin

+0

現在開始變得更有意義了!爲什麼3個引號? –

+2

由於多行。 – 2012-05-14 19:45:27

回答

2

讓我們打破它,並把它簡化爲可讀性:

bytes = """ 
      00 00 00 90 
      ff 53 4d 42 72 00 00 00 00 18 53 c8 00 00 00 00 
      00 00 00 00 00 00 00 00 ff ff ff fe 00 00 00 00 
      00 6d 00 02 50 43 20 4e 45 54 57 4f 52 4b 20 50 
      52 4f 47 52 41 4d 20 31 2e 30 00 02 4c 41 4e 4d 
      41 4e 31 2e 30 00 02 57 69 6e 64 6f 77 73 20 66 
      6f 72 20 57 6f 72 6b 67 72 6f 75 70 73 20 33 2e 
      31 61 00 02 4c 4d 31 2e 32 58 30 30 32 00 02 4c 
      41 4e 4d 41 4e 32 2e 31 00 02 4e 54 20 4c 4d 20 
      30 2e 31 32 00 02 53 4d 42 20 32 2e 30 30 32 00 
      """ 
    packet = [chr(int(a, 16)) for a in bytes.split()] 

bytes是,該"""通常用於Python的文檔字符串一個字符串,但您可以使用它們的代碼來創建非常長字符串(但他們那種吮吸,因爲你最終會在你的代碼多餘的空格。

bytes.split()將分裂的空白,並返回是空間分隔的字符串的各個部分的列表。

print bytes.split() 

['00', '00', '00', '90', 'ff', '53', '4d', '42', '72', 
'00', '00', '00', '00', '18', '53', 'c8', '00', '00' ... ] # and more 

所以後來這個:

packet = [chr(int(a, 16)) for a in bytes.split()] 

這是一個列表理解:

  • 分裂bytes並獲得該名單如上
  • 列表中的每個元素(a這裏)對其執行int(a,16),這將通過執行基數爲16到十進制的轉換(即FF將是255)。
  • 然後對該值執行chr,這將返回該字節的ASCII值。

所以packet將是一個ASCII格式的字節列表。

print packet 
['\x00', '\x00', '\x00', '\x90', '\xff', 'S', 'M', 'B', 'r', '\x00', '\x00', '\x00', 
'\x00', '\x18', 'S', '\xc8', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', 
'\x00', '\x00', '\x00', '\x00', '\x00', '\xff', '\xff', '\xff', '\xfe', '\x00', 
'\x00', '\x00', '\x00', '\x00', 'm', '\x00', '\x02', 'P', 'C', ' ', 'N', 'E', 'T', 
'W', 'O', 'R', 'K', ' ', 'P', 'R', 'O', 'G', 'R', 'A', 'M', ' ', '1', '.', '0', 
'\x00', '\x02', 'L', 'A', 'N', 'M', 'A', 'N', '1', '.', '0', '\x00', '\x02', 'W', 'i', 
'n', 'd', 'o', 'w', 's', ' ', 'f', 'o', 'r', ' ', 'W', 'o', 'r', 'k', 'g', 'r', 'o', 
... more ] 
+0

非常感謝大家的回答,特別是ovgolovin和birryree。我很欣賞你們兩個人的回答! :) –

2

""" 
content 
""" 

格式是一個簡單的方法在python以限定多行字符串文字。這是而不是評論區塊。

[chr(int(a, 16)) for a in "00 00 00...".split()]是一個列表理解。大字符串被拆分成一個數組(空格拆分),並且對於數組中的每個項目,它將其轉換爲一個十六進制數字(int(a,16)表示將字符串a轉換爲int,字符串a以16爲底數),然後返回ascii字符(chr(...))由該整數表示。

packet[:]返回列表packetshallow copy

choice(range(len(packet)))返回數據包長度範圍內的隨機數。

chr(choice(range(256)))從0,255範圍內選取一個隨機數,並將其解釋爲ascii字符,然後最後一條語句將ascii字符插入隨機選擇的位置。

10

""" 
00 00 00 90 
ff 53 4d 42 72 00 00 00 00 18 53 c8 00 00 00 00 
00 00 00 00 00 00 00 00 ff ff ff fe 00 00 00 00 
00 6d 00 02 50 43 20 4e 45 54 57 4f 52 4b 20 50 
52 4f 47 52 41 4d 20 31 2e 30 00 02 4c 41 4e 4d 
41 4e 31 2e 30 00 02 57 69 6e 64 6f 77 73 20 66 
6f 72 20 57 6f 72 6b 67 72 6f 75 70 73 20 33 2e 
31 61 00 02 4c 4d 31 2e 32 58 30 30 32 00 02 4c 
41 4e 4d 41 4e 32 2e 31 00 02 4e 54 20 4c 4d 20 
30 2e 31 32 00 02 53 4d 42 20 32 2e 30 30 32 00 
""" 

只是multiline string

""" 
00 00 00 90 
ff 53 4d 42 72 00 00 00 00 18 53 c8 00 00 00 00 
""".split() 

produces split與上述字符串的空格:

['00', '00', '00', '90', 'ff', '53', '4d', '42', '72', '00', '00', '00', '00', '18', '53', 'c8', '00', '00', '00', '00'] 

而且這樣的:

[chr(int(a, 16)) for a in ['00', '00', '00', '90', 'ff', '53', '4d', '42', '72', '00', '00', '00', '00', '18', '53', 'c8', '00', '00', '00', '00']] 

list comprehension其穿過形成列表和轉換應用chr(int(a,16))到每個都值a

int(a,16)將包含十六進制字符串表示的字符串轉換爲int

chr將此整數轉換爲char。

結果是:

>>> [chr(int(a, 16)) for a in ['00', '00', '00', '90', 'ff', '53', '4d', '42', '72', '00', '00', '00', '00', '18', '53', 'c8', '00', '00', '00', '00']] 
['\x00', '\x00', '\x00', '\x90', '\xff', 'S', 'M', 'B', 'r', '\x00', '\x00', '\x00', '\x00', '\x18', 'S', '\xc8', '\x00', '\x00', '\x00', '\x00'] 
1

您正在運行到幾個不同的概念在這裏。只是慢慢地倒退,你會發現它。

「」「00 00 00 90 ff 53 4d 42 72 00 00 00 00 18 53 c8 00 00 00 00」「」東西只是一大串。在它上面的.split將它分解成一個空格上的數組,所以在那一點上你有類似['00','00','00','90'....]

其餘的該行是一個列表理解 - 它這樣做的一個奇特的方式:

new_list = [] 
for a in that_list_we_split_above: 
    new_list.append(chr(int(a, 16))) 

Int函數是字符串轉換爲int在基地16 - http://docs.python.org/library/functions.html#int

Chr函數,然後得到ASCII使用該號碼的字符

所以在所有廢話結束時,你有所有的廢話ist'packet'

定義where的行包含該列表的長度,使用從0到長度(即每個可能的索引)的每個數字創建一個新列表,並隨機選擇其中的一個。

行爲其挑選0和256之間的隨機int和獲取ASCII字符它

最後一行在分組列表中的「位置」,在規定的隨機ASCII字符索引處替換項目這

TL;博士:去找到不同的代碼,以瞭解有關 - 這既是混亂和平庸

0

有問題的代碼示例似乎在另一個隨機字節的原始數據包來替代隨機選擇的字節(我相信,是背後的思想之一。)

packet = [chr(int(a, 16)) for a in """ 
00 00 00 90 .... """.split()] 

這是「將字符串拆分爲空白字符,將子字符串讀爲從十六進制數中的整數解碼的字符(int的第二個參數爲基數)。

what = packet[:] 

的Python成語給 「packet陣列複製到what」。

where = choice(range(len(packet))) 

在數據包中選擇一個隨機索引。

which = chr(choice(range(256))) 

製作一個隨機字符。

what[where] = which 

在先前選擇的索引處替換它。