日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

进击的Android Hook 注入术《四》

發布時間:2025/3/15 Android 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 进击的Android Hook 注入术《四》 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄(?)[-]

  • 繼續
  • 注入之后
  • 示例三
  • 輸出
  • 最后
  • 繼續

    在前《一》、《二》、《三》里已經把注入的技術介紹完了,這章開始說注入之后需要做的事情。如果對注入技術已經比較熟悉了,那么可以直接看本章,否則建議先把前三章閱讀一遍會比較好。

    注入之后

    完成了注入,那只是萬里長征的第一步。 眾所周知,Android的應用進程,都是由Zygote孵化的子進程,每個進程都運行在獨立的JVM中。通過ptrace的注入方式,我們得到了在目標進程執行代碼的機會,但距離修改JVM的內容,還差那么一點點。我們重新看一下《二》中被注入SO的關鍵代碼: [cpp] view plain copy
  • void?Main();????
  • ????
  • static?void*?_main(void*){????
  • ????Main();????
  • ????return?NULL;????
  • }????
  • ????
  • class?EntryClass?{????
  • public:????
  • ????
  • ????EntryClass()?{????
  • ????????pthread_t?tid;????
  • ????????pthread_create(&tid,?NULL,?_main,?NULL);????
  • ????????pthread_detach(tid);????
  • ????}????
  • ????
  • }?boy;????
  • 當so被注入后,我們的邏輯代碼實際上是跑在一個Linux線程上,這樣做的目的是為了不對主線程造成干擾。我們的目標是打通Java層,很自然的聯想到JNI,通過JNI我們就是可以跟Java層互動了。但這里缺少了一個非常重要的元素——JNIEnv,沒有這個對象,JNI就無從說起了。

    示例三

    我們知道,在JVM進程中,JavaVM是全局唯一的,而JNIEnv則是按線程分配。另外,Dalvik的線程跟Linux線程是一一對應的,因此我們可以把自身所在的線程Attatch到JavaVM,JavaVM就會為我們分配JNIEnv對象了。通過閱讀Dalvik源碼,從AndroidRuntime中我們可以得到JavaVm的地址,再通過JavaVm所提供的AttachCurrentThead和DetachCurrentThread兩個函數,即可完成JNIEnv的獲取,示例代碼如下: [java] view plain copy
  • JNIEnv?*jni_env?=?NULL;??
  • JavaVM?*jvm?=?AndroidRuntime::getJavaVM();??
  • jvm-AttachCurrentThread(&jni_env,?NULL);??
  • //TODO?使用JNIEnv??
  • ??
  • jvm->DetachCurrentThread();??
  • 至此,我們就拿到了至關重要的JNIEnv對象了。接下來,我們通過DexClassLoader加載我們的dex文件,關鍵代碼如下所示: 先找到SystemClassLoader [cpp] view plain copy
  • //ClassLoader.getSystemClassLoader()??
  • static?jobject?getSystemClassLoader(){??
  • ?jclass?class_loader_claxx?=?jni_env->FindClass("java/lang/ClassLoader");??
  • ?snprintf(sig_buffer,?512,?"()%s",?JCLASS_LOADER);??
  • ?jmethodID?getSystemClassLoader_method?=?jni_env->GetStaticMethodID(class_loader_claxx,?"getSystemClassLoader",?sig_buffer);??
  • ?return?jni_env->CallStaticObjectMethod(class_loader_claxx,?getSystemClassLoader_method);??
  • }??
  • 然后通過SystemClassLoader,生成DexClassLoader對象 [cpp] view plain copy
  • snprintf(sig_buffer,?512,?"(%s%s%s%s)V",?JSTRING,?JSTRING,?JSTRING,?JCLASS_LOADER);??
  • jmethodID?dexloader_init_method?=?jni_env->GetMethodID(dexloader_claxx,?"<init>",?sig_buffer);??
  • ??
  • snprintf(sig_buffer,?512,?"(%s)%s",?JSTRING,?JCLASS);??
  • jmethodID?loadClass_method?=?jni_env->GetMethodID(dexloader_claxx,?"loadClass",?sig_buffer);??
  • ??
  • jobject?class_loader?=?getSystemClassLoader();??
  • check_value(class_loader);??
  • ??
  • jobject?dex_loader_obj?=?jni_env->NewObject(dexloader_claxx,?dexloader_init_method,?apk_path,?dex_out_path,?NULL,?class_loader);??
  • 最后再通過dex_loader_obj加載dex,找到自定義方法的入口,并調用 [cpp] view plain copy
  • jstring?class_name?=?jni_env->NewStringUTF("com.demo.inject2.EntryClass");??
  • jclass?entry_class?=?static_cast<jclass>(jni_env->CallObjectMethod(dex_loader_obj,?loadClass_method,?class_name));??
  • ??
  • jmethodID?invoke_method?=?jni_env->GetStaticMethodID(entry_class,?"invoke",?"(I)[Ljava/lang/Object;");??
  • check_value(invoke_method);??
  • ??
  • jobjectArray?objectarray?=?(jobjectArray)?jni_env->CallStaticObjectMethod(entry_class,?invoke_method,?0);??
  • 至此我們的dex邏輯開始執行了。我讓com.demo.inject2.EntryClass.invoke作為的入口函數,從invoke里用上《三》示例中的com.demo.inject的代碼,對com.demo.host打印的數據再進行修改(同一個進程被連續注入兩次,應該是比較痛苦的)。下面看看inject2中invoke的代碼: [java] view plain copy
  • package?com.demo.inject2;??
  • ??
  • import?java.lang.reflect.Method;??
  • ??
  • import?android.content.Context;??
  • import?android.util.Log;??
  • ??
  • /**?
  • ?*??
  • ?*?@author?boyliang?
  • ?*??
  • ?*/??
  • public?final?class?EntryClass?{??
  • ??
  • ????public?static?Object[]?invoke(int?i)?{??
  • ??
  • ????????try?{??
  • ????????????Log.i("TTT",?">>>>>>>>>>>>>I?am?in,?I?am?a?bad?boy?2!!!!<<<<<<<<<<<<<<");??
  • ????????????Context?context?=?ContexHunter.getContext();??
  • ????????????Class<?>?MainActivity_class?=?context.getClassLoader().loadClass("com.demo.host.MainActivity");??
  • ????????????Method?setA_method?=?MainActivity_class.getDeclaredMethod("setA",?int.class);??
  • ????????????setA_method.invoke(null,?1);??
  • ????????}?catch?(Exception?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ??
  • ????????return?null;??
  • ????}??
  • }??
  • 代碼跟《三》的示例非常相似,只是入口點不一樣罷了。注意,這里同樣有雙親委派的限制。

    輸出

    am start com.demo.host/.MainActivity
    ./poison /data/local/tmp/libimportdex.so 738

    看看示例三的輸出 [plain] view plain copy
  • com.demo.inject?starts.??
  • I/TTT?????(??738):?com.demo.host?starts??
  • I/TTT?????(??738):?1??
  • I/TTT?????(??738):?2??
  • I/TTT?????(??738):?3??
  • I/TTT?????(??738):?4??
  • I/TTT?????(??738):?5??
  • I/TTT?????(??738):?>>>>>>>>>>>>>I?am?in,?I?am?a?bad?boy!!!!<<<<<<<<<<<<<<??
  • I/TTT?????(??738):?998??
  • I/TTT?????(??738):?999??
  • I/TTT?????(??738):?1000??
  • I/TTT?????(??738):?1001??
  • I/TTT?????(??738):?1002??
  • I/TTT?????(??738):?1003??
  • I/TTT?????(??738):?>>>>>>>>>>>>>I?am?in,?I?am?a?bad?boy?2!!!!<<<<<<<<<<<<<<??
  • I/TTT?????(??738):?1??
  • I/TTT?????(??738):?2??
  • I/TTT?????(??738):?3??
  • I/TTT?????(??738):?4??
  • I/TTT?????(??738):?5??
  • I/TTT?????(??738):?6??
  • I/TTT?????(??738):?7??
  • 從兩次的字符串輸出,證明這次的注入修改已經成功了。 示例中的所有代碼,都已經上傳到https://github.com/boyliang/Java_Injection

    最后

    到目前為止,我們已經實現如下功能:
    • 注入目標進程
    • 獲取JNIEnv地址;
    • 另目標進程加載Dex,并執行指定的方法;

    距離我們的目標,還差一步——截獲broadcastIntent方法,在《五》里我會再介紹一種叫BinderProxy的技術,通過這種技術,我們可以截獲任意的BinderService的方法。



    原文地址: http://blog.csdn.net/l173864930/article/details/38467497

    總結

    以上是生活随笔為你收集整理的进击的Android Hook 注入术《四》的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。