2010-08-14 77 views
0

我試圖擴展在線遊戲的遺留代碼,以合理保證與遊戲相關的資源文件是最新版本,而不是篡改。我想在不使用DRM的情況下執行此操作,無需進入內核模式,也無需硬件幫助。理想情況下,我最終解決的問題應該與用戶空間一樣安全。如果他們能夠繞過這些機制,那麼我會說他們已經有了調皮的權利 - 至少在一段時間內,我們會禁止他們。 :)輕量級文件驗證與PKI

顯而易見的做法是對每個文件進行加密散列,並將散列輸出與預先計算的散列進行比較。但必須注意確保用戶不能輕易地篡改用於與當前計算的哈希值進行比較的預先計算的哈希值。下面是我腦子裏想的措施,在體系結構層次:

  1. 使用OS設備時,過程開始鎖定所有的資源文件的寫作,所以沒有其他進程可以在事後覆蓋這些文件。
  2. 計算每個資源文件的MD5總和。
  3. 連接到https服務器,要求對存儲在客戶端可執行文件中的特定簽名證書進行驗證。
  4. 通過https下載包含「正確」散列的文件,將其存儲在RAM(而不是磁盤)中。
  5. 將計算出的散列值與通過https接收的散列值進行比較。
  6. 如果哈希值不匹配則退出。

這比存儲哈希客戶端更安全,因爲只要它們存儲在客戶端,通常有人可以修改它們。使用這種方案,攻擊者必須弄清楚如何修改可執行文件,以便更改嵌入式公共證書,以便它實際上包含攻擊者的證書,該證書針對攻擊者的https web服務器進行驗證,該證書包含與攻擊者篡改資源文件。這當然是可行的,但是如果程序使用存儲在客戶端的預先計算的密鑰,它會比它更難。

可執行文件是本地代碼,因此可能會將其封裝到打包程序中,這樣會更難以編輯二進制文件並替換公鑰。

現在,如果我剛剛描述了兩段如何潛在地攻擊我設計的方案:除了我描述的攻擊此方案之外,還有其他方法嗎?

我的第二個問題是,什麼是可以從Win32 C++(Visual Studio 2010編譯器)調用來完成這些任務的免費(如免費或自由)庫?它們可以使用內置的Windows API完成,還是需要第三方解決方案?

所以總而言之,這些問題: 1.我建議的方案是否足以阻擋大多數劇本小子;和 2.我會用什麼依賴或庫來實現它?因爲這只是一個遊戲,而不是國家安全甚至是貨幣風險(遊戲是100%免費軟件,沒有遊戲中的經濟),我實現的解決方案應該是相當不錯的,但它不會必須是工業實力。

隨意回答我的問題的一個或兩個部分,如果您認爲我提出了錯誤的問題,那麼請您糾正我。

謝謝!

回答

2

我喜歡你的解決方案。這是很好的想法。你基本上回答你自己的問題。我有幾點建議要指出。

最適合您的任務的Win32庫是散列的Windows Crypto API。它還支持我推薦的SHA-1(因爲MD5現在被認爲是脆弱和可破解的)。您可能還需要查看使用HMAC和SHA1,以便計算出的散列包含一個密鑰(嵌入代碼中)。

Wininet是一個適合下載的庫。我相信它支持使用證書驗證的HTTPS。

用於打開文件的Windows API CreateFile實質上可以鎖定內容文件。只需打開所有文件而不指定任何FILE_SHARE_ *標誌。

讓我拋出一些我在遊戲行業短暫的時間裏學到的其他想法。

大多數遊戲在作弊者移動到下一個有趣的遊戲之前只有很短的一生(幾個月到一年)。因此,鑑於確實沒有一個完美的解決方案來阻止一個堅定的黑客沒有更好的做法,你基本上在尋找可以花時間的解決方案。也就是說,您將更多的保護措施投入到遊戲中,需要一個確定的黑客破解您的解決方案的時間越長。即使您的所有保護措施不具備密碼安全性,也會爲您帶來更多時間。

如果你不關心黑客誰會嘗試反彙編和修改你的遊戲的EXE,你可能會完成你提出的解決方案。但請考慮以下幾點。

