2021騰訊游戲安全技術(shù)競賽PC客戶端方向-思路分享
作者論壇賬號:OrpheusQ
[寫在前面]
<帖子發(fā)晚了,前幾天都在練科三,今天才考完,得空整理一下分析報(bào)告>
快要畢業(yè)了,卻還沒參加過一次CTF之類的比賽,為了不留遺憾,就報(bào)名了此次的比賽,作為自己不怎么秀的首秀(決賽肯定是無望了hhhh)。
以下僅僅是個(gè)人的分析思路,分享給大家,適合像我一樣的逆向初學(xué)者閱讀,也勉強(qiáng)算是為吾愛做出一點(diǎn)微薄的貢獻(xiàn)了~
(參考答案or更精彩的解法還得參考同版塊下其他/她師傅的帖子)
[主要分析結(jié)論]
1. 外掛通過讀取 hack.dat 文件中的 flag, 通過自定義算法 1 解碼+拼接后生成游戲進(jìn)程名:
ShooterClient.exe。
2. 外掛通過自定義算法 2 解析出 hack.dll 文件的字節(jié)碼,并通過寫內(nèi)存、創(chuàng)建遠(yuǎn)程線程的方
式使得黑模塊得以執(zhí)行。
3. 在黑模塊中,通過 GetAsyncKeyState 截獲鼠標(biāo)右鍵的按下情況作為外掛的開關(guān),以遍
歷對象、基址+偏移的方式獲取人物坐標(biāo),并計(jì)算、改寫俯仰角(pitch)、偏航角(yaw),以
實(shí)現(xiàn)自瞄功能。
[分析過程]
<hack.exe 部分>
1. 先將 hack.exe 拖入?IDA?中靜態(tài)分析,依次調(diào)用 CreateFileA->GetFileSize->ReadFile,
不難猜出,此處讀取的文件內(nèi)容即為 flag。由于文件名是計(jì)算出來的,動(dòng)態(tài)調(diào)試得:
hack.dat。

2. 之后進(jìn)入到一個(gè)函數(shù) hack.exe@1400014D0,該函數(shù)由 2 個(gè) if 語句組成,分別都會(huì)進(jìn)行
解密操作,但是只有第 2 個(gè) if 語句才能解出 flag(第一個(gè) if 是用于解析出黑模塊 hack.dll
的,不同的情況下只會(huì)進(jìn)入 1 個(gè) if 語句中):
(注意:此處對flag的分析不夠周到,雖然我猜出來的flag可以開啟外掛,但后面看了其他/她師傅的帖子才發(fā)現(xiàn)有且僅有一個(gè)官方的flag, 原以為只要?jiǎng)?chuàng)建一個(gè)能把外掛成功運(yùn)行起來的hack.dat就算是通過第一關(guān)了......不夠細(xì)*1)

解析 flag 的操作:將 flag 的每個(gè)字節(jié)與 0x3F 異或,之后減去 0x13。
3. flag 解密完成后,會(huì)將 flag 從第 2 字節(jié)開始的偶數(shù)位拼接到局部變量 ProcName 中,結(jié)
合下文分析推測,應(yīng)該是要打開游戲進(jìn)程“ShooterClient.exe”,所以可得 flag 解密后
的特征應(yīng)該是:除 0 外的偶數(shù)位保證為特定字節(jié)(游戲進(jìn)程名), 其余位置可為任意值(這里
采用 0x00)。

分析出 flag 的解密過程和 flag 解密后的樣子之后,便可反過來計(jì)算 flag,計(jì)算腳本如下:

使用 16 進(jìn)制編輯器,寫入到 hack.dat 中:

4. 拼接完進(jìn)程名后,以拍攝快照的方式遍歷進(jìn)程,匹配字符串成功,打開進(jìn)程:

之后,同樣以解密文件名的方式,解析出 ntdll.dll,并獲取了該模塊中的:LdrLoadDll、
RtlInitAnsiString、RtlFreeUnicodeString、LdrGetProcedureAddress、
NtAllocateVirtualMemory、RtlAnsiStringToUnicodeString 函數(shù)地址。
5. 最后,調(diào)用 WriteProcessMemory,寫入外掛代碼,調(diào)用 CreateRemoteThreadEx 創(chuàng)建
遠(yuǎn)程線程執(zhí)行黑模塊代碼。

