前往
大廳
主題

鬼月之封包逆向教學(前篇)

廢物敗類窩囊廢漢堡 | 2022-07-27 23:48:14 | 巴幣 2424 | 人氣 664


-------------------------------此文又臭又長,不適合沒耐心的觀看-----------------------------

前篇僅有粗略分析資料處理
不含任何有用技術
但是未看完就想看中篇畫葫蘆的話
可能也無法了解其中奧妙
所以懇請想學習的把前篇看完
還有中篇難產中
我是個廢物


此影片為我現今畢生所學


此教學會含有程式供您自己練習
遊戲程式

timer_class.py
# -*- coding: utf-8 -*-
import threading


class TimerClass(threading.Thread):
    
    def __init__(self,Tthread = threading.Thread,i=1,target =None):
        threading.Thread.__init__(self)
        self.i = i
        self.target = target
        self.event = threading.Event()

    def run(self):
        while not self.event.is_set():
            self.target()
            self.event.wait(self.i)

    def stop(self):
        self.event.set()


首先建置環境

架設 server
import socket
import threading
from lib.Timeclass import TimerClass

def handle_client(client, address):
    
    connected = True
    print("One player")
    while connected:
        msg = client.recv(512)
        if msg :
            print(msg)
            client.close()
            connected = False
            
def close(clients,num):
    clients[num].close()
    clients.pop(num)
        
def main():
    print("server_Start")
    # create a socket at localhost:1234 that recv data and print it
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('', 9330))
    s.listen(10)
    while True:
        conn, addr = s.accept()
        clients.append(conn)
        thread = threading.Thread(target=handle_client,args=(conn,addr))
        thread.start()

clients = []
start = TimerClass(threading.Thread,1,main)
start.start()



使用HXD對練習程式中的 config.xml 做修改



修改成你架設的server IP

打開遊戲程式 BrightShadowCrack.exe



帳號密碼各輸入 123


點選Login並查看server


你會獲得一段看不懂的訊息(因為被加密後送至server端)

所以我們必須找尋如何加密的程式碼

現在打開工具 X64DBG (工具自行找尋 這是免費的)

點選檔案 附加


選擇遊戲程式後 附加



對命令列 下 BP send
為甚麼要下這條指令?

因為在window系統下 傳送封包常態都是使用send

指令下完後 點選登入 然後回來看斷點位置

不用理會這段直接點選執行到返回


然後到這邊再點選單單步入



到此畫面


現在已經跳出 window Send了 這邊就是遊戲程式碼的部分

不過在送出封包前

已經把資料加密了

所以send為最後一個步驟

那麼就必須逆向方式尋找

所以一樣點選 執行到返回後再點選 單單步入  跳出這個程式碼範圍


從上圖可以發現

call 0x00978160 裡面會進到 call send

這代表 加密的程式碼將在這之前

所以我逆著去觀看每個資料處理操作

先按F9 讓程式回到正常運行後

對 0041C8DB push EAX 下斷點


在遊戲內點選登入後 回來查看


斷在此處後 案三次單單步入進到該功能裡 ( 有一次為jmp到正確功能位置)



到此處後 請按G到圖形功能觀看


切換到圖形模式可以觀察到 程式碼的流程圖

還從中發現 [edi+4] 為我們輸入的資料

現在點擊資料視窗


然後按 ctrl+G 並輸入 [edi+4] 後點選確認



可以從此處發現我們輸入的資料 帳號或密碼(因為都輸入相同不清楚是帳號還是密碼)

那麼我可以先理解這個程式碼應該就是對資料做加密處理的地方

那個接下來該怎麼分析這些組語呢?

一、看到有迴圈都先下斷點
二、對看到要function call地方下斷點
三、斷點到function call時 觀察stack 變化
四、離開function call時 資料處理的變化
五、紀錄這些功能應用

這些步驟可以幫助你更快的理解作用

下圖為斷點後待分析的程式碼

斷點下完後我們要先知道封包排列的做法並且了解加密的方式

所以現在按登入再查看斷點位置


這邊我們先略過不理會
因為迴圈的部分大概率都是處理加密相關的功能
所以直接跳到下一個斷點查看
我們看到這邊 call 0x00404719
他在進入這個功能前 推入了三個資料
push ecx ,push edx ,push ebp
那我們來觀察 stack的資料
分別 247C88D9 , 4 , 0019F8E4
現在我們到資料視窗 查看 247C88D9
在這邊看不出甚麼所以然 儲存了 0x16310的資料
我們往上看一點
框起來的部分可以發現 輸入帳號密碼的資料,
加上剛剛查看的地址資料它是串接在後面的,
所以可能跟加密有相關
現在我們按單單步過跳過該 功能操作
然後查看剛剛資料視窗的變化
很顯然在這邊沒有甚麼變化
但是我們可以觀察 暫存器視窗上的資料

亮紅色的為function call 完後退出來 更動過的
接著我們對 EAX ECX EDX 做觀察 ESP基本上可以不理它

EAX

ECX

EDX

這三個資料可以發現 ECX 與 我們進到 CALL 前的位址差了幾個BYTE
ECX 與 EDX 資料有共通但不完全
而EAX為 指到EDX的末端

所以理論上 EAX作為資料標記的最後一點,所以很有可能是要將EDX的資料複製到EAX

這時我們可以繼續往下一個斷點看

斷在這邊
你可以發現之前放在EDX位址裡的資料發生變化了

框起來的部分被改變了
所以得知 call 0x00404719 也是在對資料做某些加密並放回此處

這邊我們繼續步過觀察有甚麼資料變化

