外挂学习之路(1)--- bp send 回溯寻找关键call
先廢話一下----好久沒有更新博客了,更新一下。學習外掛也有幾年時間了,零零散散沒有學習到什么東西,更沒有做出什么有用的項目,也沒有什么總結文檔,從頭再來吧,人不立志難以成事。
以下文字都是自己的感悟,不是什么正規文檔,寫給自己總結看看,如有高人看到錯誤之處希望不吝賜教。
外掛主要有模擬掛,內存掛,脫機掛。模擬掛一般指模擬點擊代替反復的人工操作,內存掛一般是指先找到關鍵call,然后寫個dll注入到游戲里面,脫機則稍微復雜一點,需要先分析游戲里面的協議,自己寫個游戲客戶端冒充游戲客戶端,完成所有游戲功能,既然游戲是自己寫的就可以隨便diy。模擬掛較為簡單(不考慮驅動保護),脫機掛較為高大上,先以內存掛為主進行學習。
內存掛主要工作是找call,找到關鍵call之后就是自己寫段匯編代碼調用該call以達到外掛的目的。當然在這之前要寫好dll以及注射器,常見的注射方式是全局鉤子hook到游戲進程和遠程線程注入,這兩個方式的具體代碼以后再做討論。再來說說各種各樣的找call方法,今天先說一種通過網絡發包下斷點回溯的方法,在od命令框里面輸入 bp send或者bp wsasend.(根據游戲具體使用的函數而定),然后對游戲進行操作如撿物、嗑藥、打怪等,客戶端肯定要向服務器發送數據包,斷點斷住之后層層向上回溯,直到執行指定操作會斷其他與服務器的交互不會中斷,比如尋找撿物call時撿物會斷而走路不斷此時斷點一般就是所搜尋的斷點。
好了暫時先寫這么多吧,后續有收獲就繼續更新。。。
近期研究一個游戲無法用上述方法追蹤到關鍵call,分析其原因如下:
上述方案適用于手工觸發之后游戲直接調用send函數向外發包,但是好一點的游戲發包都有自己的發包隊列,防止發包失敗,向外發包時候先把數據投放到一個隊列里面 ,然后寫個線程不斷的讀取隊列里面的內容,一有內容立即向外發送,即發包過程和手工觸發過程在兩個不同的線程里面,這樣通過send函數回溯call的時候最多可以回溯到那個循環發包的任務里面,無法找到真正的觸發任務的call。
----------再次更新---------
經過再次思考,估計大部分游戲都有自己的發包隊列,但是bp send找call為什么還是那么流行呢?
其實找到的call不一定對應原生的激發動作函數,只要找到這個激發動作向服務器發送了什么樣的數據包就可以了,這樣想想bp send 找call的方法又可以通用了,無論是否有發包隊列,你咋發我就寫掛也咋發就可以了。
但是這樣一來就和一般輔助教程有一點沖了,沖突如下:
寫一點偽代碼,有發送隊列的網絡模型如下
void 打坐函數()//以游戲中的打坐技能為例 {將打坐要發的數據包加入到發送隊列里面 }//發包線程 void sendpackthread() {while(true){//檢測發送數據包的隊列//發送數據包函數sendpack(...);} }//真實的發包流程 void sendpack(...) {//數據加密和壓縮處理//調用系統APIsend(); } 按照這個模型理解的話,所有動作都是調用sendpack函數發送的,外掛call的也是sendpack,這就和一般教程中的打坐call走路的時候不會中斷有沖突,有時間繼續研究....
=============================================================================================
每每在其他技術論壇一提到廣海大家就會取笑我:“廣海呀,就是那些只會BP SEND 和CTRL+F9 的那些人啊”,聽到這樣的嘲笑起初自己也十分瞧不起BP SEND有段時間甚至刻意避免使用這個斷點。其實不是人家的錯,是我們自己將BP SEND這把利器用死了,學東西把東西學死了是非常大的悲哀,我們要用聰明智慧來展示出自己的實力,實力可以攻破任何謠言。?
誠然BP SEND在網游發展的初期是一把無往而不利的萬能斷點,因為客戶端總要跟服務器通訊,所以一有動作就會斷下來。而現今網游開發人員都有防范外掛的意識和手段,在他們的作品中自然對于大家手中的這個BP SEND會使出各種手段加以遏制。?
舉個簡單的例子,星塵傳說 這是我第一個研究的游戲 他就專門針對BP SEND做了很好的處理,專門做了一個負責發包的模塊,通過消息和事件跟主體程序進行通訊,我們的單步跟蹤自然無法跟隨消息追隨到功能CALL,無數次的CTRL+F9都只能深陷在一個無盡的消息等待循環中。還有些強力的游戲制作者,自己編寫WS2_32.DLL,用于網絡通信,我們還傻乎乎的去截取系統API自然是一無所獲。還有些開發商會HOOK WS2_32.DLL,監測用戶的動作,觸發了它的規則輕則掉線,重則封號。?
游戲在進步,而我們只知道 BP SEND + CTRL+F9 可想而知,太公釣魚。?
我們先講如何穿透消息封鎖的BP SEND?
原理:雖然消息和事件可以阻擋我們對代碼的回溯跟蹤,但是作為程序運行的忠實記錄者 “堆?!眳s將程序運行的關鍵步驟都記錄下來了。然而,堆棧中并不會記錄所有的CALL調用。示意圖:?
模塊1: 游戲主體進程?
↓?
模塊2: CALL1(獲取技能ID)→CALL2(獲取角色ID)→CALL3(獲取目標ID)→CALL4(錯誤檢查)→壓入技能ID參數 壓入角色ID參數 壓入目標ID參數→技能CALL5(id1,id2,id3)→CALL6(發送消息給發包等待模塊)?
模塊3:CALL7(消息等待模塊)?
↓↑?
send( );?
這就是一個使用消息阻斷BP SEND跟蹤技能CALL的反調試手段,我們使用CTRL+F9無法跨越CALL6 和CALL 7 ,只能在 CALL7 和SEND()之間無限循環。?
而以上過程在堆棧中能在BP SEND斷下時留下什么呢?答案是會留下CALL 6 CALL 7的蹤影,我們并不會看到我們想要找到的技能CALL,會得到類似的堆棧內容:?
堆棧中記錄的是模塊與模塊中相聯系的CALL的返回地址,同時還會殘留下來部分模塊內部曾經壓入到堆棧的對后面進程有用的參數。?
事有蹊蹺,人有傻笨的,有聰明的,我們先講體無腦方法:?
老天是公平的輔助辛勤的汗水總會有回報,在尋找CALL之前如果做足了準備工作的話,那一些基本的數據例如人物ID 技能ID 怪物ID這些通過看就能看出來大概是個什么樣子,數據是幾位,都什么開頭,例如角色ID 23e7 怪物ID 4000329 技能ID 77512等等,有了這些辛勤的勞動成果,我們很容易在堆棧中發現他們,有這些數據傳遞的過程就是我們要找的地方,自然通過反復的跟蹤測試我們能夠找到最終想要的技能CALL,但是,事無絕對,如果你在堆棧中捕捉不到這些ID 的蹤影那再辛苦的勞動也會徒勞一場。?
下面就介紹個簡單易行的辦法:?
我們都知道技能CALL釋放的時候是有許多條件限制的,例如藍是否足夠,目標是否存在,是否有障礙等等,我們就抓住這里,進行展開。?
方法:使用內存搜索工具CE或者其他的可以搜索該游戲的工具對提示信息進行搜索,例如:“沒有目標”,得到這些數據的存儲地址,然后再OD或者其他調試器里,對該段內存下內存訪問段,斷下來之后,我們就會得到一個完整的堆棧內容,我們將所有的堆棧內容拷貝出來,存到一個文本文件里。?
然后,我們使用BP SEND下斷,截獲技能CALL釋放的包,同樣也會得到一個完整的堆棧數據,存 放到另一個文本文件里,我們對得到的2組 堆棧數據進行對比,從下向上,找到不同的地方就是你們該關注和下 手的地方了。至于BP SEND的一些技巧就不詳細說了,多數都是使用條件斷點來達到截取特定數據的。?
通過上面的“堆棧對比法”,我們就能找到合適的切入點,找到技能CALL,并且順帶將一些技能相關的錯誤處理CALL也給找到,什么CD冷卻呀,障礙物啊等等。?
小結:?
上面通過很長篇幅來說明如何靈活應用BP SEND,也就是不能單純的使用BP SEND,要和其他的一些斷點和方法結合起來使用,才能達到理想的效果。在實際應用中我們還有更多這樣的應用實例,大家也不要看完本文就心滿意足,啊!我又學到了一種找技能CALL的方法啦,這樣就太令我失望了,我要教給大家的不是一種技巧,是一種思維方式,我希望的是你們自己能創造出來更多更靈活的使用方法,這才是我寫本文的目的,學習分幾個階段,基礎知識,基礎技巧,熟練后就要自己創造技巧,方為尚。
總結
以上是生活随笔為你收集整理的外挂学习之路(1)--- bp send 回溯寻找关键call的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《openssl 编程》之 RSA(转)
- 下一篇: 外挂学习之路(2)--- 老生常谈“基地