其中寫入的部分,最重要的是調(diào)用 hack.exe@1400014D0 解密得到的黑模塊文件,以下2圖分別為解密前后的內(nèi)存:

?

解密 hack.dll 的算法(已在注釋中詳細(xì)說明):

至此,外掛 hack.exe 可以被打開,并成功使用,外掛功能為自瞄。

<hack.dll 部分>
1. 將外掛黑模塊 dump 下來分析,dllmain 中創(chuàng)建工作線程,進(jìn)入線程回調(diào),開頭獲取了游
戲進(jìn)程基址,并由基址+偏移的方式獲取了多個(gè)全局變量,其中就包括較為重要的,游戲
引擎 this 指針。

2. 由于外掛的自瞄功能是需要在鼠標(biāo)右鍵按下的情況下啟動(dòng),所以根據(jù)這個(gè)特點(diǎn),查找
GetAsyncKeyState?等相關(guān)函數(shù)的引用情況可以快速定位到外掛的核心代碼:

3. 在該函數(shù)中,外掛事先根據(jù)游戲引擎的 this 指針(this_engine = [module_base +
0x2F71060]),獲取到角色的 this 指針(this_player =
[[[[[module_base+0x2F71060]+0x160]+0x38]+0]+0x30]),并獲取角色的 3 維坐標(biāo)
(float)。
x = [[[this_player+0x360]+0x158]+0x164]
y = [[[this_player+0x360]+0x158]+0x168]
z = [[[this_player+0x360]+0x158]+0x16C]

添加到 ce 中驗(yàn)證一下:

再通過遍歷人物對象的方式(調(diào)用 hack.dll@180004510),獲取到敵人的指針,選出離自
己較近的敵人后(xy 坐標(biāo)系的距離<24.0),以相同的方式獲取其 3 維坐標(biāo)。
(注意:此處分析有誤,看完其他/她師傅的帖子才發(fā)現(xiàn)這里計(jì)算的應(yīng)該是屏幕中心和敵人之間的距離,不夠細(xì)*2)


之后調(diào)用 sqrtf 求出角色和敵人在 xy 坐標(biāo)系上的相對距離,調(diào)用 atan2f 求出俯仰角;再
調(diào)用一次 atan2f 求出偏航角,并將所求結(jié)果寫入到對應(yīng)的游戲內(nèi)存中,以實(shí)現(xiàn)自瞄:
[this_player + 0x398] = pitch
[this_player + 0x39C] = yaw


[自瞄實(shí)現(xiàn)]
大致思路:
·根據(jù)基址+偏移的方式獲取對象數(shù)組,過濾篩選出敵人對象(觀察發(fā)現(xiàn)敵人對象在對
象數(shù)組中的存放順序在角色之后(推測是先創(chuàng)建了角色 再生成的敵人))。
·計(jì)算每個(gè)敵人對象與角色對象的距離,選出距離最近的敵人對象,并獲得其 3 維坐標(biāo)。
·通過獲取的攝像機(jī)矩陣(如圖),將 3 維的世界坐標(biāo)轉(zhuǎn)換成 2 維的屏幕坐標(biāo)。最后通過
模擬鼠標(biāo)消息,移動(dòng)到敵人在屏幕的位置,實(shí)現(xiàn)自瞄。

·已將上述思路轉(zhuǎn)成代碼的表達(dá)形式(附件),遺憾的是最終未能完全實(shí)現(xiàn)預(yù)期的效
果(一個(gè)沒有成功的代碼就不在吾愛放出來干擾大家了)。不過在這些天的比賽中,對于一個(gè)初次分析 FPS 游戲的自己而言已經(jīng)是收獲不少,學(xué)
習(xí)到了很多新知識(shí),路漫漫其修遠(yuǎn)兮,吾將上下而求索!
原文地址:https://www.52pojie.cn/thread-1418111-1-1.html
此活動(dòng)來自騰訊游戲安全部門聯(lián)合吾愛破解論壇舉辦的【2021游戲安全技術(shù)競賽】,參加比賽實(shí)習(xí)綠色通道+豐厚獎(jiǎng)金等著你,活動(dòng)詳情:https://www.52pojie.cn/thread-1396337-1-1.html,印證那句話未知攻焉知防,只有了解攻擊才能更好做好防御,防外掛的思路可以源于做如何外掛。