Python helps understand sample code

I recently tried to learn python and found it hard to understand how this works. First of all, this is a list.

The list in question refers to 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

Actual List:

#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 one byte from it (I think?) 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 in this way, and it seems that it cannot follow how he selects everything he does. What confuses me most is packet = [chr(int(a, 16)) for a in """ , where it places all this in what seems like a block of comments ... then does .split() . 0_o

I know this is a vague question, but if someone can either explain it to me or point me towards some kind of documentation that explains this style of building a list, I would be extremely happy. This looks like a very efficient way to store / pull a large number of bytes.

+4
source share
5 answers

Let me break it down and simplify it for readability:

  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 is a string, """ usually used for Python docstrings, but you can use them in your code to create very long strings (but they kind of suck because you end up with extra spaces in the code.

bytes.split() will be split into empty space and will return a list of the individual parts of the string, separated by a space.

 print bytes.split() ['00', '00', '00', '90', 'ff', '53', '4d', '42', '72', '00', '00', '00', '00', '18', '53', 'c8', '00', '00' ... ] # and more 

So then:

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

This is a list comprehension:

  • split bytes and get this list as above
  • for each element in the list ( a here), execute on it an int(a,16) , which will receive its integer value by converting base-16 to decimal conversion (i.e. FF will be 255 ).
  • Then do chr in this value, which will return you the ASCII value of this byte.

So packet will be a list of bytes in ASCII form.

 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 ] 
+2
source

it

 """ 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 a multi-line string .

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

creates split with spaces of the specified 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 description that goes through the generated list and converts all the values ​​that apply chr(int(a,16)) to each a .

int(a,16) converts a string containing a string representation of the hexadecimal to int .

chr converts this integer to char.

Result:

 >>> [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'] 
+10
source

  """ content """ 
Format

is an easy way to define multiline string literals in python. This is not a comment block.

[chr(int(a, 16)) for a in "00 00 00...".split()] is a list comprehension. A large string is divided into an array (divided into spaces), and for each element in the array it converts it to a hexadecimal number ( int(a,16) means that string a is converted to int, string a is in base 16), and then returns ascii char ( chr(...) ) represented by this integer.

packet[:] returns a shallow copy in the packet list.

choice(range(len(packet))) returns a random number in the range of packet lengths.

chr(choice(range(256))) selects a random number in the range of 0.255 and interprets it as ascii char, and then the final statement inserts ascii char at the randomly selected location.

+2
source

You have a couple of different concepts here. Just work slowly backwards and you will understand it.

"" 00 00 00 90 ff 53 4d 42 72 00 00 00 00 00 18 53 c8 00 00 00 00 "" the material is just a big line. Dividing it on it splits it into an array on spaces, so at this moment you have something like [00 ',' 00 ',' 00 ',' 90 '....]

The rest of this line is list comprehension - its a fancy way to do this:

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

int function converts string to int in base 16 - http://docs.python.org/library/functions.html#int

the chr function then gets the ascii character using that number

so at the end of all this nonsense you have a list of "package"

a line defining where it takes the length of this list creates a new list with every number from 0 to length (i.e. each possible index of this) and randomly selects one of them.

line for which a random int is selected between 0 and 256 and receives an ascii character for it

the last line replaces the element in the package list in the where index with an arbitrary ascii character, in which

tl; dr: find another code to find out - it's both confusing and uninspired

+1
source

The sample code in question seems to replace a randomly selected byte in the source packet for another random byte (which, I believe, is one of the ideas behind fuzzing.)

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

This is "dividing a string into spaces, reading substrings as characters decoded from integers in hexadecimal (the second argument to int is the base).

 what = packet[:] 

Python idiom for "copy array packet to what ".

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

Select a random index in the package.

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

Make a random character.

 what[where] = which 

Substitute it with the previously selected index.

0
source

Source: https://habr.com/ru/post/1412421/


All Articles