1)這是一個更簡單的攻擊。在您的代碼中的某處,您可能會有一個函數,根據您描述的散列驗證解決方案決定是否可以繼續遊戲。黑客所要做的就是找到最終驗證的最終位置,並強制驗證代碼始終成功。也就是說,如果你在你的代碼,這樣的功能:

bool IsContentValid() 
{ 
    // compare the local hash with the hash returned from the https response 
    return (0 == memcmp(local_hash, network_hash, sizeof(HASH))); 
} 

則變得非常容易了意志堅定的黑客修改了自己的EXE,使這個代碼路徑總是成功。黑客只是等待代碼到達最終檢查的地步,並替換程序集以將錯誤的位置爲真。

一個明顯的解決方法是將此功能的不同變體鏈接到遊戲代碼的不同區域,並在遊戲過程中定期調用。使用#define C宏而不是函數來執行此檢查。實現代碼的10個不同變體作爲10個不同的宏。在代碼的50個不同位置調用這些宏 - 這樣黑客就必須找到它們並修補它們才能成功。這樣做,如果內容被認爲是無效的,遊戲的行爲錯誤。例如,如果他的內容文件無效,則玩家的健康和彈藥值會隨機變爲零,這樣他就很容易被殺死!

2)更經常地修補遊戲(每隔幾個月),即使除了生成內容的新哈希之外沒有任何理由,並且EXE的新佈局是另一種購買時間的保護。想象一下,你每個月都會修補遊戲,並簡單地更新加密哈希算法和對內容進行一些微調。發佈原始破解的黑客必須重新開始。如果他再次獲得成功,這需要他花費更多的時間和時間來分發他的更新版本。

3)我會做內容的本地驗證以及網絡驗證。他們應該使用不同的哈希算法。

4)購買時間的另一個cheezy hack:驗證EXE本身的HASH以及內容(本地和網絡上)的HASH。

5)使用內容和exe的另一個散列是一個簡單的加密密鑰,用於對服務器的所有網絡消息進行數字簽名。您可以簡單地附加到網絡消息:your_simple_fash_hash(content_hash,exe_hash,network_message)。服務器對所有收到的網絡消息都做同樣的事情。針對不同的網絡消息類型實施此哈希/簽名代碼的不同版本。將Murmur hash看作一個快速哈希函數示例。現在黑客也必須破解網絡代碼!

6)讓黑客很難用Softice或任何其他類型的內核調試器來反彙編你的遊戲代碼。用於存儲內容驗證散列(或任何加密密鑰)的任何變量也應加密。一個cheezy保護 - 將所有重要變量與0xAAAAAAAA(或某些其他噪聲)存儲在RAM中時異或。當你需要使用這些值時,將它們XOR回一個臨時變量var,使用它們,然後在你完成計算後立即清零結果。除了內容文件散列之外,玩家健康,燃料和彈藥的變量也應該以這種方式處理。 7)如果可能的話,找到一個聰明的方法來移動RAM中的重要變量,這樣它們就永遠不會留在整個遊戲的同一個內存位置。

好的,這是一個大腦轉儲。不止我喜歡爲在stackoverflow上只有1個聲望點的人寫信。我希望它有幫助。

+0

@selbie:我只想回到這個(老)問題,並說非常詳細和慷慨的解決方案謝謝你。我最近閱讀了這篇文章,它對我非常有幫助,現在我有足夠的信心去嘗試在我的遊戲的開發環境中進行這種改變。不要停止爲別人做這種腦轉儲的事情;這很棒! – allquixotic 2012-08-13 21:01:04

+0

今年的兩年,你還在做同樣的遊戲? :) – selbie 2012-08-14 19:07:08

+0

是的。它當然向公衆發佈,但我們仍在考慮如何實現這樣的方式來改進我們的補丁程序並在讓人們開始遊戲之前驗證資源是否完好無損。當然,我們的目標並不是像Valve Anti-Cheat那樣具有限制性和偏執性,但有些人試圖至少避免無意的文件損壞/過時,並避免偶然的腳本小子會很好。所以你的答案有幫助。 – allquixotic 2012-08-14 19:14:25