æJAVAçï¼ä½ åèä¸ä¸
主è¦æè·¯
ä»UIè·åææ¬ä¿¡æ¯æ¯æ为ç®åçæ¹æ³ï¼äºæ¯åºè¯¥ä¼å
éåUI代ç é¨åã
éå微信apk
é¦å
解å
微信apkï¼ç¨dex2jaråç¼è¯classes.dexï¼ç¶åç¨JD-GUIæ¥çjaræºç ãå½ç¶ï¼è½çå°çæºç é½æ¯ç»è¿é«åº¦æ··æ·çãä½æ¯ï¼ç»§æ¿èªå®åéè¦ç»ä»¶ï¼å¦ActivityãServiceçï¼çç±»åæ æ³è¢«æ··æ·ï¼äºæ¯è¿æ¯è½ä»ä¸çå°ç¹ä¸è¥¿ã
é¦å
å®ä½å°å¾®ä¿¡APP packageãæ们ç¥éè¿ä¸ªæ¯ com.tencent.mm
ã
å¨ com.tencent.mm
ä¸ï¼æ们æ¾å°ä¸ä¸ª ui
å
ï¼æç¹ææã
å±å¼ com.tencent.mm.ui
ï¼åç°å¤ä¸ªæªè¢«æ··æ·çç±»ï¼å
¶ä¸åç° MMBaseActivity
ç´æ¥ç»§æ¿èª Activity
ï¼ MMFragmentActivity
继æ¿èª ActionBarActivity
ï¼ MMActivity
继æ¿èª MMFragmentActivity
ï¼å¹¶ä¸ MMActivity
æ¯å¾®ä¿¡ä¸å¤§å¤æ°Activityçç¶ç±»ï¼
public class MMFragmentActivity
extends ActionBarActivity
implements SwipeBackLayout.a, b.a {
...
}
public abstract class MMActivity
extends MMFragmentActivity {
...
}
public class MMBaseActivity
extends Activity {
...
}
ç°å¨éè¦æ¾åºæååçActivityï¼ä¸ºæ¤è¦ç¨Xposed hook MMActivity
ã
å建ä¸ä¸ªXposed模å
åè [TUTORIAL]Xposed module devlopment
ï¼å建ä¸ä¸ªXposed项ç®ã
ç®åXposed模åçåºæ¬ææ³æ¯ï¼hookæ个APPä¸çæ个æ¹æ³ï¼ä»èè¾¾å°è¯»åæ°æ®çç®çã
å°ç¼å°è¯hook com.tencent.mm.ui.MMActivity.setContentView
è¿ä¸ªæ¹æ³ï¼å¹¶æå°åºè¿ä¸ªActivityä¸çå
¨é¨TextViewå
容ãé£ä¹é¦å
éè¦éåè¿ä¸ªActivityä¸çææTextViewï¼éåViewGroupçæ¹æ³åèäºSOç以ä¸ä»£ç ï¼
private void getAllTextViews(final View v) {
if (v instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) v;
for (int i = 0; i < vg.getChildCount(); i++) {
View child = vg.getChildAt(i);
getAllTextViews(child);
}
} else if (v instanceof TextView ) {
dealWithTextView((TextView)v); //dealWithTextView(TextView tv)æ¹æ³ï¼æå°TextViewä¸çæ¾ç¤ºææ¬
}
}
Hook MMActivity.setContentView
çå
³é®ä»£ç å¦ä¸ï¼
findAndHookMethod("com.tencent.mm.ui.MMActivity", lpparam.classLoader, "setContentView", View.class, new XC_MethodHook() {
...
});
å¨findAndHookMethodæ¹æ³ä¸ï¼ç¬¬ä¸ä¸ªåæ°ä¸ºå®æ´ç±»åï¼ç¬¬ä¸ä¸ªåæ°ä¸ºéè¦hookçæ¹æ³åï¼å
¶åè¥å¹²ä¸ªåæ°åå«å¯¹åºè¯¥æ¹æ³çåå½¢åç±»åãå¨è¿éï¼ Activity.setContentView(View view)
æ¹æ³åªæä¸ä¸ªç±»å为 View
çå½¢åï¼å æ¤ä¼ å
¥ä¸ä¸ª View.class
ã
ç°å¨ï¼ææçç»ææ¯è¿è¡æ¶å¯ä»¥ä»Logä¸è¯»åå°æ¯ä¸ªActivityä¸çææçTextViewçæ¾ç¤ºå
容ã
ä½æ¯ï¼å 为Viewä¸çæ°æ®å¹¶ä¸ä¸å®å¨ setContentView()
æ¶å°±å è½½å®æ¯ï¼å æ¤å°ç¼çå®éªç»ææ¯ï¼logä¸å¥é½æ²¡æã
æå¤çæ¶è·
å½åæ¢å°æåå页é¢æ¶ï¼Xposed模åæ¥äºä¸ä¸ªå¼å¸¸ï¼å¼å¸¸æºä» com.tencent.mm.plugin.sns.ui.SnsTimeLineUI
è¿ä¸ªç±»ææå°ãä»ç±»åä¸çï¼è¿ä¸ªå¾æå¯è½æ¯æååé¦é¡µçUIç±»ãå±å¼è¿ä¸ªç±»ï¼åç°æ´å¤æ趣çä¸è¥¿ï¼
è¿ä¸ªç±»ä¸æ个åç±» a
(被混æ·è¿çç±»å)ï¼è¯¥åç±»ä¸æ个å为 gyO
ç ListView
ç±»çå®ä¾ãæ们ç¥éï¼ ListView
æ¯æ¾ç¤ºå表类çUIç»ä»¶ï¼æå¯è½å°±æ¯ç¨æ¥å±ç¤ºæååçå表ã
顺è¤æ¸ç
é£ä¹ï¼æ们å
è¦è·å¾ä¸ä¸ª SnsTimeLineUI.a.gyO
çå®ä¾ãä½æ¯å¨è¿ä¹åï¼è¦å
è·å¾ä¸ä¸ª com.tencent.mm.plugin.sns.ui.SnsTimeLineUI.a
çå®ä¾ã继ç»æç´¢ï¼åç° com.tencent.mm.plugin.sns.ui.SnsTimeLineUI
æä¸ä¸ªå为 gLZ
ç SnsTimeLineUI.a
å®ä¾ï¼é£ä¹æ们å
åå¾è¿ä¸ªå®ä¾ã
ç»è¿æµè¯ï¼ com.tencent.mm.plugin.sns.ui.SnsTimeLineUI.a(boolean, boolean, String, boolean)
è¿ä¸ªæ¹æ³å¨æ¯æ¬¡åå§å微信çé¢çæ¶åé½ä¼è¢«è°ç¨ãå æ¤æ们å°hookè¿ä¸ªæ¹æ³ï¼å¹¶ä»ä¸åå¾ gLZ
ã
findAndHookMethod("com.tencent.mm.plugin.sns.ui.SnsTimeLineUI", lpparam.classLoader, "a", boolean.class, boolean.class, String.class, boolean.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("Hooked. ");
Object currentObject = param.thisObject;
for (Field field : currentObject.getClass().getDeclaredFields()) { //éåç±»æå
field.setAccessible(true);
Object value = field.get(currentObject);
if (field.getName().equals("gLZ")) {
XposedBridge.log("Child A found.");
childA = value;
//è¿éè·å¾äºgLZ
...
}
}
}
});
ç°å¨åå¾äº SnsTimeLineUI.a
çä¸ä¸ªå®ä¾ gLZ
ï¼éè¦åå¾è¿ä¸ªç±»ä¸ç ListView
ç±»åç gyO
å±æ§ã
private void dealWithA() throws Throwable{
if (childA == null) {
return;
}
for (Field field : childA.getClass().getDeclaredFields()) { //éåå±æ§
field.setAccessible(true);
Object value = field.get(childA);
if (field.getName().equals("gyO")) { //åå¾äºgyO
ViewGroup vg = (ListView)value;
for (int i = 0; i < vg.getChildCount(); i++) { //éåè¿ä¸ªListViewçæ¯ä¸ä¸ªåView
...
View child = vg.getChildAt(i);
getAllTextViews(child); //è¿éè°ç¨ä¸æçgetAllTextViews()æ¹æ³ï¼æ¯ä¸ä¸ªåViewéçææTextViewçææ¬
...
}
}
}
}
ç°å¨å·²ç»å¯ä»¥å°æåå页é¢ä¸çå
¨é¨æåä¿¡æ¯æå°åºæ¥äºãæ们éè¦æ ¹æ®TextViewçåç±»åå¤æè¿äºæåæ¯æååå
容ã好åæµç§°ãç¹èµæè¯è®ºçã
private void dealWithTextView(TextView v) {
String className = v.getClass().getName();
String text = ((TextView)v).getText().toString().trim().replaceAll("\n", " ");
if (!v.isShown())
return;
if (text.equals(""))
return;
if (className.equals("com.tencent.mm.plugin.sns.ui.AsyncTextView")) {
//好åæµç§°
...
}
else if (className.equals("com.tencent.mm.plugin.sns.ui.SnsTextView")) {
//æååæåå
容
...
}
else if (className.equals("com.tencent.mm.plugin.sns.ui.MaskTextView")) {
if (!text.contains(":")) {
//ç¹èµ
...
} else {
//è¯è®º
...
}
}
}
èªæ¤ï¼æ们已ç»ä»å¾®ä¿¡APPéåå¾äºæååæ°æ®ãå½ç¶ï¼è¿é¨åæå代ç éè¦å®æ¶æ§è¡ãå ä¸ºä» ListView
ä¸æå°çæ°æ®åªæå½åæ¾ç¤ºå¨å±å¹ä¸çå¯è§é¨åï¼ä¸ºæ¤éè¦æ¯éå¾çä¸æ®µæ¶é´å次æ§è¡ï¼è®©ç¨æ·å¨ä¸æ»å è½½çè¿ç¨ä¸æåæ´å¤æ°æ®ã
å©ä¸çå°±æ¯æ°æ®åç±»å¤çåæ ¼å¼åè¾åºå°æ件ï¼åæ¬æç¯å¹
æéä¸åèµè¿°ï¼è¯¦ç»å®ç°å¯åèä½è
GitHubä¸çæºç ã
温馨提示:答案为网友推荐,仅供参考