围观一下tp的游戏保护 一
生活随笔
收集整理的這篇文章主要介紹了
围观一下tp的游戏保护 一
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
| 普通會員 資 料: 注冊日期: Jul 2011 帖子:?73? 精華:?9 現金: 453 Kx 致謝數: 5 獲感謝文章數:8 獲會員感謝數:23 |
標 題:?【原創】圍觀一下tp的游戲保護 作 者:?thisIs 時 間:?2011-09-20,11:43:51 鏈 接:?http://bbs.pediy.com/showthread.php?t=140344 width="728" height="90" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" id="aswift_0" name="aswift_0" style="left: 0px; position: absolute; top: 0px;"> <好吧,由于之前沒法過帖子致使斑竹受累,原本本文分成了好幾篇,現追加到了一起,第二篇在25樓,第3篇在第29樓> 以下言論只當作技術探討,請勿應用在非法領域 初學驅動,閑來無事探究了一下t.p,版本為DXF中的最新版本 網上有不少介紹t.p的相關文章,我也參考了一下,順便補充其不足 首先來看一下t.p加載之后對系統內核所作的更改, 眾所周知的有: ??NtReadVirtualMemory,NtWriteVirtualMemory的入口處inline?hook ??KiAttachProcess的入口處inline?hook ??PsOpenProcess<win7>或NtOpenProcess<xp>?的深層inline?hook ??PsOpenThread<win7>或NtOpenThread<xp>?的深層inline?hook ??KdSendPacket?KdReceivePacket?的IAT?hook 這幾項網上已經給出了比較完整的解決方案,不再贅述 我們來看一下除此之外的一些東西: <由于害怕ARK遭封殺,自己造了幾個輪子> t.p加載之后創建了兩條系統線程: 創建了一個IO?TIMER: 創建了一個DPC?TIMER: 注冊了一個CreateProcess回調: <這個忘了截圖了..> 可以看到它們所涉及到的知識點還是比較多的, 想摘掉IO?TIMER就要知道如何遍歷IO?TIMER鏈, 想摘掉DPC?TIMER就要知道如何遍歷DPC?TIMER鏈, 想摘掉CreateProcess回調就要知道如何遍歷PspCreateProcessNotifyRoutine數組, 要摘掉兩條工作線程就要知道如何找到它們... 當然了,我們這里的討論的目的不是恢復它們之后可以做什么,而是單純性的通過探究它們來更深刻地理解Windows系統底層 今天我們首先來看一下最簡單的,關于遍歷PspCreateProcessNotifyRoutine數組,PspLoadImageNotifyRoutine也同理 這兩個數組保存了兩組函數地址,它們將在有進程被創建或銷毀,有鏡像被裝載或映射入內存的時候被依次調用, 當然了這兩個符號都是未導出的,而且它們的數量在xp和win7下也有所不同,xp<2k3>下最大數組數量為8,win7下為64 既然要找到兩個未導出符號,我們就在已導出的相關函數中看一下有沒有線索, 相關函數:PsSetCreateProcessNotifyRoutine,注冊或注銷一個進程創建,銷毀的通知回調 相關函數:PsSetLoadImageNotifyRoutine,注冊一個鏡像裝載,映射的通知回調 相關函數:PsRemoveLoadImageNotifyRoutine,注銷一個鏡像裝載,映射的通知回調 <PS一下:不清楚為什么那么多文章說PsSetCreateProcessNotifyRoutine,或PsSetLoadImageNotifyRoutine注冊的例程無法被刪除,從而導致相關的驅動無法被卸載,云云.. WDK中已經解釋的很清楚了,而且我平時的使用中沒出過任何異常,兩個回調都可以通過正規函數刪掉,當然手動遍歷數組刪除也沒問題> 另外值得一提的是PsSetLoadImageNotifyRoutine, 該函數注冊的回調例程會在鏡像被裝載或映射入內存之后馬上被調用, 注意它是先于DLLMAIN或者DRIVER_ENTRY被調用的,聯想到有的驅動會在被加載之后馬上刪除源文件,我們可以通過這種回調在驅動自動刪掉文件本身之前將它copy出去,這種方式比內存dump這種馬后炮的方式優雅可靠得多 首先來看一下xp的PsSetCreateProcessNotifyRoutine?<2k3下相仿>: 可以看到在入口地址不遠處就有PspCreateProcessNotifyRoutine的出現,我們可以很方便地通過搜索特征碼的方式得到. 在看一下win7下的PsSetCreateProcessNotifyRoutine: 它首先調用了PspSetCreateProcessNotifyRoutine函數,追蹤一下: PspCreateProcessNotifyRoutine在入口不遠處出現 這樣,我們就得到了xp<2k3>和win7下的PspCreateProcessNotifyRoutine的地址, 接下來就是遍歷一下這個數組看一下每個回調例程都位于哪個模塊中了, 找到之后調用PsSetCreateProcessNotifyRoutine,第二個參數設置為TRUE就能摘掉回調例程了 ...什么?你遍歷了數組但是沒有發現目標模塊中的回調?好吧,這其中貌似有些貓膩,我們來看一下: <圖中選中的項是我自己的回調例程,當然地址是我已經計算好了的,PspCreateProcessNotifyRoutine數組中并不會出現此地址> 我們來看一下這個驅動文件在內核地址空間中的范圍: <圖中選中項是我自己的回調例程所在模塊> 可以計算一下該驅動文件的地址范圍是?0x927F7000?至?0x927F7000+7000?<927FE000> 接下來我們用livekd來看一下,直接找到PspCreateProcessNotifyRoutine: 可以看到8個回調地址中沒有?0x927F7000?-?927FE000?范圍內的地址,直覺上最后一個應該是與我們自己注冊的例程有關系的數據,那么我們看一下地址?0x9c79061f?中又有什么玄機: 這..貌似沒有什么有用的數據,那么我自己注冊的例程地址保存到了哪里呢?于是我們自然想到翻看一下WRK, 在WRK中找到PsSetCreateProcessNotifyRoutine, 然后發現其中一處調用了ExAllocateCallBack,看名稱應該是為回調分配內存,我們看一下: 這里進行了內存分配,并且將傳參Function,也就是我們注冊回調時提供的例程地址,寫入了一個結構中PEX_CALLBACK_ROUTINE_BLOCK,看一下這個結構有什么成員: 我們感興趣的只有結構中的第二個成員Function. 回想一下,既然系統為回調分配了內存,那么PspCreateProcessNotifyRoutine中保存的應該是每個結構的地址了,但是回過頭我們再看一下?0x9c79061f?地址處的數據: 這里還是沒有我們要尋找的地址! 而繼續在PsSetCreateProcessNotifyRoutine中尋找線索也沒有什么收獲 于是我們開始轉換了思路,既然我們找不到這個回調的地址,那么系統是如何找到的呢? 嗯,貌似這是一個新的突破口,可是我們不知道系統是在什么時候通過什么方式調用?PspCreateProcessNotifyRoutine?中的例程的啊! 額,再想一下,系統要在某個函數中調用?PspCreateProcessNotifyRoutine?中的例程,那么應該會對?PspCreateProcessNotifyRoutine?進行引用的吧,我們在WRK中搜索?PspCreateProcessNotifyRoutine?,看一看都有哪里對其進行了引用: 于是我們找到了這里: 想想也對,因為PspCreateProcessNotifyRoutine是在進程創建,銷毀都進行調用的 跟蹤一下?CallBack?=?ExReferenceCallBackBlock?(&PspCreateProcessNotifyRoutine[i]);?這行代碼,這里應該是取得回調結構的調用 仔細看看該函數的函數頭,我們才發現原來?PspCreateProcessNotifyRoutine?中保存的是?PEX_CALLBACK?結構: 我們看這一行代碼 CallBackBlock?=?ExFastRefGetObject?(CallBack->RoutineBlock); CallBackBlock?被定義為?PEX_CALLBACK_ROUTINE_BLOCK?也就是?PsSetCreateProcessNotifyRoutine?分配的內存數據結構 它的意思很明確,就是得到這個結構的地址,看一下ExFastRefGetObject: 只是簡單地和一個常量進行了與運算 好了,我們理清思路: ??PspCreateProcessNotifyRoutine數組中保存的是?PEX_CALLBACK?類型的結構地址數組; ??EX_CALLBACK結構中只有一個成員,就是?RoutineBlock?,它是一個?EX_FAST_REF?結構; ??EX_FAST_REF是一個聯合,我們這里簡單地將之視為一個指針; ??省略掉中間步驟,?PspCreateProcessNotifyRoutine?保存的就是指針數組; ??系統將數組中的指針傳遞給?ExFastRefGetObject,就得到了?PEX_CALLBACK_ROUTINE_BLOCK?結構地址,這個結構中保存這我們想要的回調例程地址; ??ExFastRefGetObject?將傳進來的指針進行了與運算得到了?PEX_CALLBACK_ROUTINE_BLOCK?結構地址. 好了,回想一下我們自己尋找回調地址的過程,我們沒有進行最后的與運算而是直接將?PspCreateProcessNotifyRoutine?中的數據當成了結構的地址 最后看一下那個神秘的常量: win32下被定義為7,先取反再與運算,也就是低3位清零 我們回過頭在用windbg看一下: 對?0x9c79061f?進行運算得到了?0x9C790618,?看一下這里的數據: 成功得到了注冊的例程地址,我們在PT中驗證一下: 如過想通過?PsSetCreateProcessNotifyRoutine?摘掉其他進程的回調,傳參必須經過以上運算 當然了,如果你直接將PspCreateProcessNotifyRoutine數組暴力清空也行,不過既然有相對優雅的方式,何樂而不為呢? 關于IO?TIMER,?DPC?TIMER等等,?下回再和大家一起分析~~ 如有疏漏之處,請各位前輩不吝賜教 附上本人QQ:2575439022希望跟各位志同道合的朋友共同交流進步 |
普通會員 資 料:注冊日期: Jul 2011帖子:?73?精華:?9現金: 453 Kx致謝數: 5獲感謝文章數:8 獲會員感謝數:23 |
標 題:?【原創】圍觀一下tp的游戲保護 作 者:?thisIs 時 間:?2011-09-20,11:43:51 鏈 接:?http://bbs.pediy.com/showthread.php?t=140344 width="728" height="90" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" id="aswift_0" name="aswift_0" style="left: 0px; position: absolute; top: 0px;"> <好吧,由于之前沒法過帖子致使斑竹受累,原本本文分成了好幾篇,現追加到了一起,第二篇在25樓,第3篇在第29樓> 以下言論只當作技術探討,請勿應用在非法領域 初學驅動,閑來無事探究了一下t.p,版本為DXF中的最新版本 網上有不少介紹t.p的相關文章,我也參考了一下,順便補充其不足 首先來看一下t.p加載之后對系統內核所作的更改, 眾所周知的有: ??NtReadVirtualMemory,NtWriteVirtualMemory的入口處inline?hook ??KiAttachProcess的入口處inline?hook ??PsOpenProcess<win7>或NtOpenProcess<xp>?的深層inline?hook ??PsOpenThread<win7>或NtOpenThread<xp>?的深層inline?hook ??KdSendPacket?KdReceivePacket?的IAT?hook 這幾項網上已經給出了比較完整的解決方案,不再贅述 我們來看一下除此之外的一些東西: <由于害怕ARK遭封殺,自己造了幾個輪子> t.p加載之后創建了兩條系統線程: 創建了一個IO?TIMER: 創建了一個DPC?TIMER: 注冊了一個CreateProcess回調: <這個忘了截圖了..> 可以看到它們所涉及到的知識點還是比較多的, 想摘掉IO?TIMER就要知道如何遍歷IO?TIMER鏈, 想摘掉DPC?TIMER就要知道如何遍歷DPC?TIMER鏈, 想摘掉CreateProcess回調就要知道如何遍歷PspCreateProcessNotifyRoutine數組, 要摘掉兩條工作線程就要知道如何找到它們... 當然了,我們這里的討論的目的不是恢復它們之后可以做什么,而是單純性的通過探究它們來更深刻地理解Windows系統底層 今天我們首先來看一下最簡單的,關于遍歷PspCreateProcessNotifyRoutine數組,PspLoadImageNotifyRoutine也同理 這兩個數組保存了兩組函數地址,它們將在有進程被創建或銷毀,有鏡像被裝載或映射入內存的時候被依次調用, 當然了這兩個符號都是未導出的,而且它們的數量在xp和win7下也有所不同,xp<2k3>下最大數組數量為8,win7下為64 既然要找到兩個未導出符號,我們就在已導出的相關函數中看一下有沒有線索, 相關函數:PsSetCreateProcessNotifyRoutine,注冊或注銷一個進程創建,銷毀的通知回調 相關函數:PsSetLoadImageNotifyRoutine,注冊一個鏡像裝載,映射的通知回調 相關函數:PsRemoveLoadImageNotifyRoutine,注銷一個鏡像裝載,映射的通知回調 <PS一下:不清楚為什么那么多文章說PsSetCreateProcessNotifyRoutine,或PsSetLoadImageNotifyRoutine注冊的例程無法被刪除,從而導致相關的驅動無法被卸載,云云.. WDK中已經解釋的很清楚了,而且我平時的使用中沒出過任何異常,兩個回調都可以通過正規函數刪掉,當然手動遍歷數組刪除也沒問題> 另外值得一提的是PsSetLoadImageNotifyRoutine, 該函數注冊的回調例程會在鏡像被裝載或映射入內存之后馬上被調用, 注意它是先于DLLMAIN或者DRIVER_ENTRY被調用的,聯想到有的驅動會在被加載之后馬上刪除源文件,我們可以通過這種回調在驅動自動刪掉文件本身之前將它copy出去,這種方式比內存dump這種馬后炮的方式優雅可靠得多 首先來看一下xp的PsSetCreateProcessNotifyRoutine?<2k3下相仿>: 可以看到在入口地址不遠處就有PspCreateProcessNotifyRoutine的出現,我們可以很方便地通過搜索特征碼的方式得到. 在看一下win7下的PsSetCreateProcessNotifyRoutine: 它首先調用了PspSetCreateProcessNotifyRoutine函數,追蹤一下: PspCreateProcessNotifyRoutine在入口不遠處出現 這樣,我們就得到了xp<2k3>和win7下的PspCreateProcessNotifyRoutine的地址, 接下來就是遍歷一下這個數組看一下每個回調例程都位于哪個模塊中了, 找到之后調用PsSetCreateProcessNotifyRoutine,第二個參數設置為TRUE就能摘掉回調例程了 ...什么?你遍歷了數組但是沒有發現目標模塊中的回調?好吧,這其中貌似有些貓膩,我們來看一下: <圖中選中的項是我自己的回調例程,當然地址是我已經計算好了的,PspCreateProcessNotifyRoutine數組中并不會出現此地址> 我們來看一下這個驅動文件在內核地址空間中的范圍: <圖中選中項是我自己的回調例程所在模塊> 可以計算一下該驅動文件的地址范圍是?0x927F7000?至?0x927F7000+7000?<927FE000> 接下來我們用livekd來看一下,直接找到PspCreateProcessNotifyRoutine: 可以看到8個回調地址中沒有?0x927F7000?-?927FE000?范圍內的地址,直覺上最后一個應該是與我們自己注冊的例程有關系的數據,那么我們看一下地址?0x9c79061f?中又有什么玄機: 這..貌似沒有什么有用的數據,那么我自己注冊的例程地址保存到了哪里呢?于是我們自然想到翻看一下WRK, 在WRK中找到PsSetCreateProcessNotifyRoutine, 然后發現其中一處調用了ExAllocateCallBack,看名稱應該是為回調分配內存,我們看一下: 這里進行了內存分配,并且將傳參Function,也就是我們注冊回調時提供的例程地址,寫入了一個結構中PEX_CALLBACK_ROUTINE_BLOCK,看一下這個結構有什么成員: 我們感興趣的只有結構中的第二個成員Function. 回想一下,既然系統為回調分配了內存,那么PspCreateProcessNotifyRoutine中保存的應該是每個結構的地址了,但是回過頭我們再看一下?0x9c79061f?地址處的數據: 這里還是沒有我們要尋找的地址! 而繼續在PsSetCreateProcessNotifyRoutine中尋找線索也沒有什么收獲 于是我們開始轉換了思路,既然我們找不到這個回調的地址,那么系統是如何找到的呢? 嗯,貌似這是一個新的突破口,可是我們不知道系統是在什么時候通過什么方式調用?PspCreateProcessNotifyRoutine?中的例程的啊! 額,再想一下,系統要在某個函數中調用?PspCreateProcessNotifyRoutine?中的例程,那么應該會對?PspCreateProcessNotifyRoutine?進行引用的吧,我們在WRK中搜索?PspCreateProcessNotifyRoutine?,看一看都有哪里對其進行了引用: 于是我們找到了這里: 想想也對,因為PspCreateProcessNotifyRoutine是在進程創建,銷毀都進行調用的 跟蹤一下?CallBack?=?ExReferenceCallBackBlock?(&PspCreateProcessNotifyRoutine[i]);?這行代碼,這里應該是取得回調結構的調用 仔細看看該函數的函數頭,我們才發現原來?PspCreateProcessNotifyRoutine?中保存的是?PEX_CALLBACK?結構: 我們看這一行代碼 CallBackBlock?=?ExFastRefGetObject?(CallBack->RoutineBlock); CallBackBlock?被定義為?PEX_CALLBACK_ROUTINE_BLOCK?也就是?PsSetCreateProcessNotifyRoutine?分配的內存數據結構 它的意思很明確,就是得到這個結構的地址,看一下ExFastRefGetObject: 只是簡單地和一個常量進行了與運算 好了,我們理清思路: ??PspCreateProcessNotifyRoutine數組中保存的是?PEX_CALLBACK?類型的結構地址數組; ??EX_CALLBACK結構中只有一個成員,就是?RoutineBlock?,它是一個?EX_FAST_REF?結構; ??EX_FAST_REF是一個聯合,我們這里簡單地將之視為一個指針; ??省略掉中間步驟,?PspCreateProcessNotifyRoutine?保存的就是指針數組; ??系統將數組中的指針傳遞給?ExFastRefGetObject,就得到了?PEX_CALLBACK_ROUTINE_BLOCK?結構地址,這個結構中保存這我們想要的回調例程地址; ??ExFastRefGetObject?將傳進來的指針進行了與運算得到了?PEX_CALLBACK_ROUTINE_BLOCK?結構地址. 好了,回想一下我們自己尋找回調地址的過程,我們沒有進行最后的與運算而是直接將?PspCreateProcessNotifyRoutine?中的數據當成了結構的地址 最后看一下那個神秘的常量: win32下被定義為7,先取反再與運算,也就是低3位清零 我們回過頭在用windbg看一下: 對?0x9c79061f?進行運算得到了?0x9C790618,?看一下這里的數據: 成功得到了注冊的例程地址,我們在PT中驗證一下: 如過想通過?PsSetCreateProcessNotifyRoutine?摘掉其他進程的回調,傳參必須經過以上運算 當然了,如果你直接將PspCreateProcessNotifyRoutine數組暴力清空也行,不過既然有相對優雅的方式,何樂而不為呢? 關于IO?TIMER,?DPC?TIMER等等,?下回再和大家一起分析~~ 如有疏漏之處,請各位前輩不吝賜教 附上本人QQ:2575439022希望跟各位志同道合的朋友共同交流進步 |
總結
以上是生活随笔為你收集整理的围观一下tp的游戏保护 一的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 散谈游戏保护那点事~就从_TP开始入手吧
- 下一篇: Ring0和Ring3权限级