圌ã¯ããã¡ãŒã ãŠã§ã¢ãŸãã¯ãã®åã ã®ã³ã³ããŒãã³ãã®ãœãŒã¹ã³ãŒãã«å¹²æžããããšãªãããã®å Žã§å®è³ªçã«å€æŽã§ããåå¥ã®ã¢ãžã¥ãŒã«ã®äœ¿çšãææ¡ããŸããã ããããäžæã«è©å€ã®è¯ãéçºè ã¯çããŸããïŒã ããã...誰ããããå¿ èŠãšããŸããã ã
ããã¯çºæ¡ãæŸæ£ããŸããã§ããããéçºãç¶ããŸããã KitKatã2013幎ã«ãªãªãŒã¹ããããšããèåãªéçºè ã®åãã³ãã¥ããã£ã¯ã ã ããããããã¯ããŸãã«ãå±éºã§ã...ã§ã... ããšçããŸããã
ãã®éãGoogleã¯ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®æ°ããããŒãžã§ã³ãæ¯å¹ŽãªãªãŒã¹ããããšã決å®ããŸããã ãã¡ããããã¡ãŒã ãŠã§ã¢ãã«ã¹ã¿ãã€ãºããããšã¯æ¡ç®ãåããªããªããŸãããæ°ããããŒãžã§ã³ã®OSãç»å Žããã®ã§ããããè¡ãæéã¯ãããŸããã ãã®ããã2014幎ã«LollipopããŒãžã§ã³ãç»å Žããéçºè ã¯æçµçã«ãã¬ãŒã ãã¬ãŒã ã¯ãŒã¯ã«æ³šæãåããŸãããã å€åãããäœã§ããããèŠã䟡å€ãããã®ã§ããããïŒ
2015幎ã«æ¬¡ã®ããŒãžã§ã³ïŒMarshmallowïŒããªãªãŒã¹ããããã®çµæãã³ãã¥ããã£ã®å€§éšåã¯éçºãéåžžã«äŸ¡å€ããããšèªèããæ©èœãæ¡åŒµããåå¥ã®ã¢ãžã¥ãŒã«ãã€ã³ã¹ããŒã«ãããšãã圢ã§ã¹ããã¯ãã¡ãŒã ãŠã§ã¢ã«ã¹ã¿ãã€ãºã®éçºæéãå€§å¹ ã«ççž®ããŸããã ã ãããŒãããã¯å®å šã«å®å šã§ãæ¢è£œã®äŸ¿å©ãªã¢ãžã¥ãŒã«ã®ã©ã€ãã©ãªããããŸãïŒ ããšåœŒãã¯å«ãã ã
çŸåšã¯2017幎2ææ«ã§ãã Xposed for Nougatã¯ãŸã å©çšã§ãããèŠããã§ããéçºè ãšãŠãŒã¶ãŒã®çŸ€è¡ã¯ãã Xposedã¯åäœããŸããïŒå¿ èŠã§ãïŒããããé¡ãããŸãïŒ ã
ä»æ¥ã¯ãXposedãã¬ãŒã ã¯ãŒã¯ã«ã€ããŠã話ããŸãã
å 責äºé
æ¬æã«èšèŒãããŠãããã¹ãŠã®è£œååããã³åæšã¯ãç»é²ææè ã®è²¡ç£ã§ãã èšäºã®ããã¹ãã¯ãæè²ç®çã§å ¬éãããŠããŸãã èè ïŒ@Falseclockããã³xronofag ïŒã¯ããã®èšäºã®æ å ±ãè€è£œãŸãã¯äœ¿çšããããšããããšã«ããæ倱ãæ©åšã®æå·ãå©çã®æ倱ã«ã€ããŠè²¬ä»»ãè² ããŸããã èªã¿ç¶ããããšã«ãããèªè ã¯ãœãŒã¹ã³ãŒãã®äœ¿çšã圌ã«ãšã£ãŠãªã¹ã¯ã䌎ãå¯èœæ§ãããããšã確èªããŸãã
ãªããªãŒã
3幎以äžåã«ãAndroidã®ãã¡ãŒã ãŠã§ã¢ã®å€æŽã«é¢ããäžé£ã®èšäºãæžãå§ããŸããã çŸæç¹ã§ã¯ããããã®èšäºã®é¢é£æ§ã¯éåžžã«çããããã®ã§ããããã»ã¹ã¯éåžžã«æéãããããå€ãã®æéãšããŒã«ãå¿ èŠãšããé»è©±ãå®å šã«ãã©ãã·ã¥ããããŸã§ããããªééããé倧ãªåé¡ã«å€ããå¯èœæ§ããããŸãã
ããã§ã誰ããXabrã§Xposed Frameworkãšã¯äœãããããã¢ããªã±ãŒã·ã§ã³ã®ã«ã¹ã¿ãã€ãºããã»ã¹ãåçŽåããæ¹æ³ã説æããŠãããããšãæåŸ ããŠãç§ã¯çŽ2å¹ŽåŸ ã¡ãŸãããããã®çŽ æŽãããäœæã«ç²ŸéããŠãã人ã¯å°ãªããšæããŸãã ç§ã®ããŒãºã«åãããŠãæ°ååã®ã¢ãžã¥ãŒã«ãäœæããŸããããã®ãã¡ã®ããã€ãã¯äžè¬çãªãªããžããªã«å ¬éãããŠãããçŸåš1000å以äžã®ããã«äœ¿ããéçºãå«ãŸããŠããŸãã åã¢ãžã¥ãŒã«-ããã¯åäžã®ã«ã¹ã¿ãã€ãºã§ã¯ãªããèšå®ã€ã³ã¿ãŒãã§ãŒã¹ãŸãã¯è¿œå æ©èœãåããäžé£ã®æ©èœã§ãã ãã®é®®æãªäŸã¯ã GravityBoxãŸãã¯Sense ToolBoxã§ãã
ã€ã³ã¹ããŒã«ããã»ã¹ãšã«ãŒãæš©éã®ååŸã«ã€ããŠã¯èª¬æããŸãããããã¬ãŒã ã¯ãŒã¯ãšã¯äœããç°¡åãªã¢ãžã¥ãŒã«ã®äœææ¹æ³ã«ã€ããŠã¯èª¬æããŸãã
èšçœ®
以åã«ãµãŒãããŒãã£ã®ãã¡ãŒã ãŠã§ã¢ãã€ã³ã¹ããŒã«ããã«ã¯ãé»è©±ã®ããŒãããŒããŒã®ããã¯ã解é€ããå¿ èŠããããXposedã䜿çšããã«ã¯ãé»è©±ã®ã«ãŒãæš©éã®ã¿ãå¿ èŠã§ãã ä»ã§ããã»ãšãã©ã®ããã€ã¹ã§ãããã®æš©å©ãååŸããããšã¯ããã»ã©é£ãããããŸãããã¢ããªã±ãŒã·ã§ã³ãããŠã³ããŒããããšãããèªäœãå¿ èŠãªãã¹ãŠã®æäœãè¡ããæ°åã§GODèš±å¯ã¬ãã«ã®é»è©±ã®ææè ã«ãªããŸãã
ãæã§ãæäœããåç
Androidã«ã¯Zygoteãšããããã»ã¹ããããŸãã ãããã¡ã€ã³ã®ãšã°ãŒã¯ãã£ãã·ã¹ãã ã§ãã ãã¹ãŠã®ããã»ã¹ã¯ããã®ã³ããŒãšããŠéå§ãããŸãã Zygoteã¯ãã·ã¹ãã ã®ã¡ã€ã³ã«ãŒãã«ãèµ·åãããšããã«/init.rcçµç±ã§èµ·åããŸãã ã¢ããªã±ãŒã·ã§ã³ã¯script / system / bin / app_processãä»ããŠèµ·åãããå¿ èŠãªã¯ã©ã¹ãããŒãããã宣èšãããã¡ãœãããä»ããŠã¢ããªã±ãŒã·ã§ã³ã®åæåãéå§ãããŸãã
Xposedãã·ãŒã³ã«ç»å Žããã®ã¯ãã®å Žæã§ãã ãã¬ãŒã ã¯ãŒã¯ãã€ã³ã¹ããŒã«ãããšãå€æŽãããapp_processã/ system / binã«ã³ããŒãããŸãã å€æŽã®æ¬è³ªã¯ãè¿œå ã®jarã©ã€ãã©ãªãŒãç°å¢å€æ°ã«è¿œå ãããç¹å®ã®æ¡ä»¶ããã³ã±ãŒã¹ã§ç¹å¥ãªã¡ãœãããå®è¡ã§ããããšã§ãã ããšãã°ã Dalvikä»®æ³ãã·ã³ãäœæããããšããã«ããŸãã¯ã¡ã€ã³ã®Zygoteã¡ãœãããåŒã³åºãããåã«ä»å ¥ã§ããŸãã Zygoteããã»ã¹ã®äžéšãšããŠãåæã¡ãœãããå«ãä»»æã®ã¡ãœããã®äœæ¥ã«ä»å ¥ãããã®ã³ã³ããã¹ãã§ã¢ã¯ã·ã§ã³ãå®è¡ã§ããŸãã
Xposedã®å®çšç䟡å€
äœããã®ã¡ãœãããå€æŽããå¿ èŠããããšããŸããããšãã°ãããŒã«å€ã®ä»£ããã«FALSEãè¿ããŸãã æéãšè²»çšã®ãããåŸæ¥ã®æ¹æ³ïŒã¢ããªã±ãŒã·ã§ã³ã®åæãã¢ã»ã³ãã«ããã¹ãïŒã®ä»£ããã«ããã®ã¯ã©ã¹ã¡ãœããããã€ã³ã¿ãŒã»ãããããJavaã³ãŒãããåã蟌ã¿ããå¿ èŠãªæäœïŒãã®äŸã§ã¯å€ãå€æŽïŒãå®è¡ããå¿ èŠãªçµæãè¿ããŸãã åæã«ãXposedã䜿çšããŠãã¡ãœããã«è»¢éãããããŒã¿ãå€æŽãŸãã¯ç¢ºèªããããã¡ãœããã®å®è¡åŸã«ããŒã¿åŠçã®çµæãèŠã€ããèŠä»¶ã«å¿ããŠããããå€æŽãŸãã¯äœ¿çšããããšãã§ããŸãã
ãã®ã¡ãœããããã®ã¡ãœããããŸã£ããåäœãããããªãå Žåããããžãã¯ãšã¢ã«ãŽãªãºã ãå®å šã«å€æŽãããå ŽåããããŸãã Xposedã䜿çšãããšãã¡ãœãããå®å šã«çœ®ãæãããããŸã£ããæ©èœããªãããã«ããããšãã§ããŸãã
ãªãœãŒã¹ã®å Žåããã¹ãŠãã·ã³ãã«ã«ãªããŸããã ãªãœãŒã¹ãã¢ãžã¥ãŒã«ã«ããŒãããŸããã°ã©ãã£ãã¯ãšã¬ã¡ã³ãããœãªããxmlãã¡ã€ã«ãå«ããã¢ãžã¥ãŒã«ãã¡ã¢ãªã«ããŒããããšãã«ãåæåäžã«ãããã眮ãæããããšãã§ããŸãã
ãããŠä»ãäž»ãªãã®-å€ãã®å Žåããã¡ãŒã ãŠã§ã¢/ã¢ããªã±ãŒã·ã§ã³ã®æ°ããããŒãžã§ã³ã®ãªãªãŒã¹ã§ã¢ãžã¥ãŒã«ã®åäœãå€æŽããå¿ èŠã¯ãããŸããïŒãŸãã¯æå°éã®æ¹åãè¡ãå¿ èŠãããããŸããïŒïŒ ã¡ãœãããã¯ã©ã¹ãå€æ°ã®ååã¯ååãšããŠåããŸãŸãªã®ã§ãããã¯è«ççã§ãã
䟿å©ãããªãã§ããïŒ
ã¢ãžã¥ãŒã«äœæ
ã¢ãžã¥ãŒã«èªäœã¯ãéçºç°å¢ã§äœæãããéåžžã®apkãã¡ã€ã«ã§ãã ã¢ã¯ãã£ããã£ãã°ã©ãã£ãã¯ãªãœãŒã¹ã¯å¿ èŠãããŸããã å®éãåœä»€ãå«ãŸãããã¡ã€ã«ã¯1ã€ã ãã§ãããã¡ãããå¿ èŠãªãã¡ã€ã«ã«å ããŠãã¢ãžã¥ãŒã«ã¯æ©èœããŸãã èšå®ããã«ã¯ã次ã®3ã€ã®ããšãè¡ãå¿ èŠããããŸãã
Manifest.xml
ã¢ããªã±ãŒã·ã§ã³ãã€ã³ã¹ããŒã«ãããšããXposedã¯Manifest.xmlã®ç¹å®ã®ããããŒããã§ãã¯ããŸãã å¿ èŠãªè¡ã3è¡ããå Žåããã¬ãŒã ã¯ãŒã¯ã¯èšå®ã«é¢ããã¢ããªã±ãŒã·ã§ã³ã«é¢ããæ å ±ãä¿åããã€ã³ã¹ããŒã«ãããã¢ãžã¥ãŒã«ãã¢ã¯ãã£ãåã§ããŸãïŒä»¥éãããç¥ãããŠããã¢ããªã±ãŒã·ã§ã³ãå«ãããŸããŸãªã¢ãžã¥ãŒã«ã®ã³ãŒãäŸã䜿çšããŸãïŒã
<meta-data android:name="xposedmodule" android:value="true" /> <meta-data android:name="xposedminversion" android:value="2.6*" /> <meta-data android:name="xposeddescription" android:value="Uber-Driver application patch tool" /
æåã®è¡ã¯æ確ã§ãã
2è¡ç®ã«ã¯ãã¢ãžã¥ãŒã«ãæäœããããã®ãã¬ãŒã ã¯ãŒã¯ã®æå°ããŒãžã§ã³ã瀺ããŸãã åããŒãžã§ã³ã¯ãç¹å®ã®AndroidãªãªãŒã¹åãã«åŒ·åãããŠãããæå³ããªããã©ãããã©ãŒã ã§ã¢ãžã¥ãŒã«ã誀ã£ãŠå®è¡ãããªãããã«ãããŒãžã§ã³ã瀺ãããŠããŸãã
3è¡ç®ã¯ãé»è©±æ©ã§äœ¿çšå¯èœãªã¢ãžã¥ãŒã«ãŸãã¯ã€ã³ã¹ããŒã«ãããŠããã¢ãžã¥ãŒã«ã®ãªã¹ãã§ã¢ããªã±ãŒã·ã§ã³ãèå¥ããæ¹æ³ã決å®ããŸãã
/ã¢ã»ãã/ xposed_init
ã¢ããªã±ãŒã·ã§ã³ã®ã«ãŒãã§ãassetsãã©ã«ããŒãäœæããxposed_initãšãããã¡ã€ã«ãããã«é 眮ããå¿ èŠããããŸãã ãã®ãã¡ã€ã«å ã«ãã¢ãžã¥ãŒã«ã®æäœãèšè¿°ãããŠããJavaã¯ã©ã¹ãèšè¿°ããã ãã§ãã ç§ã¯XMainã®ãããªã¯ã©ã¹ãåŒã³åºãããšã«æ £ããŠããŸãã ç§ã®å Žåããã¡ã€ã«ã«è¡ããããŸã
uber.hack.XMain
Javaã¯ã©ã¹
ã¯ã©ã¹èªäœã«ã¯ããã¬ãŒã ã¯ãŒã¯ãæäœããããã®3ã€ã®ã¡ãœããã®ãããããå«ãŸããŠããå¿ èŠããããŸãã ãã¹ãŠãæå®ããå¿ èŠã¯ãããŸããã1ã€ãŸãã¯è€æ°ã®ã¢ããªã±ãŒã·ã§ã³ã«å€æŽãå ããäºå®ã®ãããã®ã®ã¿ãæå®ã§ããŸãã ç¿æ £ããããã¹ãŠããã³ãã¬ãŒããšããŠæå®ããŸãã
public class XMain implements IXposedHookInitPackageResources, IXposedHookLoadPackage, IXposedHookZygoteInit { public void initZygote(StartupParam startupParam) throws Throwable { } public void handleInitPackageResources(InitPackageResourcesParam resparam) throws Throwable { } public void handleLoadPackage( LoadPackageParam paramLoadPackageParam) throws Throwable { } }
initZygoteã¡ãœãã㯠ãã¢ãžã¥ãŒã«ãã¡ã¢ãªã«ããŒãããããšå®è¡ãããŸãã
ã¢ããªã±ãŒã·ã§ã³ã«ã¢ãžã¥ãŒã«ã®èšå®ãæã€ã¢ã¯ãã£ããã£ãããå Žåãéåžžã«äŸ¿å©ã§ãã éåžžãã¢ããªã±ãŒã·ã§ã³ããŒã¿ã¯ãã¡ã€ã«ã«ä¿åãããŸã
/data/data/YOUR_PACKAGE_NAME/shared_prefs/YOUR_PACKAGE_NAME_preferences.xml
èµ·åæã«ãèšè¿°åã1åååŸããæäœäžã«ãã®èšè¿°åããèšå®ãèªã¿åãããšãã§ããŸãã ãŸããå€æ°ãäºåå®çŸ©ãããã§ãã¯ããããšãã§ããŸãã å®éãããã¯ã³ã³ã¹ãã©ã¯ã¿ãŒã¡ãœããã«é¡äŒŒããŠããŸãã
DalvikããœãŒã¹ã³ãŒããããŒããããš ã handleLoadPackageã¡ãœãããå®è¡ãããŸãïŒ èµ·åæã®ã¢ããªã±ãŒã·ã§ã³ã ããã¯éåžžã«éèŠãªãã€ã³ãã§ãã é»è©±æ©ã«10åã®ç°ãªãã¢ãžã¥ãŒã«ãããå Žåããã®æ¹æ³ã«ãããèµ·åãããã¢ããªã±ãŒã·ã§ã³ã®ãœãŒã¹ã¯10åãã¹ãŠã®ã±ãŒã¹ã§ãå®è¡ããããŸãã ãã£ã«ã¿ãªã³ã°ã«ã¯ãããã±ãŒãžåã®å®æçãªãã§ãã¯ã䜿çšãããŸãã ãã¡ãããè€æ°ã®ã¢ããªã±ãŒã·ã§ã³ã®åäœãå€æŽããå Žåã¯ãå¿ èŠãªæ°ã®ãã§ãã¯ãå ¥ããŠãã ããã
public void handleLoadPackage( LoadPackageParam paramLoadPackageParam) throws Throwable { final LoadPackageParam llpm = paramLoadPackageParam; String packageName = llpm.packageName; if (packageName.contains("ubercab.driver")) { } }
ã¢ããªã±ãŒã·ã§ã³ãªãœãŒã¹ãã¡ã¢ãªã«ããŒããããšãã«ã¢ããªã±ãŒã·ã§ã³ãªãœãŒã¹ã眮ãæããå Žåã¯ãhandleInitPackageResourcesã¡ãœãããå¿ èŠã§ãã ããã§ã¯ãhandleLoadPackageãšåã-ã¢ããªã±ãŒã·ã§ã³ã®ååã§ãã£ã«ã¿ãªã³ã°ããŸãã
public void handleInitPackageResources(InitPackageResourcesParam resparam) throws Throwable { String pkg = resparam.packageName; if (pkg.equals("com.ubercab.driver")) { } }
ãããã§ã¹ãã§ç€ºãããŠããããã«ãã¢ããªã±ãŒã·ã§ã³ã®ååã瀺ãããšãéèŠã§ãã ããã«ãããéçºç°å¢ã§ã®ã¢ãžã¥ãŒã«ã®æ§æãå®äºããããã°ã©ãã³ã°ã«çŽæ¥é²ãããšãã§ããŸãã
ã³ãŒãäŸ
ã¡ã€ã³ã³ãŒãã¯ããã¡ããã¢ããªã±ãŒã·ã§ã³ã®è²ããã©ã³ããå€æŽããã ãã§ã¯ãªãéããhandleLoadPackageã§çºçããŸãã ãããè¡ãã«ã¯ããŸãç®çã®ã¢ããªã±ãŒã·ã§ã³ã®ãœãŒã¹ã³ãŒãã調ã¹ãã³ãŒããå€æŽããæ¹æ³ãèŠã€ããããžãã¯ã説æããŸãã
ã¡ã€ã³ããžãã¯ã¯findAndHookMethodã¡ãœããã䜿çšããŠæ©èœããŸãããfindAndHookConstructorãšfindClassã䜿çšããããšã¯ããŸããããŸããã ãã¹ãŠã®åºæ¬çãªã¡ãœããã¯ã XposedHelpersã¯ã©ã¹ã§èŠãããšãã§ããŸãã
次ã®ããã«ãªããŸãã
if (packageName.contains("ubercab.driver")) { try { XposedHelpers.findAndHookMethod( "com.ubercab.driver.feature.online.DispatchedFragment", llpm.classLoader, "onCreateView", "android.view.LayoutInflater", "android.view.ViewGroup", "android.os.Bundle", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { } @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { } } ); } catch (Throwable t) { XposedBridge.log(t); } }
æåã«ããããã¯ããtry / catchã§ã©ããããå¿ èŠããããŸããã³ãŒãã«ãšã©ãŒãããå Žåãã©ãããŒããªããšãã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³ã¯ãšã©ãŒã§æäœãå®äºããå®å šãªãã¬ãŒã¹ã¯éçºè ã«éãããŸããã¢ãžã¥ãŒã«ã課ããŸããã ãã¬ãŒã¹å šäœãã©ãããããšãã«ãXposedãã°ã«åºåããŠããšã©ãŒãçºçããå Žæãšçç±ãç解ã§ããŸãã
findAndHookMethodã§ã¯ãæåã®ãã©ã¡ãŒã¿ãŒã¯ã¯ã©ã¹ã®ååã2çªç®ã¯ã¯ã©ã¹ããŒããŒãžã®ãªã³ã¯ã3çªç®ã¯å¿ èŠãªã¡ãœããã®ååã§ãã次ã«ãå€æ°ãã¡ãœããã«æž¡ãããã³ãŒã«ããã¯ã¡ãœããã®æåŸã«æååã®åœ¢åŒã§ãªã¹ããããŸãã
ã¯ã©ã¹ã³ã³ããã¹ããååŸããŠäœ¿çšããæ¹æ³ã®äŸã次ã«ç€ºããŸã
ã³ã³ããã¹ãããã£ãã
DriverApplicationã¯ã©ã¹ã§initã¡ãœããã®èªã¿èŸŒã¿ããã£ãããã
䜿çšããŠã³ã³ããã¹ãã䜿çšããŠããããŒããã£ã¹ãã¡ãã»ãŒãžãåä¿¡è ãŸãã¯ãµãŒãã¹ã«éä¿¡ããŸãã
try{ XposedHelpers.findAndHookMethod("com.ubercab.driver.core.app.DriverApplication", llpm.classLoader, "init", new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { Application application = (Application) param.thisObject; Context context = application.getApplicationContext(); Intent intent = new Intent("uber.hack.ACTION_BACKGROUND"); context.sendBroadcast(intent); } }); } catch (Throwable t) { XposedBridge.log(t); }
DriverApplicationã¯ã©ã¹ã§initã¡ãœããã®èªã¿èŸŒã¿ããã£ãããã
param.thisObject
䜿çšããŠã³ã³ããã¹ãã䜿çšããŠããããŒããã£ã¹ãã¡ãã»ãŒãžãåä¿¡è ãŸãã¯ãµãŒãã¹ã«éä¿¡ããŸãã
ãŸãã¯ãã¡ãœããã«æž¡ãããå€æ°ãå€æŽããå¿ èŠãããå Žåã¯ã次ã®æ¹æ³ã§å€æŽã§ããŸã
beforeHookedMethod
try{ XposedHelpers.findAndHookMethod("com.htc.htcdialer.widget.DividerDrawable", paramLoadPackageParam.classLoader, "setDividerColor", "int", "int", new XC_MethodHook() { protected void beforeHookedMethod(MethodHookParam param) throws Throwable { int paramInt1 = (Integer) param.args[0]; int paramInt2 = (Integer) param.args[1]; if (paramInt1 == 4) { if (paramInt2 == -13388315) param.args[1] = Color.RED; if (paramInt2 == -13128336) param.args[1] = Color.BLUE; } } }); } catch (Throwable t) { XposedBridge.log(t); }
XC_MethodHookã«å ããŠãXC_MethodReplacementã䜿çšã§ããŸãã ååã¯ããèªäœãç©èªã£ãŠããŸãã äžéšã®ã¡ãœãããç¬èªã®ã¡ãœããã«å®å šã«çœ®ãæããŸãã USBçµç±ã§é»è©±ãã©ãããããã«æ¥ç¶ãããšãã«ãããã¢ããéç¥ãåé€ãããå Žåã®å žåçãªäŸã次ã«ç€ºããŸã
SetUSBNotification
findAndHookMethod("com.android.settings.PSService", paramLoadPackageParam.classLoader, "SetUSBNotification", "android.content.Context", boolean.class, new XC_MethodReplacement() { protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { return null; } });
ãã®voidã¡ãœããã§ã¯ãéç¥ãåŒã³åºãããŸããã ç§ã¯ã¡ããã©ããã亀æããããããã€ãŠç§ãæ©ãŸããããšãå¿ããŠããŸããã
ããè€éãªã±ãŒã¹ããããŸããã ã¢ãžã¥ãŒã«ã䜿çšããŠã·ã¹ãã ã¢ããªã±ãŒã·ã§ã³ã®ãšã©ãŒãä¿®æ£ããŸããã ã¡ãŒã«ãŒãæ°ããOTAã¢ããªã±ãŒã·ã§ã³ã®ãã°ãä¿®æ£ããã®ãåŸ ã€ã®ã¯ããŸãé åçã§ã¯ãªãã£ãã®ã§ãèªåã§ä¿®æ£ããŸããã
ä¿®æ£ããããã°
public static void tweak_fix98918() { // -------------------------------------------------- // https://android-review.googlesource.com/#/c/98918/ // -------------------------------------------------- try { final Class<?> TaskRecord = XposedHelpers.findClass("com.android.server.am.TaskRecord", null); XposedHelpers.findAndHookMethod(TaskRecord, "setFrontOfTask", new XC_MethodReplacement() { @Override protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { Object mActivities = XposedHelpers.getObjectField(param.thisObject, "mActivities"); boolean foundFront = false; final int numActivities = (Integer) XposedHelpers.callMethod(mActivities, "size"); for (int activityNdx = 0; activityNdx < numActivities; activityNdx++) { final Object r = XposedHelpers.callMethod(mActivities, "get", activityNdx); if (foundFront || XposedHelpers.getBooleanField(r, "finishing")) { XposedHelpers.setBooleanField(r, "frontOfTask", false); } else { XposedHelpers.setBooleanField(r, "frontOfTask", true); foundFront = true; } } if (!foundFront && numActivities > 0) { Object get = XposedHelpers.callMethod(mActivities, "get", 0); XposedHelpers.setBooleanField(get, "frontOfTask", true); } return null; } }); } catch (Throwable t) { XposedBridge.log(t); } } // -------------------------------------------------- // https://android-review.googlesource.com/#/c/81970/ // -------------------------------------------------- public static void tweak_fix81970() { try { final Class<?> ActiveServices = XposedHelpers.findClass("com.android.server.am.ActiveServices", null); XposedHelpers.findAndHookMethod(ActiveServices, "killServicesLocked", "com.android.server.am.ProcessRecord", "boolean", new XC_MethodReplacement() { @Override protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { // XposedBridge.log("killServicesLocked happen"); Boolean DEBUG_SERVICE = (Boolean) XposedHelpers.getStaticBooleanField(ActiveServices, "DEBUG_SERVICE"); String TAG = (String) XposedHelpers.getStaticObjectField(ActiveServices, "TAG"); Object app = param.args[0]; boolean allowRestart = (Boolean) param.args[1]; Object services = XposedHelpers.getObjectField(app, "services"); int size = (Integer) XposedHelpers.callMethod(services, "size"); // First clear app state from services. for (int i = size - 1; i >= 0; i--) { Object sr = XposedHelpers.callMethod(services, "valueAt", i); Object stats = XposedHelpers.getObjectField(sr, "stats"); synchronized (XposedHelpers.callMethod(stats, "getBatteryStats")) { XposedHelpers.callMethod(stats, "stopLaunchedLocked"); } Object sr_app = XposedHelpers.getObjectField(sr, "app"); Boolean persistent = XposedHelpers.getBooleanField(sr_app, "persistent"); Boolean stopIfKilled = XposedHelpers.getBooleanField(sr, "stopIfKilled"); if (sr_app != null && !persistent && stopIfKilled) { Object sr_app_services = XposedHelpers.getObjectField(sr_app, "services"); XposedHelpers.callMethod(sr_app_services, "remove", sr); } XposedHelpers.setObjectField(sr, "app", null); XposedHelpers.setObjectField(sr, "isolatedProc", null); XposedHelpers.setObjectField(sr, "executeNesting", 0); XposedHelpers.callMethod(sr, "forceClearTracker"); Object mDestroyingServices = XposedHelpers.getObjectField(param.thisObject, "mDestroyingServices"); Boolean check = (Boolean) XposedHelpers.callMethod(mDestroyingServices, "remove", sr); if (check) { if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove destroying " + sr); } Object bindings = XposedHelpers.getObjectField(sr, "bindings"); final int numClients = (Integer) XposedHelpers.callMethod(bindings, "size"); for (int bindingi = numClients - 1; bindingi >= 0; bindingi--) { Object IntentBindRecord = XposedHelpers.callMethod(bindings, "valueAt", bindingi); if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + IntentBindRecord + ": shouldUnbind=" + XposedHelpers.getObjectField(IntentBindRecord, "hasBound")); XposedHelpers.setObjectField(IntentBindRecord, "binder", null); XposedHelpers.setObjectField(IntentBindRecord, "requested", false); XposedHelpers.setObjectField(IntentBindRecord, "received", false); XposedHelpers.setObjectField(IntentBindRecord, "hasBound", false); } } // Clean up any connections this application has to // other // services. Object connections = XposedHelpers.getObjectField(app, "connections"); size = (Integer) XposedHelpers.callMethod(connections, "size"); for (int i = size - 1; i >= 0; i--) { Object ConnectionRecord = XposedHelpers.callMethod(connections, "valueAt", i); XposedHelpers.callMethod(param.thisObject, "removeConnectionLocked", ConnectionRecord, app, null); } XposedHelpers.callMethod(connections, "clear"); Object smap = XposedHelpers.callMethod(param.thisObject, "getServiceMap", XposedHelpers.getObjectField(app, "userId")); // Now do remaining service cleanup. services = XposedHelpers.getObjectField(app, "services"); size = (Integer) XposedHelpers.callMethod(services, "size"); for (int i = size - 1; i >= 0; i--) { Object sr = XposedHelpers.callMethod(services, "valueAt", i); Object mServicesByName = XposedHelpers.getObjectField(smap, "mServicesByName"); if (XposedHelpers.callMethod(mServicesByName, "get", XposedHelpers.getObjectField(sr, "name")) != sr) { Object cur = XposedHelpers.callMethod(mServicesByName, "get", XposedHelpers.getObjectField(sr, "name")); Slog.wtf(TAG, "Service " + sr + " in process " + app + " not same as in map: " + cur); Object app_services = XposedHelpers.getObjectField(app, "services"); XposedHelpers.callMethod(app_services, "removeAt", i); continue; } // Any services running in the application may // need to be // placed back in the pending list. Object serviceInfo = XposedHelpers.getObjectField(sr, "serviceInfo"); Object applicationInfo = XposedHelpers.getObjectField(serviceInfo, "applicationInfo"); if (allowRestart && XposedHelpers.getIntField(sr, "crashCount") >= 2 && (XposedHelpers.getIntField(applicationInfo, "flags") & ApplicationInfo.FLAG_PERSISTENT) == 0) { Slog.w(TAG, "Service crashed " + XposedHelpers.getIntField(sr, "crashCount") + " times, stopping: " + sr); EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH, XposedHelpers.getObjectField(sr, "userId"), XposedHelpers.getObjectField(sr, "crashCount"), XposedHelpers.getObjectField(sr, "shortName"), XposedHelpers.getObjectField(app, "pid")); XposedHelpers.callMethod(param.thisObject, "bringDownServiceLocked", sr); } else if (!allowRestart) { XposedHelpers.callMethod(param.thisObject, "bringDownServiceLocked", sr); } else { boolean canceled = (Boolean) XposedHelpers.callMethod(param.thisObject, "scheduleServiceRestartLocked", sr, true); // Should the service remain running? Note // that in the // extreme case of so many attempts to // deliver a command // that it failed we also will stop it here. if (XposedHelpers.getBooleanField(sr, "startRequested") && (XposedHelpers.getBooleanField(sr, "stopIfKilled") || canceled)) { Object pendingStarts = XposedHelpers.getObjectField(sr, "pendingStarts"); if ((Integer) XposedHelpers.callMethod(pendingStarts, "size") == 0) { XposedHelpers.setBooleanField(sr, "startRequested", false); if (XposedHelpers.getObjectField(sr, "tracker") != null) { Object tracker = XposedHelpers.getObjectField(sr, "tracker"); Object mAm = XposedHelpers.getObjectField(param.thisObject, "mAm"); Object mProcessStats = XposedHelpers.getObjectField(mAm, "mProcessStats"); XposedHelpers.callMethod(tracker, "setStarted", false, XposedHelpers.callMethod(mProcessStats, "getMemFactorLocked"), SystemClock.uptimeMillis()); } if (!XposedHelpers.getBooleanField(sr, "hasAutoCreateConnections")) { // Whoops, no reason to restart! XposedHelpers.callMethod(param.thisObject, "bringDownServiceLocked", sr); } } } } } if (!allowRestart) { Object app_services = XposedHelpers.getObjectField(app, "services"); XposedHelpers.callMethod(app_services, "clear"); // Make sure there are no more restarting // services for this // process. Object mRestartingServices = XposedHelpers.getObjectField(param.thisObject, "mRestartingServices"); for (int i = (Integer) XposedHelpers.callMethod(mRestartingServices, "size") - 1; i >= 0; i--) { Object r = XposedHelpers.callMethod(mRestartingServices, "get", i); String processName = (String) XposedHelpers.getObjectField(r, "processName"); Object serviceInfo = XposedHelpers.getObjectField(r, "serviceInfo"); Object applicationInfo = XposedHelpers.getObjectField(serviceInfo, "applicationInfo"); Object info = XposedHelpers.getObjectField(app, "info"); if (processName.equals((String) XposedHelpers.getObjectField(app, "processName")) && XposedHelpers.getIntField(applicationInfo, "uid") == XposedHelpers.getIntField(info, "uid")) { XposedHelpers.callMethod(mRestartingServices, "remove", i); XposedHelpers.callMethod(param.thisObject, "clearRestartingIfNeededLocked", r); } } Object mPendingServices = XposedHelpers.getObjectField(param.thisObject, "mPendingServices"); for (int i = (Integer) XposedHelpers.callMethod(mPendingServices, "size") - 1; i >= 0; i--) { Object r = XposedHelpers.callMethod(mPendingServices, "get", i); String processName = (String) XposedHelpers.getObjectField(r, "processName"); Object serviceInfo = XposedHelpers.getObjectField(r, "serviceInfo"); Object applicationInfo = XposedHelpers.getObjectField(serviceInfo, "applicationInfo"); Object info = XposedHelpers.getObjectField(app, "info"); if (processName.equals((String) XposedHelpers.getObjectField(app, "processName")) && XposedHelpers.getIntField(applicationInfo, "uid") == XposedHelpers.getIntField(info, "uid")) { XposedHelpers.callMethod(mPendingServices, "remove", i); } } } // Make sure we have no more records on the stopping // list. Object mDestroyingServices = XposedHelpers.getObjectField(param.thisObject, "mDestroyingServices"); int i = (Integer) XposedHelpers.callMethod(mDestroyingServices, "size"); while (i > 0) { i--; Object sr = XposedHelpers.callMethod(mDestroyingServices, "get", i); if (XposedHelpers.getObjectField(sr, "app") == app) { XposedHelpers.callMethod(sr, "forceClearTracker"); XposedHelpers.callMethod(mDestroyingServices, "remove", i); if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove destroying " + sr); } } Object executingServices = XposedHelpers.getObjectField(app, "executingServices"); XposedHelpers.callMethod(executingServices, "clear"); return null; } }); } catch (Throwable t) { XposedBridge.log(t); } }
ããã§ãããã§ã¯ãKitKatã®ã»ãã¥ãªãã£ç®çã§ãã®æ©èœãåæããããšãã«ããã¹ãŠã®ã¢ããªã±ãŒã·ã§ã³ãSDã«ãŒãã«æ å ±ãæžã蟌ãããšãèš±å¯ããŸããã
hookSDcardPermission
try { XposedHelpers.findAndHookMethod("com.android.server.SystemConfig", paramLoadPackageParam.classLoader, "readPermission", "org.xmlpull.v1.XmlPullParser", "java.lang.String", new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { String permission = (String) param.args[1]; if (permission.equals("android.permission.WRITE_EXTERNAL_STORAGE")) { Class<?> process = XposedHelpers.findClass("android.os.Process", null); int gid = (Integer) XposedHelpers.callStaticMethod(process, "getGidForName", "media_rw"); Object mPermissions = XposedHelpers.getObjectField(param.thisObject, "mPermissions"); Object localPermissionEntry = XposedHelpers.callMethod(mPermissions, "get", permission.intern()); int[] gids = (int[]) XposedHelpers.getObjectField(localPermissionEntry, "gids"); XposedHelpers.setObjectField(localPermissionEntry, "gids", ArrayUtils.appendInt(gids, gid)); } } }); } catch (Throwable t) { XposedBridge.log(t); }
ã¯ã©ã¹å€æ°ãšã¡ãœããã«ã¯ãXposedHelpersã¯ã©ã¹ãä»ããŠã¢ã¯ã»ã¹ããŸãã äŸïŒ
Object mActivity = XposedHelpers.getObjectField(param.thisObject, "mActivity");
ãªããžã§ã¯ããã¢ã¯ã»ã¹å¯èœãªã€ã³ããŒããããã¯ã©ã¹ã§ããå Žåãçµæã®ãªããžã§ã¯ãã¯ããã«ç®çã®ã¿ã€ãã«å€æã§ããŸã
(Activity) mActivity = (Activity) XposedHelpers.getObjectField(param.thisObject, "mActivity");
ããã«ã³ãŒãã容æã«ããŸãã ãªããžã§ã¯ããã€ã³ããŒãã«äœ¿çšã§ããªãå éšã¯ã©ã¹ã®ã¿ã€ãã§ããå Žåããã®ã¡ãœãããšããããã£ã®ãããªã䜿çšãXposedHelpersãä»ããŠäœ¿çšã§ããŸãã
äžèšã®èŠçŽïŒãã€ã§ãã©ãã§ããä»»æã®ã¯ã©ã¹ã®éçå€æ°ãšæçµå€æ°ãå€æŽã§ããŸãã ã¡ãœããã«æž¡ãããå€æ°ã確èªããå®è¡åã«å€æ°ãå€æŽããåã ã®ã¡ãœããã®çµæãå€æŽããããã³ãŒãã§å®å šã«çœ®ãæããŸãã
ã»ãšãã©ã®å Žåãç®çã®ã¡ãœããããã£ããããŠãã¢ããªã±ãŒã·ã§ã³ã®èµ·ååŸããã«ããžãã¯ãå€æŽãŸãã¯å€æŽããã ãã§ååã§ãã ãã ãã1ã€ã®DEXãã¡ã€ã«ã®ã¡ãœããæ°ã®å¶éã«ã¯æ¢ç¥ã®åé¡ããããããå€ãã®ããã°ãã¢ããªã±ãŒã·ã§ã³ã«ã¯3ã5åã®è¿œå ã®DEXãã¡ã€ã«ããããŸãã ããã«èœãšãç©ŽããããŸãã ãããåé¿ããã®ã¯éåžžã«ç°¡åã§ãïŒ
ãã«ãããã¯ã¹
public void handleLoadPackage( LoadPackageParam paramLoadPackageParam) throws Throwable { final LoadPackageParam llpm = paramLoadPackageParam; String packageName = paramLoadPackageParam.packageName; if (packageName.contains("ubercab.driver")) { // DEX try{ XposedHelpers.findAndHookMethod("com.ubercab.driver.feature.main.MainActivity", llpm.classLoader, "onNewIntent", "android.content.Intent", new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { // } }); } catch (Throwable t) { XposedBridge.log(t); } // DEX . XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { // , DEX . try { XposedHelpers.findAndHookMethod( "com.ubercab.driver.feature.online.DispatchedFragment", llpm.classLoader, "onCreateView", "android.view.LayoutInflater", "android.view.ViewGroup", "android.os.Bundle", new XC_MethodHook() { // } ); } catch (Throwable t) { XposedBridge.log(t); } } }); } }
é£èªåãããã¢ããªã±ãŒã·ã§ã³ã«ã€ããŠã¯ãäžèŠãããšãã¢ããªã±ãŒã·ã§ã³ã®æ°ãããªãªãŒã¹ããšã«ã¢ãžã¥ãŒã«ãæžãæããå¿ èŠããããŸãã ãã®ç¶æ³ããæãåºãæ¹æ³ã¯åžžã«ãããŸãããããã¯å¥ã®åé¡ã§ãã åºæ¬çãªååã¯ãé£èªåãããŠããªãã¯ã©ã¹ãèŠã€ããããã¯ãã©ããã³ã°ã«ãã£ãŠã¯ã©ã¹ãšã¡ãœããã®ååã決å®ããããšã§ãã
ãããã«
ããŸããŸãªã¢ãžã¥ãŒã«ã®éçºäžã«ééããããã°ã©ãã³ã°ã®åé¡ã«å¯Ÿããåºæ¬çãªããªãã¯ãšè§£æ±ºçã瀺ããŸããã çµéšè±å¯ãªããã°ã©ãã¯ã ãããšããã®èè ã®ããã¥ã¢ã«ã䜿çšããã ãã§ãããããåã±ãŒã¹ã詳现ã«å解ããçç±ã¯ãããŸããã
ããã§ããã¡ãŒã ãŠã§ã¢ã®æŽæ°ã«é¢ããäžé£ã®èšäºãçµäºããäºå®ã§ãããXposedã®å®çšåã®ãããã¯ã¯éããŠããŸããã ç§ãUberãã©ã€ããŒãšããŠåããŠãä»åŸã®æ è¡ã泚æã®å®è¡äžã«é«åºŠãªæ å ±ãæäŸããXposedã¢ãžã¥ãŒã«ãéçºããæ¹æ³ã«é¢ãã倧ããªèšäºã®èšç»ããããŸãããããã¯æšæºã¢ããªã±ãŒã·ã§ã³ã§ã¯æäŸãããŠããŸããã éåžžã«èå³æ·±ãäœéšãåŸãŠãçµè«ãåºããŸããïŒUberã¢ãŒããã¯ãã£èªäœã®å質ãããã³ãŠãŒã¶ãŒã«é¢ããã¢ããªã±ãŒã·ã§ã³ãä»ããŠéä¿¡ãããæ å ±ãšãããããäŒç€ŸããµãŒãã¹ãåçåããŠå°æ¥ããŒã¿ãåä¿¡ããæ¹æ³ã«ã€ããŠã§ãã