使用模糊测试库(Python)
我正在尝试使用这个库:http://pastebin.com/xgPXpGtw(使用示例:http://pastebin.com/fNFAW3Fh)。
我遇到了一些问题,因为我不想像他那样把所有的字节分割成一个数组。
我的测试脚本看起来是这样的:
import random
from random import *
def onerand(packet):
pack = packet[:]
byte = str(chr(choice(range(256))))
pack[choice(range(len(packet)))]= byte
print "fuzzing rand byte:%s\n" % (byte.encode("hex"))
return pack
test = "\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63"
while True:
print onerand(test)
实际上返回的是:
Traceback (most recent call last):
File "test.py", line 14, in <module>
print onerand(test)
File "test.py", line 7, in onerand
pack[choice(range(len(packet)))]= byte
TypeError: 'str' object does not support item assignment
那么我该怎么做才能在测试参数上使用那个函数呢?
谢谢!
2 个回答
在Python中,字符串是不可变的。你把一个字符串传给函数onerand
,参数名是packet
,然后复制它并给它一个本地名字pack
(这仍然是一个字符串,所以也是不可变的),接着你尝试去做
pack[whatever] = byte
这里的索引并不重要:你是在尝试修改这个不可变的字符串。错误信息就是在告诉你这一点,我觉得说得很清楚:你不能这样做。
我不想把所有字节分割成一个数组。
如果你需要修改其中的一些内容,那你肯定不能用字符串。你对数组有什么意见呢?可以用import array
,然后用pack = array.array('c', packet)
来代替pack = packet[:]
,这样你就能快乐地生活下去了——array.array
非常紧凑且速度快,而且它是可变的!
编辑:你也可以用列表来实现,就像被接受的答案那样,但这样做的性能代价会非常高。例如:
$ py26 -mtimeit -s's="".join([str(x)[0] for x in range(99)]); import array
> ' 'a=array.array("c",s); a[23]="b"; b=a.tostring()'
1000000 loops, best of 3: 1.09 usec per loop
$ py26 -mtimeit -s's="".join([str(x)[0] for x in range(99)]); import array
> ' 'a=list(s); a[23]="b"; b="".join(a)'
100000 loops, best of 3: 7.68 usec per loop
list
是一种比array.array
更通用的结构,而你在这里其实只需要array.array
,所以选择错误的数据结构会导致速度下降超过七倍。(在Python 2.7中情况稍微好一点,速度下降“只有”四倍多——但是,想想如果你要买一台比现在快四倍的机器要花多少钱,也许你会同意,即使速度提升“只是”4倍多,而不是7倍多,仍然是值得的;-)
与其使用 pack = packet[:]
,不如用 pack = list(packet)
,然后在最后用 return ''.join(pack)
来返回结果。
你不能直接替换字符串中的一个字节,但你可以先把字符串转换成一个字符列表,替换掉其中的一个元素,然后再转换回字符串。