一位客戶帶著他們丟失了源代碼的應用程式來找我。加載某些檔案時,此應用程式似乎隨機崩潰。我懷疑這個問題是由于競爭條件造成的,其中一個指標被洗掉,然后要么沒有設定為 NULL,要么沒有檢查有效性。
當使用 OllyDBG 逐步完成程式集時,我發現崩潰總是發生在同一個位置,所以這有點強化我的理論。這是它有時崩潰的裝配線,有時是關鍵字。
MOV EDI,DWORD PTR DS:[EAX]
是否可以通過本機匯編或通過行內匯編呼叫(或類似的東西)提取地址的 C 來驗證記憶體地址是否有效并且存在?
uj5u.com熱心網友回復:
C 中沒有通用的標準方法來驗證記憶體地址。也沒有我所知道的這樣的組裝說明。
在記憶體映射系統(例如任何現代作業系統)上,您可以使用系統特定的 API 檢查是否已為行程映射地址。從 C 的角度來看,映射到行程的地址并不能保證該地址有效,但未映射的地址肯定是無效的。
此外,即使可以發現一個地址是有效的,也不能告訴您您期望的物件是在該地址中還是在其他地方。
在 C 語言1之外,還有一些用于驗證記憶體訪問的工具。例如 Valgrind 和編譯器提供地址清理器和記憶體清理器。大多數情況下,這些有助于檢測不會導致程式崩潰的無效訪問。但它們通常也可以提供有關該記憶體的附加資訊。
1如果您有權訪問源。
我懷疑這個問題是由于比賽條件造成的
能夠驗證記憶體地址并不能解決這個問題。您應該做的1是使用除錯器找出正在訪問的物件,找到訪問該物件的所有位置。如果這些地方中的任何一個沒有持有可能同時訪問該物件的所有其他地方共有的互斥鎖,那么這就是你的錯誤。
1如果您有權訪問源。
丟失了源代碼
如果您有大量預算,那么您可以嘗試對其進行逆向工程并嘗試弄清楚它在做什么。我不會屏住呼吸;最好將其宣布為失敗的原因。
uj5u.com熱心網友回復:
每個人都提供了一些很好的回應。不幸的是,在這種情況下,客戶不愿意為軟體的完全重新開發付費。
我設法否定了崩潰......在確定崩潰發生的確切位置后,我使用了將代碼注入到 JMP 到自定義 C 函式。C 函式使用 __try __except 塊。在 Try 我放置了問題匯編代碼,如果問題代碼導致崩潰,__except 會捕獲它。之后,只需分析問題代碼在做什么以及何時開始執行其他操作,然后在捕獲例外時跳轉到問題函式的“其他”部分的開頭。
它并不能準確地檢測記憶體位置是否有效,而只是在導致例外時跳過代碼。希望這最終對某人有所幫助...
uj5u.com熱心網友回復:
是的,可以驗證指標的內容。但是,驗證目標是否正確則比較困難。
為了驗證指標,您需要:
- 有效地址范圍表(實作的地址及其范圍)。
例如,在嵌入式系統上,解碼的地址可能并非在所有位置都有記憶體或設備。 - 對于支持分頁或虛擬記憶體的作業系統,您需要弄清楚程式記憶體區域的限制(由作業系統給出)。作業系統可能會占用您的可執行檔案的一部分并將它們與硬碟驅動器上的代碼交換。
- 對于支持虛擬記憶體的作業系統,您必須確定允許指標訪問的“虛擬”記憶體中的哪個位置。閱讀有關記憶體映射檔案的資訊。
- 在某些平臺上,地址 0x0000 是有效地址。驗證您的目標平臺上是否存在這種情況。
恕我直言,可以驗證指標內容,但驗證可能非常復雜。
更喜歡使用參考。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/481977.html
上一篇:RISCV無分支編碼
