# BTLO - Nonyx 一題逆向工程的題目,雖然玩過CE,但我最不會的就是逆向了(X ![image](https://hackmd.io/_uploads/Skov5WIkxl.png) 應該最主要碰的是這三個檔案 ![image](https://hackmd.io/_uploads/Syt8ibLJxe.png) Readme.txt給的提示是這個,使用取證工具時要用WinXPSP2x86,畢竟是2007年的惡意程式了 :::info WinXPSP2x86 is the profile you must use. It is best to place the output of the vol2 commands to a .txt file for better readability. WinXPSP2x86 是您必須使用的設定檔。 最好將 vol2 命令的輸出放在 .txt 檔案中以提高可讀性 ::: BlackEnergy.vnem是要檢測的檔案,應該是這個很老的惡意程式,然後這是他的VM快照檔案(.vnem) ![image](https://hackmd.io/_uploads/SyernbIyel.png) 這邊為了後續方便調用所以先丟進volatility的資料夾內了 然後最後一個檔案volatility,這是記憶體分析的工具 :::info 可參考網頁 [記憶體分析工具Volatility簡介](https://blog.neithnet.com/?p=4422) [内存取证-volatility工具的使用 (史上更全教程,更全命令)](https://blog.csdn.net/m0_68012373/article/details/127419463) [Volatility取证分析工具](https://wiki.wgpsec.org/knowledge/ctf/Volatility.html) ::: 他工具幫你裝好了,我們要使用的檔案是`vol.py` 用`python vol.py`來使用他 ![image](https://hackmd.io/_uploads/rkIX1fL1gx.png) >一堆教學都寫直接用`vol.py`就可以下指令了,在那邊騙(X >![image](https://hackmd.io/_uploads/B1PbgzLyge.png) >![image](https://hackmd.io/_uploads/rk921GUkeg.png) >還好有常在用linux跟python,知道怎麼下指令讓他跑,新手不友好(X >[name=羽澤] ## 解題 一共有6題 ### 1. Which process most likely contains injected code, providing its name, PID, and memory address? (Format: Name, PID, Address) :::info 哪一個行程最有可能包含注入程式碼,請提供其名稱、PID 和記憶體位址? (格式:姓名、PID、地址) ::: 使用指令 `python vol.py -f BlackEnergy.vnem --profile=WinXPSP2x86 malfind` >指令拆解 >`-f <filename>` - 指定要讀取的memory檔案名稱 >`--profile=<platform>` - 該memory檔案所使用的系統 (題目提示是WinXPSP2x86) >`malfind` - 查到隱藏和注入的代碼 目標是這段process ![image](https://hackmd.io/_uploads/SJl89GI1xx.png) >看不懂嗎? 沒關係,我也看不懂(X >所以我們來請GPT來解答 >[name=羽澤] 這些是他的基本資訊,process、Pid、執行的記憶體Address等,這邊不多贅述 ![image](https://hackmd.io/_uploads/r1ux3z8ygg.png) 主要注意的點是下面這個`Protection: PAGE_EXECUTE_READWRITE` 這代表這個記憶體區塊可以被: * 讀取(READ) * 寫入(WRITE) * 執行(EXECUTE) 這種權限一般不會在正常程式中出現,因為: * 合法的程式碼區(Code Section)只需要 READ + EXECUTE * 合法的資料區(Data Section)只需要 READ + WRITE * 三者全開 → 容易被注入 shellcode 或 payload 然後接下來是記憶體區域,他是`MZ`開頭 ![image](https://hackmd.io/_uploads/H1zzTM8yge.png) `4d 5a`是 ASCII 的 "MZ" → Windows 可執行檔 (PE) 的開頭。 如果你在一段記憶體中看到 MZ 開頭,表示有人把整個 EXE 或 shellcode 注入記憶體了。 再來是這邊 ![image](https://hackmd.io/_uploads/B1MKpGI1ex.png) `MemCommit: 1` = 只分配了一小段記憶體(可能只 1 page),這不是一般 EXE 的行為,因為一個正常的EXE會是大型檔案,會要求很多記憶體區塊。 有完整的 PE header (MZ、然後一堆 `00` 填充),但沒有檔案對應 → 通常表示是從外部載入進來、或動態構建的。 所以這段記憶體異常的原因包括: |指標 | 說明| |---|---| |PAGE_EXECUTE_READWRITE | 注入者最喜歡的權限配置| |MZ header | 代表有可執行的 PE 被塞進記憶體| |svchost.exe | 正常系統進程,常被拿來偽裝使用| |沒有對應 DLL 或模組 | 有可能是透過 VirtualAlloc + WriteProcessMemory + CreateRemoteThread 注入| |記憶體內容偏離正常流程 | 原本的 svchost 不該有這種自構 PE 片段| :::success Ans:svchost.exe,856,0xc30000 ::: ### 2. What dump file in the malfind output directory corresponds to the memory address identified for code injection? (Format: Output File Name) :::info 在 malfind 的輸出資料夾中,哪一個 dump 檔案對應到上一題你發現的那個記憶體位址? 格式:輸出檔案名稱(例如 pid.856.addr.0xc30000.dmp) ::: >抱歉這題我真的通靈不到,直接問GPT了,他的Google翻譯真的太鳥了(X >我一開始還以為是要用`pslist`去找他可能接下來呼叫啥之類的 >最後決定讓GPT幫我翻譯了 >[name=羽澤] 他只是要你在指令的最後加上 `--dump-dir=./` - 讓他輸出成dmp文件存下來 所以整段指令會變成 `python vol.py -f BlackEnergy.vnem --profile=WinXPSP2x86 malfind --dump-dir=./` 檔案會長這樣 ![image](https://hackmd.io/_uploads/rJ61Zm8Jgl.png) :::success Ans:process.0x80ff88d8.0xc30000.dmp ::: ### 3. Which full filename path is referenced in the strings output of the memory section identified by malfind as containing a portable executable (PE32/MZ header)? (Format: Filename Path) :::info 在那段被 malfind 標示為有 PE(MZ 頭)的記憶體區中,用 strings 抽出字串後,裡面提到了哪一個完整的檔案路徑? 格式:完整路徑檔名(例如 C:\Windows\Temp\malware.exe) ::: 這一題是用`strings`這個指令來讀取剛剛dump下來的dmp檔案內容,這指令通常用於讀取二進位檔案。 指令為`strings process.0x80ff88d8.0xc30000.dmp` 裡面會長這樣 ![image](https://hackmd.io/_uploads/HJTEXmUJgx.png) 我們要的東西在這 ![image](https://hackmd.io/_uploads/By_LQXLJgg.png) :::success Ans:C:\WINDOWS\system32\drivers\str.sys ::: ### 4. How many functions were hooked and by which module after running the ssdt plugin and filtering out legitimate SSDT entries using egrep -v '(ntoskrnl|win32k)'? (Format: XX, Module) :::info 在執行 ssdt 插件,並且用 egrep -v '(ntoskrnl|win32k)' 過濾掉正常 SSDT 條目後,有多少個函數被 Hook,且是哪個模組 Hook 的? 格式:數量, 模組名稱(例如:5, shadydriver.sys) ::: 這題叫我們使用的指令是 `python vol.py -f BlackEnergy.vnem --profile=WinXPSP2x86 ssdt |egrep -v '(ntoskrnl|win32k)'` 他說使用`ssdt`的模組,他可以顯示ssdt的條目 ![image](https://hackmd.io/_uploads/B13MvmIJxx.png) 但在繼續下去之前,先來拆解這個題目的解題過程跟知識 :::warning SSDT(System Service Descriptor Table)是什麼? SSDT 是 Windows 用來管理核心 API 函數(如 NtOpenProcess, NtReadVirtualMemory 等)的表格,每個函數都會對應一個指標(實際函數的位置)。惡意驅動常透過 hook SSDT 來攔截 API 呼叫,例如: * 你想開啟某個進程 → 惡意程式攔截後讓你失敗或偽造結果 * 你想列出某個進程 → Hook 後讓該進程「消失」 ::: :::warning Hook 是什麼? Hook(鉤子)指的是:原本應該指向合法函數的指標被偷偷改掉,指向某個惡意函數。 ::: :::warning (ntoskrnl|win32k) 是什麼? 這是 Windows 核心合法模組: * ntoskrnl.exe 是核心本體 * win32k.sys 是視窗管理模組 所以題目透過 `egrep -v` 過濾掉這兩個,只留下非官方的函數來源 → 惡意驅動最常這樣做 ::: :::warning 我要怎麼知道被HOOK? 首先什麼是「正常的 SSDT」? SSDT(System Service Descriptor Table)就像是 Windows 核心的函數跳板表,它列出所有「Nt 開頭」的 API 對應的記憶體位址。 正常情況下,這些指標會: 全部都指向 ntoskrnl.exe(Windows 核心)或 win32k.sys(視窗子系統) 也就是說,這些地址會落在某些固定範圍的記憶體區段中,通常是: |模組 |位址範圍(x86 範例)| |---|---| |ntoskrnl.exe |0x804d0000 – 0x805d0000(大約)| |win32k.sys| 0xbf800000 – 0xbf9xxxxx| 至於為什麼會落在特定區塊,因為這些是他的基址,每次系統啟動後這些地方就是會固定被他佔用的記憶體位置 --- 怎麼看出「被 Hook」? 當 SSDT 裡某些函數的實作指標: * 不在 ntoskrnl 或 win32k 的範圍裡 * 而是指向未知的地址(例如 00004A2A) * 而這個地址又沒有對應到正常模組 那就幾乎可以確定這是被「Hook」過了(通常是 Rootkit 或惡意驅動的行為) ::: 呈上知識,沒有被奇怪程式接管的部分會長這樣 ![image](https://hackmd.io/_uploads/B1Jyh7IJxg.png) 再回來看這張圖 ![image](https://hackmd.io/_uploads/rJ_DYXUJxg.png) 會發現很多都被`00004A2A`這個記憶體位置接管了 然後就是數他接管了幾個,owned是誰 :::success Ans:18, 00004A2A ::: ### 5. Using the modules (or modscan) plugin to identify the hooking driver from the ssdt output, what is the base address for the module found in Q4? (Format: Base Address) :::info 根據上一題中找到的 Hook 模組,用 modules 或 modscan 插件找出它的模組資訊。請問這個模組的起始(Base)記憶體位址是? 格式:Base Address(例如:0xf8500000) ::: >這邊開始腦袋炸了,放棄思考了 >[name=羽澤] 根據題目提示使用模組`modscan` `python vol.py -f BlackEnergy.vnem --profile=WinXPSP2x86 modscan` 會出現下面這些東西 ![image](https://hackmd.io/_uploads/rkm1ZVLylx.png) 往下就可以看到剛剛的00004A2A,答案是他的Base ![image](https://hackmd.io/_uploads/H1F2e4LJge.png) 其實這邊有點複雜,尋找被隱藏的位置計算方式是 ``` Base <= 0x00004A2A(這是HOOK位置) < Base + Size ``` 但這通常試用於找「哪個模組負責這段位址」,然後去做計算說哪一段有包含HOOK的位置 比如 Base是1 Base+size是5 Hook是3 ,那這一段的位置剛好是1-5,就代表他HOOK被包含在這個程式裡面 但這一題直接是他創造了一個00004A2A的位置,他不屬於任何合法程式內 所以以正常的察看方式的話為什麼在 modscan 看不到合法模組包含 0x00004A2A? 因為他不在任何合法程式的記憶體範圍內: * 0x00004A2A 指向的是非法區段 * 在 modscan 中找不到任何合法模組的 Base ≤ 0x00004A2A < Base + Size * 所以答案就是:它就是自己 fake 的記憶體段本體 就很像是玩CE的時候,妳自己在別的空白記憶體位置創建了一個指針那種感覺,他並不屬於任何程式中 那`0xff0d1000`是哪來的? 應該是另一條 SSDT 的記憶體地址,不是 0x00004A2A 本身的模組。 因為整份 SSDT 表是很多函數組成的,你有些函數會跳去 0xff0d1000(合法),有些會跳去 0x00004A2A(非法) 所以推測應該是00004A2A是額外創建的指針,然後讓0xff0d1000來這邊使用00004A2A內的函數 簡單來說就是 惡意程式在記憶體開了一塊區段(0x00004A2A),並偷偷把某些 SSDT 表中的指標改成指向這裡,這樣當系統呼叫那些 API 時,就會被騙到這段惡意 code 來執行它們自己的邏輯。 :::success Ans:0xff0d1000 ::: ### 6. What is the hash for the malicious driver from the virtual memory image? (Format: SHA256) :::info 請從記憶體映像檔中,找出這個惡意驅動檔案,然後算出它的 SHA256 雜湊值。 格式:SHA256(例如:9c6d49a6a5c91f4d...) ::: 利用`moddump`模組來下載那個部分的文件 `python vol.py -f BlackEnergy.vnem --profile=WinXPSP2x86 moddump -b 0xff0d1000 -D ../` >`moddump` - 儲存記憶體驅動程序成可執行文件 >`-b` - base 位置 >`-D` - 要儲存的資料夾位置 ![image](https://hackmd.io/_uploads/ryour4Lygl.png) 最後用`sha256sum`來算出他的SHA256 `sha256sum ../driver.ff0d1000.sys` ![image](https://hackmd.io/_uploads/Bkk_BNLyge.png) :::success Ans:12b0407d9298e1a7154f5196db4a716052ca3acc70becf2d5489efd35f6c6ec8 :::