暫存器視窗
從這邊變動只有EAX 和EBP可能要觀察一下

EAX


EBX


(灰色括起來部分才是原位置)
現在看這兩個指向位址

只有EBP的部分在前面一幾個byte發現 輸入的帳號密碼資料
看不出甚麼所以然
所以遇到這種function call 我就先不理她了
剛好接下來也有一個 call 0x009BAA4A 我就暫時不理它了
直接跳到下圖這位置

這邊只有push 一個 0的資料到stack
所以我直接 步過看一下其他資料變化

發現EDX 和 ESP 有變化
這時觀察EDX的資料
框起來的部分就是我們目前不清楚的資料
這邊先不理它
本想直接繼續跳到下一個斷點的
但是發現一個蠻重要的指令 下圖
這兩個指令也是迴圈的一種
目的是將A地址的資料複製到B地址的資料相關的事情
我在這邊下斷點跳過來觀察
這邊可以看出 要對EDI做操作
我們直接步到rep stosb後觀察EDI的變化
可以發現 EDI  208B16B4 -> 208B16C1
可以發現 差了13個byte
現在往回看之前的資料
剛好標記了13個byte符合這邊括起來的
所以下一個斷點可能就是要複製資料了
來去下個斷點

暫存器視窗
可以看到它push EAX 又發現 EDX 剛好為 D 十進位(13)
這時我們看看EAX

剛好是空出來的資料
步過看一下變化
明顯被複製過來了
這邊的fuction就可以正式理解為 資料複製

接下來下面又出現了兩個 rep 相關的指令

一樣在第一個rep斷點
並觀察暫存器視窗
上圖可以發現 EDI 為 2D41B93C
離開此處後下個斷點

EDI為 2D41B95C
如 EDX的 20 十進位(32) 一樣
所以開了 32個byte要放資料
我們資料視窗來到 2D41B93C

步過 call 0x009B91B0 來看變化

竟然在此處沒有變動 當時原本以為是我的判斷錯誤
但是我不相信果斷下面的fuction call 不看直接 步過

冰果! 跑出一坨悉
但是重點來了 遠本的資料只有簡單的
01 31 32 33 00 31 32 33 00 B0 DA CD AB
現在卻跑出一坨悉
0D E8 A3 66 29 30 51 45 BE 8F 76 9B A4 6E 2A
05 0B 3D 5F 01 51 FE 4A 1E 10 67 69 9D A4 45 AB

然後資料還被加密了
所以可能這兩個 function call 都有對某些資料加密
在此先記下來 然後繼續往下看

到了下個斷點
這邊並沒有進到迴圈
所以可以把斷點去掉了 然後到下個斷點

可以發現這個function 在call 前又推入了 ecx 和 eax
我們觀看 暫存器視窗
可以發現 EAX 竟然是先前 那一坨悉的地址

資料視窗跟到EAX後 步過後看一下變化好了


EAX並沒有變化

但是暫存器視窗卻顯示出這邊資料的長度

真是頭疼

接下來進到最後兩個斷點的位置

觀察 EBP的資料
原來是加密過的輸入資料
步過看一下變化
並沒有改變
所以這就是最後回送到伺服器端的資料了

20 00 20 00 0D E8 A3 66 29 30 51 45 BE 8F 76 9B A4 6E 2A
05 0B 3D 5F 01 51 FE 4A 1E 10 67 69 9D A4 45 AB 00

看來這兩個function call 也不需要理會
剛好下一個是 push EBX
就順便看一下 EBX的資料
結果這是我們最初送給server的資料

結論 一個是加密後  一個是原資料
現在我們讓程式執行並到 server端看它print出來的資料

b'\xec \x00\x00\r\xe8\xa3f)0QE\xbe\x8fv\x9b\xa4n*\x05\x0b=_
\x01Q\xfeJ\x1e\x10gi\x9d\xa4E\xab\x00'
挖這資料好奇怪喔!!! 看不懂ㄟ!!!

我們對它加工一下


比對上面送出前的


除了開頭 20 00 被換成 EC 以外 大同小異

那麼前置粗略分析就完成了

深入解析請待中篇撰寫完畢

創作回應

請不要對我做傻事
請問一下,既然封包加密的過程是在本地端的遊戲程式做,那直接攔截加密前的封包不就好了?,何必需要逆向加密的演算法,然後自己再重新寫一遍。如果只是單純要做封包攔截,並且解密,是我的話,就直接寫一個internel hack,把加密前的封包直接攔截。還是說自己重新寫一遍有特別的用處?
2022-07-28 12:32:19
廢物敗類窩囊廢漢堡
痾...加密前並沒有(封包)這東西,所以怎麼攔截,還有要傳輸的數據資料只有經過加密後變成封包再發送,窩不知道哪邊可以做出你所謂 [internel hack] https://truth.bahamut.com.tw/s01/202207/198aa321f476f92c397719a3478800e0.JPG
2022-09-04 02:31:55
skps950129
https://truth.bahamut.com.tw/s01/202209/3f910afa82e1678d691e9ee2c574b814.PNG
2022-09-04 05:20:59
skps950129
https://truth.bahamut.com.tw/s01/202209/f9d5841904e7e71ed1a9b8e86f4e92d8.PNG
2022-09-04 05:21:17
skps950129
要寫成c才看得懂..
2022-09-04 05:32:51
skps950129
整個遊戲的封包加密都是由同一個函數完成ㄇ
2022-09-04 05:40:17
廢物敗類窩囊廢漢堡
一個函數裡面包很多函數
2022-09-04 11:04:00

更多創作