preface

This article teaches you how to get the cover of goddess wechat “Moments of Friends” (Evil face)

Actual combat process

Wechat friend’s profile picture can be directly saved to the album, but the cover of moments does not provide the entrance to save, let’s find the address of the cover of moments step by step.

Note: this is for “micro channel V6.6.7” source analysis, different versions of the code because of confusion after the cause, not necessarily applicable. If you want to download the historical version of wechat installation package, you can download “PP Assistant”, you can find the historical version of wechat.

1. TopActivity analysis

Positioning to the friends of the current Activity is com. Tencent. Mm. The plugin. SNS. UI. SnsUserUI

2, Jadx decompiled source code

Using Jadx to decompile the source code, save it as a Gradle project, so that you can directly view the source code in Android Studio, but this export, is not able to run. I personally like to view the source code in Android Studio because it’s easy to use features like find, jump, and class structure.

  • Take a look atSnsUserUISource code, found there is no cover related place, but there is a class that seems to hide a lot of operations, and passed in several key field information, suspicious:

  • Click on class BB, in itsonCreate()Method to find the wrapper class for the coverSnsHeader

  • Continue to look atSnsHeaderFind the cover set of the sourceImageView, should be the picture red box control, why so sure? Because clicking on the cover will bring up a pop-up window to change the cover, the log prompt inside is also very obvious

  • Tracking variablesthis.nWh.nWtIs where to set the value, find the following code that can be seen to give the cover SettingsbitmapValue as well as the resource name of the default cover, wherebitmapThe corresponding variable name is a

  • This method has a suspicious argument:accSnsPath, with the

  • You can seeaccSnsPathThere are two values, guess the cover image processing should be using the “three-level cache” mechanism, first read memory, memory is not available, read local, local is not available, and then network request to obtain. So the first assignment is: local storage path; The second place of assignment is: networkurl.

3, the hooks

According to the above analysis process, hook the following 3 classes, there is a “small skill”, is shared by “Nicholas Zhao 4”, if there is no clue in the code analysis process, you can hook the Log class, in the printed Log, look for clues.

Again, hook for wechat V6.6.7 source code, using YAHFA hook

public class HookWxG {
    public static String className = "com.tencent.mm.plugin.sns.model.g";
    public static String methodName = "a";
    public static String methodSig = "(Ljava/lang/String; Ljava/lang/String; Ljava/lang/String; ZLcom/tencent/mm/storage/av;) Landroid/graphics/Bitmap;"; Public static Bitmap hook(String STR, String str2, String str3, Boolean z, Object avVar) {//"@ @ @"."url:" + str2);
        return backup();
    }

    public static Bitmap backup() {
        returnnull; }}Copy the code
public class HookWxAf {
    public static String className = "com.tencent.mm.plugin.sns.model.af";
    public static String methodName = "getAccSnsPath";
    public static String methodSig = "()Ljava/lang/String;";

    public static String hook() { String result = backup(); // Image storage path (without id) log.w ("@ @ @"."path:"+result);
        return result;
    }

    public static String backup() {
        return""; }}Copy the code
public class HookWxLog {
    public static String className = "com.tencent.mm.sdk.platformtools.x";
    public static String methodName = "d";
    public static String methodSig = "(Ljava/lang/String; Ljava/lang/String;) V";

    public static void hook(String tag,String msg) {
        if ("MicroMsg.SnsHeader".equals(tag)) {
            Log.w("@ @ @", tag + ":" + msg);
        }
    }

    public static void backup(String tag,String msg) {
        return; }}Copy the code
  • Take a look at the printout:

  • Copy the value of this URL to your browser and see:

  • Verify that the local path is correct, find the corresponding folder to see, in fact, there are many subfolders, which we log has printed bgId, find prefix isSnsb_ + bgId file(/storage/emulated/0/tencent/MicroMsg/c3d467aeabb4fae4b1bbf3a7a6839f5d/sns/b/c/snsb_12944115522489626761) toPicture mode – OpenCan.
path: /storage/emulated/0/tencent/MicroMsg/c3d467aeabb4fae4b1bbf3a7a6839f5d/sns/
Copy the code
MicroMsg.SnsHeader:showName x452460984 get bgId:   Id: 12944115522489626761; nullCopy the code

  • Add a button to the interface, copy the URL and jump to the system browser to view it, the code is as follows:
public class HookWxSnsUserUI {
    public static String className = "com.tencent.mm.plugin.sns.ui.SnsUserUI";
    public static String methodName = "onCreate";
    public static String methodSig = "(Landroid/os/Bundle;) V";

    public static Activity SnsUserUI;

    public static void hook(Object thiz, Bundle b) {
        Log.w("@ @ @"."SnsUserUI oncreate");
        SnsUserUI = (Activity) thiz;
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                View decorView = SnsUserUI.getWindow().getDecorView();
                if(decorView ! = null && decorView instanceof ViewGroup) { LinearLayout llContainer = new LinearLayout(SnsUserUI); FrameLayout.LayoutParams containerLp = new FrameLayout.LayoutParams(-2, -2); containerLp.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT; llContainer.setOrientation(LinearLayout.VERTICAL); llContainer.setLayoutParams(containerLp); llContainer.setGravity(Gravity.CENTER); llContainer.setBackgroundColor(Color.parseColor("#ececec"));

                    Button btnCopy = new Button(SnsUserUI);
                    int wrapContent = LinearLayout.LayoutParams.WRAP_CONTENT;
                    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(wrapContent, wrapContent);
                    params.topMargin = SizeUtils.dp2px(8);
                    btnCopy.setLayoutParams(params);
                    btnCopy.setText("Open in browser");
                    btnCopy.setTextSize(12);
                    btnCopy.setIncludeFontPadding(false);
                    btnCopy.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if(! HookWxG.URL.equals("empty")) {
                                ToastUtils.showShort("Copy succeeded"); / / copy ClipboardManager clip = (ClipboardManager) SnsUserUI. GetSystemService (Context. CLIPBOARD_SERVICE); clip.setText(HookWxG.URL); Intent intent = new Intent(); intent.setAction("android.intent.action.VIEW");
                                Uri content_url = Uri.parse(HookWxG.URL);
                                intent.setData(content_url);
                                SnsUserUI.startActivity(intent);
                            } else {
                                ToastUtils.showShort("Oops, the address was not assigned successfully ~"); }}}); llContainer.addView(btnCopy); ((ViewGroup) decorView).addView(llContainer); }}}, 2000); backup(thiz, b); } public static void backup(Object thiz, Bundle b) {return; }}Copy the code