iOS遊戲如何防禦外掛及IAP破解

Game2遊戲:


文/ Dani Lee
今年3月初寫過一篇《iO平臺遊戲安全小議》,到現今已有7個月了。在這段時間內,iOS平臺上的安全問題也產生了不小的變化。從作弊方式來說,從以前稍有門檻的手工操作(命令列操作)發展成了傻瓜式的只需要點擊按鈕的外掛工具的普及,使得作弊方式可以大量的氾濫。從防禦方式來說,發展雖然緩慢,但也有了一定的有效對策。
遊戲,無論是運行在哪個平臺,PC機,掌機,街機,電視還是手機上?無論是單機,弱聯網的,強聯網的?無論是否具備用戶端,網頁遊戲還是用戶端遊戲,本質上就是資料與指令。總的來說由三部分組成
1.負責邏輯處理即指令部分
在windows上它有exe,dll尾碼,好識別(還有swf,air等尾碼),基本是PE32 executable格式。
在linux/unix系統上為ELF executable,so格式
在mac/iOS上它為Mach-o executable,dylib格式
在Android上它為dalvik dex,so格式
無論是啥格式,都是可以依靠調試與逆向來查明或修改其處理邏輯,唯一的區別就是實現語言和運行平臺的不同帶來的使用工具和逆向難度有所不同。
實現語言不同,決定了得到的彙編代碼還是源碼,像java和as可以直接獲得源碼,而objective-c(c或類c)目前只能獲得彙編代碼。
運行平臺不同,得到了彙編代碼也會有所不同,是Intel的還是arm的,目前手機上都是arm的。
2.留在本地的資料(記憶體+硬碟)
雁過留痕,運行在本地的遊戲,會將資料寫入記憶體和硬碟。這也是遊戲作弊的重點物件。
通過修改寫入硬碟的資料作弊的外掛,往往會有xxx(遊戲名)存檔修改器xxx(遊戲)存檔補丁/外掛程式這種直白的名字。
(存檔修改是個比較綜合的半手工作弊方式,計畫專門為其寫一篇博客)
通過修改寫入記憶體的資料作弊的外掛,名字則會有趣得多,windows有名的有cheat engine,手機上的有八門神器
很明顯cheat engine要比八門神器功能要強大的多,它支援多種數數值型別(包括自訂資料類型)和掃描方式,八門神器雖然支援的類型較少但也足以應付常用遊戲資料類型的修改了,並且我相信只要手機遊戲繼續繁榮,在不久的將來其功能畢將更加完善。
記憶體修改器對遊戲收費與遊戲壽命的破壞非常大。對大多數玩家而言,遊戲過程就是打怪升級的一個過程,給一個目標,然後達成它,無論目標是獲得更多的積分還是爭取更多的遊戲幣。如果這些數值不做加密處理,是非常容易使用工具定位和修改成指定的數值。
對玩家而言,如果目標容易達成,遊戲的樂趣也隨著減少了,可能會尋求另一款遊戲。而且免費可以獲得的東西大多數人是不會再花費獲得了。即使玩家是真正喜好遊戲的,作弊獲得好處的人帶來的不公平感也會迫使玩家離開遊戲。
想想這個場景,如果1000個遊戲幣需要100塊人民幣,當你發現通過八門神器可以不花一毛錢將遊戲幣的數量改成999999的時候,你會再花費嗎?
要保護遊戲不被八門神器這種工具破壞,就要從工具的原理,修改物件及缺陷著手處理
記憶體修改工具的原理都是通過不斷改變待修改資料的大小來縮小位址範圍來定位實際的資料存儲位址並給以修改
玩家的修改物件是在遊戲運行過程中,存儲在記憶體中的可以在遊戲介面看到變化的遊戲數值,比如說遊戲幣,道具數量,等級,HP,攻擊力等等。
由此我們可以得知八門神器只能定位到特定資料類型(浮點型資料,自訂資料,和需要服務端做驗證的資料都不能修改)的數值,並且只能進行精確數值的修改,而普通玩家也只會修改在遊戲介面有回顯的數值
因此我們可以將存儲在記憶體中的資料經過加密演算法來進行轉換(將遊戲數值由常規類型變成自訂資料類型),使得記憶體修改器不能定位到搜索的數值,也就無法進行修改。
例如
int c = 30000 常規存儲為 0000 0000 0000 0000 0111 0101 0011 0000
可以通過特定演算法來進行位轉換和位移動操做來變成自訂存儲格式,例如存儲為0000 0000 0000 0000 0001 1100 0000 0010
這種加密方式可以防禦普通玩家使用工具進行修改,但抵擋不了逆向高手獲知加密演算法邏輯後定制的特定搜索修改器,但已經從很大程度的防禦了普通玩家作弊。針對外掛專業工作室的防禦,將是逆向與反逆向的領域了,相信只有火到一定程度的遊戲才會引起這些人的專門破壞。
最後,為了減輕定位到修改數值後造成的破壞,最好在調用該數值的時候,檢測一下數值的邏輯範圍,將過於誇張的數值判定為非法。
3.傳輸在網路中的資料
遊戲從app store中下載需要聯網,遊戲中有購買行為(例如購買道具,解鎖關卡)也需要聯網,如果遊戲需要在開發商伺服器上存儲資料或進行邏輯處理(例如登錄),也是需要聯網的。
總的來說,聯網過程涉及到三方,app store,開發商伺服器(即遊戲服務端),和玩家設備(即遊戲用戶端)。這三方間的資料傳輸,只要經過玩家設備的都可以通過代理工具捕獲並進行修改。
對於需要在登錄驗證並在服務端存儲資料的遊戲,最常犯的錯誤,就是在玩家登錄遊戲後,將伺服器拉取的遊戲資訊明文返回給用戶端。
例如來自同一公司也具備同樣錯誤的space city和contract killer遊戲,就是登錄的時候,從伺服器返回當前的金幣數TapPoints,我們可以通過抓取伺服器返回給設備上應用的資料包,將金幣數量修改為想要的數量就ok了。

