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