我正在国际开发协会中拆卸一个固件(西门子C165处理器- 00-en%5B8%5D.pdf?fileId=db3a304412b407950112b43a49a66fd7) .
我有固件,所以我也可以通过Python读取它。
我需要找到一个字符串是
0, 1, 2, 3, 4, 5, 6, 7 (0-7)编写了这个简单的程序:
from itertools import permutations
l = list(permutations(range(0,8)))
print(len(l))
with open("firm.ori", 'rb') as f:
s = f.read()
for i in l:
hexstr = '\\x'.join('{:02x}'.format(x) for x in i)
hexstrfinal = "\\0x" + hexstr
#print hexstrfinal
if(s.find(b'hexstrfinal')>0):
print "found"然而,它没有发现任何东西。
我以为序列会是相邻的,但也许不会。
只想确保程序是正确的。
实际上,0-7应该是一小部分,所以这是否意味着我需要搜索,例如,作为一个组合:
0x01, 0x23, 0x45, 0x67 上面是字节。
有人能证实这一点并建议如何搜索吗?
更新1:
尝试第二变体
from itertools import permutations
l = list(permutations(range(0,8)))
print(len(l))
with open("firm.ori", 'rb') as f:
s = f.read()
for item in l:
str1 = ''.join(str(e) for e in item)
n = 2
out = [str1[i:i+n] for i in range(0, len(str1), n)]
hexstr = '\\x'.join(e for e in out)
hexstrfinal = "\\x" + hexstr
#print hexstrfinal
if(s.find(b'hexstrfinal')>0):
print "found"但也没有线索..。
知道我做错了什么吗?
发布于 2019-01-14 04:33:45
在您的代码中有一些误解,以及一个主要的低效率。让我们从误解开始。
由于firm.ori是以二进制模式(rb)打开的,所以s = f.read()的结果是一个bytes对象。尽管有类似于字符串的方法,但这不是字符串!它包含字节,而不是字符。当您显示它时,\x...输出并不表示包含ASCII反斜杠和xes的bytes对象。相反,每个\x...都是一个转义序列,用于表示与ASCII可打印字符不对应的给定字节的十六进制值。
在您的循环中,您只处理字符串:hexstr = '\\x'.join('{:02x}'.format(x) for x in i)接受您的置换,并将其格式化为类似于bytes对象的字符串表示形式。希望您能从上一段中了解为什么这不起作用。
s.find(b'hexstrfinal')搜索文本ASCII数组b'hexstrfinal',而不是搜索名为hexstrfinal的变量。当然,后者不能工作,因为hexstrfinal有str类型,而不是bytes类型。如果要使用简单的bytes将其转换为hexstrfinal.encode('ascii'),则会得到b'\\x...',这完全不是您想要的。正确的方法是
s.find(hexstrfinal.encode('ascii').decode('unicode-escape').encode('latin1'))希望您能够理解为什么三次转换字符串以获得您想要的bytes是不必要的低效。每当您开始使用字符串作为拐杖来操作数字时,都是评估您的方法的好时机。这就开始了我们对代码中的低效率的讨论。
您目前正在尝试迭代所有可能的0-7排列,而不是寻找实际存在的排列。考虑到文件的大小只有200 or,期望在文件中出现全部甚至大多数排列是不合理的。此外,您正在搜索整个文件中的每一个可能的排列。对于文件大小N和K排列,您的代码运行在O(N * K)时间,而只需一次通过文件或O(N)就可以做到这一点。有了适当的数据结构,即使是用普通Python编写的循环也可能比当前代码的优化版本运行得更快。
策略很简单。遍历s。如果当前字符和下面的七个构成了一个有效的排列,则启动一个聚会。否则,继续寻找:
N = 8
allowed = set(range(N))
for index, b in enumerate(s):
if b in allowed and set(s[index:index + N]) == allowed:
print(f'Found sequence {s[index:index + N]} at offset {index}')这里有很多可能的优化,您可以通过numpy或scipy更有效地完成整件事情。
如果允许在序列中重复,事情也会变得更加复杂。在这种情况下,您必须对序列进行排序:
allowed = sorted(...)
N = len(allowed)
for index, b in enumerate(s):
if b in allowed and sorted(s[index:index + N]) == allowed:
print(f'Found sequence {s[index:index + N]} at offset {index}')如果你要去寻找小吃,事情会变得更加复杂。我将完全删除check b in allowed,只需编写一个可以在每半步应用的自定义检查:
N = 8
def build_set(items):
output = set()
for b in items:
output.add(b & 0xF)
output.add((b >> 4) & 0xF)
return output
def matches(seq):
if len(seq) == N // 2:
return build_set(seq) == allowed
elif len(seq) == N // 2 + 1:
check = build_set(seq[1:-1])
check.add(seq[0] & 0xF)
check.add((seq[-1] >> 4) & 0xF)
return check == allowed
else:
return False
allowed = set(range())
for index, b in enumerate(s):
if matches(s[index:index + N // 2]):
print(f'Found sequence {s[index:index + N // 2]} at offset {index}.0')
if matches(s[index:index + N // 2 + 1]):
print(f'Found sequence {s[index:index + N // 2 + 1]]} at offset {index}.5')在这里,build_set只是把小吃分成一组。matches检查一个字节(4个元素)上对齐的由8个字节组成的数组,或者一个由8个字节(5个元素)偏移的数组。这两起案件都是独立报告的。
发布于 2019-01-14 03:46:59
还不清楚你想找什么但是..。
(0,1,2,3,4,5,6,7)的每一个排列都将是一个类似于此的七项元组。
t = (7, 6, 4, 1, 3, 5, 0, 2)您可以像这样制作两项字符串。
>>> a = [''.join(map(str,thing)) for thing in zip(t,t[1:])]
>>> a
['76', '64', '41', '13', '35', '50', '02']然后生成字符串的整数并将其输入bytes。
>>> b = bytes(map(int,a))
>>> b
b'L@)\r#2\x02'那就去找吧
>>> b in s
????如果它找不到它,它就不在那里。
下面是一个十个字符字节对象(类似于您的文件)
>>> b = b'\xcbl\x7f|_k\x00\x9f\xa2\xcc'只是碰巧:
>>> bytes([203, 108, 127, 124, 95, 107, 0, 159, 162, 204])搜索3字符(或3整数)序列
>>> bytes([127,94,107]) in b
False
>>> bytes([127,95,107]) in b
False
>>> bytes([124,95,107]) in b
True
>>>当我处理二进制文件时,我真的认为整数不是字符。
https://stackoverflow.com/questions/54173185
复制相似问题