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

歡迎訪問 生活随笔!

生活随笔

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

Android

【Android 安全】DEX 加密 ( Application 替换 | 分析 ContentProvider 组件中调用 getApplication() 获取的 Application 二 )

發布時間:2025/6/17 Android 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android 安全】DEX 加密 ( Application 替换 | 分析 ContentProvider 组件中调用 getApplication() 获取的 Application 二 ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一、 ActivityThread 中的 installProvider 方法 ( 創建 ContentProvider 內容提供者 )
  • 二、 installProvider 方法的第三分支分析
  • 三、 ContextImpl 中 createPackageContext 方法分析
  • 四、ContentProvider 中替換 Application 的總結



前置博客 : 【Android 安全】DEX 加密 ( Application 替換 | 分析 ContentProvider 組件中調用 getApplication() 獲取的 Application )





一、 ActivityThread 中的 installProvider 方法 ( 創建 ContentProvider 內容提供者 )



在 installProvider 方法中 , 通過 反射創建 ContentProvider ;

// ★ 反射創建 ContentProvider localProvider = (ContentProvider)cl.loadClass(info.name).newInstance();

在 創建 ContentProvider 之后 , 調用了 attachInfo 函數 , 注意此處與 Activity , Service , BrocastReceiver 不同 , 這三個組件創建后調用的是 attach 函數 ;

// XXX Need to create the correct context for this provider. // ★ 創建 ContentProvider 之后 , 調用了 attachInfo 函數 // 注意此處與 Activity , Service , BrocastReceiver 不同 , // 這三個組件創建后調用的是 attach 函數 localProvider.attachInfo(c, info);

這里分析 attachInfo 中的 c 參數 , 也就是 Context 上下文的獲取過程 :

聲明空的 Context c 對象 ,

// ★ 該上下文對象很重要 Context c = null;

獲取 ApplicationInfo 信息 ApplicationInfo ai , 即 AndroidManifest.xml 中配置的 application 節點信息

// 該 ApplicationInfo 是 AndroidManifest.xml 中配置的 application 節點信息 ApplicationInfo ai = info.applicationInfo;

進行如下三個分支的判定 :

  • 分支一 : if (context.getPackageName().equals(ai.packageName)) : 在應用中配置的代理 Application 包名與真實 Application 包名都是相等的 ;
  • 分之二 : else if (mInitialApplication != null && mInitialApplication.getPackageName().equals(ai.packageName)) : 與分支一類似 , 也是要求包名相等 ;
  • 分支三 : 上面兩個分支沒有命中 , 就執行第三個分支 ;
// ★ 該上下文對象很重要 Context c = null;// 該 ApplicationInfo 是 AndroidManifest.xml 中配置的 application 節點信息ApplicationInfo ai = info.applicationInfo;// 該 context 是 ProxyApplication , 代理 Application if (context.getPackageName().equals(ai.packageName)) {// 在應用中配置的代理 Application 包名與真實 Application 包名都是相等的// 該分支是命中的 c = context;} else if (mInitialApplication != null &&mInitialApplication.getPackageName().equals(ai.packageName)) {// 該分支中 mInitialApplication 就是 Context context 參數 , 肯定不為空 // 該分支無法命中 c = mInitialApplication;} else {// 上述兩個分支都無法命中 , 才進入該分支 // 需要將代理 Application 的包名 與 真實應用的包名設置成不同的// 此時上面兩個分支都無法命中 try {c = context.createPackageContext(ai.packageName,Context.CONTEXT_INCLUDE_CODE);} catch (PackageManager.NameNotFoundException e) {// Ignore}}

上面的分支一 與 分支二 都是將 代理 Application 分支 , 因此必須要命中第三個分支 ;

如果將 代理 Application 的 getPackageName() 獲取包名的方法返回空 , 此時肯定無法命中前兩個分支 , 只能命中第三分支 ;


相關代碼示例 :

public final class ActivityThread {/*** Installs the provider.** Providers that are local to the process or that come from the system server* may be installed permanently which is indicated by setting noReleaseNeeded to true.* Other remote providers are reference counted. The initial reference count* for all reference counted providers is one. Providers that are not reference* counted do not have a reference count (at all).** This method detects when a provider has already been installed. When this happens,* it increments the reference count of the existing provider (if appropriate)* and returns the existing provider. This can happen due to concurrent* attempts to acquire the same provider.*/private ContentProviderHolder installProvider(Context context,ContentProviderHolder holder, ProviderInfo info,boolean noisy, boolean noReleaseNeeded, boolean stable) {// ★ 聲明 ContentProvider ContentProvider localProvider = null;IContentProvider provider;if (holder == null || holder.provider == null) {if (DEBUG_PROVIDER || noisy) {Slog.d(TAG, "Loading provider " + info.authority + ": "+ info.name);}// 該上下文對象很重要 Context c = null;ApplicationInfo ai = info.applicationInfo;// 該 context 是 ProxyApplication , 代理 Application if (context.getPackageName().equals(ai.packageName)) {// 在應用中配置的代理 Application 包名與真實 Application 包名都是相等的// 該分支是命中的 c = context;} else if (mInitialApplication != null &&mInitialApplication.getPackageName().equals(ai.packageName)) {// 該分支中 mInitialApplication 就是 Context context 參數 , 肯定不為空 // 該分支無法命中 c = mInitialApplication;} else {// 上述兩個分支都無法命中 , 才進入該分支 // 需要將代理 Application 的包名 與 真實應用的包名設置成不同的// 此時上面兩個分支都無法命中 try {c = context.createPackageContext(ai.packageName,Context.CONTEXT_INCLUDE_CODE);} catch (PackageManager.NameNotFoundException e) {// Ignore}}if (c == null) {Slog.w(TAG, "Unable to get context for package " +ai.packageName +" while loading content provider " +info.name);return null;}try {final java.lang.ClassLoader cl = c.getClassLoader();// ★ 反射創建 ContentProvider localProvider = (ContentProvider)cl.loadClass(info.name).newInstance();provider = localProvider.getIContentProvider();if (provider == null) {Slog.e(TAG, "Failed to instantiate class " +info.name + " from sourceDir " +info.applicationInfo.sourceDir);return null;}if (DEBUG_PROVIDER) Slog.v(TAG, "Instantiating local provider " + info.name);// XXX Need to create the correct context for this provider.// ★ 創建 ContentProvider 之后 , 調用了 attachInfo 函數 // 注意此處與 Activity , Service , BrocastReceiver 不同 , // 這三個組件創建后調用的是 attach 函數localProvider.attachInfo(c, info);} catch (java.lang.Exception e) {return null;}} else {}return retHolder;}}

參考路徑 : frameworks/base/core/java/android/app/ActivityThread.java





二、 installProvider 方法的第三分支分析



下面代碼中的三個分支就是給 ContentProvider 組件設置 Application 上下文的代碼 ;

public final class ActivityThread {private ContentProviderHolder installProvider(Context context,ContentProviderHolder holder, ProviderInfo info,boolean noisy, boolean noReleaseNeeded, boolean stable) {// 該上下文對象很重要 Context c = null;ApplicationInfo ai = info.applicationInfo;// 該 context 是 ProxyApplication , 代理 Application if (context.getPackageName().equals(ai.packageName)) {// 在應用中配置的代理 Application 包名與真實 Application 包名都是相等的// 該分支是命中的 c = context;} else if (mInitialApplication != null &&mInitialApplication.getPackageName().equals(ai.packageName)) {// 該分支中 mInitialApplication 就是 Context context 參數 , 肯定不為空 // 該分支無法命中 c = mInitialApplication;} else {// 上述兩個分支都無法命中 , 才進入該分支 // 需要將代理 Application 的包名 與 真實應用的包名設置成不同的// 此時上面兩個分支都無法命中 try {c = context.createPackageContext(ai.packageName,Context.CONTEXT_INCLUDE_CODE);} catch (PackageManager.NameNotFoundException e) {// Ignore}}return retHolder;}}

參考路徑 : frameworks/base/core/java/android/app/ActivityThread.java


在上面的分析中 , 如果要使得分支一 context.getPackageName().equals(ai.packageName) 與分支二 mInitialApplication.getPackageName().equals(ai.packageName) , 都無法命中 , 就需要 Application 的 getPackageName 方法獲取的包名不等于在 AndroidManifest.xml 中的包名 ai.packageName , 這里重寫 ProxyApplication 的 getPackageName 方法 , 使該方法返回值為 “” 字符串 , 這樣就無法命中前兩個分支 , 只能進入 else 分支 ;





三、 ContextImpl 中 createPackageContext 方法分析



繼續分析 分支三 中的內容 , 如果 Application 的 getPackageName 方法返回 “” , 將導致分支一二都沒有命中 , 進入分支三 ;

public final class ActivityThread {private ContentProviderHolder installProvider(Context context,ContentProviderHolder holder, ProviderInfo info,boolean noisy, boolean noReleaseNeeded, boolean stable) {// 該上下文對象很重要 Context c = null;ApplicationInfo ai = info.applicationInfo;// 該 context 是 ProxyApplication , 代理 Application if (context.getPackageName().equals(ai.packageName)) {} else if (mInitialApplication != null &&mInitialApplication.getPackageName().equals(ai.packageName)) {} else {// 上述兩個分支都無法命中 , 才進入該分支 // 需要將代理 Application 的包名 與 真實應用的包名設置成不同的// 此時上面兩個分支都無法命中 try {c = context.createPackageContext(ai.packageName,Context.CONTEXT_INCLUDE_CODE);} catch (PackageManager.NameNotFoundException e) {// Ignore}}return retHolder;}}

參考路徑 : frameworks/base/core/java/android/app/ActivityThread.java


分支三中調用了 , context 的 createPackageContext(ai.packageName, Context.CONTEXT_INCLUDE_CODE) 方法 , 該方法在 ContextImpl 中定義 ;

在 ContextImpl 中的 createPackageContext 方法 , 調用了 createPackageContextAsUser 方法 , 調用了如下代碼 , 創建 Context 上下文 ,

ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, user,flags, null);

上述代碼中創建 ContextImpl 時 , 使用的 mMainThread , pi , 都沒有替換過 Application , 因此分支三創建的 ContentProvider 對應的 Application 也是代理 Application , 替換前的 Application 對象 ;


class ContextImpl extends Context {// 在該方法中調用了 createPackageContextAsUser 方法創建上下文@Overridepublic Context createPackageContext(String packageName, int flags)throws NameNotFoundException {return createPackageContextAsUser(packageName, flags,mUser != null ? mUser : Process.myUserHandle());}@Overridepublic Context createPackageContextAsUser(String packageName, int flags, UserHandle user)throws NameNotFoundException {if (packageName.equals("system") || packageName.equals("android")) {// The system resources are loaded in every application, so we can safely copy// the context without reloading Resources.return new ContextImpl(this, mMainThread, mPackageInfo, null, mActivityToken, user,flags, null);}// 注意該 LoadedApk 對象LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());if (pi != null) {// 創建新的 ContextImpl // 此時還沒有替換 Application ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, user,flags, null);final int displayId = mDisplay != null? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;c.setResources(createResources(mActivityToken, pi, null, displayId, null,getDisplayAdjustments(displayId).getCompatibilityInfo()));if (c.mResources != null) {return c;}}// Should be a better exception.throw new PackageManager.NameNotFoundException("Application package " + packageName + " not found");}}

源碼路徑 : frameworks/base/core/java/android/app/ContextImpl.java

ContextImpl 中的 public Context createPackageContext(String packageName, int flags) 方法是公開方法 , 重寫該方法 , 在重寫的 createPackageContext 方法中 , 先進行一次 Application 替換 , 然后繼續執行 super.createPackageContext 方法的后續操作 , 這樣創建的 ContentProvider 中的上下文就是用戶自定義的 MyApplication , 不再是 ProxyApplication ;

只有在創建 ContentProvider 時才調用到該 createPackageContext 方法 , 如果沒有調用到該方法 , 說明該應用中沒有配置 ContentProvider ;





四、ContentProvider 中替換 Application 的總結



ContentProvider 中替換 Application 的總結 :

  • ① 分支選擇 : 首先要命中 ActivityThread 中 installProvider 方法的分支三 ;
  • ② Application 替換 : 然后要在 ContextImpl 的 createPackageContext 方法執行前進行一次 Application 替換 ;

總結

以上是生活随笔為你收集整理的【Android 安全】DEX 加密 ( Application 替换 | 分析 ContentProvider 组件中调用 getApplication() 获取的 Application 二 )的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 欧美色xxx | 亚洲精品一区在线观看 | 日韩欧美精品免费 | 精品自拍第一页 | 精品黄网| 亚洲高h| 精品日本视频 | 久久免费国产视频 | 懂色av蜜臀av粉嫩av分享吧最新章节 | www日韩在线观看 | 日韩深夜在线 | 大胸奶汁乳流奶水出来h | 秋霞久久精品 | 久久伊人热 | 少妇天堂网 | 在线免费观看国产精品 | 精品欧美黑人一区二区三区 | 一区二区有码 | 国产精品毛片一区二区在线看舒淇 | 尤果网福利视频在线观看 | 苏晴忘穿内裤坐公交车被揉到视频 | 奇米网7777| 精品免费av| 欧美成人黑人xx视频免费观看 | 91成人观看 | 我爱52av| 久久av资源 | 涩色网站| 91蜜桃在线观看 | 欧美久久久久久久久久久久久久 | 欧美激情喷水 | 国产欧美精品在线观看 | 日韩天堂网 | 亚洲AV无码AV吞精久久中文版 | 波多野结衣av一区二区全免费观看 | xxxx69国产 | 草草影院在线免费观看 | 免费无遮挡无码永久在线观看视频 | 一级黄色美女 | 黄色美女一级片 | 国产精品美女自拍视频 | 国产真人做爰毛片视频直播 | 欧美激情视频一区二区 | 韩国久久久 | 三级无遮挡 | 一区二区三区日韩欧美 | 国产精品伊人久久 | 色女仆影院 | 一卡二卡在线视频 | 亚洲午夜不卡 | 黑丝美女av | 久久手机免费视频 | 国产天天操 | 亚洲美女屁股眼交 | 日本精品一区二区三区四区 | 另类小说色 | 国产情侣露脸自拍 | 在线播放日韩av | 大胸喷奶水www视频妖精网站 | 国产激情久久久久 | 午夜影院免费 | 国产视频一区二区三区四区 | 96超碰在线 | 在线国产三级 | 亚洲欧美小视频 | 久青草资源福利视频 | 超碰在线香蕉 | 精品影院 | 免费人妻精品一区二区三区 | 久久aⅴ乱码一区二区三区 亚洲成人18 | 日日骑夜夜操 | 四季av在线一区二区三区 | 99热在线看| 美女扒开腿让男生桶 | 日本在线天堂 | 久久亚洲AV成人无码国产人妖 | 青春草免费视频 | 麻豆视频成人 | 亚洲人吸女人奶水 | 日日麻批免费视频播放 | 国产亚洲欧美视频 | 欧美老肥妇做.爰bbww视频 | 婷婷激情在线 | wwwxxx在线播放 | 日本高清视频一区二区 | 国产一级特黄视频 | 国产毛片在线看 | 久久精品在线 | 色av一区| 亚洲AV无码精品久久一区二区 | 97香蕉超级碰碰久久免费软件 | 国内成人免费视频 | 99热这里只有精品在线观看 | 蜜臀久久精品久久久久 | 亚洲成人www | 中国字幕一色哟哟 | 欧美亚洲另类图片 | 永久免费在线观看视频 | 黑白配高清国语在线观看 |