這種在設備上安裝代理工具,劫持並修改通信包的方式,是具備悠久歷史的,也叫中間人攻擊MITM(man-in-the-middle)。唯一的區別是不同的運行平臺有不同的工具,越成熟的平臺工具越容易操作越方便普及,而不成熟的平臺則需要命令列操作和資料包分析等專業知識,操作門檻越高遊戲相對越安全。

當然安全也取決於破壞物件帶來的利益是否具備足夠的吸引力。而IAP(in-apple-purchase)遊戲內購(即通過IAP下載到設備內的額外的解鎖內容,英文全稱是DownLoadable Content,通常簡稱DLC)解鎖就具備了相當大的吸引力,在這一功能上,破壞方法也是非常精彩的,從早期的iap cracker工具,到現在非常流行的iap free工具,還有非越獄機也可以使用的通過偽造IAP認證伺服器的俄羅斯遊戲內購方法,都非常好用。
補充:遊戲內購部分的本質就是需要付費才能下載到本地的遊戲內容,而通過存檔修改覆蓋也可以達到解鎖的目的,網上有名的遊戲內購解鎖網站也多是有償提供這種存檔來解鎖盈利,計畫在下篇存檔修改博客中具體介紹這種方式
從iap cracker發展為iap free,我們可以看到外掛功能更新的一個過程。
(1)iap cracker
我們從IAP的API上分析iap cracker到底做了什麼,相信具備IAP功能的遊戲中一定有這樣一段類似的代碼
開發就是根據transaction的類型來決定內購狀態變化所要呈現的東西的, 購買狀態transaction的值有四種
SKPaymentTransactionStatePurchasing
SKPaymentTransactionStatePurchased
SKPaymentTransactionStateFailed
SKPaymentTransactionStateRestored。
而所有交易成功的消息就會進入到SKPaymentTransactionStatePurchased這個case中,而iap cracker就是類比了返回交易成功的消息而進入到了這個case中。如果不做下一步驗證,當我們應用中收到這個「假的」交易成功的消息就會直接給使用者加錢,加設備,加各種東西,iap cracker運行的整個過程甚至都無需聯網驗證。
有趣的是這款軟體在使用說明上就標注是使用了什麼樣的漏洞,只要不需要遊戲伺服器再次驗證的處理方式就會中招。
而針對這個問題,apple給開發者的建議就是驗證付費收據,如果檢驗失敗,則將該使用者(設備udid)加入黑名單,進行封號處理,封號階段,從該設備向伺服器發送的所有請求都將被拒絕。(有趣的是這一處理方式滋生了另一個叫UdidFaker的輔助工具,可以隨機偽造設備的udid。)
HTTPs://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StoreKitGuide/VerifyingStoreReceipts/VerifyingStoreReceipts.html#//apple_ref/doc/uid/TP40008267-CH104-SW1
驗證的重要步驟如下:
1.將提取的訂單資訊轉換成如下json格式
{
 "receipt-data" : "(receipt bytes here)"
}
2.將生成的json資料通過HTTP POST方法傳入到HTTPs://buy.itunes.apple.com/verifyReceipt去驗證
3.app store server驗證完成後,會返回以下格式的json資料,根據status的值就可以判斷訂單是否合法,只有為0才是合法的,如果不為0,則是非法的
{
 "status" : 0,
 "receipt" : { (receipt here) }
}
以下是合法的訂單情況
{“receipt”:{“original_purchase_date_pst”:”2012-07-12 05:54:35 America/Los_Angeles”, “purchase_date_ms”:”1342097675882″, “original_transaction_id”:”170000029449420″, “original_purchase_date_ms”:”1342097675882″, “app_item_id”:”450542233″, “transaction_id”:”170000029449420″, “quantity”:”1″, “bvrs”:”1.4″, “version_external_identifier”:”9051236″, “bid”:”com.zeptolab.ctrexperiments”, “product_id”:”com.zeptolab.ctrbonus.superpower1″, “purchase_date”:”2012-07-12 12:54:35 Etc/GMT”, “purchase_date_pst”:”2012-07-12 05:54:35 America/Los_Angeles”, “original_purchase_date”:”2012-07-12 12:54:35 Etc/GMT”, “item_id”:”534185042″}, “status”:0}
(2)iap free

