本文為看雪論壇精華文章
看雪論壇作者ID:唱過阡陌
目的起因1. 相對u3d遊戲進行hook基本上離不開 Il2CppDumper 的使用,有時候想要找個函數什麼的就很麻煩,第一步就得使用上面這工具來找到函數地址。2. 第二就是每次都要用 Il2CppDumper 來找函數地址不能方便的實現 frida 腳本的自動化,既然都用到了 frida 當然是越方便越爽。
經過之前搞了一個通過 Il2CppDumper 拿到的 script.js 加上一點python 篩選,來實現對函數的批量斷點,方便實現對點擊事件或者是其他關鍵函數(Like:Show,Click,Button,Rewarded)多函數的批量斷點,方便我們分析代碼調用。
這還是不夠優雅,要讓他自動去拿到這些地址,我們就得讀一點點,在源碼層面去hook拿到一些我們需要的關鍵點。
分析網上也有很多類似的相關文章,比如:
[unity]Real-time Dump:https://floe-ice.cn/archives/502
一套強勁的 Il2cpp Hook 框架:https://www.52pojie.cn/thread-978958-1-1.html
IL2CPP的原理:https://blog.csdn.net/feibabeibei_beibei/article/details/95922520
都可以去參照、去細品。
分析的入口點從加載 global-metadata.dat 入手。這是一個非常標誌性的入口,不管是在源碼還是在IDA中都很容易的定位:IDA中從字符串窗口搜索該關鍵詞也可以輕鬆的定位到一下代碼。IDA中F5也是隨意的改改名字,改改結構體就差不多一個樣了。
在源碼中讓後看,可以看下面就開始對此處分配出來的內存填數據了,後面我們用的時候也是無需但是未初始化的問題。這裡的s_ImagesTable是一個指向一個 Il2CppImage 列表的開頭,sizeof(Il2CppImage) = 52,可以去頭文件查看。這一步我們關注的只有 const char *nameNoExt 以及當前位置的指針位置由此寫出。
這些玩意其實就是我們用Il2CppDumper拿到的哪些dll。
然後下面就可以進入正題。使用命名空間,類名,方法名,參數個數拿到我們需要的函數 內存地址以及IDA中靜態分析的地址。下面介紹兩個主角函數(這裡引入的兩個函數都是libil2cpp.so的默認導出函數)。
位置:D:\Program Files\Unity\Editor\Data\il2cpp\libil2cpp\il2cpp-api.cpp* il2cpp_class_get_method_from_nameps:這裡做的事情其實,就是和做數學一樣,把未知量用已知函數去代替,帶入到我們能解決即可。結果展示:
看到此處的話目的算是勉強達到了,但是還有待優化把,比如一開始的這兩個位置需要我們手動IDA去找。
新的問題
從上述結果中確實看到了我們可以成功的調用函數拿到函數的返回值,但是僅限於我們已知Il2CppImage*的時候有效,也就是僅僅在我們list_Images中列出的地址對應的子函數可以這麼操作(使用il2cpp_class_from_name()獲取對應的Il2CppClass),所以我們為了通用得考慮新的思路。兩個關鍵結構體:Il2CppImage 和 Il2CppAssembly。可以看到第三個指針指向的地址的第一個區域由指回來了,就是咋們的Il2CppImage*。上面這張圖不是重點,重點在上上張圖第二三個圈起來的部分,也就是TypeDefinitionIndex typeStart;
uint32_t typeCount;
這兩位,分別記錄了偏移位置和方法個數,偏移位置的開始在(還是去參考IDA拿到地址,同樣也是bss段的一個指針)。根據上述SeeHexA(0xcf80ec00)中可知偏移0x0,方法個數0x5c2(即1474個方法),接下來就可以寫出以下demo。上述故意方法數多加一,看到最後空命名空間和<Module>基本就穩了,就是這意思沒猜錯。
拓展讓 Il2CppDumperTool 脫離 Il2CppDumper 以及python腳本更易用。* UnityEngine.GameObject.SetActive(Boolean)* UnityEngine.Object.GetName(UnityEngine:Object):String* UnityEngine.Application.get_identifier():String* UnityEngine.PlayerPrefs.GetInt(String,Int32):Int32以上展示只是一個簡單的分析,其實就上述這樣東西還是非常不好用,上述的addr並不能找到所有的方法及其地址,後續就想著讓他更加智能一點,就嘗試手動去解析一下結構體,然後就得到了一下效果。首先是針對我們需要的三個參數的自動解析,主要涉及到ldr尋址:這裡為了實現找到我們需要的參數,主要是通過導出函數il2cpp_init的地址往下找找到bl進去然後再找到ldr,並解析到ldr加載的值,如果出現了「mscorlib.dll」,說明我們找到的bl是正確的,然後我們同理找下層的「global-metadata.dat」即可定位到函數 bool il2cpp::vm::MetadataCache::Initialize()。找到上述位置後,我們稍微看一下就可以發現特徵 IL2CPP_CALLOC 函數,老規矩通過這個bl指令去解析到函數地址,記錄所有調用的該函數的當前地址放進數組,接下來就是 通過數組訪問到 [1] [4] [5] 位置就是我們需要的三個初始參數,從當前位置往上解析它,第一條 mov r0,#xx 的立即數就是我們要找的,好了介紹到這裡,上效果:這種找法效果還行,能解決大部分問題,也不能解決全部問題,總有些奇葩adr之類的東西,這些就自己手動IDA查看了。
然後就是挨著列出:
也可以解析的更加詳細(其實還可以繼續深入解析出方法類型返回值類型的,暫時沒有繼續深入)用新的方法來解析找函數就不存在解析不到函數的問題了(隨意解析這個so裡面的任意函數)
實際用處隨便舉個例:斷點 public extern void SetActive(GameObject obj,bool value);
1. 有了gameObject就可以拿到transform,以及他的名字,再遍歷拿到父級名字,整個調用鏈你都清晰了。2. 有了gameObject用以上的函數API可以隨意的移動,顯示隱藏 ...
看雪ID:唱過阡陌
https://bbs.pediy.com/user-home-868525.htm
*本文由看雪論壇 唱過阡陌 原創,轉載請註明來自看雪社區。