In one sentence

Hook wechat step by step to realize the anti-withdrawal of wechat messages.


The introduction

Last Saturday after work, as usual, I went to have dinner with my colleagues and then played a ball. When I was paying, I suddenly found that my wechat id was blocked, and a page like this appeared (someone else’s screenshot, but I didn’t take a screenshot at that time, I just wanted to unseal it) :

God, imagine me never carrying my wallet in Shenzhen, if I only used wechat Pay without my colleagues…

Think of extremely fear, unseal words need to send text messages, and then let another friend help you unseal, to lose ID card, mobile phone number, bank card after eight to help you unseal. A little tedious, I began to recall when I used the wechat plug-in, was hook wechat steps before, a few days 98800 steps, then donate steps, was detected? But the step change was a long time ago. How long did it take to detect it? The next day only to find that I was not a person to be banned, on the force to see this article:

“How to look at wechat June 15 large area closure problem (install Xposed plug-in)?”

The discussion was less heated on Weibo, but it got really hot on Cool Ann:

It seems that the goal is to hit most of the wechat business plug-in, but feel friendly injury to many ordinary users ah, the principle seems to be to detect whether the xposed installed, installed the words directly sealed… The last section hook under the kitchen test xposed routines, see if can also be used in wechat, decompile a wave of dex file, and then global search xposed:

XposedBridge, em… Behind this com. Zte. Heartyservice. SCC. FrameworkBridge again? A Baidu search for the name of a packet turned out to be zte’s mobile phone butler

Uh, a butler APP? Is it possible to freeze applications without root? So as long as you install xposed, whether you have no use wechat related plug-in will be sealed! Wow, people who eat melons are hurt…

All right, so much for the closure of the storm, this section wants to do something about a wechat message to prevent withdrawal of the east east, the reason is this, one day and UI little sister chat late at night:

In case little elder sister is to express to me, then shy withdrew again, I am not a loss is ~

All right, I’m kidding, but I steal taxes when I see something taken back, and some old drivers like to start a car and take it back, and before the picture is loaded, they take it back, and their pants are off.

Therefore, there is this article, Hook wechat to achieve information withdrawal!


1. Random analysis of the first wave

Figure 1

Steps from sending to withdrawing a wechat message

Without looking at the source code, what would be the process if you were to do the message withdrawal? First of all, the information must be persisted locally, usually in a database, otherwise how can you open it every time.

Retract action -> retrieve records from the database based on a tag -> Delete records -> Update page -> Send information to the server to update the retract status of other users.

Maybe is like this, and then began to follow the code, is still fishing for the reverse routine: method tracking + decompile source + log location. Start from the point below undo tracking, until the page shows the undo success ~, start with the keyword SQLite, and then involved in each of these classes:

com.tencent.wcdb.database.SQLiteCursor
com.tencent.wcdb.database.SQLiteQuery
com.tencent.wcdb.database.SQLiteSession
com.tencent.wcdb.database.SQLiteConnection
com.tencent.wcdb.database.SQLiteDatabase
com.tencent.wcdb.database.SQLiteProgram
com.tencent.wcdb.database.SQLiteStatement
com.tencent.wcdb.database.SQLiteQueryBuilder
Copy the code

The next step is to see what the classes do. Open the decompiled project with AS, then open the classes and select on the left

SQLiteDatabase SQLiteDatabase SQLiteDatabase SQLiteDatabase SQLiteDatabase SQLiteDatabase SQLiteDatabase SQLiteDatabase

Then refine the keyword search, method tracking.

Go into the code and look at the update method

Ok, update calls the method **updateWithOnConflict()**, print out the arguments, okay?

The result of the run found that each received a message will trigger this method, even the public number information will be called. (PS: The number and order of parameters should be corresponding when Hook, I missed a string at the beginning, the log has not been printed, I thought the problem of garbage Meizu, did not disgust me to death)

Ok, so let’s take a look at the two cases of self-retraction versus someone else’s retraction:

It’s not hard to see that the first argument should be something that represents the type of the message. The normal message is Rconversation, and the retraction message is Message. The second argument should be ContentValue, which is a class that accesses key-value pairs. In addition to the content above, the retraction type of information has the following block:

We need to make it clear that we don’t want to retract information from someone else but ourselves, so we need to filter out our own information first, and then compare the two situations to draw the following conclusions:

-> check if the first parameter is message -> check if the type in the second parameter is 10000

Modify the program so that it only handles messages sent by other people, check Log,

Looking at the Log, I accidentally found a problem:

Yes, you withdrew a message. The reason for this message is that wechat has a relatively intimate function:

The reason why the user retracted the message is probably because of an editing error, and within five minutes, the user can click on it and they can click on it and get the text message that was retracted, and then they can edit it again, and after five minutes it’s like you retracted a message.

So this filter condition is added to the criteria, so the code becomes:

Go ahead and look at Log:

Okay, it’s a smart guy who knows that there’s something in the msgId field.

Figure 2


2. Mess with the second wave

Figure 3

Let’s jump out of the first wave and figure out how what are we doing? The simple process of information processing goes like this:

It will be inserted into the database, and then it will be withdrawn which is to remove the corresponding information from the database!

