This article is based on Android WeChat 8.0.3.
Recently, I started learning reverse engineering of some software and decided to document my progress.
This article is the first in a series about WeChat, focusing on the analysis of the dice rolling and rock-paper-scissors features.
Both dice rolling and rock-paper-scissors produce random results, so I speculated that they are implemented using random numbers. Later, I discovered that this is indeed the case.
1. Finding the hook point#
The corresponding class for the Java Random class is java.util.Random. I used objection to watch it:
When sending the dice emoji, I found that the following methods of Random were called:
I watched java.util.Random.nextInt again, rolled the dice again, and dumped the call stack, arguments, and return value:
nextInt(n): Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and n (exclusive).
The parameter of nextInt is 6, and the return value is 1, which means the result of rolling the dice is 2.
Actually, this can also be used as a hook point, but it is not detailed enough. The only points that need to be hooked are dice rolling and rock-paper-scissors. Hooking the random number methods of the Java utility class directly is a bit crude.
Tracing back the call stack, getIntRandom is a method in the Tencent SDK, which is obviously a method for generating random numbers.
Continuing to trace back, om.tencent.mm.plugin.emoji.e.f.o, I watched these two methods to see if I could get any additional information.
android hooking watch class_method com.tencent.mm.sdk.platformtools.Util.getIntRandom --dump-args --dump-return
android hooking watch class_method com.tencent.mm.plugin.emoji.e.f.o --dump-args --dump-return
Rolling the dice again, this time the result is 5.
The parameters of the e.f.o method are:
The return value is:
From the parameters and return value of this method, it can be inferred that dice.png is the image of the dice and dice_5.png is the image of the dice with 5 points.
In this call process: From the image, it can be seen that the random number obtained by getIntRandom is "0-5", corresponding to the points "1-6" of the dice rolling result.
Next, I looked at the logic of rock-paper-scissors, which is the same as dice rolling.
- The field_name is 'jsb.png', which is the acronym for rock-paper-scissors in Chinese:
- The parameter of getIntRandom is 2, which gets a random int between 0 and 2:
- The field_name in the return value is jsb_b.png, which corresponds to the result "布" (cloth) in rock-paper-scissors.
Based on this analysis, during the utilization process, it is possible to determine whether to obtain a random number for rock-paper-scissors or dice rolling based on the parameters of e.f.o, and then hook and modify the return value of getIntRandom to get the desired result.
In summary, the points that can be hooked are:
com.tencent.mm.plugin.emoji.e.f.o(com.tencent.mm.storage.emotion.EmojiInfo)
com.tencent.mm.sdk.platformtools.Util.getIntRandom(int,int)
2. Writing Frida script#
Setting: Only scissors for rock-paper-scissors, and only 6 points for dice rolling.
Writing the Frida script:
function main() {
Java.perform(function () {
Java.openClassFile("/data/local/tmp/r0gson.dex").load();
const gson = Java.use('com.r0ysue.gson.Gson')
var jsb = 0 // Only scissors
var dice = 5 // Only 6 points
var efo = Java.use('com.tencent.mm.plugin.emoji.e.f')
efo.o.implementation = function (x) {
var xstr = gson.$new().toJson(x)
if (xstr.search('dice.png') != -1) {
console.log('Rolling the dice')
hookIntRandom(dice)
} else if (xstr.search('jsb.png') != -1) {
console.log("Playing rock-paper-scissors")
hookIntRandom(jsb)
}
var res = this.o(x)
return res
}
})
}
function hookIntRandom(a) {
Java.perform(function () {
var util = Java.use('com.tencent.mm.sdk.platformtools.Util')
util.getIntRandom.implementation = function (int1, int2) {
var res = this.getIntRandom(int1, int2)
return a
}
})
}
setImmediate(main)
Note: The script uses Gson by r0ysue to print objects, which works well.
3. References#
References
Printing [object] with Frida to solve the problem of Gson package name conflict - https://bbs.pediy.com/thread-259186.htm