iap free則在iap cracker的基礎上(偽造SKPaymentTransactionStatePurchased 的transaction狀態),在你與app store server進行收據驗證的步驟中,增加了偽造假收據的功能
最新的iap free針對開發商會根據UDID或mac位址這些設備唯一標識來進行封號處理推出了UDID和mac位址偽造功能。
(3)俄羅斯遊戲內購方法(偽造成app store server)
第一步:登出已登錄的apple ID
第二步:在設備上安裝證書檔
http://system.in-appstore.com/certs/cacert.pem
HTTP://system.in-appstore.com/certs/itcert.pem
第三步:修改設備接入wifi的DHCP設置中DNS伺服器欄,替換為駭客提供的位址
二、三步就是通過在iOS設備上安裝偽造的SSL證書,修改DNS表將正常請求重定向到攻擊者搭建的伺服器上,使其可以偽造成app store server,無論訂單是否合法,都返回合法的狀態來達到iap內購破解的目的
第四步:進入遊戲,打開購買連結,在如下彈出框中選擇like,然後隨便輸入非真實的apple id,就可以購買成功了。

和iap free類似,最終目的都是返回購買成功的訂單資料,只不過iap free是在遊戲用戶端將來自app store server的驗證資料由失敗狀態改成成功狀態。而俄羅斯遊戲內購,則是偽造成app store server,讓其直接返回購買成功的驗證資料。
這種即使有了IAP收據驗證,也能被iap free和偽造app store server進行遊戲內購破解的關鍵原因是,收據驗證過程是由iOS設備與app store server直接驗證的
再次強調,從iOS設備上游戲用戶端返回的資料是不可信的,是可以篡改的。如果要保證驗證過程的安全,也只有由遊戲伺服器與app store server進行直接驗證
蘋果針對(2)(3)這種收據驗證漏洞,也給出了相應的處理方法
HTTPs://developer.apple.com/library/ios/#releasenotes/StoreKit/IAP_ReceiptValidation/_index.html#//apple_ref/doc/uid/TP40012484
第一種情況:收據驗證,是由開發商自己的遊戲伺服器與app store進行驗證(不經過iOS設備上的遊戲用戶端)
不會受iap free和俄羅斯內購破解的影響,是蘋果推薦的最佳驗證方式。安全的驗證流程應該如下圖所示

