banner
Silas

REAO

Be a better man
github

WeChat | Analysis of Dice Rolling and Rock-Paper-Scissors Functions

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:

image

When sending the dice emoji, I found that the following methods of Random were called:

image

I watched java.util.Random.nextInt again, rolled the dice again, and dumped the call stack, arguments, and return value:

image

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:

image

The return value is:

image

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.

image

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.

  1. The field_name is 'jsb.png', which is the acronym for rock-paper-scissors in Chinese:

image

  1. The parameter of getIntRandom is 2, which gets a random int between 0 and 2:

image

  1. The field_name in the return value is jsb_b.png, which corresponds to the result "布" (cloth) in rock-paper-scissors.

image

image

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.

image

3. References#

References
Printing [object] with Frida to solve the problem of Gson package name conflict - https://bbs.pediy.com/thread-259186.htm

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.