亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

200kB的文件要搜索8個!Python 或 IDA 中的(40320 個排列)

200kB的文件要搜索8個!Python 或 IDA 中的(40320 個排列)

冉冉說 2021-10-10 16:36:53
我正在拆解固件(西門子 C165 處理器 - https://www.infineon.com/dgdl/Infineon-C165-DS-v02_00-en%5B8%5D.pdf?fileId=db3a304412b407950112b43a49a66fd.7)我有固件,所以我也可以通過 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"但也沒有命中...任何想法我做錯了什么?
查看完整描述

2 回答

?
藍山帝景

TA貢獻1843條經驗 獲得超7個贊

您的代碼中有一些誤解,并且效率低下。讓我們從誤解開始。


由于firm.ori以二進制模式 ( rb)打開,因此結果s = f.read()是一個bytes對象。盡管具有與字符串類似的方法,但這不是字符串!它包含字節,而不是字符。當您顯示它時,\x...輸出不指示bytes包含 ASCII 反斜杠和 xes的對象。相反,每個\x...都是一個轉義序列,用于表示與 ASCII 可打印字符不對應的給定字節的十六進制值。


在您的循環中,您專門處理字符串:hexstr = '\\x'.join('{:02x}'.format(x) for x in i)采用您的排列并將其格式化為看起來像一個bytes對象的字符串表示。希望您從上一段中了解為什么這行不通。


s.find(b'hexstrfinal')搜索文字 ASCII 數組b'hexstrfinal',而不是名為 的變量hexstrfinal。后者當然不起作用,因為hexstrfinal有 type str,而不是bytes. 如果您要將其轉換為bytes使用簡單的hexstrfinal.encode('ascii'),則會得到b'\\x...',這根本不是您想要的。正確的方法是


s.find(hexstrfinal.encode('ascii').decode('unicode-escape').encode('latin1'))

希望您能明白為什么將字符串轉換三次以獲得所需的效率會不必要地低下bytes。任何時候您開始使用字符串作為操縱數字的拐杖時,都是評估您的方法的好時機。這開始了我們對代碼效率低下的討論。


您目前正在嘗試遍歷 0-7 的所有可能排列,而不是尋找實際存在的排列。鑒于該文件只有 200KB 大小,期望所有甚至大部分排列都出現在其中是不合理的。此外,您正在為每個可能的排列搜索整個文件。對于文件大小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檢查一個字節對齊的 8 個半字節數組(4 個元素),或偏移半字節(5 個元素)的 8 個半字節數組。這兩個案例都是獨立報告的。


查看完整回答
反對 回復 2021-10-10
?
蕭十郎

TA貢獻1815條經驗 獲得超13個贊

目前尚不清楚您要搜索的內容,但是...


的每個排列(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

>>>

當我處理二進制文件時,我真的認為整數而不是字符。


查看完整回答
反對 回復 2021-10-10
  • 2 回答
  • 0 關注
  • 183 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號