通過看這個流程圖,我們可以得知之前iap實現所犯的錯誤,

iap cracker有效的原因是由第8步到第9步,iOS設備上的應用直接相信了偽造的SKPaymentTransactionStatePurchased狀態。
iap free和俄羅斯內購破解有效的原因是收據資訊由app store和用戶端直接驗證,客戶的相信了偽造的購買成功的收據資料。
正確的過程應該是由第11步到12步,由遊戲伺服器與app store直接通信去驗證收據資料。如果收據合法則下發購買部分內容給用戶端應用(第12步到第14步)。
第二種情況:收據驗證,是由遊戲用戶端直接與app store進行驗證
雖然蘋果建議開發商最好採用第一種情況的驗證流程,但無疑這種流程增加了伺服器與app store的通信驗證等待時間,針對無線網路不穩定的情況下,可能導致支付過程中端,影響使用者的付費率。
我觀察到不少iOS應用,其中不少是國外的知名遊戲開發公司出品的(例如日本的音樂類遊戲樂動魔方就完全可以內購破解)仍然選擇由客戶的驗證收據,或者連收據都不驗證。不知道是否有這方面的原因。
對堅持由用戶端直接與app store進行驗證的,蘋果也給出了以下對策:
1.檢查用於連接app store server伺服器的SSL證書,確認是否是EV 證書(Extended Validation SSL Certificate)
2.檢查返回的驗證資訊是否與SKPayment物件中的資訊一致
3.檢查收據上的簽名是否合法
4.檢查transaction ID是否唯一
並提供了相應的驗證實現代碼HTTPs://developer.apple.com/library/ios/releasenotes/StoreKit/IAP_ReceiptValidation/VerificationController.zip
蘋果提供的兩種驗證方式都屬於事前驗證,只有在通過驗證的情況下才下發購買部分內容給用戶端。
在早期的iap實現中,一般採取的是事後驗證,即在交易完成後,將收據存儲到伺服器上,然後再次與app store server對賬,非法交易的給予封號處理,為了怕影響玩家情緒,往往只對超大金額的玩家給予懲罰處理,懲罰其失去聯網部分功能,但對於弱聯網的遊戲,這種懲罰並不能帶來威懾。並且在遊戲推廣爭取使用者階段,有封號,也就有相應的解封操作,解封過程一般採取客服人工解封,在iap free這種傻瓜式工具氾濫的情況下,大量的非法訂單帶來的封號解封處理必然增加了客服工作量。
總的來說,遊戲安全的發展是與外掛博弈的過程,因為太多的原因,或是遊戲性能,或是玩家體驗,或是人力成本,有效防禦總是滯後于攻擊手段的。但正是這些有趣的外掛,讓我們遊戲實現更具挑戰。
下一步計畫打算寫寫iOS遊戲存檔修改(包括依靠存檔替換進行內購解鎖)
參考
1.HTTP://www.himigame.com/iphone-cocos2d/673.html
2.iOS軟體逆向工程應用 & 手機遠程監控技術 by大可
3.HTTPs://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StoreKitGuide/VerifyingStoreReceipts/VerifyingStoreReceipts.html#//apple_ref/doc/uid/TP40008267-CH104-SW1
4.HTTPs://developer.apple.com/library/ios/#releasenotes/StoreKit/IAP_ReceiptValidation/_index.html#//apple_ref/doc/uid/TP40012484

本文轉載gamelook,編輯僅做翻譯。詳細請查看原網站文章。

Comments are closed.