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

歡迎訪問 生活随笔!

生活随笔

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

Android

Android 联想K5 Play 8.0 Notification突破拦截(vdex反编译 )

發布時間:2023/12/15 Android 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 联想K5 Play 8.0 Notification突破拦截(vdex反编译 ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:

部分國內ROM系統對消息欄做了攔截,因此,需要用戶手動授權開啟消息欄通知。 若是能夠找到開啟的代碼,是否可以繞過攔截,默認開啟呢?

本篇文章,介紹如何找到攔截點,如何去突破。至于其他的ROM系統的攔截,也是類似。

聯想K5 Play為案 , 探究消息欄突破攔截


1. 獲取到system文件夾

通過下載系統的Rom 包,或者adb pull方式獲取到系統的system下的文件。

具體如何操作,請閱讀Android反編譯之各大手機廠商的系統(adb pull和Rom包).

這里,本人通過去聯想官網下載到對應Rom壓縮包,再通過Rom助手,提取出system文件夾,如下圖所示:

2. 反編譯Framework層源碼或者系統app的源碼

找到system/framework文件夾下,通常都是反編譯boot.oat就可以獲取到Android.jar對應的系統源碼,但這里會發現多個了一個vdex文件,如下圖所示:

通過查找度娘,這里,稍微總結一下:

  • dex: 是Android平臺上(Dalvik虛擬機)的可執行文件,里面包含了該app的所有源碼, 通過反編譯工具可以獲取到相應的java源碼。
  • odex: 是同名apk經系統優化后的dex文件,通過反編方式可獲取到dex文件。
  • vdex:Android 8.0引入了全新的vdex文件,為了避免不必要的驗證Dex 文件合法性的過程,通過反編方式獲取到dex文件。

更多dex, odex,vdex,oat的資料,請自行度娘搜索。

將oat2dex.jar拷貝到該system/framework文件夾下,然后,打開命令行執行java -jar oat2dex.jar boot.vdex ,納尼,神奇發現,里面沒有需要的源碼,找到一個假的李逵。

苦命的娃,繼續找,直到反編譯boot-framework.vdex,會發現android.jar里面的源碼藏到這里了,如下圖所示:


實際上,部分Rom廠商的android.jar的源碼放到boot.oat或者boot-framework.oat 中

依葫蘆畫瓢,繼續反編譯service.vdex,獲取到sevice層的系統源碼。

3. 查找對應的攔截或者開啟的源碼

查看framework.dex ,service.dex的源碼,一路追蹤,會發現最后跑到SystemUI 中PhoneStatubar類開啟了Notification。這里不探討Notificatin源碼分析走向,否則,文章篇幅會過大。

打開聯想K5 Play的設置,一直到到開啟消息欄的界面,如下圖所示:

這時候,只需要確定該Activity處于哪個apk中,就可以反編譯,從而查看到開啟的代碼。

查看界面屬于哪個Activity:

執行以下命令行adb shell dumpsys activity top查看到棧頂的Activity ,這里是Activity是SubSettings,顯示的fragment是AppNotificationSettings。

查看當前Activity屬于哪個Apk

執行以下命令行adb shell dumpsys activity activities ,發現當前activity屬于sysytem/priv-app/ZuiSetttings/ZuiSettings.apk

反編譯ZuiSettings.vdex獲取到對應的dex文件,打開如下:

在AppNotificationSettings類中,查找到開啟消息欄的源碼:

protected void setupBlock() {View inflate = LayoutInflater.from(getPrefContext()).inflate(R.layout.styled_switch_bar, null);this.mSwitchBar = (SwitchBar) inflate.findViewById(R.id.switch_bar);this.mSwitchBar.addOnSwitchChangeListener(new OnSwitchChangeListener() {public void onSwitchChanged(Switch switchR, boolean z) {boolean z2 = false;if (AppNotificationSettings.this.mShowLegacyChannelConfig && AppNotificationSettings.this.mChannel != null) {int i = z ? NotificationManagerCompat.IMPORTANCE_UNSPECIFIED : 0;RestrictedSwitchPreference restrictedSwitchPreference = AppNotificationSettings.this.mImportanceToggle;if (i == NotificationManagerCompat.IMPORTANCE_UNSPECIFIED) {z2 = true;}restrictedSwitchPreference.setChecked(z2);//這里是重點AppNotificationSettings.this.mChannel.setImportance(i);AppNotificationSettings.this.mChannel.lockFields(4);AppNotificationSettings.this.mBackend.updateChannel(AppNotificationSettings.this.mPkg, AppNotificationSettings.this.mUid, AppNotificationSettings.this.mChannel);}//這里是重點AppNotificationSettings.this.mBackend.setNotificationsEnabledForPackage(AppNotificationSettings.this.mPkgInfo.packageName, AppNotificationSettings.this.mUid, z);AppNotificationSettings.this.mAppRow.banned = true;AppNotificationSettings.this.updateDependents(z ^ 1);if (z) {AppNotificationSettings.this.mSwitchBar.setText(AppNotificationSettings.this.getResources().getString(R.string.notification_allow));} else {AppNotificationSettings.this.mSwitchBar.setText(AppNotificationSettings.this.getResources().getString(R.string.notification_close));}}});}

以上的代碼中mBackend屬性對應是NotificationBackend類對象,打開該類查看調用的updateChannel()和setNotificationsEnabledForPackage():

public class NotificationBackend {private static final String TAG = "NotificationBackend";static INotificationManager sINM = Stub.asInterface(ServiceManager.getService("notification"));//省略部分代碼public boolean setNotificationsEnabledForPackage(String str, int i, boolean z) {try {sINM.setNotificationsEnabledForPackage(str, i, z);return true;} catch (Throwable e) {Log.w(TAG, "Error calling NoMan", e);return false;}}public void updateChannel(String str, int i, NotificationChannel notificationChannel) {try {sINM.updateNotificationChannelForPackage(str, i, notificationChannel);} catch (Throwable e) {Log.w(TAG, "Error calling NoMan", e);}} }

最終,發現是跨進程通訊,調用在NotificationManagerService中。

4. 編寫適配對應Rom的代碼

根據以上的源碼追蹤,鎖定如何開啟的功能代碼。編寫以下反射代碼:

/*** 聯想 K5 play 8.0系統適配: 需要系統進程(未適配成功)** @param context*/private static void adapterZUISystem8(Context context) {String packageName = context.getPackageName();try {Class<?> NotificationManager = Class.forName("android.app.NotificationManager");Method getService = NotificationManager.getDeclaredMethod("getService");getService.setAccessible(true);Object mNotificationService = getService.invoke(null);int uid = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0).uid;try {final int IMPORTANCE_UNSPECIFIED = -1000;//先獲取到NotificationChannelMethod getNotificationChannelForPackageMethod = mNotificationService.getClass().getMethod("getNotificationChannelForPackage", String.class, int.class, String.class, boolean.class);getNotificationChannelForPackageMethod.setAccessible(true);Object NotificationChannel = getNotificationChannelForPackageMethod.invoke(mNotificationService, packageName, uid, "miscellaneous", true);//設置NotificationChannel中值Method setImportanceMethod = NotificationChannel.getClass().getDeclaredMethod("setImportance", int.class);setImportanceMethod.setAccessible(true);setImportanceMethod.invoke(NotificationChannel, IMPORTANCE_UNSPECIFIED);Method lockFieldsMethod = NotificationChannel.getClass().getDeclaredMethod("lockFields", int.class);lockFieldsMethod.setAccessible(true);lockFieldsMethod.invoke(NotificationChannel, 4);//更新NotificationChannelMethod updateNotificationChannelForPackageMethod = mNotificationService.getClass().getMethod("updateNotificationChannelForPackage", String.class, int.class, Class.forName("android.app.NotificationChannel"));updateNotificationChannelForPackageMethod.setAccessible(true);updateNotificationChannelForPackageMethod.invoke(mNotificationService, packageName, uid, NotificationChannel);} catch (Exception e) {e.printStackTrace();}Method setNotificationsEnabledForPackage = mNotificationService.getClass().getMethod("setNotificationsEnabledForPackage", String.class, int.class, boolean.class);setNotificationsEnabledForPackage.setAccessible(true);setNotificationsEnabledForPackage.invoke(mNotificationService, context.getPackageName(), uid, true);} catch (Exception e) {e.printStackTrace();}}

開開心心的運行以上代碼,結果還是很悲催,報錯安全 SecurityException異常。猜測該方式只能在系統進程中調用。

為了驗證一番,打開service.dex,找到NotificationManagerService類,找到該調用方法,如下圖所示:

查看checkCallerIsSystem()

private void checkCallerIsSystem() {if (!isCallerSystemOrPhone()) {throw new SecurityException("Disallowed call for uid " + Binder.getCallingUid());}}

最后,不得不放棄,宣告適配失敗。

這里扯上幾句屁話

  • 適配國產ROM系統,程序員還是很辛苦的,特別是遇到混淆后的系統源碼,盯著幾個a ,b ,c,簡直需要誦讀佛經,消除戾氣。
  • 適配工作長路漫漫,需要不斷的探索,和打抗日持久戰的耐心
  • 適配沒有成功也不需要氣餒,不過接下來的時候,就該讓公司的商務出馬,和手機廠商談合作,增加白名單。

資源參考

  • Android反編譯之各大手機廠商的系統(adb pull和Rom包)
  • Android反編譯之APK(apktool、dex2jar、jd、jadx)

總結

以上是生活随笔為你收集整理的Android 联想K5 Play 8.0 Notification突破拦截(vdex反编译 )的全部內容,希望文章能夠幫你解決所遇到的問題。

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