內(nèi)存解析libmono函數(shù)地址

前面文章搞了搞libil2cpp.so用來批量hook函數(shù)確實方便
https://bbs.pediy.com/thread-264813.htm
https://github.com/axhlzy/Il2CppHookScripts/tree/master/MonoHook
這里又想著搞搞libmono.so,在加載*.dll 的過程中看看能不能搞點東西出來


  • 大概思路就分為四部分吧:
  1. 找到MonoImage,找到MonoClass(mono_image_loaded , mono_class_from_name)
  2. 找到函數(shù)Method的對象指針(mono_class_get_method_from_name)
  3. 能去主動調(diào)用函數(shù)(mono_runtime_invoke)
  4. 能去攔截函數(shù)的調(diào)用并獲取和修改參數(shù)及其返回值(mono_compile_method)

  • 找到MonoImage

啟動時候HookDlopen,并在加載libmono.so的時候?qū)?dǎo)出函數(shù) mono_image_open_from_data_with_name 進行Hook 拿到加載進來的dll的image對象,返回值就是一個_MonoImage結(jié)構(gòu)體指針

_MonoImage結(jié)構(gòu)體

關(guān)注上圖中的
*raw_data dll在內(nèi)存中的起始地址
raw_data_len dll的長度
即可寫出,記錄下arr_imgs_addr 和 arr_imgs_name

/**
 * 啟動時候Hook mono_image_open_from_data_with_name 記錄dll的起始位置,名稱
 */
function HookMono() {
    //MonoImage *mono_image_open_from_data_with_name (char *data, uint32_t data_len, mono_bool need_copy,MonoImageOpenStatus *status, mono_bool refonly, const char *name);
    Interceptor.attach(Module.findExportByName(soName,"mono_image_open_from_data_with_name"), {
        onEnter: function (args) {
            this.name = args[5].readCString()
            this.size = args[1].toInt32()
        },
        onLeave: function (ret) {
            var t_ret = ret
            LOG("[*] "+t_ret + "\t"+this.name,LogColor.C36)
            var t_arr = this.name.split("/")
            var t_name = t_arr[(t_arr.length)-1].split(".dll")[0]
            arr_imgs_addr.push(String(t_ret))
            arr_imgs_name.push(t_name)
        }
    });
}

以上為啟動的時候就進行Hook可以拿到Image結(jié)構(gòu)體,不在啟動的時候Hook同樣也可以拿到
使用導(dǎo)出函數(shù)中的 mono_image_loaded 即可

MonoImage    *mono_image_loaded   (const char *name);

對于如何拿到method對象的話,我們還是沖導(dǎo)出函數(shù)入手,使用IDA查看一下導(dǎo)出函數(shù),看看關(guān)鍵字method,可以看到這些函數(shù),選幾個長得像那么回事的函數(shù)去源碼搜搜


導(dǎo)出函數(shù)

搜了一下源碼得到一下聲明

MonoMethod *mono_get_method (MonoImage *image, uint32_t token, MonoClass *klass);
MonoMethod *mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count);
MonoMethod *mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags);
MonoMethod *mono_class_get_methods       (MonoClass* klass, void **iter);

第一個token我們不好找,放棄
第二個flags也不好找,放棄
第四個顯然就是一個通過class來遍歷method的方法,可用但是沒必要


  • 找到 MonoClass

所以看參數(shù)我們要去找 MonoClass,那繼續(xù)去找導(dǎo)出函數(shù)


O475Z2F~WT6XC)51D_SM)SB.png

于是找到了 mono_class_from_name

//函數(shù)聲明
MonoClass *mono_class_from_name       (MonoImage *image, const char* name_space, const char *name);

struct _MonoMethod {
    guint16 flags;  /* method flags */
    guint16 iflags; /* method implementation flags */
    guint32 token;
    MonoClass *klass; /* To what class does this method belong */
    MonoMethodSignature *signature;
    /* name is useful mostly for debugging */
    const char *name;
    .....
}

struct _MonoClass {
    MonoClass *element_class; 
    MonoClass *cast_class; 
    MonoClass **supertypes;
    guint16     idepth;
    guint8     rank;          
    int        instance_size; 
    ......
    MonoImage *image;
    const char *name;
    const char *name_space;
    ......
}

struct _MonoMethodSignature {
    MonoType     *ret;
#ifdef MONO_SMALL_CONFIG
    guint8        param_count;
    gint8         sentinelpos;
    unsigned int  generic_param_count : 5;
#else
    guint16       param_count;
    gint16        sentinelpos;
    unsigned int  generic_param_count : 16;
#endif
    unsigned int  call_convention     : 6;
    unsigned int  hasthis             : 1;
    unsigned int  explicit_this       : 1;
    unsigned int  pinvoke             : 1;
    unsigned int  is_inflated         : 1;
    unsigned int  has_type_parameters : 1;
    MonoType     *params [MONO_ZERO_LEN_ARRAY];
};

  • 找到函數(shù)Method

由此我們需要的參數(shù)也都籌齊了,寫出一下hook代碼

/**
 * 獲得 MonoMethod
 * getMethod("UnityEngine","UnityEngine","Application","get_identifier",0)
 * getMethod("UnityEngine",'UnityEngine','Debug',"LogError",1,true)
 * @param {String}  imageName 
 * @param {String}  NameSpace 
 * @param {String}  className 
 * @param {String}  FunctName 
 * @param {Int}     argsCount 
 * @param {Boolean} showDetail 
 */
