I've been trying to learn python recently, and ran across something that I'm having a hard time understanding exactly how it works. Primarily, it is the design of a list.
The list in question is from this security article talking about a simple fuzzing tool: http://blog.securestate.com/post/2009/10/06/How-a-simple-python-fuzzer-brought-down-SMBv2-in-2-seconds.aspx
The actual list in question is:
#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()]
He pulls a single byte (I think?) from it using the following lines:
what = packet[:]
where = choice(range(len(packet)))
which = chr(choice(range(256)))
what[where] = which
I have never seen a list designed this way, and can't seem to follow how it is selecting whatever it does. What is confusing me most is the packet = [chr(int(a, 16)) for a in """
, where he houses all of that stuff in what appears to be a comment block... then does .split()
. 0_o
I know this is a vague question, but if anyone could either explain this to me or point me in the direction of some documentation that explains that style of list building I'd be exceptionally happy. This looks like a very efficient way to store/pull out a large number of bytes.
This
"""
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
"""
is just 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 with spaces of the abovementioned string:
['00', '00', '00', '90', 'ff', '53', '4d', '42', '72', '00', '00', '00', '00', '18', '53', 'c8', '00', '00', '00', '00']
And this:
[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']]
is a list comprehension which goes through the formed list and converts all the values applying chr(int(a,16))
to each a
.
int(a,16)
converts string containing string representation of hexadecimal into int
.
chr
converts this integer into char.
The result is:
>>> [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']
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With