tag:blogger.com,1999:blog-4991340253510030952024-03-25T21:58:10.620+08:00X駭客教學實驗室 (Hacker Tutorial Labs)xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comBlogger88125tag:blogger.com,1999:blog-499134025351003095.post-84312105479457443552021-02-17T17:58:00.001+08:002021-02-17T17:58:55.222+08:00劍靈(Blade & Soul) - 商用殼介紹(nProtect、WinLicense、Themida)<p>現今的線上遊戲(MMORPG)為了抵擋駭客來逆向分析遊戲的主程式,會利用商用殼(Packer)來保護遊戲的主程式,因為直接購買商用殼就不需花費大量的時間和人力去開發加殼軟體,所以就能專注在遊戲的開發。也許有人認為商用殼會被駭客破解,因此並不是特別安全,不過商用殼也有强弱之分,所以只要將無法破解商用殼的駭客抵擋在外就能達到此目的。<br /></p><p></p><span><a name='more'></a></span><p><br />劍靈這款線上遊戲,使用三種不同的商用殼(nProtect、WinLicense、Themida)來保護遊戲的主程式,接下來我們就會介紹這些商用殼的特性。<br /><br />一、nProtect<br /><br />nProtect是一款韓國公司所開發的商用殼(Packer),主要是應用在遊戲軟體之上,為了防止遊戲外掛的開發所使用的,它的技術分為32 bit和64 bit,如果在32 bit平台上會利用Hooking NtOpenProcess、NtReadVirtualMemory、NtWriteVirtualMemory等等的Kernel API來偵測遊戲程式的記憶體是否被竄改和檢測是否有被Debugger工具加載以及是否被DLL Injection,因為主要涉及Kernel層,因此在解殼的過程,增加一些困難度,另外如果在64 bit平台上,就不能對Kernel層下手,因為Win 7以上的x64版本都有PatchGuard來保護Kernel的記憶體,防止被任何程式來竄改記憶體,所以nProtect只能從Application層來Anti-Debugger。<br /><br /><img src="https://lh6.googleusercontent.com/lCpeXSjsOeLaBLHkWZtnaVfXjKlm7enN5XksVPq714X0usUD2uz6rt0dRCvG-1_6nblQ94y8M1g8ykGsWj0PcBKBMiKZ_ytmGuta5hPV5TheG2AirMSnIDzPd5An_ybUfS6PnwYZgFTXt4tX7Q" /><br /><br />劍靈在載入遊戲前,會將nProtect加載進來,此時有任何的Debugger工具在Debug遊戲的Process,那麼nProtect就會偵測到有人在分析程式碼,因此會讓遊戲程式自動結束,這樣一來,駭客就很難知道它是用什麼手法來偵測Debugger工具。<br /><br /><img src="https://lh6.googleusercontent.com/sj-T2te-ownyt2RGVlMHUig4bQBVsQGrRl6oQF-n9Ve6bV1vxUcDf7pbJVt5Llhr82DI2sKOKvFeyfzuoLITLYYSylxLnz3w98MvLY56Cr7fyuiA01dFW0_TGxupleZ4RKMSWJsnPzsy8iM7dQ" /><br /><br />通常在研究一款商用殼(Packer),我都會去它的官方網站查看它的防護功能有哪些,一方面能有效率的猜測它是透過哪些技術來做防禦的,這樣也比較容易繞過這些防護技術。<br /><br />我們從官方網站找出的功能表,其中主要還是透過加密殼和動態偵測Debugger工具,還有一些針對Hooking DirectX 3D API 檢測,因此如果當前要分析遊戲的主程式,其實只要繞過動態偵測Debugger工具(x64dbg、ollydbg、windbg)的防護功能即可。<br /><br /><img src="https://lh4.googleusercontent.com/soTPm9PI6eRG47mq-0Prcsmtt2rgMgpPDb_KpRC0WqP_Q_bYXY5cQsGV03T8KI0zWxacd-sJmkV98gycydFhbJy4her3fmhOWi_hh-Yq9e_4V3_IbHSMp342PB2KsZ9KQzYYBPIIlwsnPdn9Tg" /><br /><br /><img src="https://lh6.googleusercontent.com/GI7IRUUREwykW86dhUEMULwm40BBroxKQRvipKBlS-FuWIfV5W5TVa9xF9RKxHvO0xt3B9kuFayt9ho6_XZF-wBfvyCNrf3CCZb9SfyATHCjRc3GJAKiKC0BXzth89sF6QD5LoChvfKu_SNM3w" /><br /><br />二、WinLicense<br /><br />WinLicense是一款結合Themida的強勁商用殼,包含了大多數防護之技巧,使得駭客要分析遊戲的主程式會顯得非常吃力。<br /><br /><img src="https://lh3.googleusercontent.com/BEDwrdZVJgg3z9MydMQuqVc5W4IZIFNwgi30usTsBStyCg9VD1DNEKOS4MPucOIm99ervZdr2_1euSwW6k1Pc6II9CPoF-s9TDOnFY1P3zTehv44M8rVI9pNMrFr5lgoh3fOpSTa4J1zeGcRCg" /><br /><br />我們從官方網站獲取的防護功能,雖然功能非常多,主要還是融合壓縮殼、加密殼、VMProtect、Anti-Debugger之技術,其中比較特別的是,他還會針對Anti-Anti-Debugger的防護,因為有些Debugger工具會讓Anti-Debugger失效(x64dbg scyllahide),所以就有加強這方面的技術。<br /><br /><img src="https://lh6.googleusercontent.com/PP4LxOmyS6hIc1p041c87mQJ1fowX9FPWSY8QrFbJE0f0q6FoRjw5LhQnbkbcMwNZjlq57xAdQi7RS3-R9X6lzRCtXGGPZlBgmgyq2zYY46rJd_kbPKAkZlAMaTyuyTG9yChCoDmuVexYbr8fw" /><br /><br />WinLicense和nProtect比較不同的是,它並不會動態偵測Anti-Debugger,不過遊戲只要一開始有載入Debugger,還是會偵測到它,並且跳出一些錯誤訊息,然後結束程式。<br /><br /><img src="https://lh6.googleusercontent.com/g8sSWBogiHyzo4F4rQgk_Xnjkmk63TAKyMNubPC0_UUiKio_GkdFXPCvjENBpRgQTiFsg8djnoQ9ED_0vc3DDaKbkJAbJMeDe7cI5w8NYzpDd0V2wkVpfTpkeev47NY5RXOgSivYhK4mbmoeCA" /><br /><br />三、Themida<br /><br />Themida主要是透過Obfuscator-LLVM之技術來防範駭客能輕鬆的分析程式碼,它會將原本的程式碼變得非常之複雜,使得大多數的駭客驚慌失措,並且放棄分析程式碼。<br /><br /><img src="https://lh3.googleusercontent.com/I6Hh-I5JqLH_wX8ZxLvvxu9WcCS7dlmI5lR1ZFr13LH_DmiY0LFJe1RXDueQeHtiu2AthVoW9p07iKQHxA5bYuhg4Eh8zYSk54uQLwFcOkm-mK9IYIXlUviaSx6gby1aEtnGCvIq9EywmAGBGA" /><br /><br />從Themida的官方網站上獲取它的防護功能,因為它是從很久以前就被開發的商用加殼工具,所以隨著時代的演變,它也附著了非常多的防護功能,因此跟WinLicense也有點相像。<br /><br /><img src="https://lh3.googleusercontent.com/zSMyO0iP6dAUwicuuyRkT96bpTObnsDcJWx1Dbie-f9uRfhAnSiNiQ3E-BrjnivTnHIf-2lcJT_sdLPOyKnjsyWppgjA_Jgdo9nE-AJAoru4j8a-3jqS_HNjoJFmdRhfhtTu2mcRxqmT3XCSTQ" /><br /><br />Obfuscator-LLVM主要之技術就是讓原本的程式碼變的非常複雜,使得駭客分析程式碼的過程變得非常困難,其中它會將原本的運算值和調用API的參數分開計算,並且每個運算區段會用無數個無意義的迴圈來增加分析的困難度,在跳入其它的運算區段會使用jmp語法來防止駭客觀察Stack,因為call語法會將調用位址紀錄到Stack,所以如果不用call語法,就不能輕易的突破關鍵程式碼。<br /><br /><img src="https://lh5.googleusercontent.com/b2djUbux5SLSMwRsa6S19-qliZLKGM2kHDIfUfBjxkkou1XLEnjoWMWlhKdDA3xpmImruXmoWcYWx6W9-sxkEIitIGx2czuPIBLkSoCjn8a4nxl5KuVOSCPkx4xtIj0lAkLFv8B3bBBWeE_bMg" /></p>xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-44673905493829202222021-02-04T20:47:00.001+08:002021-02-04T20:47:48.360+08:00Android - DexProtector商用殼破解心得<p>DexProtector是商用版的加殼(Packer)軟體,它有支援Android和IOS這兩種平台,一般來說只要是商用版的加殼軟體,在解殼的過程都會顯得非常的難,因此有些惡意程式會使用它來加殼,這樣大多數的分析人員可能會選擇放棄,如果本身沒有研究商用殼的原理,可能需要耗費非常多的時間來解殼,不過就算遇到這類的加殼惡意程式,也不需要懼怕它,那麼接下來這篇會介紹它的解殼原理。<br /></p><span><a name='more'></a></span><p></p><p></p><p></p><p></p><p><br />由於我們找到的惡意程式是APK檔案,因此只會涉及Android平台上的解殼原理。<br /><br />一、事前分析工作<br /><br />大部分的商用加殼軟體在網路上,可能都有熱心的人分享解殼相關資訊,但是DexProtector找不到任何解殼資訊,只知道它的相關特徵,這樣只能先去下載它的試用版來分析,因為這樣能控制加殼的設定,會比較好分析,不過DexProtector的試用版不能直接下載,必須跟他們的業務從中獲取,因此我們就只能直接分析惡意程式了。<br /><br />在分析之前,DexProtector的官方網站有提供它的防護功能,基本上只要是商用殼,該有的安全防護都會提供,例如Obfuscator-LLVM(程式碼混淆)、Anti-Debugger(gdb、jdwp偵測)、字串加密、主程式加密、完整性驗證(Signed APK)、模擬器偵測、Hook偵測、xposed偵測、frida偵測、VMProtect等等,非常多樣化。<br /><br /><img src="https://lh6.googleusercontent.com/xSrSiRvd7_q3ZxjrJekPlPUqZWmylRH_ZB8BkVoF-1b5cPT4IzV-QcqtbA5GvX5OP4uf6K5EliFUAtbN6IYxYe8J5ldrjGt9HUQz9eoixj-v3uXfhWLWZL43-JtZeupdDfbWpzzOxsaEEk6GIQ" /><br /><br />二、DexProtector運行原理<br /><br />DexProtector運行原理如下說明:<br /><br />1. 運行APK:在程式運行的開始,會判斷系統的環境,以利要解密哪個so檔(C++ Base),並且解密當前要使用的字串,因為整個Dex檔的字串都會被加密,所以只要有字串的部分都要進行解密。<br /><br />2. 解密so檔(Native Code、C++ Base):加密的so檔會從assets資料夾獲取(dp.arm-v7.so、dp.arm-v8.so、dp.x86.so、dp.x86_64.so),並且將它解密,然後運行到記憶體,此時的so檔身兼重任,其中包含Anti-Debugger、解密中繼Dex、APK完整性驗證(Signed APK)、解密主程式Dex,並將主程式執行到記憶體。<br /><br />3. Anti-Debugger:這個部分包含環境模擬器的偵測、gdb和jdwp等等的偵測,只要有相關Debug訊息,就會讓JNI_OnLoad回傳-1,這樣會使Native Code (C++ Base)運行完JNI_OnLoad就會直接Crash,此時很多人第一次分析時,並不知道發生了什麼事,不過要繼續動態分析解殼的部分,就必需繞過Anti-Debugger。<br /><br />4. 解密中繼Dex檔:加密的中繼Dex檔是存放在Java端的記憶體區塊,在解密完後,並且將它運行到記憶體,接下來主導權就交給中繼Dex檔,那麼它的主要任務是透過so檔(Native Code、C++ Base) 來加載惡意程式的主程式,其中包含完整性驗證(Signed APK)、註冊so檔的Native Method、初始化主程式全域變數(Static Field)。<br /><br />5. 完整性驗證(Signed APK):中繼Dex檔會調用so檔的函式來運行完整性驗證,並且判斷APK的簽章是否有被替換,如果有,就不會繼續運行,然後讓JNI_OnLoad回傳-1,因此如果有修改程式碼再封裝APK,就必須繞過完整性驗證。<br /><br />6. 註冊so函式:可能有些同學會好奇為什麼它要註冊so函式(Native Method),由於so檔捨棄Java_class的宣告,這樣可以讓分析人員找不到對應的函式名稱,因此它才需要透過FromReflectedMethod或RegisterNatives來註冊so檔的Native Method。<br /><br />7. 解密主程式(Dex檔):加密的主程式會放在assets資料夾底下,檔案名稱是classes0.dex,它會先透過簽章和數值的運算後,再與數值運算後的結果進行解密,解密完後,我們就能從陣列上看到完整的Dex檔(Header是dex 035),在運行到記憶體之前,會先初始化主程式的全域變數(Static Field),然後再透過DexFile::OpenCommon或ArtDexFileLoader::Open來載入Dex檔到記憶體上,最後再調用主程式的Main Activity。<br /><br /><img src="https://lh6.googleusercontent.com/wWhIW1durn1RKplZMfZHFupOdG7GEda5vMT5VgY71Wl9k1bDlYX8LDbmSHpZQcJVj0pqTi9vO0BBAQAMmA2hAJ1T4lTG1t2Lrya5eCrslTqY2qFJHzR64thzScUzjHkH_Dh9iRfIE7fTNC9oag" /><br /><br />為了使Dex檔更難被行為分析,所有的Dex檔的字串都會加密,其中包含一開始的Dex檔、中繼Dex檔和主程式Dex檔,它會利用Package name、Class name、Method name合併成一個字串,然後進行Hash,接下來再比對此Hash是否為有效Hash,最後才會進行解密的運算。<br /><br /><img src="https://lh4.googleusercontent.com/-yXawbcw5Anzzj7mmx_7rksRIldbXL1xDV6CzXHoDjgq4HP5SQbb63rsxDqbaR46lugqEJ42qCOLRPY5beVI5a55OkXLQU8H_3eu-cG-pB05kWXw5STXFreHehukin5f05xDDkFOqFC4JTbVOQ" /><br /><br />接下來我們開始探討在DexProtector使用的類似VMProtect的加殼技術,它主要是將Java端的程式碼封裝成Native Method(C++ Base、so檔函式),然後透過Native Method來完成Java端的實作,首先Java端會傳遞要運行的Method ID、參數、Method和Field名稱的字串,接下來Native Method會透過Method Reflection來獲取Java端的Method Address,這樣就能從Native Method調用Java端的Method,那麼要處理全域變數(Static Field)就會利用Field Reflection,這樣就能獲取Java端的全域變數,最後運行完後,就會開始處理回傳值,如果接收端是區域變數,就不會在Native Method處理此數值,它會直接return這個區域變數給Java端程式碼。<br /><br /><img src="https://lh4.googleusercontent.com/3gyttMdHC_tHG7LGPVgT_e0uPFblhF_SjBqBf6Jt7bI3IXBi8AYc-HWlhnLx8SHLoIv_HsqfaIO3-KPvFCii4mxcgzYYDPSJhQPIOwPoCfDPxxmZcJXGkaXbPf5XSPjfJamzJs5p1nBAaUVjXA" /><br /><br />classes0.dex是被加密的主程式(Dex檔),dp.xxxx.so是被加密的so檔,它會先判斷手機是屬於哪個版本的CPU,然後再進行so檔的解密。<br /><br /><img src="https://lh4.googleusercontent.com/IQNhjj3Y2eOvD47rm9e5Yj6YbWLRvizj9U2IKqxWay_uZHsXzlfkNlGLpUnX0J4IJPIGtijppPOTriIiQCzWOrd_0UcclyaUCiljOz1ZQXxEFwmmbQ6-pG2kKbTQXWSxmOiBrf4P1tHOc3D-sQ" /><br /><br />onStart是解密字串的Method,解密完後,會回傳so檔的檔案名稱(libdexprotector.1415.so),其中1415是當前程式的PID,然後將此檔創建後,才會開始對so檔解密,並且將它載入到記憶體,最後還會將so檔從rom移除,主要是防止分析人員Dump。<br /><br /><img src="https://lh3.googleusercontent.com/UwyZObGMH1HNKvb18YYrikLb0ZOdot212SrR4eD3JeoRJ8hrwGqJptxP8pODhev4G6kRPAMsUuHoM_B7iJGBWfQEpSVN93toWqV2WTuXWA1kbAnfg5n0f8FjJIz2R0KOQF1Da_FsYXzf05rPcw" /><br /><br />so檔不但有被加密,而且在載入中繼Dex檔之前,關鍵函式還會先自我解密,這邊主要有運用到加密殼的技術,因此僅僅只有靜態分析是找不到關鍵的程式碼,另外它還有隱藏JNI API的調用,所以透過API分析是沒有用的,因為它在調用JNI API會利用dlsym來抓取函式的起始位址,所以一定要從動態分析來了解它的運行邏輯。<br /><br />加密的中繼Dex檔,並不是像so檔是在外部檔案,它是存放在一開始運行的Java端程式碼裡(Dex檔),這邊是使用apktool工具來還原的Smali程式碼,我們可以看到x陣列就是存放加密的中繼Dex檔(此檔案非常大,圖中只截取部分的資料)。<br /><br /><img src="https://lh3.googleusercontent.com/X_Slr3bq1GU8_tcnO8ZizZfIDqcHiFdyBeuExuAe7YI7SgkVkUBl_PkGESTK-mcjxoRta0ucAHZkf6cguLsJOYwQek9qxsTBFzdvP7ZxyXzGDsSKlOT6LutSeNjTmtPSV138UK4Itk15VzVCXA" /><br /><br />DexProtector使用類似VMProtect技術,不外呼就是將主程式的程式碼(Java)交給so檔(C++ Base)實作,這樣就算分析Java程式碼,也並不知道其中的運作,因此我們可以在一開始的Dex檔程式碼(Java)看到它有宣告大量的Native Method,那麼有同學可能覺得,我只要分析so檔就能直接還原Java程式碼了,然而不幸的事,這些Native Method在so檔都是運行時才透過FromReflectedMethod或RegisterNatives來註冊的,因此還需要利用這2個API來找出所有Native Method對應的程式區塊,不過Java端的程式碼非常大,Native Method就會非常的多,那麼要還原整個Java端的程式碼會非常的耗時。<br /><br /><img src="https://lh3.googleusercontent.com/So0-03pP0f-wX1jxmafwOneazHAcAfVp1nStPQ0Gq_4HyAvrlhZV9LcQC9hhcNCr-fPA97gLeSTt5GrxkYIyEaBLjShj5WPvsDu_RYYRoLvhw8NB5MxBmUvpvvXjUX-GQkIGYcylwL7O4C2AhA" /><br /><br /><br />三、突破DexProtector的防護策略<br /><br />DexProtector在解密主程式的Dex檔,裡面的所有方法(Method)都被它替換成其它的Method(LibMyApp.i是Native Method),在運行時會讓Native Method (C++ Base、so檔函式)來調用這些原來Java端的Method和處理全域變數(Static Field)傳輸的資訊,這樣分析主程式(Dex檔、Java程式碼)的行為就顯得相當困難,此種做法類似於VMProtect。<br /><br /><img src="https://lh4.googleusercontent.com/pVqrNdEmKwSawpZ1GdlYVypG-KHBtdWMGA_w_U4Em-N_BglK3OHH1YGmrVjj0g1socvkCCPdE2VKIDYZf7HQSrmmHc_urtRl2PqGKAuJIM1AuVwvMULVHjwE01ElOM1cSzgyVcCxoAoXhLveMA" /><br /><br />如果要做到完全解殼(主程式獨立執行)可能真的會耗費很多時間,那麼我們就解一半吧,只要能做到我們的目的就行了(分析主程的行為、修改主程式)。<br /><br />可能有同學會提出疑問,什麼是將殼解一半 ? 解一半的意思,主要是跟殼(Packer)共存,但在最後運行的主程式我們會將它替換成我們修改好的Dex檔,不過還需要繞過完整性驗證(Signed APK)才不會運行時閃退。<br /><br />主要用到的技術就是修改初始運行的Dex程式碼,並且我們還會另外撰寫自己的so檔,然後加載到記憶體,其中我們會Hooking它原本so檔(libdexprotector.1415.so)的部分函式。<br /><br />Hooking的關鍵點有2個,一個就是在驗證完整性的函式,另外一個就是載入主程式(Dex檔)之前的函式,只要在載入主程式之前,替換成我們修改好的Dex檔,就能讓主程式運行如我們預期的行為了。<br /><br />經過VMProtect加殼的主程式,大部分的邏輯都已被摧毀殆盡,甚至字串也被加密了(Dbiqjw是解密的Method),如過要能正確的判斷它的行為,就必須將Method ID(-27064、30008、27237等等)解密出來。<br /><br /><img src="https://lh4.googleusercontent.com/5uPmzM9dPG8L3HRRl_F6svqfl6hLY1mHTPfktUO9nOM_7K0Vc0eyPJwSoaxW-5JW5nsX2ozTOfH8TaZmP_dQ7ebeN-CfVNYl0KOTahTLlvJ60XGNSag6t5M8OSOoVMecvc_YO5X2fvbFO1c7mQ" /><br /><br />最後我們將Method ID解出成相對應的Method name字串,並且將它的參數之輸入輸出也都還原成字串名稱,也順便解密全部的加密字串,這樣就能不費吹灰之力就能分析它的行為了。<br /><br /><img src="https://lh6.googleusercontent.com/IF2AgkcIMX1_ogD8wAaxDcawUdZv66F1-lywULyKhb3m7su5wP0OSveKSaWaKki62oBycwyA16k_UMA7wA94Mrrr8UGun3d5FmxWEY-JErtNcWxBp9AtUiLmNH9nsmGZie56moKbyugQryki3w" /></p>xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-13322155564954597912021-01-31T17:48:00.000+08:002021-01-31T17:48:46.978+08:00Android Unity - Method injection<p>在之前的篇章已有討論Android Unity的程式碼修改和Code injection(程式碼注入),不過都稍有不足之處,一般來說程式碼修改只能做到在程式碼的長度不變的前提下,然後加以修改它,使其達到其它的運作,但如果要修改的程式碼大於當前的程式碼,就不能完成此項運作,另外Code injection雖然能補足程式碼修改的缺點,但是要編寫大量的程式碼也會非常的麻煩,因此我們來實作Method injection就能完美的補足這些問題,因為我們可以直接編寫Unity的Method,然後直接將它注入到要Hack的Unity,並且再透過Code injection來調用注入的Method。<br /></p><span><a name='more'></a></span><p></p><p></p><p><br />一、找出要注入程式碼的區塊<br /><br />我們還是沿用之前的遊戲,並且可以比較這三種方法的優缺點。<br /><br />此款遊戲是射擊當前怪物,只要在螢幕出現的怪物都擊殺完成,就能到下一關卡,每個玩家會有3發子彈(Left),如果射完3發子彈,怪物還沒被完全消滅,遊戲就回被終止,並重新遊戲,其中Shoot是記錄當前射了幾發子彈。<br /><br /><img src="https://lh6.googleusercontent.com/DzMNZmVwZt6mEzZE25xIn_MdloU-s6qFRuW5z8N2tsBmcYoRMPmr2BHCdq760W-hijff_b3UhGumj5IGHvxhZlH7sDXw8w_vHOGWVgTWUsfZ0ruWtc_j-UnXEtStNiIJgx9Vc5YAFwaTdrDShQ" /><br /><br />了解遊戲運行方式後,我們需要找到Shoot和Left的相關程式碼,並修改它,這樣就可以無限輸出子彈,怎樣都不會終止遊戲。<br /><br />接下來我們要知道Unity遊戲的主程式是放置在哪個檔案裡 ? 我們可以從assets\bin\Data\Managed資料夾裡面找到Assembly-CSharp.dll,它就是Unity遊戲主程式。<br /><br /><img src="https://lh6.googleusercontent.com/Hw5XU86qHGmZNyeUpsc6-aCYb6VLkj3yCYEmhRXPm_YwPKOU6RBb8aOXFD_fJ9h7n8af8G-kb_BsU2411hJy8K9OVYJqyOwun-ekrTMAB-udmJp4lBz9yhcsvYkbQoiA6k2kUavJNRYS3GBg-A" /><br /><br />在Unity遊戲程式碼裡,我們找到射擊相關的程式碼, --this.shotTime和++this.shooted,只要將Method注入到它的之前或之後,就能完成任務了。 <br /><br /><img src="https://lh3.googleusercontent.com/FXnycCTlUeDWCxAHsSc-IENrxWvhVMUhrGeI2KgsoxpD8MivbwczC0JN1BDpX0_WUR7A5SWoEAwWyM9oEFDQFPSUlroIfVY-CukcwVpF07zNj13GHoYbn0lyGhz_IYdLawvGZXJPA-62UAO4kw" /><br /><br />二、Method injection<br /><br />我們在Method injection的時候,是將整個Class都注入進去,因此不要跟Hack的Unity衝突Class的名稱。此Method會需要傳入一個參數,這個參數是object型態,因為我們需要修改GameManager的shotTime和shooted的成員資料,所以我們會傳入GameManager物件給HackSooting,這樣就能完成修改成員的資料。<br /><br /><img src="https://lh5.googleusercontent.com/8mhfXUoKTV9ieLM7DUDUuDTz1apaowOyI5hYvBrQUP6_YUepwYbgsPtN_B6qcPfA_1JcFEblV61nbMukgjLsM6xs2U-kxOL4kzj2s17cKiDR-emkM2sIGnbsecX3G_yaHw3OC5YcNt_-TcRijA" /><br /><br />當然還沒完成整個流程,由於我們目前只將Class和Method注入到Unity,那麼還需要讓它調用HackSooting,所以還需要利用Code injection,因此我們在shotTime和shooted的程式碼之後注入Cheat.HackSooting,與此同時這樣就能完成實作Method injection。<br /><br /><img src="https://lh4.googleusercontent.com/lV9WGf7ccSwuUomycRzCXNK_yS2hd_EsvPRrjbbzwIb3Zv--0ZzV9sF1fiG6V0OO8ZzAgX-mfP0G6_H6m6lIg05jdEedbE2iQasf3kC9kHow1Bp1BKik0ZejKbrjsr6X6o13ay_8OoaKMFk2OQ" /><br /><br />三、運行結果<br /><br />實作Method injection和Code injection完成後,重新封裝apk檔案,並且安裝到手機裡面,這樣我們不管怎麼射擊都能讓遊戲持續運行。<br /><br /><img src="https://lh4.googleusercontent.com/IZ7hLiFFih9HQWeKIi4FFvHyddnU3Ypnnf8k9B5M6ASuGly0GLPWkzhHeyvwECDrM2BwgSDQ8Xmd6pYxK7qsVwfQl8DR0WR_ios3dYgZybQB2IG5wGWHtHiZQe_uPDArjwJINB48fDg6h5BXDg" /></p>xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-91250211010346871532020-12-31T18:00:00.003+08:002020-12-31T18:00:50.723+08:00109年金盾決賽 - Android reverse engineering (咖啡機IOT)<p>今年的金盾獎決賽有增加特殊的題型,例如IOT (Internet of Things)和教學題,其中IOT需要與設備互動來藉此解題。此篇的題型是要連線到咖啡機,然後透過逆向分析獲取藍芽密碼,並且泡上一杯咖啡,即可獲取Flag。在決賽時,並不是每隊都能解到IOT的題目,因此在這裡提供咖啡機IOT的題目給各位,不過並沒有提供實體設備,只要解出藍芽密碼即可。<br /><span></span></p><a name='more'></a> <p></p><p>題目下載連結<br /><br /><a href="https://drive.google.com/file/d/1pfguXLZHEOuXkDhl9OjI_X8AuZNK9y8h/view?usp=sharing">https://drive.google.com/file/d/1pfguXLZHEOuXkDhl9OjI_X8AuZNK9y8h/view?usp=sharing</a></p><p>一、題目介紹<br /><br />在比賽時,會有時體的咖啡機放在現場,只要能解開藍芽密碼並且泡出咖啡就能獲取Flag。<br /><br /><img height="416" src="https://lh5.googleusercontent.com/VDL2FQKHcEDqXnaUHmpsJ4fQcmGsN8ucQiitohNqNVTiyGGb9tj3pUNFJ8S4X-zzVk-V03IImGA1eOm527v0HwWzgtns43X02yc-aWaK9ok0_Cnfb1pwHrMPa0Th50Xm-Yx4drQjqgtcM35wuw=w364-h416" width="364" /><br /><br />題目裡的內容會有一個可以連線到咖啡機的apk (joe_v2.1.0.com.apk)檔案和咖啡機APP的相關儲存資訊的資料夾(ch.toptronic.joe)。<br /><br /><img src="https://lh5.googleusercontent.com/D4AO3ozEipQxelcTlyJVvtDN9WrJfbE3eoV2t0DRudmbB7P1MQcuqUmYgF1-1pLqyBXKIpaYQrK6DCTxUjVtpQVbgTx-EUjqykikuO_KV845m4DLNN2q5_dc4wVCPTUvYuHhERsPRCi6tV6o5A" /><br /><br />二、解答<br /><br />將joe_v2.1.0.com.apk解壓縮,然後將classes.dex透過jadx反編譯。<br /><br /><img src="https://lh3.googleusercontent.com/BJnwnKT5kJAzJcWl2zOG8o4uXrkS4wEXQHDtbP-TNZpen2JBVJFiH7wUBuy5um3pkwzC3T5Mu3IPlCWH6euBCFyldwugNHn7-VHebVECTXFWtyPBkZRgb8mA-6o3WGoYu3ALPuDZ3E7dJwTecg" /><br /><br />從題目得知APP連線方法是使用藍芽(Bluetooth)連線,因此尋找相關資訊(包含class name、method name、field name等等) 。<br /><br /><img src="https://lh6.googleusercontent.com/wYAxSWfXmoVQif3m-9N0raCYaATK6awJIiev-wlKlLz8sw5d4AdIgtdIF031pHUlal8k1wsFGVHytXjmdntg-6AEcRnHd3mRHanJ1Kyu-rEhAI4hOzT9cz3ydfYYsQomLqquIIKOPJtFQjrwBA" /><br /><br />從onScanResult方法發現CoffeeMachine相關的物件,並且分析CoffeeMachine 類別結構,找出與藍芽連線相關的資訊。<br /><br /><img src="https://lh5.googleusercontent.com/3BJsrLlPcokdOrXffa0qUvgoj2UVR0hQQ1LTo4ylnWITDyL5y_ugdY1UxR59_dddMJf-lpoyJNHaaEuFH6k3ayVsX1keeqPYwFsXmdEPXQsLe91LVt0AmVkClI09zQIh6auuJkY5qhda9wocsg" /><br /><br />在CoffeeMachine 類別中找到與藍芽連線相關的資訊(String pin)。<br /><br /><img src="https://lh4.googleusercontent.com/xAoyX7ltJQyhjbZiPKwso-BHaZgzuurII674UzJ9jwxnQdXtqe6M7XDfvBysuImDfSOU_o4TRrZua4RknUUbHXd0fZAfLS6oyvoPgwe044umwEv7hLBujccwLvFU2aY-LXCHMAGWgdqjzLR45w" /><br /><br />搜尋pin成員找出相關調用方法,從中發現CoffeeMachineJsonSave類別的restore方法有調用setPin方法,並且進一步繼續分析。<br /><br /><img src="https://lh4.googleusercontent.com/jm9raDP1YcbdsAqBmeC0vA6idzUElFxis1eGEw6qRY36XGoNh8AwZ1cZUdRwsMxR6-HuElQCORu-Kd6wn_HqWAilvsJx9mluXVOvh0U0EtHy4czrD1Uo-P7dD60CDpQ2UxImeOe8qBxHLi6KmQ" /><br /><br />我們知道setPin是設置pin成員的方法,因此可以搜尋setPin相關的調用。<br /><br />除了restore方法裡有調用coffeeMachine.setPin,另外CoffeeMachineJsonSave類別中也發現有個setPin的方法。<br /><br />我們持續分析此方法,可以找到pin的解密演算法(pin xor 3) – 1。<br /><br /><img src="https://lh5.googleusercontent.com/96p_9CdpVIyftGKYxxneVPs4DwRri3RozNZIloXhHp95q79XckEYBTkJrilo9jyTJggnEeeRFVkfL3G4hbhnHGgPgO_EkoXxHfasjmOeZ4h4w0VxvLzf4d4W1op5suvmGud1_v_VyjSYzrP_BQ" /><br /><br />找到pin的加解密演算法後,我們繼續找出它的密文會存放到哪一個檔案。<br /><br />透過搜尋CoffeeMachineJsonSave類別,可找關聯到一些方法。<br /><br /><img src="https://lh3.googleusercontent.com/N7dWgD3_73g7SjxLuWZbVTxMSs9p8yqOQHKFS7gaMBvF-HV73s8D6z8KzTcmiTgdv1Mu2B-UJ59JJE0_ABsq960zxuSAITi2RYQF6VgTuFLc3XLuDFQyCzLVLG3L5mZnWfOeCmrU1FF37KWw3g" /><br /><br />分析m7506c方法會發現,setPin執行後的pin資訊將儲存至外部檔案。<br /><br /><img src="https://lh6.googleusercontent.com/sjsV769IYi81nE0sQmA9CMqQKeW29Em2m_iGR8Np_jwJy1kx-NHTu448gH_MuViLYHBkF0QuPOHC75OVd0xrDDHVj51uAuQl1CKUXeB_YTBopOMXzCDc3XGoxSHz3LNX8CDpwPpKv387pN34zw" /><br /><br />分析coffeeMachine.buildMachineFileName,它會藉由調用getUniqueName和getMachineProductionDate來產出檔案名稱。<br /><br />在getMachineProductionDate會獲取Data相關格式字串,而且最後會是json格式的檔案。<br /><br /><img src="https://lh6.googleusercontent.com/crTQ28qSXqPPnnpBBOkgHJHz51NqtpBkGxI_rYLbjdoJGbQvhrOxsKRB5hl8gXEzWFblAigbke3YLygJw2chXo3i_WU-Q6iC_eATrF4rjzyuV5rN-QnXG54ZnnCPIuSvSOU5Y1to0yD26_IZNg" /><br /><br />由題目提供的資料夾ch.toptronic.joe中找出內含JSON檔案的資料夾。<br /><br />經分析可知檔案名稱為日期相關格式,於是探索2019082153280.json。<br /><br /><img src="https://lh4.googleusercontent.com/2F6fBHy4NGG1dnmJv6yE-cuYS4i-M-x168fdE0st7ZFEUNQHnTQq9gTtwjIhGWWBj9oqrT0m1MyQhZRi1wZU4q6nNPYudDTR0SEbS7bEiewCLqLIZix4iCNvVCDmLAAAPWjt4nt6vk10lLBxCQ" /><br /><br />2019082153280.json檔案內含pin欄位,猜測即為藍芽密文。<br /><br />透過運算下列解密演算法,最後方可解出真正的密碼,解密演算法為(pin xor 3) – 1。<br /><br />(1 xor 3) - 1 = 1,(4 xor 3) - 1 = 6,(9 xor 3) - 1 = 9, (5 xor 3) - 1 = 5。<br /><br /><img src="https://lh4.googleusercontent.com/WjWw26jDx7y4xnUhZOmmDFBbMqJZDBvg6-rPINjDsSgdCvr2f7UYkuF3vxlmXMHUz6PW5rzBEGWsrdYh5iVx3CHTdwN_hy7Av1mVQv40zXGoU9SdC6ToxK9J6bRMojMHTxkV-t8u" /></p>xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-80720937781416480522020-12-21T19:09:00.001+08:002020-12-21T19:09:18.431+08:00109年金盾決賽 - Format string attack<p>今年的金盾獎決賽有增加特殊的題型,例如IOT (Internet of Things)和教學題,其中教學題的目的在於有參與決賽的學生,如果解不出此題型,可以直接點選詳解,就會顯示完整的解題步驟,達到教學的宗旨。此題的教學題,是要利用Format string attack的技巧來獲取flag,難度差不多是介於中間偏簡單,如果沒有解出此題的同學,還可以再挑戰看看,亦或想要多了解金盾獎決賽題型的方向,也可以研究一下。<br /><span></span></p><a name='more'></a> <p></p><p>題目下載連結<br /><br /><a href="https://drive.google.com/file/d/16Fmmql-KTBvuyRrjHP2tWfAHcuSvCuWo/view?usp=sharing">https://drive.google.com/file/d/16Fmmql-KTBvuyRrjHP2tWfAHcuSvCuWo/view?usp=sharing</a><br /><br />虛擬機下載連結<br /><br /><a href="https://drive.google.com/file/d/1UMW7wuNDBjzfWHZuHELI4XxR67jcw1eN/view?usp=sharing">https://drive.google.com/file/d/1UMW7wuNDBjzfWHZuHELI4XxR67jcw1eN/view?usp=sharing</a><br /><br />一、題目介紹<br /><br />直接執行題目或者連線到虛擬機上的題目,會提示大家要輸入account,輸入完會出現輸入password的提示,最後會顯示是否為正確的password,主要還是找出Format string vulnerability,並且撰寫Exploit code來獲取此題的flag。<br /><br /><img src="https://lh6.googleusercontent.com/JmxuQ39QmwPZJaRJrRXb7EfrEiA2_3H-mgSOK0cpq4pYwcTRz8DnYCBfD6HKFQawcLm2Nbt6-HQNpO5Q9VJmlasCdrxfNoubWw8AcaXRBsbVvHHOMt2WHqI31JMqCgwhG7dz9RfpidemAl6ymw" /><br /><br />二、解答<br /><br />我們發現,它將[ebp+account](account的輸入參數)的位址移到eax,然後直接調用printf,因為account的參數是使用者可以任意輸入字串,像是%d、%x、%n等等,所以這邊有Format string的漏洞,不過有一個前提條件,在輸入account時,需要有@的字元,不然它不會觸發Format string的漏洞。<br /><br /><img src="https://lh4.googleusercontent.com/Qk_ZLhEaviOp14OTbxaPVENjey0XGC0XnY8yyndkqFuKVGZyybehL6MERBZuH-wzpbXaITPoNimyTU8Rkjqov8kUhXHlAptS8RZhxng_Om8uYr1S12rYdgSePl23xso2OTohBBWp_wXRVEly_w" /><br /><br />找完程式的漏洞,其實還不能獲取到flag,因此要想辦法利用Format string的漏洞,所以繼續往下分析,接下來它會輸入password,然後會透過strcmp來比對字串,因此我們可以覆寫strcmp的GOT(Global Offset Table)來達成我們的漏洞利用並讀取flag。<br /><br /><img src="https://lh3.googleusercontent.com/V3IDrLJhqcDMABJgHl3tPo9MH91Tv2AJ-_WWPFywngtcX1NxGcafLsgp95YZXRxojPKXSpMvOfqqygNHj7Ss5kOGwWeRvixdACFuFg7sgPiZkAYbntAIjh7Tk4smwkrlY8thWDDfKE5mpt0n4g" /><br /><br />在調用checkInfo之後,會利用system(“exit”)來結束程式,因此我們將strcmp的GOT替換成system的調用函式位址(plt調用位址),這樣就可以利用ls和cat指令來查看flag的內容。<br /><br /><img src="https://lh5.googleusercontent.com/J_nqkrNfqZJjP4NIuQmJgBpHkbNqMcFKjM2qBjjSAc_WwMvE1LoDZ8eLkDoSrFrfqW524rPMpx7XjCVFJ1Aqpf-JFplp_XGTxV3GaUhHEN_il5I3wDKSxwBXp_p2V4RP4t0m2zGngqwp0to8_w" /><br /><br />輸入AAAA@%x.%x.%x.%x.%x.%x.%x.%x.%x,得知輸入的AAAA會在堆疊的第8個位置(41414141)。<br /><br /><span id="docs-internal-guid-b31f961b-7fff-7b30-03a8-e0ec95fbec78"><span face="Calibri, sans-serif" style="font-size: 12pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><span style="border: medium none; display: inline-block; height: 95px; overflow: hidden; width: 493px;"><img height="95" src="https://lh5.googleusercontent.com/LJO_HsbbM-b0sdoMHFOVmMh3-E0uSntGWhadgn8KJjNUnuNbhC2ZtFimf6DaC_2wogW3_HZeWaWl28wvXD0nVL6pUJES8fY6LUV7bGuDyekPsypIRudJJKLjnFN9AGZwLO7v79bupY01gz94dQ" style="margin-left: 0px; margin-top: 0px;" width="493" /></span></span></span><br /><br />使用objdump來獲取strcmp的GOT位址,得知strcmp的GOT位址為0x08049a4c。<br /><br /><img src="https://lh3.googleusercontent.com/GJZT8fVHeB_6CiUvI9rDuBydXf8D063d4wpI-5-la4iK9JWyWhw0qw3nzc6S9FDTdBdJBVSGX8d0VSts3OAfwAr9AL8a30-WLvpC6fjLXvS5YGdmiOOO9XEq0PmqYMz-7WZc82IcIzol9RuCiA" /><br /><br />利用gdb查看調用system函式的位址(調用plt位址)。<br /><br /><img src="https://lh5.googleusercontent.com/2MNkzq9rF9pYziMrxbDWiEa1XfnHpVk61kfL5V2S80WsCLs0n1hS0YWXFG-bRhn8VUfEnvvooiopg7QsH2D7BrPhRwYHXA7pmxLrRleKLoCHF530M1DR3o6jmWtfnW2XQJvWpmYcnqEwteBnKw" /><br /><br />最後建構的Exploit字串如下。<br /><br /><span style="color: red;">\x4c\x9a\x04\x08\x4e\x9a\04\x08%33820x%8$hn%33760x%9$hn@</span><br /><br />Exploit程式碼下載連結<br /><br /><a href="https://drive.google.com/file/d/1Tyz-9k4XUEX5uc2g1UXpQVSQC-tcKoS_/view?usp=sharing">https://drive.google.com/file/d/1Tyz-9k4XUEX5uc2g1UXpQVSQC-tcKoS_/view?usp=sharing</a><br /></p><div><br /></div>xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-43521576391014187172020-11-10T23:25:00.000+08:002020-11-10T23:25:04.985+08:00Android Unity - Code injection<p>之前的篇章有提到Unity程式碼的修改,不過僅限於修改已存在的程式碼,這樣靈活性就會非常的差,因為如果要增加自己的程式碼到Unity裡面,以現行的做法是行不通的,接下來要介紹如何在Unity程式碼裡面,插入一段自己的程式碼,來改變程式運行的結果<br /></p><span><a name='more'></a></span><p></p><p></p><p></p><p></p><p><br />一、找出關鍵程式碼區塊<br /><br />這次的範例沿用之前的小遊戲,一樣是讓遊戲的子彈無限輸出。<br /><br /><img src="https://lh5.googleusercontent.com/6hr3N7jWHHK57ZHwfCcse4BJV1SDOOYUON4yEsTS8p8_PXAcnnfHLT8VPryKmz2NcDjNC639Rle_Cc76hQ2023DxPpkxXNU-Yvu-apaX3CGy4fPgF6D0t5FqPCE9u2YsnOVr9D7r50lOv8XuDQ" /><br /><br />我們一樣在assets\bin\Data\Managed目錄裡找到Assembly-CSharp.dll的檔案,不過這次並不是修改裡面的程式碼,而是注入程式碼(Code injection)。<br /><br /><img src="https://lh5.googleusercontent.com/rKEY6yXsxumxkEfG5KRXqIg1tLRoKx6rwlAwJ9kFldIA5fWV7hfT49B681DQvEh1lUCjQKd-I1QMn9rKIEwkos1QJnbTtZlLTvrPYJaJZMCT1T7DsAOAld2OtRKP7dD5tItexCSpjr2mV76pjw" /><br /><br />這邊是原始的程式碼, 其中--this.shotTime是遞減、++this.shooted是遞增,如果this.shooted到達3,怪物沒完全消滅,遊戲就會失敗並且結束,那麼接下來我們就來透過程式碼注入(Code injection)改變遊戲的勝負條件。<br /><br /><img src="https://lh5.googleusercontent.com/R6FMHNqX34Fj3BtpLgZLDWyxIh7hrcxnjfn5dBdBV8p_2ieuUqbKQ1qdoZcMEoaWT59vmeNlHDxR_m5HmdHpLYl5g_s1sHVtthu1SkFsvRIc5NafzKkbRjpHfZHV7wIPuvcOS9hKWs23xlV0nw" /><br /><br />二、程式碼注入(Code injection)<br /><br />我們在原本的程式碼下方,注入我們的程式碼(++this.shotTime、--this.shooted),這樣就能完美的抵消this.shotTime的遞減和this.shooted的遞增,一樣能讓子彈無限輸出。<br /><br /><img src="https://lh3.googleusercontent.com/bCZC6G9rxQSoQr63wx7irdg8YGh5MrwFo6uAYrbeitvV8WIqIW-xf4IdBdw_ztc3Bf4LCxWJtNz1Lzv5Uisb7_WvgEuwFovi28jPJyCh2ybZvHe1Fe7r9CMRI6eKr5MdvPp0GVfClTbHAdYfvw" /><br /><br />三、運行結果<br /><br />程式碼注入(Code injection)到Unity程式碼後,重新封裝apk檔案,並且安裝到手機裡面,我們也能跟修改程式碼一樣的效果,而且又比較靈活,不會局限於現有的程式碼。<br /><br /><img src="https://lh3.googleusercontent.com/Zj6O41Ua0qxYSNUOfN9TUUXPYeCpKY4GoO4sAUOb1iKWeMLbZGwxlbmhMD0DFUQmOs5M5enNhSO1siVya7Q60mZZBROe1hNidqwoxb6TEAory3Xgdfju59_cahlkJUj9ND87QVFBUyK8TBqaPg" /></p>xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-36728577074494638842020-11-01T22:22:00.001+08:002020-11-01T22:22:34.326+08:00Android Unity - 修改遊戲程式碼<p>Unity是跨平台的遊戲引擎,平台支援包括Windows、Linux、MAC、IOS、Android等等,那麼此篇會介紹如何修改Android平台上的Unity遊戲,讓各位了解,在沒有任何的防護裝置(Packer、Obfuscator-LLVM等等)的情況下是非常容易竄改程式碼。<br /><span></span></p><a name='more'></a> <p></p><p>一、找出關鍵程式碼區塊<br /><br />此款遊戲是射擊當前怪物,只要在螢幕出現的怪物都擊殺完成,就能到下一關卡,每個玩家會有3發子彈(Left),如果射完3發子彈,怪物還沒被完全消滅,遊戲就回被終止,並重新遊戲,其中Shoot是記錄目前射了幾發子彈。<br /><br /><img src="https://lh6.googleusercontent.com/9M8lO8WMHWau1yJd_V74O4MhLSh6TnKzODfMrR4SlcWH-UEbekljOY-umrBsOdnPXJ98kjx6HwGUNxtqxSHDTyEW-rLiqSWJZpwZo3qek2lAf4TN5EF2h5Av-Y4RuXnq9_3bcQjp0ALuFt1diw" /><br /><br />了解遊戲運行方式後,我們需要找到Shoot和Left的相關程式碼,並修改它,這樣就可以無限輸出子彈,怎樣都不會終止遊戲。<br /><br />接下來我們要知道Unity遊戲的主程式是放置在哪個檔案裡 ? 我們可以從assets\bin\Data\Managed資料夾裡面找到Assembly-CSharp.dll,它就是Unity遊戲主程式。<br /><br /><img src="https://lh3.googleusercontent.com/_I_ec3fg2tgmsgo3qkal4rOK550r2fD5sAUH-B5oQ-Tm4CNe7ygw_KqlWBhpasTDCeQDNyg5ryfFI_moyZj8c-nvY0G1Zp7dqP_pkPeBbiqW8pbQKWBK48Y2_jb2UobwGxp3HxYcmM9Dr0JNGQ" /><br /><br />在Unity遊戲程式碼裡,我們找到射擊相關的程式碼, --this.shotTime和++this.shooted,只要將其移除就能完成我們此次的目的。 <br /><br /><img src="https://lh4.googleusercontent.com/T4x1lqNJGyMs_dUv4w1i-R31SfekzphcIwVnUS1wNLJdWlu-ToH3R9awhNTB1WPYOwN9M13zgane66Q3pQRXnQcmepFDvpUqkmCq0NO9b44gb0l-58pwGqdZfgbRn1PR8MV5RmqJ9vrg0G37Nw" /><br /><br />二、修改程式碼<br /><br />將--this.shotTime和++this.shooted的程式碼改成NOP,修改完成後,再觀察程式碼,就看不到這二行了。<br /><br /><img src="https://lh5.googleusercontent.com/pUYKt_2F0GaVXq43R18Zn3jY5KdIqT5bOhjXhbqz0yVJLU8dm14ZZ7iMt5U3RQtlsCxP4QMObgREZJGi5xVdpnARySl0cMmGqg9qScrnKXtKUbM-_ojbEW4JKFl-GVHqgefKjxdPbHsc4o-zDw" /><br /><br />三、運行結果<br /><br />修改完成Unity程式碼後,重新封裝apk檔案,並且安裝到手機裡面,這樣我們不管怎麼射擊都能讓遊戲持續運行。<br /><br /><img src="https://lh4.googleusercontent.com/mkw2fA-808smFO7-yg_WrsV-Y4FJFyPucNH308N8-5De5TMuonzk_ZV3pzj5G2lW1kDtlxdOIs6PvamdrZtfF3R3rmpF8HVtJ-B344aHmfeDyWiteTy0-HqykfWcmUz_Ey8zfLk_cCqYPvFQ0w" /></p>xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-20905811619162040242020-10-26T23:30:00.003+08:002020-10-26T23:33:01.685+08:00Windows 7 x86 - Hooking SSDT<p>之前的篇章已經有說明什麼是SSDT(System Service Descriptor Table),接下來我們要做更有趣的事情。此篇的主要目的是要攔劫(Hooking)OpenProcess,然後讓計算機程式(calc.exe)運行不起來,並且回傳存取失敗,最後實現控制OpenProcess的存取限制。<br /><span></span></p><a name='more'></a> <p></p><p>* 32 Bits和64 Bits的差別</p><p>如果想要在64 Bits去Hooking SSDT的難度會比較高,因為SSDT並沒有被Export,需要從初始化SSDT相關的記憶體找出它的位址,甚至有PatchGuard在檢測Kernel的記憶體是否有被修改,只要有被修改就會讓系統崩潰(藍底白字),因此必須要繞過PatchGuard,不過新手要分析PatchGuard的架構會非常困難,因為它初始化是利用除法運算讓商溢位產生Exception,然後初始化並運行DPC(Deferred Procedure Call),並且定時檢測Kernel記憶體是否有被竄改,相對32 Bits就相當能讓初學者比較好上手。<br /><br />一、獲取SSDT起始位址<br /><br />在32 Bits的系統裡,SSDT的結構有被導出,它的名稱叫做KeServiceDescriptorTable。<br /><br /><img src="https://lh5.googleusercontent.com/FL5p0XXsXSc4Ns_GeIZcFHvphX-iLqWbKCT7i6rt76dON9gU9gJu7PvEKHoRoK0GREkkOy376UVVDky_Rb7p4PGBeL5S2vVBl9yl_njKUIZwOT9xJLtFAfUQUOf3IdvB0wyWsaigsgvlRFq7VQ" /><br /><br />獲取SSDT結構位址。<br /><br /><img src="https://lh3.googleusercontent.com/HNdP28nNKC1yLInqIUfb8C7TSsaGXbsHPbRn0RLuScYkpyuMva_V9MEic1fjpUvYdYl235-uYQKhjJDmy1TA2UlmtzR7DgEFFdY3NL7dJUyEzC079YVgYeUAiQkTLt3BkONLZbxE3LHRy0OQ9A" /><br /><br />其中ServiceTableBase就是SSDT的起始位址。<br /><br /><img src="https://lh4.googleusercontent.com/fO3IwDGsZbnpSG44c_H2Na0i30EQWuo1IE8DigPg6LO_cSdBEzNyqfuqQNqURYdc_UrEukK3jB_iuFWeTu6fo_SxwK9U_vulmBu14SsTpLJrV-5lSh4WHxF66RsnGRikxdIttBvz2x3sgdxeBg" /><br /><br />二、獲取OpenProcess起始位址<br /><br />因為我們要知道OpenProcess是在SSDT的第幾個位置,這樣我們需要知道系統是如何調用它的,所以我們可以觀察ZwOpenProcess的程式碼,從而得知,可以在ZwOpenProcess的位址加1,就能抓取它的位置(0xBE)。<br /><br /><br /><img src="https://lh5.googleusercontent.com/5w3WNCZfuf1_J9mSjHTvV2SDPinWaAjJOAgXQexJvWKIkwZnnyG9Te9KiDKRgkoPCPuhAluGBLrruBNg5D4LhPpPIZYyPRmbUfVpBeEcu0wAjWJ7LjIBjMlpA8H94CsbX0q5c2bc4c0DfVpwKw" /><br /><br />SSDT的陣列每格是4 Bytes的長度,因此需要位置(0xBE)乘上4,然後再獲取OpenProcess的起始位址。<br /><br /><img src="https://lh6.googleusercontent.com/32SCuPGUuhH5P1Fm1nZfOA3J1qAKuYbuyo42D70Q3EynZYgZfvpjDYBwhMjiHQkfiriQEywggz4KqXc5E4rBdoEbP5T7wN2kcqGx9497ifBtlrAi1xHTj2nHgW4hsOOasZGenz8X4CJ3wNwi1w" /><br /><br />三、修改CR0 (Control register)<br /><br />如果要修改Kernel記憶體,我們需要改變CR0(特殊暫存器)的第16 Bits數值,它是決定是否可以寫入Kernel記憶體。<br /><br /><img src="https://lh6.googleusercontent.com/eUuwJ32KfW4pwkleN3qtTFURYW1LG1VJndwUnv6gR2x5Rpr6iGtz3IbtCMx2leakcPkI0kvlg_XgODRmOyErXeoRblnuwKQVpjdqmE1n579D-_aCx2-lJXJCWZohshGA8MwKJbleH0Gv7MEZvA" /><br /><br />四、Hooking OpenProcess<br /><br />Hooking OpenProcess,只要將SSDT上的OpenProcess的位址覆蓋成自己的函式就可以達到此效果。<br /><br /><img src="https://lh5.googleusercontent.com/ZvxRn_uJhyIF8lCYGBwFMgoMja9gX_GwyZQuaA7b81enjAIZLxVC2xZBAGezYpiG2TAecVriW_Jj38dCpOT_JRn6V7KoxAbEPIJjsAy5LosdTsCt-L_G8D-dvV-I-zqFacMNwm9AiDSYfjvmvg" /><br /><br />五、控制OpenProcess的回傳值<br /><br />通常在Hooking OpenProcess時,我們需要知道當前是哪個Process,因此會利用ZwQueryInformationProcess來獲取Process的名稱,這樣就能讓計算機程式(calc.exe)運行失敗。<br /><br /><img src="https://lh4.googleusercontent.com/Ecnae2XAzb8t2y5LeviHUii8KYzru501kGWiMJOkOtezaAeSK2HfSesVjfyWNBLrjT95S5872fchYTPRExtYJwKgg081UkZs2w5HAJlb9AUvtFUX4ZgT0NsOCq_F0vOIpd2nJV8Rbg0c-yiK_A" /><br /><br />六、執行結果<br /><br />在運行計算機程式時,被我們寫的Hooking OpenProcess偵測到有被運行,然後將它強制關閉Process,這樣計算機程式就永遠運行失敗。<br /><br /><img src="https://lh5.googleusercontent.com/zyWQjYklmBL1tGn7dBBjH7YAswue3cOPdnH9OnKvJA16W7MY-rjcGWB0mIvbvuihnT8UDEqJxwNcQFPZI8K5O7FrLIOU8fFMFNWJFXJbyJU8zHBkbIZv687VM470jrMwpcolKtoYPriOSTX9VA" /></p>xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-6201620182639112902020-09-18T11:43:00.000+08:002020-09-18T11:43:09.624+08:00Windows 7 x86 驅動程式編譯<p>一般在Windows平台上,可能比較少會遇到驅動層級的惡意程式,不過如果遇到了,我們也要知道如何分析它,那麼需要知道驅動程式是如何編譯以及運行它在系統上,因此這篇教學是傾向於如何編譯Windows驅動程式,然後將它運行到記憶體上。<br /><span></span></p><a name='more'></a> <p></p><p>工具<br /><br />1. Windows Driver Kit 8 <br /><br />2. Visual Studio 2012 Professional<br /><br />3. Dbgview<br /><br />4. OSR Driver loader<br /><br />5. 驅動程式運行環境:Windows 7 x86<br /><br />一、安裝Windows Driver Kit 8<br /><br />Windows Driver Kit 8 是Windows在開發驅動時的模組,要先安裝完Visual Studio後,再安裝它,就能在Visual Studio裡面開發驅動程式。<br /><br />執行wdksetup.exe,安裝過程都使用預設的設定即可,接下來都按Next,最後就能完成安裝。<br /><br /><img src="https://lh5.googleusercontent.com/2eMuMbmjMflkGvpWAgdBoLFdljwTe6W4AbgPNRBxhW5stLCkZ_85V8bOfFNwbM-pGCRuh2k7U2kZ51_hG2FPIbTP9FBiMBZbhJk9xZvdoSG1G5U5Miz5yBRNrDK59mQtcTuY2ctcurZ0pqylWg" /><br /><br />二、設置Visual Studio驅動開發環境<br /><br />首先創建驅動程式的空專案,滑鼠左鍵點選File->New->Project->Templates->Visual C++->Windows Driver->WDM。<br /><br /><img src="https://lh4.googleusercontent.com/4aau3xWivFme9sXETNUGgjBOeH2lQ82R3ZFaxS-ufvm5IIW9URbMwFnd4CnUr7ngAjE0s4DRDFHRQrJkOWKRWI2db7KDgzYte7rAkHWVW1kGjbqg3jxKv8bx3UthMwVi6L73eMbwah7pvUjswQ" /><br /><br />由於我們建立的是驅動空專案,因此裡面什麼檔案都沒有,需要自行創建Main.c。<br /><br /><img src="https://lh3.googleusercontent.com/KoiR7hpiV10nctrQ5efGViWJCjfpVC6zOteVrCuK4ntbW7IQ1i6QFVkGDxs-J4q6GVX2dxSOUZuHnISDWsrppImnkHDQPOfxNoTK59ZlwLaSFGIgTLVWkHdRieHFPsKMSvg0dGlygKwmDCzFrw" /><br /><br />將Driver Files底下的HelloDriver.inf刪除。<br /><br /><img src="https://lh6.googleusercontent.com/BnzR-OhJJ0W1BDNpp13cTN12mVDG1TmTwmC-vv5xAuZXig2aZ0uOMo2pLagazAxP5ksLnx450aA6-XW09y1Fn2Rw2xwrClv4gqocCqWAtrS6jlVbzxIR4uJ3uecUvP0eZB1ncUPZoWNijL4uFQ" /><br /><br />在專案點選滑鼠右鍵->Properties->C/C++->Advanced->Compile As,並且將它修改成 Compile as C Code (/TC)。<br /><br /><img src="https://lh3.googleusercontent.com/Dxif8_NvAb5TcvdCu39eqakpnpZ3Sea4QujN6UntzlaZNprPrGapPuPStcQWe-IBoNHBWRs670e5tifmiuPaiYR94-rJmyGvHeLOeLkFFQNv3z98M6OpCFRdGEs9IoVuF3NO53hgdrq5K0UQ8w" /><br /><br />在專案點選滑鼠右鍵->Properties->C/C++->All Options-> Treat Warnings As Errors,將它修改成 No (/WX-)。<br /><br /><img src="https://lh5.googleusercontent.com/Q9WPKA5i_5kKmAzX3AhymChZTiNMzhhtwA6WRJN753nHqgqpidTFQW4NuQ078BgbG1NN0jVuxdq4qMh2vhQANHhOMTsogXTMU97UWL9cXy__pr5fLF-cnAFAKt6vo-0_dQ7kRYM1xFl6ClQpkw" /><br /><br />我們的驅動程式會運作在Windows 7 x86底下,因此在編譯的設定需要選擇Win32和Win7 Debug。<br /><br /><img src="https://lh3.googleusercontent.com/2FsY2DyRk4jVHJSC1Bar-vM26fNVXIeD7fDMIHxuNvwmAVwY76kaMZDIzlPMNdA1kJ2fJxH8alB_XgaUKyNKmIET2jTpxCoIPZFZLWclpoazXqfmaxGmoyGDOyouJFksArNjyFkSZdDMj1P4Ng" /><br /><br />三、編譯驅動程式<br /><br />在Main.c裡面撰寫簡易的程式碼。<br /><br />#include <ntifs.h><br />#include <intrin.h><br /><br />VOID DriverUnload(PDRIVER_OBJECT objDriver)<br />{<br /> UNREFERENCED_PARAMETER(objDriver);<br /> DbgPrint("DriverUnload\n");<br />}<br /><br />NTSTATUS DriverEntry(PDRIVER_OBJECT objDriver, PUNICODE_STRING strRegPath)<br />{<br /> UNREFERENCED_PARAMETER(strRegPath);<br /> objDriver->DriverUnload = DriverUnload;<br /> DbgPrint("Hello Driver\n");<br /> return STATUS_SUCCESS;<br />}<br /><br />寫完程式碼後點選Build->Build Solution開始編譯驅動程式。<br /><br />編譯完成後,在Output欄位,會顯示編譯成功的訊息,輸出檔案會放在此專案主目錄的Win7Debug資料夾底下,其中HelloDriver.sys就是它的執行檔。<br /><br /><img src="https://lh3.googleusercontent.com/siLu-NYCV-UZ8OfxdSBbEUBEO3ZYW4puBz9tpAk2oKtDN29xopotupOPB11DMdCcH-INXuqUIkwRE9FrknGfgmjjzTatJgVK6JDpy6IN0UBhAHGCKVJ1cy3CoQwgf1T8n6JmxF7YXr175L3h5A" /><br /> </p><p>四、載入與卸載驅動程式<br /><br />載入驅動程式我們可以透過OSR Loader工具幫助我們完成這項工作。<br /><br /><img src="https://lh6.googleusercontent.com/rAAB_RBjsgpKsMjiZGWCbuOiPn3m2k4Vk29XB2J1Z0Fv2Oi79vkItDKt4MaUX58mvhjgf6yi8282zjISwXxWoLTZ_z48GZDKyIhzEoSbENBv231PQnA1Ubk-FCVV7o4W5lxwC85zYnK9abhP1A" /><br /><br />執行OSRLOADER後,滑鼠左鍵點選Browser,然後選擇要載入的驅動程式(HelloDriver.sys)。<br /><br />接者按Register Service,出現操作順利完成的視窗後,再按Start Service,就能順利載入我們的驅動程式。<br /><br /><img src="https://lh6.googleusercontent.com/WrNJBIO5BpfVIJPklN_wl6KVnvcnkbUuhAeZDKy_TzIYCacUar966KkVOfKDWjVraCeHIb2s4bSduXRPPnYI5KY9hbTjAQr4LSJ987D2iDKREbzG8-sSzVWf3671MpSwM_O1EXGa89hfZTwksQ" /><br /><br />如果想要看到驅動程式印出的訊息,我們在運行驅動程式之前利用DebugView將它的訊息印出來,不過需要設置DebugView抓取資料的設定,將Capture Kernel和Enable Verbose Kernel Output啟用。<br /><br /><img src="https://lh4.googleusercontent.com/e5OimgeBwYar_ISawFxIzigWR5GXnGvH2IYtTkc0pgvXJN6j0z_Bh_s8x3yc41nFFuprUm_370MXIJ5sIuhHrpnCppCkRYsJ3QjvF7A7rnKNp672cwtW61WiUhbAj-K00pvYnDeLPx122fWD1Q" /><br /><br />在驅動載入後,我們可以看到它印出的訊息。<br /><br /><img src="https://lh6.googleusercontent.com/kaokjDSF_8G-_hsUiFZVI835mlmN5vNXT0mtxMwQ4kKVO_awm_TOOCkyFMVO7Z0TpW6ULZTUEF2JmwkGy8kMgApFFuDm2IiWSWSvkSCOPYqejEQmk-jRIt0yyrPmfTBzrgnTMk_bZenl74mrmA" /><br /><br />如果要卸載驅動,一樣也是透過OSR Loader,先讓驅動程式停止運行Stop Service,然後再執行Unregister Service,這樣就完成卸載驅動了。<br /><br /><img src="https://lh3.googleusercontent.com/IPkvv_7RMm0HtjPSQ_fHw9OZR8kbGmv0FxXNkv186YqC5xhEkm2N20D_BB9f96KkF9-0HohFM3637DGrivY7n_JBjD18O9MsTQ3MFQ2BJkfYhDjTDjmimiNAZ_icIm5lbgyoruIdCat-8_5qJA" /><br /><br />在卸載驅動後,一樣能看到我們印出的字串。<br /><br /><img src="https://lh6.googleusercontent.com/_2-dxaa_TZrtS7etenrifaIxaDDstkBRry5NSR8sx5xsgbR99-hLjtNt7zMLyQ4PFcweZ87d5pp6vhdXqUiyWWck3CJ-3Z7Oxwt_KGMpPBmx6jIltuIElSfvsVC7XcYO5M3w2diDbOXcaHgaFg" /></p>xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-912260504958533002020-09-03T00:40:00.002+08:002020-09-03T11:03:46.639+08:00Windows SSDT(System Service Descriptor Table)簡單介紹<p>SSDT(System Service Descriptor Table)是Windows kernel非常重要的結構,一般應用層(Application layer)在調用API時,會透過DLL(Dynamic-link library)來完成它,不過最後還是必須要讓核心層(Kernel layer)的API來實作,因此會使用INT 0x2E中斷指令來調用SSDT裡面的API,所以這樣就能不讓應用層接觸到核心層的記憶體又能告訴核心層來完成此功能的運作,接下來我們就來分析SSDT的架構。<span></span></p><a name='more'></a><br />一、尋找SSDT起始位址<br /><br />使用指令dd nt!KeServiceDescriptorTable來查看SSDT起始位址,其中0x83e7b6f0就是它的起始位址,0x191是SSDT裡所有API的數量。<br /><br /><img src="https://lh6.googleusercontent.com/U96FZ3arrJ_dBgBxru9wgoooda4lSdtmqEFDomoWAZ2KMIu9xqixFy3j4pUERSBdpMVCJyiUSG4uMhknHYxzP5Ahyvz_hlzGfY-XIylm5vQRrxa665AUOkenu22lPR3wlF_kKPqGe7WuxsKhqg" /><br /><p>二、Kernel API</p><p>這些API是運行在核心層,因此我們稱它為Kernel API,利用dps 83e7b6f0 L191來檢視Kernel API所在的位址和對應的名稱,例如nt!NtAdjustPrivilegesToken的起始運行位址為0x84010875。<br /><br /><img src="https://lh3.googleusercontent.com/ElAXdIHS4A-s0X9G78rfqz-W42XPlpupluYO6iDVJqzlAidq4JzolUCFf91hDXDfrSfuuKHDrBmtoFR7TxGtA4cUnYUWBYa-Wcx81W80buth2op_9GmjV0yweGI6mL_v_EYHyfD-7Yh-OVNXsg" /><br /><br />另外我們也可以使用u nt!NtAdjustPrivilegesToken,這樣也能顯示它運行的起始位址。<br /><br /><img src="https://lh3.googleusercontent.com/WkAXb_ie4QCGRhvkA_d2GBGMiO6m-cbF-mPB9rFdnfua2dV54ZQZwk5SXBZI2-3Kx8ge29PUIqc3C5vDmh2nF62Sy-tQxzdNtexq7XDrE_IBZTceDq55byryhIAbzfj8-xcx9bAyXNq__QzWcw" /><br /><br />三、利用IDA分析<br /></p><p>在分析大量的程式碼,通常會搭配IDA來使用,因此我們如果要分析核心層的程式碼,可以在路徑C:\Windows\System32\ntoskrnl.exe,將ntoskrnl.exe拖曳到IDA。<br /><br />打開IDA後,點擊Exports尋找要分析的Kernel API (NtAdjustPrivilegesToken)。<br /><br /><img src="https://lh3.googleusercontent.com/fL_26sNZHfQN6xe4-HT_w-XGPrFMngffH6WWaeQhJSvMYr_TgZUbdZk_rEmS8jpHPaiMh1B9Cycjfcpqo6q2TfyDDY9GIJ5QTmx1so6Nhoe3efuqDeyRZwB_Iz8VbVBeN9wIXlvNXBJH_h5N0Q" /><br /><br />在Exports找到的Kernel API (NtAdjustPrivilegesToken),然後按滑鼠左鍵2下,就能快速找到要分析的程式碼。<br /><br /><img src="https://lh5.googleusercontent.com/rNxGTvezX1dQkCVM_kJyoAt6qWQUb2sXvInBC8W4furGCDzcV-yjpWDGE7Y7qH7FxDtCWjr2I48RqTzpcyxNq70DMr4Y_0C6zpi_nA1KrYDg6BlAK43g57nFu-m7RwkXrCFfVPNxr3VuK-qqGg" /><br /><br /></p><p></p>xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-43351271007199977992020-08-24T10:45:00.001+08:002021-03-30T23:20:38.002+08:00Windows 7 x86 kernel debugging<p>研究作業系統除了一些基礎知識可以透過網路文獻或者書本上的訊息來得知,我們也可以利用動態分析的技巧來了解它的運作行為,因此需要Debugger的工具來協助我們分析作業系統。本篇會使用VMware安裝Windows 7 x86,並且利用VirtualKD建立Debugger的橋樑,再透過windbg來Debug作業系統,我們之所以會使用VirtualKD是因為建置環境比較方便並且分析時會比較順暢,在運行單步執行的途中不會卡卡的。<br /><span></span></p><a name='more'></a><p></p><p>工具<br /><br />VirtualKD:<a href="https://sysprogs.com/legacy/virtualkd/">https://sysprogs.com/legacy/virtualkd/</a><br /><br />windbg:<a href="http://www.windbg.org/">http://www.windbg.org/</a><br /><br />VMware:<a href="https://my.vmware.com/web/vmware/downloads/#all_products">https://my.vmware.com/web/vmware/downloads/#all_products</a><br /><br />一、安裝VirtualKD<br /><br />下載完VirtualKD後,直接執行它,它會將檔案解壓縮,我們需要將target資料夾移到VMware裡面的Windows 7。<br /><br /><img src="https://lh4.googleusercontent.com/dp5kS5iSvBQvHcJSbddOAbn1O6DSnJE4C4qdmtNKuxvYJhp_x1Jz10GDNKQNsf70wpGk2NK5zQurDwjW6sn0V3tF2JID0OE_K31h52b0zeKkmRfiHOQ3_iGLYgqCet5qyaRJuq2szoATG8_JCA" /><br /><br />接著安裝vminstall。<br /><br /><img src="https://lh6.googleusercontent.com/Q9GWKqdKnXl87IZsyKzZMKFO86a3tzpYYY6vB_ZV6x7pe_21gSbRKfwTsxOE9myvEx6QAsnYVUmNMu8uXBCvCMbNS88G019qB1Gk-GHEOXuH12Kg-OXdyvvE7sS39yGUuVZ45WxZwlqmGFYm1Q" /><br /><br />在安裝的過程中,我們直接使用它預設好的設定,並且按下Install。<br /><br /><img src="https://lh5.googleusercontent.com/PIJaaOWLMOXBPGcAUwjAe1yxjCrenBkjOE9nJtgyNHJaP5Qu1xjwNpSlnuANhfo6-vZOZpYmpRXmVjTpBYp41TKca5j4EXlPyr68mDhs3q8rlpRSdKB4SggUr9mzsQwxlRmN3lnf5tjI42HFEA" /><br /><br />二、設定Debugger path<br /><br />執行VirtualKD的vmmon,它可以監控VMware裡面的Windows 7系統,也可以透過windbg來Debug Windows 7 kernel,不過需要設置windbg的路徑,首先點選Debugger path,然後移到windbg的安裝目錄,並且選擇windbg的執行檔(如果沒有安裝windbg,需要先安裝它)。<br /><br /><img src="https://lh5.googleusercontent.com/VcH0Vzg1hewMChcj1GHi_VVnFo0rpRpSxDgtac4DfXOn1U03wsKjoDtvyPlFN4kpl-J6H2PqPzBRpyYd4YQq-sGooN8bNx_7hoX5qusqYPDkGunTv6tNhfrNt-Ikb5oKI0d66j2cYDwPyYDPRg" /><br /><br /><img src="https://lh3.googleusercontent.com/BM-TmXxeBYUItTpbew_mVdizFWyu7FSpRo6qrgrqZKBDfrkxiqOUz5w_CM4gR60SZzbTuzwdHuvPEbefRloiqZmZsPFI8YZx_x3aQGWWrYjrx27MYZ7R5B6lV2hfx6gBHIsM17V31v16xt8zGQ" /><br /><br />三、設置windbg的Symbol<br /><br />我們在使用windbg分析Kernel時,可能會透過API(Application Programming Interface)的名稱來下中斷點或者分析API的程式碼,此時需要從Windows的網站來下載這些Symbol。<br /><br />在windbg的工具欄點選File->Symbol File Path後,它會跳出Symbol設定的視窗,然後設置下載的網址和目的資料夾,設置完後,我們需要建立C:\WinSymbols\X86的資料夾。 (srv*C:\WinSymbols\X86*https://msdl.microsoft.com/download/symbols)<br /><br /><img src="https://lh6.googleusercontent.com/Fzk1C7Z8ZKfJKzOtdgu8GYmt2s4kbLkGj5-hC9poClfW2pi-HnyAQjWTWNzBLEDiM_zxgQz3NPJaK-EriNvqTYzQgpj-fQmzFNXZfMtnnCBsKysEB6cDGKO6lTv43RIZfWWktwHJTFlCVNR7Ug" /><br /><br />接下來開始下載Symbol,在Command的式窗執行!sym noisy和.reload /f指令,需要等待一段時間,直到它下載完畢。<br /><br /><img src="https://lh6.googleusercontent.com/cmB3of3JCe5fbHiVnlb63IzOxKc9YeQa-WOSssMZJMLl169Qonz8v7cwfGfjYylmyg9yAey37uY-_2mNyPooWYIAS8ttAeugZPFc7HENxuKrJvluWGe7mE2cc9LMPEDiDcOcRVx7aXi7RT5R3w" /><br /><br />四、Windows 7 Kernel Debugging<br /><br />當VMware執行Windows 7,可以在vmmon上看到系統的資訊,如果要Debugging kernel我們需要按下Run Debugger。<br /><br /><img src="https://lh4.googleusercontent.com/RM0NTaQ9AvHFQ8W-d0WLCn6VwrgCKWomyDUJe20Du7-f7eHZ3vXux3TrlRnywCMh6bE06CE5arj_XhTpIICeqgei_lSpoKJxJp3NsSHyqdfnYspQTm_bXaUee2mYmP-1ElyUBnAQX1Lu_dy2zA" /><br /><br />在按下Run Debugger後,要開機VMware裡面的Windows 7,它會停留在開機選單直到超過30秒,與此同時按下VirtualKD的偵錯模式。<br /><br /><img src="https://lh5.googleusercontent.com/lBrZYE7oN1tn_dRZ-lyYCMIG6YAm4Ubmjhf9Zl4sToZtTvN2_fPzQk1u3MAzVGfi9OcmTW3qCXz-_0kH3X9g1Z6351lxSUUWQQbfUVF7t_ECVWUpqYjMcnEOe54W2kJhlnrxkBtd0QmAutbHeA" /><br /><br />在windbg還未接管Windwos 7 kernel,它會跳出Debuggee not connected的訊息。<br /><br /><img src="https://lh4.googleusercontent.com/TBP8_kfRcz7_nqXwg4ZVfK1pnhdB4upe7jTcSKdrp8NMl6aYf4c3tbWeTTCmxzSN2UGT35JuhR1qmWMFc3vn-RVcETDuB5XsDWyKRJQuepzPLjl2kHJYOIlC-K_CpYFlUcoAxCF9Y_VPXPnQog" /><br /><br />在等待幾秒的時間,很快的它就會接管Windows 7 kernel,我們就可以開始分析Kernel的程式碼。<br /><br /><img src="https://lh5.googleusercontent.com/Eg8qYv7jw49tANvbU5B3qskinaHQvMovC3L_T81htzOnf8b4EKqJOoFfqApE8jiFtctpzG6PMPcmvhn07lAOKZj0v8OrxpaXLwCF3kPd2CDEa4vfyMM_RRRsSO2iedrdfqgG-Ltq8pQGsrxkBw" /><br /><br />在windbg接管後,VMware裡面的Windows 7就會卡住,如果要讓它繼續運行,需要在windbg裡面按下Run (F5)。<br /><br /><img src="https://lh3.googleusercontent.com/EZZeWHbzu6zapEcdTPKM4iO1r2QyqNCgCjucH1RSwHd-ivOfTG2C0S8Lqnepe5gpbgTLrPHVPzVnBM-p5gW08qTOdisUfVLyCsVFJjSrMQTO6N_muLBXnQV6bAeAkaYLKa6XxqVZG4x4pdUNRQ" /><br /><br /><br /><br /></p>xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-59881501414774655752020-08-06T16:30:00.000+08:002020-08-06T18:43:18.006+08:00AssaultCube - 修改無限子彈<div>AssaultCube是一款第一人稱射擊遊戲(First-person shooter),它可以選擇單機跟AI(Artificial intelligence)對戰,也可以連到網路與其他玩家對戰。此篇的主要目的為如何透過Cheat Engine來分析記憶體資訊,進而找出遞減子彈的程式碼,我們可以將此程式碼修改成NOP(無任何意義的指令),這樣就能完成無限子彈的效果,雖然難度不高,但是也是能增加遊戲分析的經驗。</div><span><a name='more'></a></span><br />一、找出子彈數量的記憶體位址<br /><br />子彈數量在遊戲介面的下方,可以直接地看出總共有20發子彈的數量。<br /><br /><img src="https://lh3.googleusercontent.com/xDm3AVrQ5ySBuP_A7mKCjzcpUWnfZMkj9SSJGzFHSAI18x7dTgV4E5RLb-gkHZnXm43SVTMj8eAGPOmYJyl6qcFI84RjqbMYiPHLBZfwjXaYBM3pbJveFRAzjiJlcZZR91-uu70gG1mh_9E1dw" /><br /><br />在Cheat Engine掃描記憶體數值為20,Scan Type為Exact Value,Value Type為4 Bytes,都設置好後,再按下First Scan。<br /><br /><img src="https://lh6.googleusercontent.com/EvgJbCKMPbF3ZTYBBxf1OT9U4BY76L7fiUgst--3KD_DL3egRoAx2CHMgE1zvgpaj53q6NBGsUB3px2X16KjdJfQ5ipe4qlXYfxswggI1Wqf06dC_q948MMQAOnqx7uNW5IecC7eKg978MEeZQ" /><br /><br />緊接著,在遊戲中射擊一發子彈,子彈數量會變成19,然後再Cheat Engine掃描19的數值,再按Next Scan,就會繼續過濾記憶體位址,我們在UI(User Interface)左邊,可以看到只剩下2個記憶體位址的數值為19。<br /><br /><img src="https://lh3.googleusercontent.com/ojdhE9lfvqEMlDBHdaIb7OV8zYchH77EUQhtPaOtVsP--TC87NJB7yTZQgi4hjVdYWXA2jUjOsqxrRgiJr8Olno3huKRulls_alEl6k-yL6X7ShU1Nkbf5r2Pl81zhKtwVWecw2qpFsJBXLY1A" /><br /><br />我們在這2個記憶體位址按滑鼠左鍵2下,然後我們可以在介面下方看到此記憶體位址,這邊可以讓我們編輯記憶體位址的數值。<br /><br /><img src="https://lh4.googleusercontent.com/lGxISEPtEEKlpeiBnGXlEwvaDP9biLnGRNWgJUlG-5JWTWh_ty4S6F52fQjlkpl9ZRZouSgSl4mV7htvooQtXhDPMj5KmSjqBhFwEmnL4e6b4jDt6x2CY29tn_-XdWoBLVsLFzX9X63TmHLDFA" /><br /><br />接下來我們在0x0240A470記憶體位址的Active按左鍵一下,然後它會顯示一個紅色的X,代表此數值被鎖定,因此在遊戲裡面,我們射擊一發子彈,會發現遊戲中的子彈不會被減少,這樣我們就確信0x0240A470記憶體位址,就是儲存子彈數量的記憶體位址,而不是0x0BA27964記憶體位址,它只不過是在運算中放置到此記憶體位址又沒有被覆蓋到其他的數值而已。<br /><br /><img src="https://lh6.googleusercontent.com/HtypcDvUQlWpc3c4Tx0asSstt5aiAgOTsMyUMMygPOF1EWFvWD_m06kexwHjSYjgaCCaAuYNc2x3n_BGgqKLkSrO56o3_omjQ3n_rIVh6XeTyrXrVmOVUttpABQDtfKCK1nSSqhlnE4jJF4n7Q" /><br /><br />在確認記憶體位址是否為子彈的數量,我們也可以通過修改記憶體數值來驗證它,在0x0240A470的Value欄位按左鍵2下,會跳出Change Value的視窗,我們將數值修改成100。<br /><br /><img src="https://lh5.googleusercontent.com/TML47xWCjFIrMOF6cp0FgzuGz4rA-wAIuYC0ai-hTr3iowcEI0r2LFLYfTR41-u2LJ0qSVp3s9R6kQyfGKTPgIuEY2Y3kKfhzzbnZaeJYLxjWUgcunfmv7n1mM7W3L5V61uuPJgK6R7GX_kZ6A" /><br /><br />我們可以看到遊戲的子彈數量,已被改成100了。<br /><br /><img src="https://lh3.googleusercontent.com/ivfBrWe3t9jqHIaveQ4hF23xKbotDM4JervscrqaiT2Sm1hbQoaVJm0TMW6xK8C_oJ1GJQqiuPJQ6qeQBtLLqqkZ_1HAk854b1e4uHhbQ7e8zZc19WOjW0KTcH_9tH-Y1tonJ1O5O5JWlUwvfQ" /><br /><br />二、找出修改子彈的程式碼<br /><br />在0x0240A470記憶體位址按下右鍵,選擇Find out what writes to this address,我們可以觀察此記憶體有哪些程式碼去寫入它。<br /><br /><img src="https://lh4.googleusercontent.com/N4qNWnfOwOeKlvuhzUOV-DzwxUtvoLLOMdWv_QWtsv29H7icBc6rRgXBpBSw3eeS1wpmcRtrcb-oMkoMRVtIwHBZZs8DyhQMaZ34OXDO-eHnwBkMx8Fb7uqV_2liSlM5CD2EUgqrDq8T3gHnWw" /><br /><br />此視窗是讓我們觀察記憶體被寫入的情況,在還沒有進入遊戲射擊子彈,是不會有寫入資訊。<br /><br /><img src="https://lh4.googleusercontent.com/QkQbm9WUG2ZaYzZmlv_fS0NaoOSZY63G4TTeoyG6601EFCH4f3UGt6gmPVzyxpG6dXHz5JkMovPfb-ENEn3fK49L4QGJz2r3Gd9nCrWmecAxc0DzDWX3e6nKkamCpCTgO_Dag70fZDhylHeA0g" /><br /><br />切換到遊戲,並且射擊一發子彈,然後會出現此記憶體寫入的資訊,我們可以將0x4637E9的位址記錄起來。<br /><br /><img src="https://lh5.googleusercontent.com/kTwksCBkk01q16YxN8DWA2hvQHeB812vZ-m4CKN-17Lk-e5RPnPg8_o6l7b_ZFyZqhuMgFbPgT_rtvufq3zHiLbh-A07EXFoqyONtagH-sLvQ2KpnNXZrymtHuw_Vv9Ya9Hce5gqk81m6MGmUQ" /><br /><br />三、修改子彈數量遞減程式碼<br /><br />Cheat Engine的任務已經完成,我們先將它關閉,然後換x64dbg,我們在0x4637E9下中斷點,再讓遊戲射擊一發子彈,它就會停在中斷點,從程式碼我們知道它會遞減esi的記憶體位址的數值,此esi的記憶體位址為0x240A470,它所存取的數值為0x62,也是我們的子彈數量。我們已經知道它會通過這邊的程式碼來減少我們的子彈數量,因此只要將程式碼修改成NOP就能子彈無限。<br /><br /><img src="https://lh4.googleusercontent.com/8Ey8lnF4QJQ3IIyTdfVl2wL20psZ0aeZlPvxTnihmhJHpXKWy5k36mLVq6ltgfesoHlS_F2H4l8wKByzvRO7mOablbPWgbQssEiHzK4StaMDBPV0i2YmSoYpg6AfjqSnsL64MxRZVmn00mF07Q" /><br /><br /><img src="https://lh3.googleusercontent.com/4jZEi4Co7-dqSG1IJz5Zku2emUzUMAiBNL3NDTI411Z2g88l7HKRw3InN_bDxtpUGb1pp6uEAGYg03c-GIt-LBQyuPmEZRzpL8iSIkGE_MRzT4NKPFlaEXSToTiyGI1E90WPuiQTAFhNem_lwg" /><br /><br />NOP指令的作用是不做任何事情,因此也不會修改我們子彈的數量,這樣不管怎樣射擊子彈,都不會遞減子彈數量,也達到子彈無限的效果。<br /><br /><img src="https://lh6.googleusercontent.com/Wl3OUNF6kM546IC6sR4lPx1VmrB2TFlQw75gAVUb2exRfU38J2WBoxgJlP0D0iAQd563lYXovP1PdUVqTPZ8nAL-Dqkcm3AtlGBrWiRCeOiOIXQdRgCcOsZrXLKCCYtFxh-MvTW6zUZqtfbgNw" /><br /><br />切換到遊戲畫面,我們可以任意射擊子彈,子彈的數量都不會被改變了。<br /><br /><div><img src="https://lh6.googleusercontent.com/ia2-H6f7JKjavR8dk7Us53Uc4yCZaIEwrPeVERJlc3_-dqv_iPqMHBfWL_QfMZPI0sv6meHuhLYPGtuGtW9nbIgtVW4p1wjDhoknVpAOwowIW2KOs-kgtpQ3UZYvmULPrmeAMCLCD7y6gphu4Q" /></div><br />xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-12333012322029420622020-07-27T10:35:00.001+08:002020-07-27T10:35:52.935+08:00Format string attackFormat string (格式化字串)是程式的API (printf、snprintf 、puts等等)指定輸出參數的格式與相對位置的字串參數,例如%d、%x、%f和%s等等,都是代表在輸出參數上顯示什麼樣的數值格式。<br /><a name='more'></a><br />一、Format string漏洞程式碼<br /><br />此漏洞程式,主要是將輸入參數(argv[1])複製(strcpy)到區域變數的buf,然後透過printf直接將buf裡的字串印出到螢幕上,因此我們在輸入參數時,使用%x將堆疊上的資訊印出來,達成資訊洩漏的弱點,另外也可以使用%n來寫入資料到記憶體,這樣就能將數值隨意寫入記憶體。<br /><br />#include <stdio.h><br /><br />void main(int argc, char **argv)<br />{<br /> char buf[1024] = {0};<br /><br /> strcpy(buf, argv[1]);<br /><br /> printf(buf);<br /><br /> system("exit");<br />}<br /><br />二、檢視堆疊上的資訊<br /><br />我們使用AAAA來檢測它是在堆疊上的哪個位置,由於參數使用%x,它會從堆疊上獲取4 Bytes的數值將它印出到螢幕上,我們發現在堆疊的第4個位置有顯示A的Ascii(0x41),因此我們可以寫入某個記憶體位址到堆疊上,然後透過%n將數值寫入此記憶體位址。<br /><br /><img src="https://lh4.googleusercontent.com/Aa_cBKtaj-RqGxkxHX9hFoAHgdMI3ec5NeCFIATeMhb9cLFu7BCLkYgtEOJmRKg1yHbN4FItITNZmvcsQXCUtRVOl3pU-JcOGkUgp0oTV_dOgzuhufBQ6_yaTDX-3uZMs74VXNh3FxCGjWlzAw" /><br /><br />三、查看GOT (Global Offset Table)<br /><br />Linux在調用API時,會從GOT裡面獲取該API的調用位址,因此我們可以覆寫目標API的GOT,就能控制調用的API。<br /><br />system的在GOT的位址為0x080496ec。<br /><br /><img src="https://lh3.googleusercontent.com/8DFKPzaLg3FzLH5tqjMeo1AST6m1PsZEJuxu1zTrjGucqd-12tZjBbV8b2ZFW41lAmTtc_lClEOhx9yJfmjkywDcihN0n8GZ9xc3TrYqnYkFnFFOrCvNjFblmhcLWEzpVNhBHwlJyhqL6jTQTQ" /><br /><br />四、覆寫system的GOT<br /><br />進入gdb後,在0x0804846a下中斷點,我們可以觀察在調用printf後,是否有成功將數值覆寫system的GOT。<br /><br /><img src="https://lh5.googleusercontent.com/AAzl7ctAU_GxCHmcfwCXaAzKc061nqNeqMeBAL_jq9IHFPygdmULwwIBfbWTbgaht7lPznzaNJzcVoiJb9gELnbd20zzwIdig46BY2xkMSn3zIjdjAnkJNK6Nv_Jy6K-UcmSadKM1OwPMLVIvA" /><br /><br />如果直接輸入參數,它會在堆疊上寫入Ascii的數值,那麼我們要寫入16進制的數值到堆疊上就必須使用shell指令來讓它轉換,因此我們透過shell指令間接調用python,在參數的前綴使用\x,代表它是16進制的數值,然後我們寫入0x080496ec到堆疊上,由於x86記憶體是Little endian,因此寫入順序是反過來的。<br /><br />我們在第二步驟已知參數前4 Bytes的數值,會寫在堆疊第4個位置上,我們會在參數設置%4$n,%n會寫入數值到記憶體位址,其中4$是指定堆疊的第4個位置,我們可以看到0x80496ec有被寫入4的數值,因為%n要寫入多少數值會由%n前面的字串占有多少Bytes,從我們的例子來看,%n前面的字串有\xec\x96\x04\x08,種共占4 Bytes。<br /><br /><img src="https://lh6.googleusercontent.com/-vYuOBIE6pQaphDfZarV8-LiXdxF96HX_diQCV7NlfO65WaR5ijjKDbrNI_KD8KYO19vveloRz60iggoDndiFzUMZ0WSl13rl6DVjBu6cjM0NQRNlVXUiP9PRKtyvUnYyw73Y07T63_L-EITjQ" /><br /><br />接下來我們預計將0x12345678寫到system的GOT。<br /><br />%n要寫入多少的數值是由前面占的字串Bytes總數,我們在%x的x前面加上數值,就能增加它的Bytes數,不過它並不能一次寫入4 Bytes數值的長度,因此我們僅能2個2 Bytes來填入4 Bytes,那麼我們會透過%hn來寫入2 Bytes。<br /><br /><img src="https://lh5.googleusercontent.com/7RuJOUwZeDMEaRSu4tS4Y41tmbq0vxOSVMixL-ShuhtQc8STDdjFT1od4R80rXl9JNL2BSB8ylnDac7i6r-iabB5lCHZp2stvG-cFmFmP4IqGS0fJbXrDolNqIea_wz1uCg0Ua80LTTVbM-8ug" /><br /><br />我們要如何計算將0x5678寫入堆疊的第4個位置,並且將0x1234寫入堆疊的第5個位置 ?<br /><br />0x5678減去前面占據的Bytes數。(0x5678 – 8 = 0x5670,將0x5670轉成十進制為22128)<br /><br /><img src="https://lh6.googleusercontent.com/w7F8c79xDumu7mYKYYaDelLxyhUSR_2YH9Kq2zmRn4y5SgHk7YfCyLIn5P0IImxhXqOPd45BMGjEq4q526MK3tgwZoWs_O0naE5Tc1MXvSRk6fX9nE9kDhR5q50nimW44Ho8jfUAA_rxCJF6DQ" /><br /><br />0x1234減去前面占據的Bytes數後,會變成負數,因此在0x1234前面加1就會是正數。(0x11234 – 0x5678 = 0xBBBC,將0xBBBC轉成十進制為48060)<br /><br /><img src="https://lh4.googleusercontent.com/yYqTUMZUA_AEJiYOHnHpULECeJW_SBwrV9hAazMKmSAQyTFA9Mdcx28UwT4ZKVMCG2Pu7yQ8WibpStXrxVnx-ihKSbDVuT3uIQZdyVkbHRygIqm7D7dvL1frD7Ye9W7wpIjh5MuhlLpKEXreQA" /><br /><br />因為我們的參數有%22128x和%48060x,它會在執行printf後,在螢幕上印出0x12345678個空白。<br /><br />最後成功將0x12345678覆寫到system的GOT,<br /><br /><img height="16" src="https://lh3.googleusercontent.com/v8xfisvD7nI4g3SgqG2t7iApZrDD21vvXxJLdk7l3MRZS6mJnn-Ep4c1z7FywO-fpo7FU5hMq2R46D4HMRPAdwhyUnQwBeP-lAbdwkr1r22m80vgevIsmzrOAMIZT70inBqAJ_jNqTckqqEhBw" width="640" /><br /><img src="https://lh5.googleusercontent.com/M0GC3P91puVAqL8A2aisc7pnmw5UlBIu0qZ43nZwhkPOwmKSMFdrSdHXvpB3YIz786yDulR46eIXytF9xbWcarUIkTC56qNmzmSFV73fsD661gOoII_mY3TMfF1-9hBBp4RRfuGbK6NXAVfYcg" /><br /><br />xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-26047388011914612402020-07-18T14:00:00.001+08:002020-07-18T14:00:13.366+08:00大富翁6 - Cheat Engine修改遊戲金幣遊戲外掛的製作,也許是非常多人感到有興趣的議題,不過這些技術大多數的新手並不知道要怎樣入門,因此此篇就透過Cheat Engine工具來實作修改遊戲的記憶體,這也是非常簡單的作法,任何新手都可以一步一步的來完成修改遊戲記憶體的實作。<br /><a name='more'></a><br />一、Cheat Engine Attach<br /><br />首先將安裝好的大富翁6運行起來。<br /><br /><img src="https://lh5.googleusercontent.com/yHtpkR-6-h93l8UEYNa5O574eSjXIoyOkmyJbVLI4zfNZVIGSEgrQkaBvxyfoBsmY0CtGMpPocvVGRo0iJ9ibq1LmxAF8x2Ky3wQwvIs2RXgiFowWJz3iF8MsQeMQHNKJ-kzTFLeVRtbNbe-mQ" /><br /><br />在Cheat Engine的左上角點選電腦圖示,它會跳出Process List視窗,然後再選擇大富翁6的程序(Process)。<br /><br /><img src="https://lh5.googleusercontent.com/rXqeTCF0zFnyI-aDGMBPlJ0H9MF0cx2QQPa6F4D_DSe1Ah_LE_CBwEczodyN3TiAiDF3yGhgdDUhBdfp4sB9buDAh3I0IJLQ4dNh5XgWYYplq6ckdqWWo4LHeeNT3v6h0HThWsCA0YbMfJj8Cw" /><br /><br />二、掃描記憶體<br /><br />在遊戲裡面,我們可以直接看到遊戲的金幣,總共240000元。<br /><br /><img src="https://lh4.googleusercontent.com/kai4644yvbrK5ZsFg69bJ4KhEEM32fjTijdiCuIJSCsboHK0YEa1bup5i0_EjwEedeasixx_7XSKZDXJicyKihFQAP1Zy3zgywXjo8h2HXJ2HsqMPnFgZ1KI3H-un9nAcrFIHmf4yQVzlxpawQ" /><br /><br />從遊戲介面顯示的金幣,我們推測它可能是佔有4 Bytes的整數形態數值,所以在Cheat Engine的Value Type選擇4 Bytes,Scan Type選擇Exact Value,Value寫入240000,再按New Scan。<br /><br />按完New Scan,左邊介面會顯示記憶體掃到此數值的所有位址,總共數量有5個。<br /><br /><img src="https://lh4.googleusercontent.com/vlEkCBwwzdcmzPcH9o4gB0pxqxR5CGi3Y8LntFk6GtY3N9TZbMyoSHB9uPwrG9V2sQ0tjNWnRbnGfxupRNIuUiq8Y6LIorP5yNWmgeKMI2aTHu75EaPl6f5ZE-iIkE7E7yZegnS8yM874O3prQ" /><br /><br />三、再次確認金幣的數值<br /><br />從上一步,我們總共有掃到5個相同數值的記憶體位址,通常掃到這麼少的數量的記憶體位址,可以一個一個修改,就能猜到哪些是存放我們金幣的記憶體位址,不過如果相同數量非常多,我們要如何解決這個問題 ?<br /><br />我們需要在遊戲裡面購買土地,因此金幣就會被改變成其他數值,然後可以從改變的金幣數值再一次掃描記憶體。<br /><br /><img src="https://lh5.googleusercontent.com/7X2TEDcE61t5NKNm3ddxNrJtXDtM4LS6UfxPaTvgOCmeE86EO66YCOlaWwSI4dpIr6-293xVpaQdIjZeUteRkoot-cy62JBSIWOtbgj2DZRdSL9M2n8pgBSKvNZqDDtgJZlI9T8WPkC2DGgrUA" /><br /><br />在購買土地後,金幣變成238000。<br /><br /><img src="https://lh5.googleusercontent.com/LNGev3WnOrDyfvu2fcGFdfFYZ3HRT_vPxpKuJQwOTPBzP_baetwqaF-LtUkKKm8jDnLBKTdwchxWCD3mJL6NBMLyXGKeY-17XMP5kkRkFwALev3IAzfAp7eDc8IdnDuR0VPrvcAwSRtEMaDV6g" /><br /><br />在Cheat Engine裡面也看到改變後的金幣,通常如果掃到記憶體位址的數量非常多,我們會在Value寫入238000,再按Next Scan,它就會繼續過濾記憶體,直到能確認此數值的記憶體位址。<br /><br /><img src="https://lh4.googleusercontent.com/HXuk-eGJRS7aYyTqC5a389i13x1fhfojEJeW632jUxuT3Ti6UqF6FjX9GY9WTCs9ayYMOulS9sJgZ2a8sohGxTIcfwyXi2FwsFkBC09tYiyWHDdLy5b7IySefsm3WXMY5kUs8ZgWvyF1U5UViA" /><br /><br />四、修改金幣數值<br /><br />我們從掃描到的記憶體位址,點擊滑鼠左鍵2次,它就會將此筆資料顯示在介面的下方,這樣我們就可以修改記憶體位址。<br /><br />這邊有2個數值為238000的記憶體位址,其中6884C64為顯示介面金幣的數值(它會從5244E94來更新此數值),5244E94為金幣本身的記憶體位址,因此只要修改5244E94,就能將金幣改成我們要的數值了。<br /><br /><img src="https://lh4.googleusercontent.com/9RE9GqJnyXaZG1FsrudCCVHMkCm0OR7TAiGqkQfCLY6MFDmDBwNM3DxfphaA_M0lHwlgGAgcd-bM5nbWzwqxZriYEvs7nDDDWmSwaHGsb2UwuygKvKVDxofY3LCaxUAZww7jQ7edLI0hn3gUVQ" /><br /><br />我們在Value點擊滑鼠2下,它就會跳出Change Value視窗,我們可以將數值改成500000。<br /><br /><img src="https://lh4.googleusercontent.com/4iZ7r0ytK62QZ5syAeb_p632e0k-c0msqMVredDahBR8-dwQfhnhjzv0yOxf75vX7c4Sq97nVWXF5ZnLbXnMpIySEd7Ts8aNJxNtCf4Ocy0Jvvl6QYFVu5VCiASLA7L9VJ22Jf8l41bQlB291g" /><br /><br />在Cheat Engine改完記憶體後,遊戲的金幣就成功的修改成500000元。<br /><br /><img src="https://lh5.googleusercontent.com/OTbVCqQ_uKlIlEHnRSQlYgZ5gVWul0v_4WQDeTxheEDn96iD6Z5FH-QuMcBH4Po0zrvZdMUZStn0mmupDp4iYTbjNJpF9DI4ZpV725Bk2XxRBZiYewpiF-2k6pqKIZoNlPc3aBpB0cbHVvUiDg" /><br /><br />五、深入探討<br /><br />在透過Cheat Engine來掃描記憶體,經過遊戲的互動,讓需要掃描的數值有所變動,這樣就能將記憶體位址過濾到較少的數量,也比較好驗證哪些記憶體位址是我們真正需要的,不過這些都是建立在我們已知此數值的資訊,像是金幣的數值就是顯示在介面上,因此我們可以較為直覺的知道此數值為多少,那麼如果我們要掃描未知的數值呢 ? 例如MMORPG的人物坐標,此數值大多數的遊戲並不會顯示在介面上,這時我們需要使用Cheat Engine進階的功能Unknown Initial value、Unchange value、Change value、Increased value、Decreased value等等,不過要找出這些數值,還是需要了解遊戲相關的架構,這樣才能比較精準的猜測數值的形態,另外有些資訊是比較不容易透過記憶體分析來找出,像是附近怪物的資訊、技能的調用資訊、遊戲坐標系統資訊、障礙物資訊等等,這些都需要軟體逆向工程的基礎知識才能突破的。<br /><br />五、結論<br /><br />我們利用Cheat Engine來修改單機遊戲的記憶體資訊,這也是較為簡單的Hacking遊戲,因此新手也可以非常容易竄改其它的記憶體資訊,如果對於遊戲外掛有更進一步的興趣,可以學習軟體逆向工程相關的知識。xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-15553950105848137822020-07-02T10:55:00.003+08:002021-02-19T00:38:51.640+08:00劍靈(Blade & Soul) 逆向分析研究 - 自動打怪Bot經過一系列的逆向分析,我們能從遊戲裡獲取相關的資訊,並且利用它們原生的功能來實踐我們的自動化過程,因此將之前撰寫的每個功能整合起來,就是一個簡易的自動打怪的系統,那麼如果想要讓此系統更豐富完整,還需要分析更多的運作資訊(與NPC交易、換裝備等等),那麼分析方法,都跟之前一樣,因此想要完成腳本的功能,也不是什麼問題了。<br /><a name='more'></a><br />一、自動打怪Bot<br /><br />在影片裡,我們讓遊戲人物自動去尋找怪物,然後透過技能來攻擊最近的怪物,如果怪物死掉會繼續尋找下個目標,在攻擊怪物的同時,也會判斷血量是否需要補給,盡可能的讓遊戲人物不要低於血量的下限值。<br />
<br />
<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="514" src="https://www.youtube.com/embed/1VEiInxyRtw" width="914"></iframe>
xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-67320544493693181992020-07-02T10:44:00.003+08:002020-09-04T14:32:15.847+08:00劍靈(Blade & Soul) 逆向分析研究 - 自動移動到NPC<p>在分析完遊戲的坐標系統以及障礙物的相關資訊,我們接下來要撰寫路徑搜尋的程式,因此需要使用路徑相關的演算法。可能大部分沒有接觸這塊領域的同學,也許不知道要使用什麼路徑演算法,我們可以效法遊戲公司最常使用的路徑搜尋,那個演算法就是A*路徑演算法,A*在網路上已經有相當多的現成程式碼,因此我們只要稍微修改一下,就能符合我們需要的功能了。<span></span></p><a name='more'></a><p></p><p><br />
一、移動到附近的NPC<br />
<br />
在影片裡,我們透過自己的程式,讓遊戲人物自動的移動到附近的NPC。<br />
<br />
<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="514" src="https://www.youtube.com/embed/pZn3NRzw0Ns" width="914"></iframe></p>xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-77750539621070449022020-07-01T18:37:00.001+08:002020-07-01T18:37:58.976+08:00簡易繞過Anti-Debugger技巧現今已有非常多的軟體會使用Anti-Debugger的技術來規避軟體被反編譯,因為如果不規避,可能會讓軟體被破解,造成公司的損失,然而惡意程式也會學習這些商業軟體的Anti-Debugger技術,如果並不熟悉這些技術,是非常困難繞過,因此我會推薦一些工具來簡單的繞過Anti-Debugger,不過並不是可以將全部的Anti-Debugger都能繞過,它的成功率大約在70%-80%左右,像是Integrity check和Debug API hooking等等,都沒辦法繞過,只能透過Try and error來分析它是如何檢測Debugger。<br /><a name='more'></a><br />工具<br /><br />1. x64dbg<br /><br />2. ScyllaHide<br /><br />測試程式碼<br /><br /><a href="https://drive.google.com/file/d/1f1d9wcfEgZuCtDqMWWrhdWE0sOQHBnuF/view?usp=sharing">https://drive.google.com/file/d/1f1d9wcfEgZuCtDqMWWrhdWE0sOQHBnuF/view?usp=sharing</a><br /><br />一、安裝ScyllaHide<br /><br />ScyllaHide它是一款兼容ollydbg和x64dbg的Plugin,此工具是用來繞過Anti-Debugger。<br /><br />這邊練習的範例是32 bits。<br /><br />1. 將ScyllaHideX64DBGPlugin.dp32移到x64dbg的plugins裡。<br /><br />2. 將HookLibraryx86.dll移到x64dbg的plugins裡。<br /><br /><img src="https://lh3.googleusercontent.com/Ug3JBKwk0bJHGGNl0kIZrGN-DLyXwnfuJAA06jP3QTPDxkai6JquLth-i6-9IMXv3Bm1MC_OPXYs6bUxauZ2xzNcCjVTTro-7cL4c8-MJ18RBa6OQb9T-nim29_O1Y-agczJtgbrS1pmU4ugTg" /><br /><br />二、Attach程式<br /><br />如果沒有安裝ScyllaHide,就會被偵測到Debugger。<br /><br /><img src="https://lh6.googleusercontent.com/GmQJcywEZVbyZ2PHSVQp-PgKTVPKNsFWBJnQu0AUTYCcFfRezP_O_rUsHSdl7tOgk0celKK8FcrWJwSFvldRK1XKMyDpBzCsRLN45C7c43GFjMZtSMw3pHZ6dKwW4u3E3MVm69IiHuSy1kkVXQ" /><br /><br />安裝ScyllaHide成功後,可以在Plugins裡看到ScyllaHide的選項。<br /><br /><img src="https://lh5.googleusercontent.com/cAC3Ne5gN0lA_n2ZFjGwJvrxdxAqXeGGRx847AfIClp5jOAmL1Dhdr4aqlkAobaofiUiVFIqKHfRiJnBYHJvAv9JEmsb1QB_KRalTLTEfx5NzxXmfWFTwqOcwVE7dKYUKVuvek6ukvyg5fJaCw" /><br /><br />在使用Attach的方法,有時候還是會出現一次被偵測到Debugger。<br /><br /><img src="https://lh6.googleusercontent.com/Z-ESWcHFzHV6j4nvU3PH6g7cb0K8IGgWUkbm5DamdzEh2ajER2_PaC1i30yHSnGW_g6qY_4qFZxkzsZHMedggy6-aUpQS8Kkl2gT2UZ-gqDy1pad5YraE9er4gqj_BWJ_A2JT6PaapYBNetsjA" /><br /><br />三、Anti-Debugger範例<br /><br />在範例裡面是使用IsDebuggerPresent來偵測是否有被Debugger,因此它會從fs[18]->[eax+30]->[eax+2]來檢查此bytes是1還是0,如果是1就代表有存在Debugger,所以在Attach程式時,ScyllaHide會將它清為0,不過只要在它偵測的瞬間,還來不急修改,就可能會被偵測到。<br /><br /><img src="https://lh5.googleusercontent.com/twJj6AXDwrXPjpqna_M6WaKRy-lIZnRa3V-zpPmpLGvuakSBF4xVkyP4tyETa-jCDUmzAzd3ixzRy1YPN8KaVPCZjHeGBvLtxi7Km-NtldDSaQYlzQ105jG8CbTGf-CdzXpINxAL7NCZ0y7n1w" /><br /><br />四、拖曳程式到x64dbg<br /><br />利用拖曳的方式來附加程式,就能完整的規避Anti-Debugger。<br /><br /><img src="https://lh3.googleusercontent.com/vWbziOQc4_rvRouhY7PEiaa_KIbVmqY20bWf6LR8SEkeLPK3yRzut_F5z0PPLXuEiZJfQN--tDnua0ZMO3e96qxzAePwoB1ipTdbfYKaOORj_jBTngegJ9dZnI0zRpRLORVqhmWN1PWY0Zdl8w" />xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-76068705340196152072020-06-30T23:47:00.002+08:002020-06-30T23:47:51.168+08:00劍靈(Blade & Soul) 逆向分析研究 - 人物移動方向計算人物在移動時,如果遇到轉彎,需要讓它識別什麼時候是左轉、右轉或是往後移動,所以我們需要分析人物在移動到下一個坐標前,它的移動方向是哪裡。<br />
<a name='more'></a><br />
<h3>
劍靈人物移動方向有兩種方式:</h3>
<br />
1. 使用鍵盤來移動人物,方向的移動是透過滑鼠。<br />
<br />
需要獲取人物坐標,然後自行去計算滑鼠移動的距離。<br />
<br />
<img src="https://lh5.googleusercontent.com/mnoUFoPvCtSfx5Pjiw3_cFeRMrfaNIMQbB1CdLo6Jkgev9H0VYLc_rlqV8W2J27It8e3WRqFuE9YxBnBiNL4lmHjiKjD7l8adaCZ9sWN7FP00sbV0O9j3OlA3uQKOCYIWuYu_21m5RpxtaPLCg" /><br />
<br />
2. 透過滑鼠來移動人物和方向。<br />
<br />
程式裡面就有計算人物移動方向的函式,因此我們可以分析它是如何計算的。<br />
<br />
<img src="https://lh5.googleusercontent.com/1uNoJEmDQcEUGJDqFGmhhBENJ6UwPxzvQH2kvrgQ9bAONKz1Y5SqBYlrGGNF8QqxSI4WBdcKPBFzSwKl6tRH4q0qCPkiMvL8YeArAAYw1Pj_4FkCP_7dg3w2yO0v9kPo4TzVcriMALekl0ZmuA" /><br />
<br />
<h3>
人物移動方向分析</h3>
<br />
步驟一:<br />
<br />
xmm4是人物當前坐標x。<br />
<br />
xmm3是人物當前坐標z。<br />
<br />
xmm2是人物當前坐標y。<br />
<br />
[rdi+80]是人物移動坐標x。<br />
<br />
[rdi+84]是人物移動坐標z。<br />
<br />
[rdi+88]是人物移動坐標y。<br />
<br />
人物當前坐標減去人物移動坐標。<br />
<br />
<img src="https://lh4.googleusercontent.com/6uKEx2lfyHs3bje_3XcXzDm12q9WI7QQF21ysFg4u4rA1ItveRAxGB71aOT7kIUsOLMKXyZy1eF_w7vy2xemgHq8zxMPQgMOR5o3FRXJHO7rlMkm6MbQnio2FBEV0iFNMSybJ0RIn_bnUADYYg" /><br />
<br />
步驟二:<br />
<br />
xmm1和xmm3是步驟一的坐標z相減後的值。<br />
<br />
xmm1乘上xmm3。<br />
<br />
xmm0和xmm4是步驟一的坐標x相減後的值。<br />
<br />
xmm0乘上xmm4。<br />
<br />
xmm1加上xmm0。<br />
<br />
<img src="https://lh4.googleusercontent.com/JB-ipP9R_zRNJlgp5l-I9h9xuyXTH4JFYkqJwpyomQYJ32YCUea8YyZu0apZNZBKzVdF5j5lFAUpnmlqvcHFGfx9imSpjNrCvxXO31daW-sSt3yOxYBLdt_6A0xdPaR6V_JQp8CW-FyUDzZdLw" /><br />
<br />
步驟三:<br />
<br />
xmm1是步驟二的運算結果值。<br />
<br />
xmm1平方根計算。<br />
<br />
xmm2等於1。<br />
<br />
xmm0是平方根運算後的值。<br />
<br />
xmm2除上xmm0。<br />
<br />
<img src="https://lh4.googleusercontent.com/s3HmicRm7pMa0IK9KRdPNa-o648g20ja8Nri2aZt2THH27UgBb41rxSYXw-xhhvDlkM1_0gEp-EwG9UbRYrDVc-jDWX3xfcHpCKPVA5572MuPnuZOP9Q3PcJ3vJ0kBdF7LcCXxUv4x1DIQILyQ" /><br />
<br />
步驟四:<br />
<br />
xmm3是步驟一的坐標z相減後的值。<br />
<br />
xmm2是步驟三的運算後的值。<br />
<br />
xmm3乘上xmm2。<br />
<br />
xmm4是步驟一的坐標x相減後的值。<br />
<br />
xmm1是步驟三的運算後的值。<br />
<br />
xmm1乘上xmm4。<br />
<br />
<img src="https://lh6.googleusercontent.com/fvw0xKa9Q-T_PmbRT5c9R_E6nWlrqkvZFGMO_R_tJHwj0C4R4Sk2G8pbAYcHsKqxUCILjuH4-E9DjjVeuoWonHtRAOp5fLGyGNW9lCgTHjzGPUUj1SgNxZadQzWRc46QYfUdgbeWRLkPplm2_Q" /><br />
<br />
步驟五:<br />
<br />
調用移動方向計算的函式,它需要2個參數,第一個參數是步驟四運算完的結果值(x、z),第二個參數是回傳值。<br />
<br />
參數1和參數2都是浮點數坐標結構(x、z、y),其中回傳值是參數2的位移長度4 Bytes (rax+4)。<br />
<br />
<img src="https://lh6.googleusercontent.com/eBWqPTJiwOgAC8TVfHaiq50U6SYzjBE74svf0Mp929Qw2vbZpy_6xx_wpWkkLqZpcV_KTvOVuLdwFMdyFzaRYmMwd2oLZgEKbd18WykW0QmFuedYSRPObeJuNXSGkj4eYyH23Vd3qqbG7z8jXQ" />xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-87828312672845197862020-06-16T10:16:00.001+08:002020-06-16T10:16:08.930+08:00劍靈(Blade & Soul) 逆向分析研究 - 坐標系統分析在設計Bot之前,分析遊戲裡面的坐標系統是非常重要的,因為在尋路的過程我們需要坐標的轉換,以利我們在二維坐標的障礙物偵測,不過有些障礙物只能透過三維坐標來偵測障礙物,因此需要了解整個遊戲的坐標系統的轉換才能繼續開發我們的Bot程式。<br />
<a name='more'></a><br />
一、二維坐標系統<br />
<br />
在遊戲的右上角,會有小地圖顯示,我們可以抓取小地圖的Pixel值,分析地圖的邊界位置,不過我們也要知道遊戲中的三維坐標是如何轉換成小地圖的螢幕坐標。<br />
<br />
<img src="https://lh6.googleusercontent.com/e8_A_XZxqBn5QITkH1ogmopFVcQIqVTMbGrKIk3kLS6-ggyKiyPIA9g6BDNlGLnBWAMzmvoicnczrAzpi_YIAKnUKWPPiMWt2KhUNNli4ugqsVIa0wWnJThbfgdWpmu5IXFT8UETgy3Ty_c2PA" /><br />
<br />
另外我們在小地圖上,可以看見其餘的物件,這些都是遊戲將小地圖透過DrawPrimitiveUP繪製再螢幕上後,再將剩下的物件會制上去,物件包含Boss位址、人物位址、地圖資訊等等,這些都可能會影響我們抓取小地圖邊界的雜訊,因此我們需要將繪製物件的函式Nop掉。<br />
<br />
去除小地圖上的物件雜訊後,就顯得乾淨許多,也可以比較準確的透過Pixel值來抓取小地圖上的邊界位址。<br />
<br />
<img src="https://lh3.googleusercontent.com/I2Ezo87C5T-ReWrR78nqige5wWf4QPK2l7Hw1YKm3kTzXSfrHy7-LHMRhA95wQEBqNYR_fy4pb_lB0mh7HhB5lUt2yPZiUOEG1EBT4KOvnsuOr6DJKuox2ou-BAN83C8G5ld2FNXhha7QClmIw" /><br />
<br />
二、小地圖的二維坐標轉換<br />
<br />
subs xmm0, [r9+4],其中xmm0是三維坐標的z坐標值,[r9+4]是worldScaleZ,那麼z坐標值減去worldScaleZ,是計算z坐標值轉換成小地圖的x坐標。<br />
<br />
subs xmm1, [r9],其中xmm1是三維坐標的x坐標值,[r9]是worldScaleX,那麼x坐標值減去worldScaleX,是計算x坐標值轉換成小地圖的y坐標。<br />
<br />
<img src="https://lh3.googleusercontent.com/XRIbwINA4Shx7fFJ8kgZ-B4wgBcIel_OGQ2IfPEHDR3bnQY2ZqKqRsvPpwlU7R_nCRn9zNUzqOA512NR9nNm7FLrphoKJLrLTXVrqOiaxKznTNroetOkM9uIbV6Fx_nsYDW71sj0ocSa2PTP1g" /><br />
<br />
mulss xmm1, [rbx+4](乘法運算),其中xmm1是1 / 75,[rbx+4]是上一步計算的x坐標值。<br />
<br />
mulss xmm0, [rbx] (乘法運算),其中xmm0也是1 / 75,[rbx]是上一步計算的z坐標值。<br />
<br />
<img src="https://lh6.googleusercontent.com/FRGEiZQXHG54kdDaegjPCpHw4cP3TyGUPIBUEmjFRMWdCL_S5ItgTU-wQU92dzsSx_UCWfyME_SC8OPLPh4OnLUNH9BYmfbspl8IvC4H4CLWE72XgSnDkp6ZKgCStSQ2iU8XOwkGI0uO_GepfA" /><br />
<br />
在上一步x和z都會乘上1 / 75,以利轉換成螢幕坐標,不過還並未轉換成小地圖上的坐標位置,因此在這步會進一步計算x和z值。<br />
<br />
addss xmm0, [r9](加法運算),其中xmm0是小地圖x軸的差值計算值,[r9]是上一步計算後的z值。<br />
<br />
subss xmm1, [r9+4] (減法運算),其中xmm1是小地圖y軸的差值計算值,[r9+4] 是上一步計算後的x值。<br />
<br />
<img src="https://lh3.googleusercontent.com/5ydGPNYndOJd6AecIgc_s1EMDzZSvEHYYNDVM6WWYiNGaLu0NUclozRJwXmgoU6I1mpgnWfGDiJ-mB9mUqNGIj_xQ-HpeibPpaev-zn44Su31V1YjEe4UuP9rU0Z-kwBPERDqSZZwd_ApZh1vA" /><br />
<br />
三、螢幕坐標轉換遊戲裡的三維坐標<br />
<br />
在小地圖裡面,有些障礙物是不會顯示的,因此要仰賴之前的障礙物分析來躲避它,不過我們需要知道我們所檢測的螢幕坐標對應的三維坐標的數值,這樣才能準確的判斷這裡是否會碰撞到障礙物。<br />
<br />
在遊戲裡我們滑鼠點擊左鍵,它會在我們點擊的位置出現類似驚嘆號的標示,並且人物會移動到此位置,因此這會是我們坐標轉換的切入點。<br />
<br />
<img src="https://lh4.googleusercontent.com/SZsz67uvxbEljpj2x54xR6fE1cOY9747T4iY_lblyhom4J05mFnfflM8lI-rjOq3-XcnbBUYg-TvUcvbjadvGc2gL6dLU5zJrKr-1O2pnxqJL5GOdHk7bGhATPJ2rpAxWEQ1x3FymWf1AzIACg" /><br />
<br />
在遊戲裡會透過GetCursorPos來抓取滑鼠在螢幕上的位移坐標值,然後再利用ScreenToClient轉換成遊戲視窗裡的坐標位置。<br />
<br />
<img src="https://lh6.googleusercontent.com/CLefGJuTYXgPLtq8kMiTUWaBaIGJlKPHKpDNLIR7cZNB1k1XkHFCGo9QcwovNppHvyEjn0nYV1_jPAiRY-mbldB3cFv_uuxxKfql386df2yTY6w0R_vR7R1717XJdCj0kWXokHD8WesS7OhmSg" /><br />
<br />
mov r9d, [rsp+18C],其中[rsp+18C]是ScreenToClient回傳的y坐標值。<br />
<br />
mov r9d, [rsp+18C],其中[rsp+188]是ScreenToClient回傳的x坐標值。<br />
<br />
lea rdx, [rsp+50],它會在調用call 502AB00之後將三維坐標值的差值運算值存放到[rsp+50]裡面。<br />
<br />
lea rcx, [rsp+98],它會在調用call 502AB00之後將一個三維坐標值存放到[rsp+98]裡面。<br />
<br />
<img src="https://lh5.googleusercontent.com/mpLjhUv_9ig6POjO2iNWIovxYFwfAb89MPTRJqNDNVZcA-rDckZd7OR-TuQnQqS8nAW5POdUJSJ1JU-sUYi652llBrVS_aVuu-ubU_Sk7HcNyskJcr9rZOPfQr5gZMElglfmcTyioc3CLUJ3Hw" /><br />
<br />
在三維坐標的差值運算後,會將結果存到[rsp+A8](x坐標)、[rsp+AC] (z坐標)、[rsp+B0] (y坐標)。<br />
<br />
<img src="https://lh4.googleusercontent.com/-aQbc96zEyzYFiV8pmb_SrwCID0O0h7eygFG61BhKrtN0OBR8nOXmhvFwazOg7FE65l9rS45VHSgbu1cbfBPYyVYn0-xUe2GWhR6GRbSM7yzte73YjQ5JV9e9gor-lSTTc-DWYwIZpaxbctr3Q" /><br />
<br />
[rsp+50]是調用call 502AB00回傳的差值運算值,[rsp+98]也是調用call 502AB00回傳的三維坐標值,[rsp+A8]是前兩者運算後的結果值,上述這些參數都是為了從螢幕坐標轉換成三維坐標的前置作業,最後再調用call 5503790後的回傳值rax,其中rax+0x10是螢幕坐標轉換三維坐標的起始位址(x、z、y)。<br />
<br />
<img src="https://lh3.googleusercontent.com/LNqZFt8jfcprOEXKA8lM-3CFnFC8LZP7q__t41V7wWLwiZXBwqCfdocKE7tauEp0UZRtb6CetH7os744cH_98X-aqj4ysrdxDo0yZgjuBEhAN_OnuJUQ6PWbczW_MW3EEhfZTvYtyTh0z16Nug" />xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-8872824737033317022020-06-15T10:15:00.001+08:002020-06-15T10:15:14.371+08:00調用外部程序函式技巧程式設計對於一個有著資訊工程基礎的人,可能不會太困難,但是有些技巧在學習程式設計卻永遠學習不了,這方面的知識需要透過額外學習系統相關的資訊,才會了解,原來可以這麼做,因此這篇的主題是關於如何調用外部程序(Process)的函式(Function),這種技術通常會使用在惡意程式或遊戲外掛上面,惡意程式是為了隱藏自己而附著在外部程序之下;遊戲外掛是為了要蒐集遊戲的資訊以及調用遊戲中的函式,所以我們來探討一下要如何做到這種技術。<br />
<a name='more'></a><br />
要調用外部程序的函式之前,我們需要擁有外部程序的記憶體空間,不過一般遊戲程式或惡意程式是在ring3層(應用層),因此存取記憶體的權限並不能像ring0(核心層)那麼大,所以我們需要透過Code injection或DLL injection技術來同步外部程序的記憶體。<br />
<br />
Code injection:通常惡意程式比較會使用此技巧,因為可以毫不留下痕跡的附著在外部程序之下,但是所有用到的API都需要重載它們的位址,也不能使用全域變數,因此局限性非常高。<br />
<br />
DLL injection:遊戲外掛最常使用到此種技巧,因為它的撰寫方式較為容易,只要撰寫一個DLL的程式,隨後再利用注入程式將它注入到外部程序之中。<br />
<br />
在了解Code injection和DLL injection的優劣,我們也會挑一種做法來達到我們要的目的,我們就挑選DLL injection這種比較簡單的做法來實踐調用外部程序的函式。<br />
<br />
這邊先說明一下,我們等下要調用的函式是64位元的外部程序,因此會比32位元複雜一點,在32位元調用組合語言只需要使用asm語法,然而在64位元並沒有此語法,所以需要透過別的方法來完成此技巧。<br />
<br />
工具<br />
<br />
1. Visual Studio 2015<br />
<br />
2. x64dbg<br />
<br />
3. Cheat Engine<br />
<br />
程式碼<br />
<br />
<a href="https://drive.google.com/file/d/1eJmbx9UBieYX_KgcsrWRzf2vMob90GbE/view?usp=sharing">https://drive.google.com/file/d/1eJmbx9UBieYX_KgcsrWRzf2vMob90GbE/view?usp=sharing</a><br />
<br />
解壓縮密碼:1111<br />
<br />
一、編輯範例程式<br />
<br />
我們接下來要撰寫要被調用函式的範例程式,File->New->Project,Win32 Console Application->next,然後將Empty project打勾。<br />
<br />
<img src="https://lh4.googleusercontent.com/e2BlJlFWXsAsQUzgtG454chwC96vdQ_78cAZg8kR6RcOnfJMFr0hgFcfAGtIKXH37wdHDfLFZBZDfYLh1bn5W2L8ABM3tMvX3r3jLxDT0b_IADwq7-zRiZT4LSIKYIY7AiCRP1WOY0wvGUiXbg" /><br />
<br />
<img src="https://lh4.googleusercontent.com/g2ySFDp7KlWLaokl8rjO1tWLAEC7X42mvY3KmjDUTkBcj3pClB1sDuqf5OTnAjKN4EqYNshiF1zwf2825-oZ_ZIdzwPTKO5ZXqv8Fgs7xY6H18sTdGpC5zKXFa5I_2VWn7-X7pBNWKyZ_3Ns8w" /><br />
<br />
在專案名稱按右鍵->properties->Linker->Advanced->Target Machine->改成MachineX64。<br />
<br />
<img src="https://lh5.googleusercontent.com/jVnDCLkNFFj_6DQrIkdU74lObbnySZXF6V9o0tzLhgLL3gfVTn7_y2aCjIIwiomNmB7GY8CrEgXel6Ru47oVFshZyAxLJLL4pjMxbBF7NG6tCbWZC-FJsjq0Z2skGBvm40eHUTyGSnS-4gkXiQ" /><br />
<br />
在上方的編譯選項改成x64,這樣程式在編譯後就是64位元的程式。<br />
<br />
<img src="https://lh3.googleusercontent.com/tGyXv6eLFnRYvjFEjrAfD45tJJlaOmNwbzXYjmJyDamPtWugOSQsc6Qgi4y5EKFMrsF1i9YuVT7ZVE1wMvxwaSauRDmze0pieDuw7JWQIReau2dTyFMT4HAtzl6quHNrDrG_LCUo6TzwUL8Mnw" /><br />
<br />
範例程式執行後,什麼都不運行,只會無窮迴圈,我們後續會透過DLL來調用PintString函式。<br />
<br />
<img src="https://lh5.googleusercontent.com/50z3vMyB28sBWj2Oa0-Fs_oo2rJ5YJnhudNQdhG7KYZAxEoQKCwRQKTmSy-_0-OZn3ywK-lj5qBK5ssetdQRUFa4ANCKvvb7GMC7fyzTMHYdRvrAY5qoNzObDuJ4tT3yTIrmgJdv-qq7gLU6UA" /><br />
<br />
二、編輯DLL程式碼<br />
<br />
首先點選File->New->Project,Wim32 Project->next,選擇DLL專案,然後將Empty project打勾。<br />
<br />
<img src="https://lh5.googleusercontent.com/GdmnPpxfdpqQUQ8wYohzHoX1Yw3Awo7LDy83KALHJcMsHJjqWt6Y2eDt7LPCpCDzxtCR0ikGBKLuoHwviUE3cSIbYK_mgHgF2z6zcOy2_5Q8v0H1NJ7gI0Mn9uBJZ1VoBiZbKANpvarZ2A6fAA" /><br />
<br />
<img src="https://lh5.googleusercontent.com/vdiaofsj2ifEz-v5S-TLWmKwKnDDnNALTcDDMXkFLOSEMUhgRXFDM6bUi8cW_g1eEDNIgYx77G0otZrntb0g99Pq6-Q2xeyg9KTbVjuGFt-a9PFq0r1I-6lEewffUFoxAdtICwh1sphuudMz0g" /><br />
<br />
我們接下來要調用的函式是64位元的程序,因此我們也要使用x64來編譯程式碼,跟範例程式相同的設定,這邊就省略了。<br />
<br />
接下來在專案名稱按右鍵->Configuration Properties->General->Configuration Type,選擇Dynamic Library(.dll)。<br />
<br />
<img src="https://lh3.googleusercontent.com/lAWahLPkVzTI0jpdPsyIZzjQen08YO_ZNVBWaKtfvLLgugBBXo6d3FqOMA43cPoVteqZG-dwgI7ijyFKuiOIqPp-qJOtNUnxcb58DDE4GA_dSUoANiDIuCWhR3uZ-SRH4FZhYQp1M2H17nFXbg" /><br />
<br />
一樣在專案名稱按右鍵->Build Dependencies->Build Customizations…。<br />
<br />
<img src="https://lh4.googleusercontent.com/5UCirotgex3pAZg3HR7gsaNArxiZ4uwUsdBMdMaCuBhEgZbudL-8x4XgpJYlrWK5Cq57sZPQ-QsNviY-Fq0QD0gbyXTIRddNDtf999NDJyvABBMKnrleTSYIE3-EsQLnqigPlBzDofp4HCAXfw" /><br />
<br />
接著將masm的選項打勾,這樣就能在此專案調用組合語言的函式。<br />
<br />
<img src="https://lh5.googleusercontent.com/EWZ889HC4WcfmlvVkx5gQltBdehSOfK14iXovawUo1fLzDmpTiuKCmMkwfdIgYDzPmwP_vv-lNtgj2ChW9EeBu3WG2jo3aKeu2DfGXG9oIdNM5hP-O4eEKUH94ZSfAw23Db0ODxmqpjJpN3wtw" /><br />
<br />
DLL程式碼的部分需要注意的是,調用組合語言要透過extern來宣告,它的傳入值是0x13F1216F0(要調用的函式位址),我們在後續會解釋為什麼是0x13F1216F0。<br />
<br />
<img src="https://lh6.googleusercontent.com/lo4jqr5KOfNUDsac1krN_wJO4YZTRMcS8OtCpWxzlAQ2SVFaQ_UALwaLhO9eMrAvj5YMF65oC4rtcw35G4ts-4L7-522tdBtUgZ518XxfX5gMJZVD5FIU9lXFProEJk4ehxXu1-6952-HjiD1Q" /><br />
<br />
三、編輯組合語言程式碼<br />
<br />
<img src="https://lh5.googleusercontent.com/UAKUMNe-HyFrP9Oy4Hy6NlNbQb-Ejq3YmEfIhpdDrcl9VLKlK9qXZJnUHxavwslaJvQqI8bpoaJvhbwcrkHVxDwkjysQfxivzDfxv9V0o2oi0BYFqjVw6kN2a-pSxv5yoKISbjsugxYU6AD1Wg" /><br />
<br />
組合語言的部分就相當簡單,不過可能會有很多人有一些疑問吧,為什麼是call rcx,因為在64位元的Calling convention的第一個傳遞參數是rcx,所以直接call rcx就能完成調用函式。<br />
<br />
<img src="https://lh5.googleusercontent.com/Dd8hg5h3VMCH8wYEhs7Rdws9TVv8OluHDXq_v7EGgc3CzvRHYC_h-k0RXjjTxhHjHqjO9oPRnNhRlwBvw_dmRxHtTC4eIXya6eHBe0eE2GjBn4PYB9F8apkmSkQDIArTagk2hFlr_OnEqP60hw" /><br />
<br />
四、尋找調用函式位址<br />
<br />
首先執行CallFunctionSample.exe,再運行x64dbg->Attach。<br />
<br />
<img src="data:image/png;base64,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" /><br />
我們找到PrintString的函式位址,它是位於13F1216F0,所以在DLL程式裡面調用的位址就是它。<br />
<br />
<img src="https://lh3.googleusercontent.com/Ej46R5g252Bsudnvshk_ymttRHlMdwgg7yle3nT6HzeIxuxYnFzGK9TKGk7DijR9CCiCIyduhVi2eNT-MQX3HfzuCv1uBqgvHZBgzjCpeJaqqlOU7hI04AWSKXrNdaJaovcTKVXWWDwX-n4cxw" /><br />
<br />
直接調用13F1216F0,其實是比較偷懶的做法,在64位元程序會有ASLR (Address space layout randomization),所以程序重啟後,就會變成其它的位址,通常我們會獲取此程序的模組啟始位址,從記憶體上我們知道它的模組啟始位址是13F110000,所以要調用的位址是callfunctionsample.exe + 0x116F0,這樣就能保證每次都能成功調用此函式。<br />
<br />
<img src="https://lh3.googleusercontent.com/Dkbf6FTz23dZPMV20uMOGq8yZwhPcdS7mULae9RyJInMpTrS5jHXqHdEfa7A6ptIu2fwNmA7rRQyreeLRAVV2v-xMH_msp9E-Ct686tz7FBjiE8JqfuXxlWSW4hY7IfaQVlI3n1PMJJp6PB0fw" /><br />
<br />
五、DLL Injection<br />
<br />
我們接下來不會撰寫DLL injection的程式,因為Cheat Engine工具能幫我們完成這項任務。<br />
<br />
首先在Cheat Engine Attach CallFunctionSample.exe。<br />
<br />
<img src="https://lh5.googleusercontent.com/yUqt8SQDIr4eV244lyzdZk0bAPvDCsPDYcfdP4lhylAdl8CpHh_E8YKu8pQiclVZyUSLO1oOr0WgN_mPYcAC0jnxRmlzF0JC8qMIUKHkwdYFuVoZqmpODpn-Mod1_hhGDo_7y2chkUCbZS9wfQ" /><br />
<br />
然後選擇位於中間的欄位Memory View->Tools->Inject DLL,選擇剛才撰寫好的DLL(CallFunction.dll)。<br />
<br />
<img src="https://lh4.googleusercontent.com/SIYkGdly5AtJNJPY4uZ2R_mnzqeMzhTQTXeFHTZOc3rkwAGDVtuQWfY2OrIIcVzvBdWNJBToxmCIANPyWrvw9uYo9LUD3cxM0ndCZXB8VzT_5PIjobhnRcYP-4y5EjAepaMchDFJ8adNTHORpQ" /><br />
<br />
最後在輸出結果就會顯示此函式調用的字串。<br />
<br />
<img src="https://lh6.googleusercontent.com/VvJ6a5jUWWxtiWVuo9vWA_MI9GbvzYHd64fNx6BE5Co6-A3Zcwd7vBfku1aBkvUiX_RrQ6aSo4W6K46k5DyHf5bkoY_wNR2Iron2njtcomwxi6fFuQXx3wQx27t7iL_9R7E5o_7v7S6uaD_V1A" />xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-87522278713459669292020-04-30T18:26:00.001+08:002020-04-30T18:26:44.079+08:00CLR C++ 逆向分析技巧之前幾篇有教學如何逆向分析.Net Framework的程式,不過是關於C#的程式,因此這篇就換分析CLR C++,它也是.Net Framework家族的成員,由於方便開發惡意程式,所以我們也要學會加殼的CLR C++要如何分析。<br />
<a name='more'></a><br />
測試CLR C++程式<br />
<a href="https://drive.google.com/file/d/1BBetKwdETXAKYWmO4OomYVrK57yGJGJ-/view?usp=sharing">https://drive.google.com/file/d/1BBetKwdETXAKYWmO4OomYVrK57yGJGJ-/view?usp=sharing</a><br />
<br />
一、尋找編譯程式<br />
<br />
在CLR C++它會透過clr.dll去調用clrjit.dll來編譯(Compile)程式碼,所以我們要分析編譯函式(call clrjit.635BBDA8)的參數。<br />
<br />
編譯函式的第二個參數(push edx)位移0x8 Bytes ([arg2+0x8])是編譯程式資訊,位移0xC Bytes[arg2+0xC]是編譯程式長度;第三個參數(push eax)是編譯完後的程式碼位址;第四個參數(push [ebp+1C])是編譯完後的長度位址。<br />
<br />
我們可以藉由第三個參數來獲取編譯完後的程式碼起始位址,然後再下中斷點,就能迅速的進入主程式的運行位置。<br />
<br />
<img src="https://lh6.googleusercontent.com/3ODOpzzWLbAMWLSY_PxhgMlrVoQGF4dN6Vg8h5gO9675f-beSCQIojpKlNzav5QvpZ1PU8LVkdeO2NqdqPpvUiJFyU8-6hjtwiHuu8dGBzQ5j0lGvGjlleCn5q_crB5HrlHQuF_K75LEMmZsfg" /><br />
<br />
因為CLR C++會初始化許多程式,所以它會調用編譯函式(clrjit.635BBDA8)非常多次,因此會比較難找到主程式,不過我們可以在clr.622E9A3E這邊先下中斷點,再到編譯函式下中斷點,可以更快速找到編譯完後的主程式運行位置。<br />
<br />
<img src="https://lh3.googleusercontent.com/Rc6MyxFCpJuWtO4FHV9lHKeWV5EJzizzza-2nzDakogFkUGmah9CJRZPUEbaiJS25LLZOk-KRSdinOTWDx7tBmnn4uRYOp7uWMJrL9ABcCjXv_75EEJw8Ajcsu29ajdqHslbBRlHfcC0519rEg" /><br />
<br />
二、利用Windbg找出Method名稱<br />
<br />
只要是.Net Framework相關的程式碼,在調用方法(Method)時,都會透過mscorlib_ni.dll來間接運行此方法,因此我們很難從一開始調用mscorlib_ni.dll的函式來知道它是調用CLR C++的什麼方法,不過我們可以透過Windbg來使用sos.dll的IP2MD指令來查找它是屬於什麼的Method名稱。<br />
<br />
在使用Windbg之前,我們可以設置Symbol,這樣它才會在標準的API顯示名稱。(srv*D:\Symbol*https://msdl.microsoft.com/download/symbols)<br />
<br />
<img src="https://lh6.googleusercontent.com/KCz6Pia4CXf0HzMj8pE34raangBdItyESZ1BvKx0TlKXw-HAVrls4wcbXYFTmye8qspPoCuladgaYDsMSzAwp9wY4OoD-aeJ3qEgMiHJ_4lhGMK7gU4Z-6CbgSafSXX83QWd2uoUA_bmz8MJGQ" /><br />
<br />
在載入sos.dll之前,我們需要知道程式是使用什麼版本的.NET Framework,這樣才能知道要載入哪個版本的sos.dll。<br />
<br />
<img src="https://lh5.googleusercontent.com/Sr9FgIabqoX0xUYlh3QtuG7233-jE-HfWz9x-Un_KCmKSHJwoVxNK3KAFyTolVOLwwSxa9MXSpbNN6BsPM2qn52ESPbmOVH7hxFlmV3euipjLHxVBoGYxzIoVJU1DzR4cR8cGrgY7lABxONiLg" /><br />
<br />
從上一步我們知道是使用v4.0.30319版本的.Net Framework,我們可以使用.load指令載入sos.dll模組,不過這樣還不能查詢Method名稱,因為程式還沒有載入mscorlib_ni.dll和clr.dll模組,所以我們需要在載入mscorlib_ni.dll後,中斷程式,因此還需要使用sxe ld mscorlib_ni.dll指令來確保程式已載入mscorlib_ni.dll。<br />
<br />
<img src="https://lh5.googleusercontent.com/pqQQt4cjgWBRmQEI78ij1qSwZQB8ABFG8BIs6MBrac4qy0v3M4_8veHhz65g4slgpYekmaeB4ypf_qclsVPTZkTOishaxX6tmXcUgeXwWuIjZFHNjcih--J7b_ZajRfJXF6bA0WR90ed6tqU4g" /><br />
<br />
完成上一步後,再執行lm指令,就能發現mscorlib_ni.dll和clr.dll都被載入進來了。<br />
<br />
<img src="https://lh3.googleusercontent.com/f1qeFq3JUJeAIGqGJOxZgixGLqz1lQ5FQpKcGvfXUeWbGYbbzGmgF6FFQXbRyumRmRmyV2APMt0NCxmVR9zFfk-Kihd18Lzqo0gcVm95blAd-cLXLFUxp2lj0Sg8v6gi1yENcQlcMJserveicw" /><br />
<br />
我們從編譯完後的主程式發現,它會透過call mscorlib.ni.6142D4B0來調用Method,接下來我們就利用IP2MD指令來顯示它的Method名稱。<br />
<br />
<img src="https://lh5.googleusercontent.com/a6vyklZBl-l8ueGIs6EfSUtitF909g9NVoK07TbliW1HkDhIdwaef89loJ3OcyyrYMn41kZoVyQFsRB7AJRtO3wxomb1LaGtMdDqxxB3LuN0OytxczHFJaHjYEilD7yK5Vlm47tKNTfxoQ-9rw" /><br />
<br />
使用!IP2MD 0x6142D4B0,這樣就能簡單快速的知道它是調用WriteLine的Method。<br />
<br />
<img src="https://lh3.googleusercontent.com/r2HvDeZF-dRG_3qWYcC3fq18ZDZrr6i1rbX15Fyvns5fuU_4Irw8bw2iwq5DY5I2-LbIiPZ6qdYUtYKoFK6fX9LOVGZGx_9rZ_ttxAEcOKVnoKFU3uBCjL0xLWg627qKl66nwh_zD824xiK6Qg" /><br />
<br />
我們也可以使用相對位置(!IP2MD mscorlib_ni+0x39D4B0)的方式來查找Method名稱。<br />
<br />
<img src="https://lh5.googleusercontent.com/A7uh14pLsq2u6Amw5C22-qU5Zt8hh4Gwefs9mSuUO7sIUPOsQd4gVkt5xOvN5ojeJbjtWkRWTvYmnPS4UQjQEUHEuwADLYsGSwJlznGUAqMAwXH5JLwwcq1sAWcj82kAKAqt6zIkcDOTvP7LwQ" /><br />
<br />xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-24977556212651733632020-04-24T18:21:00.002+08:002020-04-24T18:21:59.449+08:00淺談DNGuard解殼演算法DNGuard是一款針對.Net Framework程式的商用加殼軟體,許多惡意程式會使用它來保護程式,以免被別人反編譯,如果想要知道程式是如何運作,我們需要了解DNGuard是如何在運行時解殼,這樣我們也可以學習還原本來的程式碼,不過這篇還是聚焦在它的解密演算法,因為要還原本來的程式碼還需要更進一步了解.Net Framework編譯的原理和.Net執行檔的架構,所以我們就不探討這部分。<br />
<a name='more'></a><br />
DNGuard它會將原本的執行檔,重新打包成另一個新的執行檔,主要會修改程式進入點(EntryPoint)並且加密以及混淆原本的主程式,然後運行時會解密主程式再利用.Net Framework的編譯函式來編譯(Compile)程式碼,所以我們可以透過編譯函式來回推解密程式碼在哪裡,不過DNGuard有導入Themida商用殼來混淆解密相關的程式碼,因此會耗費大量的時間來找尋解密程式碼,不過我們可以透過記憶體分析,來解決此問題。<br />
<br />
一、.Net編譯函式<br />
<br />
這邊的.Net Framework編譯函式是C#,可能與CLR C++、VB .Net有所不同,不過分析方法都一樣。<br />
<br />
編譯函式call 6C73568B總共有6個參數,主要第二個參數(push eax)的第8項位移([arg2+0x8])是需要被編譯的程式碼,第0xC([arg2+0xC])項位移是它的程式碼長度;第三個參數(push edx)是回傳編譯完程式碼的位址;第四個參數(push [ebp+0x1C])是回傳編譯完程式碼長度的位址。<br />
<br />
<img src="https://lh5.googleusercontent.com/M3sxWH_06QAKVWxeroNJUbd_-m92v4TegYQGubSo5Xnnj2pZv1IKzizQwD0ug-4eh2uXV8kT0PRcDgBlDu3QCYFq8iEBrY_PDOwu1Gng7bIGS7fR3qJwf6xv9O6poUkeoLR4Rgghiyxz__uX8w" /><br />
<br />
二、尋找DNGuard利用.Net編譯函式的位置<br />
<br />
DNGuard不管是解密還是使用.Net編譯函式,都是在HVMRuntm.dll裡面運作,所以尋找解密函式都是分析此DLL。<br />
<br />
之前說過DNGuard有使用Themida混淆,不過我們可以透過記憶體分析來接近DNGuard利用.Net編譯函式的位置,雖然程式碼的運作會看起來很零散,但是還是能了解它是如何運作。<br />
<br />
push 0是.Net編譯函式的第6個參數;push ecx是第5個參數;push edx是第4個參數。 <br />
<br />
<img src="https://lh3.googleusercontent.com/w7oUeYj3hfFtoK2E060-ODST2mRHPofZy_k06r6dkeIKenj5XNBK2VfIEbs2kbYud1W2J9UvdRumWQWBmCD8aiuO74U9gc7MWwLQ8OvtQScJq0ve6w_YuelIczilIyLXYlN59hoccYEa--fglg" /><br />
<br />
push ecx是第3個參數;push esi是第2個參數。<br />
<br />
<img src="https://lh5.googleusercontent.com/cqkPv_J0AzEYn5egyFy2Mr4NhVMvY2H6nHC0T98Imuj9Rjc-nAs9su5FUFTGnjANKhWzqvwbdUs1nEA2R9L9pMfHvNp_zPOrCw7RNguxIHL66pG1nZsvUmFqYUN-5by4ENaLGB9Z0RCGkqD7Rg" /><br />
<br />
push edx是第1個參數。<br />
<br />
<img src="https://lh5.googleusercontent.com/kP8Gc0AObnR5Dz-IsivU9hk5Gyt_32VBYfvWE-c7qeKz0r6IV21NbFBR-PXLfWCfpSLh7fcnZJTAlx5-ANNlVUKR-dfZzQmrjjtMMVYOC3UjsrCg5bjXg6tnXrHaVzIxFBR4ijXbwtXVK08u9g" /><br />
<br />
call eax,其中eax就是.Net編譯函式的位址。<br />
<br />
<img src="https://lh5.googleusercontent.com/RG7JW1fRIiS1zpfKO5bbirl3Kks0v1Aep2iNhchP5rEEtM8xtFdwrxhFEH09LE0YXmMbJZ-P20dYcGOOGA-XdSqXVsvGwjIFi0LETplq0sde1ujMdc76J8xrSfIIQhx0xKOLTv9DNKDJBOAb9A" /><br />
<br />
三、尋找解密的程式碼<br />
<br />
我們已經知道它會在哪裡來使用.Net編譯函式,因此可以輕易的推敲解密程式碼的位置。<br />
<br />
這裡是解密的演算法,其中cmp ecx, eax是判斷是否完成解密,[edx+edi]是解密的Key(總共16 Bytes,因為會做and edx, F),[ecx+esi]是要被解密的密文,解密完後,會將明文寫入[ecx+esi],它的演算法非常簡單,密文和Key做xor(互斥或運算),就能解出明文,不過真正的程式碼還會在這裡解密第二次,因此它還會去解密編譯相關資訊和程式碼的長度,然後再進來此程序,再運作一遍才是真正的主程式碼資訊。<br />
<br />
<img src="https://lh3.googleusercontent.com/bRiVaC5OHartDjoxbi2kOTeXLaukWKxxfvgXvY_XKAF9DCN1Ym1nvm9yoZMWp1EuzWb6iwWH1lJZxEEabeyeUximih_kopc6NnSFnUTobfMaP_iFSZroV4GMEHU70VhAV2XyIJeYTb2MFB7XlQ" /><br />
<br />
在載入HVMRuntm.dll時,會透過DLLMain來初始化16 Bytes的Key。<br />
<br />
<img src="https://lh6.googleusercontent.com/F-Q-7xMtLTyYsAbE52iSSrfJ0byKbSLa42ovuzI9TD7V_pcAhcs-pC6nRNp-7tgMHZTv0BUCRD4c5jm0nx5ed62E2GVk-rJR6fJcsUBi63F3leEirAxMvmxBMZpgk9OorIDdTaXrx2rLDutvag" /><br />
<br />
四、分析DNGuard解密的Header資訊<br />
<br />
我們只知道解密的演算法在哪裡還是不夠,還要知道加密的內容在執行檔的偏移位置,因此我們要知道它的解密Header在哪裡,Header裡面有存放密文的起始偏移和密文長度。<br />
<br />
這邊會將解密Header移動到新的記憶體空間,其中[eax+ebx]的ebx是Header的起始位址,然後將Header所有數值存入[eax+esi](eax是Counter,esi是新的記憶體空間位址),另外詳細的偏移如下:<br />
<br />
1. [ebx+0x4]是被加密過的起始加密偏移位置的Key1。<br />
<br />
2. [ebx+0x20]是編譯相關的資訊和解密後的程式碼長度的密文長度。<br />
<br />
3. [ebx+0x1C]是DNGuard驗證相關偏移的長度。<br />
<br />
4. [ebx+0x48]是被加密過的起始加密偏移位置。<br />
<br />
5. [ebx+0x4C]是程式碼密文的長度。<br />
<br />
<img src="https://lh6.googleusercontent.com/-NYe94zdt2RzJ9Vl33ZtB1B9GANKlgUTA7HQ2lmVgWFrhm0eWvUbYpRbWqj-mMZmiD7sssiUWHvG3n5H0aLI_WKbzp5F7g1-h2sh3jfRj_4Z862XSNL0n0krK_IlhFnqqSMcI_3maH-hk--ohA" /><br />
<br />
五、獲取起始加密的偏移位址<br />
<br />
因為[ebx+0x48]有被加密,所以需要經過解密,才能獲取起始加密的偏移位置,這邊需要補充一下,它主要是透過2種Key來完成解密,其中Key1是步驟四的[ebx+0x4],Key2在試用版的DNGuard是使用GetVolumeInformation來獲取硬碟的lpVolumeSerialNumber,但是惡意程式不可能會使用試用版,所以這邊還需要留意一下。<br />
<br />
這邊的[esi]的數值為(not Key2) or (not (not Key1 or [ebx+0x48]) or (Key1 or not [ebx+0x48])),[esi+4]的數值為Key2 or not (not (not Key1 or [ebx+0x48]) or (Key1 or not [ebx+0x48])),[esi]和[esi+4]會個別存到ecx和eax,然後再做not,最後ecx和eax再做or,結果值為ecx,ecx就是起始加密的偏移數值(執行檔起始位址+ecx就是起始加密的位置)。<br />
<br />
<img src="https://lh3.googleusercontent.com/jLAWvwFNTcttlNWSgrIVqZcJaua0LuO0-vjl4TaowY8zSCDTjFEocPsQZLhe38rjE3LqJmSOx4eIaX6K87TV-LWmFdeGL61d778X83Mo9bwJMswJy_eDxuaXkBp78kbhNImXcR6jodhv8yxxlg" /><br />
<br />
六、獲取DNGuard驗證相關偏移的長度<br />
<br />
我們從第五步驟獲取起始加密的偏移數值ecx,可以透過執行檔起始位址+第五步驟的ecx定位到要開始解密的位置,不過要被解密的起始位置是DNGuard驗證相關偏移數值的密文,所以我們需要獲取它的長度,再來取得主程式的密文位置。<br />
<br />
接下來我們要獲取它的長度,要先透過簡易的運算,因此這邊[edi]的數值為[ebx+0x1C] + [ebx+0x1C](步驟四),[edi+4]的數值會等於[edi],然後[edi]和[edi+4]會個別存到edx和eax,最後再相加到edx,edx就是DNGuard驗證相關偏移的長度。<br />
<br />
<img src="https://lh4.googleusercontent.com/6rOs0B6vrpPdiXHYpumdkO4WSyqRp-bjWsBZOWRVh4nqnnp-uDKhB95aP13o09sG9HhKorRxILaYFTTBebCCirrrvCIPikyWyZSWDer9Lw8A2WRKfoqyhjAajXIFFyTVQncJlKhIjow6sK2tqQ" /><br />
<br />
在獲取它的長度之後,它會透過第三步驟解密,並且獲取它的偏移值,再透過執行檔起始位址+偏移數值edx,就是DNGuard驗證相關的資訊,如果這些資訊被修改,程式會跳出錯誤的訊息,然後結束程式。<br />
<br />
七、獲取編譯訊息和主程式的長度<br />
<br />
我們已經知道程式的密文位於執行檔的哪裡,將執行檔起始位址+第五步驟的ecx+第六步驟的edx,全部加起來就是主程式的密文起始位置,那麼密文長度為第四步驟的[ebx+0x4C],接下來可以透過第三步驟來解密。<br />
<br />
之前在第三步驟有說明,它會在第三步驟解密2次後,才是主程式的明文,不過在解密第二次之前,會獲取主程式的長度,然後才運行第二次解密。<br />
<br />
這邊會獲取編譯訊息和主程式長度的密文,其中[esi+ebx]的ebx是執行檔起始位址+第五步驟ecx+第六步驟的edx+第四步驟的[ebx+0x4C],總長度為第四步驟的[ebx+0x20],這裡補充一下它的前1 Bytes是此密文的長度,edi是此密文的第4 Bytes,[esi+ebx]的esi是數值5,所以它是從第5 Bytes開始運算,[eax]和[eax+4]的eax是新的記憶體空間位址,每次循環esi會加5,eax會加0x1C,edi會減1,直到edi等於0。<br />
<br />
<img src="https://lh6.googleusercontent.com/t9AoQHxpSs2YdTywI1b6Jx7nbyipR9iacmd0f1W-J4NMktniaYLnP6r0kJCGi-A3CrrailCtyxGnl-kPctRCroV-jAI3hAScMv_Hqixl89adMji3HSCWl-kDU57et3jLybjI9qIfHY8DTWdseA" /><br />
<br />
上一步循環結束後,call 10010F60會建置類似二元樹的資訊來準備獲取密文資訊,[esp+0x10]就是上一步的eax的記憶體位址。<br />
<br />
<img src="https://lh3.googleusercontent.com/fOCkwup8FwFLIxadypz9j5RLxNiYR2ocLrDVwg6aYk64iWPi07TxC1atczvj-xkUQTy8gECGKCmGBf0g6cRdLdl-MrF5QiBNUCwFHX0fMXE4drzZJLgBYBCjY8Y-gakn9jjnGh5C6OHjTtgSGQ" /><br />
<br />
建置完類似二元樹之後,它會獲取裡面的資料,其中[edx+14]( [ecx+14])和[ecx+18]有點類似左子樹和右子樹的取值,取完值會存到[edi+eax](edi是Counter,eax是新的記憶體空間位址),直到edi大於密文的長度[ebp],這樣就順利完成獲取密文資訊,然後再利用第三步驟來解密。<br />
<br />
<img src="https://lh5.googleusercontent.com/IO0foxQPy6J2jHoH5TL-XNrqbwC-V7gDI6q7a-EkOXoeGruo4YLOhZF2Ox8Q6zxrEurgPs269Py70oLHmikkNjunIRMX4_ogYuAFmZ__5iupGXSdCm0c9bwqwG_1RNf0sDxOXNN-BQPdNIttcQ" /><br />
<br />
從第三步驟解密後,[eax]是解密後的資訊,將它存取到edi,edi再右移8 Bytes來獲取主程式的長度。<br />
<br />
<img src="https://lh5.googleusercontent.com/5etg-u8eAMTDUqKTXItZAiKhUB_RJvZ4QBpvEHMjopDP6PQYfJOtfsY-sTTI1jBgzfWUKchfwNU3yzMKhH7jQOY6rzj5C5oXGid6rSUMSfnHuwfQxX0-WvEPV5QCt-N-j51ZklerVqidoZzNdg" /><br />
<br />
在解密完後的[eax],除了可以獲取主程式的長度,此內容還有編譯相關的訊息,因此接下來會先運行第三步驟的第二次解密主程式碼,然後再調用.Net Framework的編譯函式,最後才會執行原本的主程式。<br />
<br />
八、結論<br />
<br />
DNGuard的運行依序如下:<br />
<br />
1. 獲取解密的Header資訊<br />
<br />
2. 解密起始密文的偏移位置<br />
<br />
3. 獲取驗證相關偏移的長度<br />
<br />
4. 獲取主程式碼的密文<br />
<br />
5. 第一次解密主程式碼<br />
<br />
6. 獲取編譯相關資訊和主程式長度的密文<br />
<br />
7. 解密編譯相關資訊和主程式的長度<br />
<br />
8. 第二次解密主程式碼<br />
<br />
9. 調用.Net Framework編譯主程式<br />
<br />
從這些步驟看起來相當複雜,不過比較麻煩的是第七步驟的演算法,這裡可以直接調用它的函式來建置(類似二元樹的函式),不需要將此函式完全分析。<br />
<br />
惡意程式一定會使用專業版或企業版的DNGuard,因此程式的字串可能會被加密,不過透過這些分析方式,我相信一樣可以迎刃而解的找出解密演算法。xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-50436716155286075092020-04-23T19:12:00.002+08:002020-06-30T10:42:36.440+08:00劍靈(Blade & Soul) 逆向分析研究 - 障礙物分析在路徑規劃前,我們需要知道附近的所有障礙物,這樣才不會被障礙物卡住,因此這篇會介紹如何分析遊戲中的障礙物資訊。<br /><a name='more'></a><br />
一、碰撞偵測<br /><br />在人物移動時,遊戲會判斷人物是否有碰撞到障礙物,如果有的話,人物會被障礙物卡住,因此我們可以在人物移動時,去尋找相關碰撞偵測的函式。<br /><br /><img src="https://lh6.googleusercontent.com/NiC6ekzLJF3KZLgizrVEPhnt7nrINTrX20IKch71W3DX-hfLxWPP9gITGbQMOI-lq6nSq7KedSogVTujLxRcFtpnlVbnTsfP3bodtG8z7S6A30ijGf0snObAzCDANhtlzmheqZjsueySmx7hAw" /><br /><br />call 0x55B3790是碰撞偵測的函式,其中r9存放人物的坐標,r8存放人物移動後的坐標,執行後,回傳值如果不是0,代表有碰撞到障礙物。<br /><br /><img src="https://lh4.googleusercontent.com/kOaMfE9dObEuuqQe0qF_It6729FZhgmi032YJbMIvz1N74IQCcxxUIMAc4RfJVqEag4-bBp-Mg4qOw-h--Bmn6Dw3mFRI5d8VouQ2XFUB36Bjf7cWSBIlFHrc9w1xxEC0uzwnGgop_-WSNaejQ" /><br /><br />繼續往下更進一步分析call [r10+308]是主要判斷人物與障礙物的碰撞比對,如果有碰撞到,回傳值是0,然後我們可以透過rsi知道障礙物的相關資訊。<br /><br /><img src="https://lh4.googleusercontent.com/4Pkx5ocakzzFCcw81YP0ND_SFVASyh04fJQD2TElLXMKlW9z-IHNQcuKSSnhGi04FnhGHnN9NtQGgcW3vmR0kxSuRjItm8wLOa2RfZtr1orJQRHurwNS4D4lTPlVq0FChdGAU-buCmjkF_PRYA" /><br /><br />在call [r10+308]之前程式碼有獲取[rsi+0x118],它是障礙物的中心頂點坐標。<br /><br /><img src="https://lh5.googleusercontent.com/Crnx0Rprtd1z75vsrrtFOc2VFlsBsyu7QjjwVFFgHbtAuoLvCOER8U8AZiYRC8DyRYZyjFzxBjwuwAeq7HoALgDd6dhPVXbUblnRNpfo4o2gy2ca4Q5xfzRt0lAtFHF0T6_mW8BWKAQ8VR684Q" /><br /><br />二、推算障礙物的全部頂點坐標資訊<br /><br />不過我們需要知道障礙物的全部頂點坐標,才能比對此坐標是否有碰撞到障礙物,因此我們還要藉由之前找到的障礙物資訊的物件rsi來分析出障礙物的所有頂點坐標。<br /><br />透過記憶體分析,我們找到[rdi+29C]有存取到rax,此時rax的數值會跟rsi一樣,這樣我們就能知道這裡其實有在列舉障礙物的相關訊息。<br /><br /><img src="https://lh6.googleusercontent.com/Gk-Yfy4NDTMmYDYYfONbeeoWxk_mOZ3cV005ldlK8fD51NSzmuhiWfWPKHA9Yh4ypeTY7oRS0EdFHPkqI22a6H9SZ77m6lE5eXbvjCQr9vPei_bp1o8kRrc6LLCEM2OoPyjdwzAgqLPLILozBA" /><br /><br />接下來回到前一個函式,我們可以觀察到rcx是障礙物所有頂點坐標的物件。<br /><br /><img src="https://lh5.googleusercontent.com/75Ux9I18tZ9OHRmxkpSwlDheFzlDdpQk4YpkGKWQ2C_oObFX7iihYMN5uJAcjZ0v9MBN2s68LcNxZYjmFROqUB3gVQiFELh8yRJEJDIcFRUEnO_ZrpeQDTuaGELCghJFdeZI_mXc4uXiUX35gw" /><br /><br />在記憶體觀察rcx,其中0x76ED36E0是存放障礙物的所有頂點坐標,0xA是頂點坐標的數量。<br /><br /><img src="https://lh3.googleusercontent.com/jKMSHQEDXz6JWE6jYyv-4ayp83gyDFRKPvaLCKiWpIEIEaYNQBNT36BhzTAqhchpSL2d6-IrkNd3AKpLgU-RBDyOZGVfk3G__s1RLdO_v9bcfmFc3Bj_Hqwn6iCAHZJpwUGQ_hb3pGGDdEsRMQ" /><br /><br />從記憶體觀察0x76ED36E0,我們可以看到除了障礙物的中心頂點坐標,也包含其他的頂點坐標,由於頂點坐標數量是0xA,礙於截圖截不了全部,我只列出前面7個頂點坐標。<br /><br /><img src="https://lh4.googleusercontent.com/Q5xMpSvHvAx4RW6qPMipTfyXl_o9Kt5yMTpt9bGBu2e0qLBWFnfkgtZHrhWvwNHAIBROAiuMkZkJc_KRE_6izdGs0Nu8bQ09cgCBhhdHAhmcmVWjshOGZMCdtrfdHBX57OAbZTWFOeFfgba1iQ" /><br />
<br />
三、驗證是否為障礙物<br /><br />在分析的過程中,我們需要驗證是否為障礙物的相關程式碼,因此會修該相關的程式碼,例如遊戲在繪製障礙物時,我們指定一個障礙物不讓它繪製出來,如果從畫面沒有顯示此障礙物,代表我們分析是正確的。<br /><br />原來的攤車已消失不見,只剩下部分的零件,因此通過驗證的行為使我們在一開始的假設是正確的。<br /><br /><img src="https://lh6.googleusercontent.com/5BoaKCR_94q0eN2sRTlOhrBkbmQO9ceA6ZG5Sjx6MFiYZHngjyyD5ZWF1YIFOheg3-5O7CvLbUV-oo5YRV4UFOrmvdHqFWTWQYPXrOsVHWo5pqIRGEp07284HJ80aVQHQwsP3HqdPZFgfCBlCQ" />xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-73828515897482827782020-04-09T19:05:00.001+08:002020-04-09T19:05:39.875+08:00C#逆向分析技巧C#是Windows提供給開發商撰寫軟體的程式語言,那麼駭客也有可能會使用此語言來開發惡意程式,所以我們需要知道要如何分析它。大部分的資安人員在分析.NET Framework的程式,通常都會使用.NET Reflector或dotPeek等等的靜態分析工具,如果程式有透過加殼軟體來加殼主程式,靜態分析是完全沒用的,因為主要程式碼都被加密或壓縮,所以我們這篇是要克服這種情況,進而騷擾加殼程式。<br />
<a name='more'></a><br />
<div>
C#是屬於MSIL(Microsoft Intermediate Language)特性的程式語言,它在運行時會透過.NET Framework來進行編譯,編譯完才開始執行主程式,所以我們接下來要尋找是透過哪個函式來編譯主程式的,藉由此函式來知道主程式運行的起始位址。<br />
<br />
C#測試程式<br />
<a href="https://drive.google.com/file/d/1fAIZW4BKkuvk4XA7gvYsIEczS8K7F8oD/view?usp=sharing">https://drive.google.com/file/d/1fAIZW4BKkuvk4XA7gvYsIEczS8K7F8oD/view?usp=sharing</a><br />
<br />
一、尋找編譯程式</div>
<div>
<br />
在.NET Framework裡面的mscorwks.dll會調用mscorjit.dll去動態編譯我們的主程式,所以我們只要將編譯好的主程式的起始位址紀錄下來,在對起始位址下中斷點,就能快速定位主程式。<br />
<br />
[ebp+18]是主程式的起始位址回傳值。</div>
<div>
<br />
<img src="https://lh3.googleusercontent.com/sXSO1kxs42WyoHX3lYl-A0-Yi-QahGT_9Iih3RHkIUfv7kH_TqdAT4oPWS_i7STz9a_WrVrIkuz4Wt16ZeAAvf6BEGct6mWH7jDsqYyxdacpK_t3b2P0rlGmLF3kWkBIl3VPLDNRmQeHCtvRoQ" /><br />
<br />
<img src="https://lh5.googleusercontent.com/dYBmpknRbxqPRq3ELN-uIk_DNQP6_m3l0xhxa4I85dsVQOFErpNswuPvq5eMdI5gxpmqN-SNy2cGNMUKfa3p1j45Z_FRlLzL76eH2Y1FucELAdle1DN2tq-IOA54zcte_ZIQinzBefCMokJ4oA" /><br />
<br />
執行完編譯函式後,16EE20會寫入主程式的起始位址。<br />
<br />
<img src="https://lh3.googleusercontent.com/ph3XRKgCGcdH08HWCPwxIp9riElNtZjGDara-s7qDWDN1oSly4L2Vmp--5ZkB_g3H5EwbQF4XWfxWbt8Yum2Zw7OJZkieESvbaKuMZzmeBc4C6duUqmswHj5hF2YNbMsjxcoRgdoNKL5D-yP_A" /><br />
<br />
在4B0070的位址下中斷點就能輕易的找到主程式的起始位址。<br />
<br />
<img src="https://lh5.googleusercontent.com/IdSOk5tdrHlm3E63ZL-bHsdjEBPTbM4pB0IHweO8-pSqPna1nYYrNH3PXQjq-hY9vXebMlcLAMELlnUO7f-8kXFtLsPJTZo_Sd0A1e2DjQEQktjoZfWcIGBSl_Bmf-7ckxm7bCe6xLPv-2UMsg" /><br />
<br />
二、結論<br />
<br />
編譯函式可能在不同的.NET Framework的Patten可能會有所不同,但唯一不變的是mscorwks.dll會調用mscorjit.dll的函式來編譯主程式,所以我們可以遵循這個規則來找它,另外如果是有加殼的程式,它可能會調用好幾次編譯函式,直到編譯到主程式,我們也是一樣可以藉由這個方法來找到主程式的起始位址。</div>
xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.comtag:blogger.com,1999:blog-499134025351003095.post-71163551008154162732020-03-26T18:57:00.001+08:002020-03-26T22:12:20.391+08:00Windows Keylogger逆向分析在惡意程式當中,最常見的行為是木馬/後門,接下來就是鍵盤側錄(Keylogger),因此我們這篇就要來研究它是如何運作的,雖然在技術上並沒有特別困難,不過想要入門惡意程式逆向分析的同學,會是不錯的選擇。<br />
<a name='more'></a><br />
在分析Keylogger之前,我們先了解一下它是利用哪個API來記錄我們的按鍵。<br />
<br />
SetWindowsHookEx是Windows提供給開發人員來Hook鍵盤、滑鼠、視窗訊息等等事件,因此Keylogger最常使用這個API,其中第一個參數(idHook)是要Hook哪種事件的行為,第二個參數(lpfn)是觸發此事件需要處理的函式(Callback Function)位址,第三個參數(hmod)是Current Module Handle,第四個參數(dwThreadID)是要Hook的Thread id,如果第四個參數是0,代表全局(桌面上運作的所有程式)Hook。<br />
<br />
<img src="https://lh6.googleusercontent.com/sIpAlIGHFzc0YMm6l_yWQIrLZ0oQUVoF9uHqa2_1YkiuXoR9kz2Q6MN6eTQGnWE8erCX--oj28KFqZTUrJmk1_t90gVFIX3W4IKAI4XS_t1Js7KbLUW_DTqvMP2AEBkPYF8BZDhu1BhK-7TL4g" /><br />
<br />
鍵盤事件有分WH_KEYBOARD(數值為0x2)和WH_KEYBOARD_LL(數值為0xD),WH_KEYBOARD僅Hook視窗程式在調用GetMessage或PeekMessage時,按下鍵盤的按鍵,才會進入處理函式,不過WH_KEYBOARD_LL是在驅動層來過濾按下的按鍵,所以它可以更完整的監控所按下的按鍵。<br />
<br />
一、SetWindowsHookEx分析<br />
<br />
我們可以在SetWindowsHookEx下中斷點,並且分析它的參數,第一個參數它是使用0xD(WH_KEYBOARD_LL),也就是驅動層鍵盤的Hook,第二個參數是0xB21118,這個位址是處理鍵盤按鍵的函式(Callback Function),接下來才會進一步分析此函式的運作行為,第四個參數是0,代表是桌面上的所有程式都會被監控。<br />
<br />
<img src="https://lh6.googleusercontent.com/2umrts0LBkPHztnzf3i-jQ1X9MaXXFQfgqDaGxTWxQEOKklBscvix4nO0nrIIqvFMtN_NMfrDdJu_zJ2kvk0mTjoCv5u8XChLE_hatnKlP8hlyp1He-4MBnZgeE6IdPaqKEkB6gVobCJlGfSAQ" /><br />
<br />
二、Callback Function分析<br />
<br />
我們先來了解一下此函式的參數,第一個參數(nCode)是觸發的事件是屬於哪種行為,鍵盤是HC_ACTION(0x0),第二個參數(wParam)是紀錄鍵盤是屬於按下(WM_KEYDOWN)還是彈起(WM_KEYUP),第三個參數(lParam)是存取鍵盤相關的結構資訊(KBDLLHOOKSTRUCT),其中vkCode是按鍵的資訊。<br />
<br />
<img src="https://lh4.googleusercontent.com/ewQUXZ8I3l8ZkATnTZnW1-30cyosbwssBNMokQseelD2QcEXHj6eeokoAmcDdN_apjpM_rfVxlQVmWmqN3ZS-efKZqIZ13-XE6Dx8LofZ3nmrFcCXytdbJkn4kaU9NP8nDJ4XMOMY5sUu1vOGQ" /><br />
<br />
<img src="https://lh5.googleusercontent.com/MWBznR02xcbfbDqKx744kZjrRur_PUcIedVwA88IEeXMheul3F6AW3j4iWiBC-QKIm8A1mn2ZUrJwTcxV467BojYAuE_wfj3CcGG3yeuZGRlkwZ7GMZRaLI4RUMJTnl52tNPHWHYjeunwN9BnA" /><br />
<br />
[ebp-10C]是存放lParam的位址,並移動到eax,所以[eax]裡面就是vkCode(按下的按鍵資訊),接下來通常它會一系列的判斷是否有按下Shift或Enter等等的特殊按鍵,不過有時候會在輸出結果(可能利用WriteFile寫入到檔案)下中斷點,直接分析它的輸出結果。<br />
<br />
<img src="https://lh6.googleusercontent.com/GxpnUWDuWsdoqNhFmdp9GKqHQUGmHWSo7uRe5Jt1uLDu3q_fretXZpWtMw5JD0suyNtXVhBbc99tEtPukVdlaRGi8R5GviacmCQ4Qfh5GSUo60ByKOf1vjeF5hZF46bY9kwXeEFx7WAsypInEA" /><br />
<br />
利用GetForegroundWindow和GetWindowTextA來獲取當前按下按鍵的視窗名稱,這樣就能進一步知道它是從哪隻程式按下此按鍵。<br />
<br />
<img src="https://lh4.googleusercontent.com/ccOc4agSEKw51BTg6PGRA0jSole5ONAJHYAoPpLS44LtZbk0mkOymvoj8aSpsl8FA18vg9j1E9RwboNpGTboZKEPKiQl1-Y7wqxENZdZr_YouYaH8QvZa7Gw5fCbE33WXMPrJt57LuAmuKUoAw" /><br />
<br />
三、輸出結果<br />
<br />
從輸出結果判斷它會記錄當前按下的按鍵時間、當前視窗名稱和按鍵資訊,如果有使用Enter或其他特殊按鍵會特別標記它([ENTER])。<br />
<br />
<span id="docs-internal-guid-a2e25b03-7fff-3be6-7533-45c3f374b5f5" style="background-color: transparent; color: black; font-family: "calibri" , sans-serif; font-size: 12pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"><span style="border: none; display: inline-block; height: 335px; overflow: hidden; width: 554px;"><img height="335" src="https://lh6.googleusercontent.com/KUuCI62lrnE18SbwFb4VU2WPHSrTIdMZ5MVD-Sqxu96aNze5xzErCER6JhX5ATxj9gEWBqfhywmZP-bPuvZo_UueKHXarz-zC19HriyxhJ4_Tc3mzgojrcB9K3lx8FbcF8rjHJli" style="margin-left: 0px; margin-top: 0px;" width="554" /></span></span><br />
<br />xtutlabhttp://www.blogger.com/profile/09286472204096327128noreply@blogger.com