function getMethod(imageName,NameSpace,className,FunctName,argsCount,showDetail){
    if (imageName==undefined ||NameSpace==undefined||className==undefined||FunctName==undefined||argsCount==undefined) return ptr(0)
    if (showDetail == undefined) showDetail = false
    // var mono_thread_attach = new NativeFunction(Module.findExportByName(soName,"mono_thread_attach"),'pointer',['pointer'])
    // var mono_get_root_domain = new NativeFunction(Module.findExportByName(soName,"mono_get_root_domain"),'pointer',[])
    var mono_class_from_name = new NativeFunction(Module.findExportByName(soName,"mono_class_from_name"),'pointer',['pointer','pointer','pointer'])
    var mono_class_get_method_from_name = new NativeFunction(Module.findExportByName(soName,"mono_class_get_method_from_name"),'pointer',['pointer','pointer','int'])
    var mono_image_loaded = new NativeFunction(Module.findExportByName(soName,"mono_image_loaded"),'pointer',['pointer'])

    // mono_thread_attach(mono_get_root_domain())

    var p_image = getImageByName(imageName) == 0 ? mono_image_loaded(allcStr(imageName)) : getImageByName(imageName)
    var p_class = mono_class_from_name(ptr(p_image),allcStr(NameSpace),allcStr(className))
    var p_method = mono_class_get_method_from_name(p_class,allcStr(FunctName),argsCount)

    if (!showDetail) return ptr(p_method)

    LOG(getLine(85),LogColor.C33)
    LOG("MonoImage\t---->\t"+p_image,LogColor.C36)
    LOG("MonoClass\t---->\t"+p_class,LogColor.C36)
    LOG("MonoMethod\t---->\t"+p_method + " ("+ReadMethodName(p_method)+")",LogColor.C36)
    LOG(getLine(85),LogColor.C33)
}

運行見效果:


運行見效果

  • 主動調(diào)用函數(shù)

簡單的看了一下導(dǎo)出函數(shù),發(fā)現(xiàn)有一個 mono_runtime_invoke 傳參就是 MonoMethod
于是可以嘗試主動調(diào)用

//MonoObject* mono_runtime_invoke (MonoMethod *method, void *obj, void **params,MonoObject **exc);
var mono_runtime_invoke = new NativeFunction(Module.findExportByName(soName,"mono_runtime_invoke"),'pointer',['pointer','pointer','pointer','pointer'])
function invoke(monoMethod, obj, params,monoObject){
    obj = obj == undefined ? NULL : obj
    params = params == undefined ? NULL : params
    monoObject = monoObject == undefined ? NULL : monoObject
    return mono_runtime_invoke(ptr(monoMethod),obj,params,monoObject) 
}

這里選了一個get_identifier 來主動調(diào)用,可以發(fā)現(xiàn)沒問題
(但是這里僅限于不帶參數(shù)的Static方法)


主動調(diào)用

看著這個mono_runtime_invoke(MonoMethod *method, void *obj, void **params,MonoObject **exc)的聲明參數(shù)就不想看他了,可以去研究,但是有更簡單的方法,這里就簡述一下這個簡單的方法
我們換一個思路,總所周知,dll是被加載進去內(nèi)存在動態(tài)編譯的,這里我們手動調(diào)用mono_compile_method來編譯這個MonoMethod即可得到類似于il2cpp中的MethodInfo的函數(shù)指針,詳見下圖

函數(shù)內(nèi)存地址

  • 能去攔截函數(shù)的調(diào)用并獲取和修改參數(shù)及其返回值

最后這部分也沒啥好說的了,函數(shù)地址都有了,剩下的就是交給各位大佬為所欲為了

function TestAttach(){
    HookMonoMethod("UnityEngine",'UnityEngine','Debug',"LogError",1,{
        onEnter:function(args){
            LOG(readU16(args[0]))
        },
        onLeave:function(ret){}
    })
}

function HookMonoMethod(imageName,NameSpace,className,FunctName,argsCount,callbacks) {
    var mPtr = mono_compile_method(getMethod(imageName,NameSpace,className,FunctName,argsCount))
    Interceptor.attach(ptr(mPtr),callbacks)
}

補充:

https://github.com/axhlzy/Il2CppHookScripts/tree/master/MonoHook

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • [#go74pe]比較typeof與instanceof? 相同點:JavaScript 中 typeof 和 i...
    劉巴哥閱讀 157評論 0 0
  • 轉(zhuǎn)自長亭知乎專欄,實習(xí)時小姐姐的約稿,已經(jīng)不在那邊了所以版權(quán)不歸我哈 筆者一直自認玩過不少游戲,無奈水平太菜,日常...
    hyrathon閱讀 1,932評論 0 0
  • 0x00 引子 平時做應(yīng)用測試時,手機root對測試人員來說是件很重要的事(沙箱目錄訪問、代碼hook等操作),但...
    老江_閱讀 5,809評論 2 7
  • 推薦指數(shù): 6.0 書籍主旨關(guān)鍵詞:特權(quán)、焦點、注意力、語言聯(lián)想、情景聯(lián)想 觀點: 1.統(tǒng)計學(xué)現(xiàn)在叫數(shù)據(jù)分析,社會...
    Jenaral閱讀 5,970評論 0 5
  • 城空了,有樹長出來 我的城死了 鑄起它的人,殺死它的人 不愿因為這件事而驕傲 一座城的終結(jié) 永遠因為終結(jié)這件事而顯...
    于十六閱讀 3,090評論 6 17

友情鏈接更多精彩內(nèi)容