So we can:

  • 1. Find something to store all incoming information;
  • 2. When the retraction is triggered, then we find the information we saved through an identifier;
  • 3. Insert this information into the database as a new piece of information;
  • 4. Change the retraction prompt

To emphasize, carrying. At first, I was thinking about processing finding information, getting something, adding something. Later found that the cost of modification is very large, and do not know what kind of problems will be caused, so get the information directly to pass, do not add special effects!

Then is to find a logo, guess is the first wave of analysis out of msgId, and so we need to verify the next! Select * from ‘insert’ where ‘insert’ = ‘database’; select * from ‘insert’ where ‘insert’ = ‘database’;

Not directly like this bt.f class, because the arguments are the same, and performing the insert operation is sure to call more than one method, following the parent method of the method,

To continue with

Yes, the arguments are different, indicating that the information is constructed from here, and then several methods are also called. Open the source code to view this class: Com. Tencent. Mm. Storage. And this method b, class structure can be seen from the left, b method has several, but the first parameter is the same (bd bdVa) into the bd class see com. Tencent. Mm. Storage. Bd

What a complicated class, plus the confusion, the death of the individual, as mentioned above, handling, not processing the information, all we need to do is find the same mark in the information as msgId. MsgId:

Well, is the field_msgId, we get the value of this variable through Xposed, and then do the next comparison, verify our guess! Then write a program like this:

Restart your phone, send messages, withdraw messages, and check your logs

That’s right. Now we’re going to store the whole Map of key and value pairs, and then we’re going to try to pull out the corresponding information based on the msgId and call the insert method when we trigger the retraction. So let’s change the code above, we’re going to get the object that called the b method. Then you have code like this:

Run it and see what happens

Normal wechat retraction:

Hook wechat:

Yes, although XX was prompted to withdraw a message, the message was not really withdrawn, so the Hook was successful ~ then we will optimize some details and change the withdrawn message. Print out what you can, and change the Content:

Under the print:

Uh, something seems wrong with my wechat. Oh, my god, is it my profile picture? :

What type of message do you recall?

Well, I see the message, but it shouldn’t be like this, so if the updateWithOnConflict method returns 0, that’s it, so set the return value to 1, that’s it (param.result = 1)

Well, normal is normal, but there is something wrong with the order, the retraction message is a little faster than the message we inserted, so let’s add it.

Run to see:

At about the same time, an old classmate posted a link this morning, and then withdrew it. The retraction message prompt became this:

After that, I still want to splice it into such a prompt message, don’t show the specific content in the prompt message:

Piglet intercepted the message withdrawn by XXX

The end result is this, yes, it’s great:


3. Mess with the third wave

Figure 4.

When I thought everything was over and I was bloated with self-congratulatory, the test boy found a Bug unexpectedly. He sent voice, picture and video, although he did not withdraw, but failed to open, which probably means that the file was deleted.

In Android, if you want to delete a File, you need to call the delete method of the File class. If you want to delete a File, you need to search for the delete method.

If the delete method is called, filter a wave, do not delete the File, directly return the result true, deceive wechat File deletion success, to hide the truth ~ code as follows:

Send voice, picture and video in turn, and then withdraw, corresponding delete record:

Observe the path rules, it is not difficult to find the corresponding folder is voice2, image2, video, so filter a wave of path, if the path contains these three direct filtering Settings return value is True, in addition, the public account, the chain, are text information, but wechat did a special analysis, such as the baidu Post bar above, So just treat it like normal information.

Then I found that only the voice could be opened normally, but pictures and videos could not be opened normally. I followed the next path.

Use the ES browser to go to this path:

This is very strange, images clearly exists, but is not properly loaded, and it opens at each will perform a delete operation, that is to say still holds the record in the database, undo information just delete the database record + delete files, delete files is certainly no problem, then the problem must be delete in the database records there. Trace the delete() method in SQLiteDatabase and print the parameters and return values:

Do it in sequence: send voice, send picture, send video and then withdraw log tracking.

Combine this with the delete method:

Combining the above log with the delete method code, we can conclude that:

  • 1. Audio references go in voiceInfo, image references go in ImgInfo2, and video references go in VideoInfo2.
  • WxFileIndex2 = WxFileIndex2; WxFileIndex2 = msgId; WxFileIndex2 = WxFileIndex2;

The following code returns the value: the executeUpdateDelete() method, in the SQLiteStatement class

The number of rows changed? Generally speaking, when deleting a piece of data correctly, the number of rows affected will be 1. And only the voice can play properly, is that why? If the first argument is one of the four tables, set the return value to 1

Try sending a message and retracting it

Okay, so videos and pictures are open, so this is a perfect solution, and it’s been a lot of twists and turns. Then change the UI page, make up the last kitchen Hook Xposed detection of light and anti-withdrawal switch. The final interface looks like this:


summary

This is why I do not like to toss Xposed, too much unknown, always want to guess, to verify their guess, constantly install restart, when you think you can, and then a new problem, if not the reason for the design of the little sister, really do not want to touch this thing.


Attached: because the code is longer, and changed under the kitchen, and king of glory related code, so do not post the code, directly give the warehouse link to take github.com/coder-pig/C…