4、Implementation (Step 2 must be done well before starting this step)

0 24
Disclaimer: This article is for security research and discussion only and is str...

Disclaimer: This article is for security research and discussion only and is strictly prohibited for illegal use. The consequences will be borne by the violator.

The readers of this article are developers with certain Android development experience and those who want to learn security technology. Only the core code is provided here.

1. Preface

In the [certain communication tool] emojis, I particularly like the 'naughty **' series of emojis, which are simple, fresh, and have a cute design style, which is very popular among young people.

Several months ago, I noticed an emoji in the 'XX Paid Emoji' page of [certain communication tool] and found that it cost 1 yuan to use this emoji... Yes, just one yuan, but for someone like me who is 'tight-fisted', I definitely wouldn't be willing to pay. So I didn't buy it and directly closed the payment window.

A few days ago, in the XXX technology group, I saw a certain big shot posted several 'naughty 6' emojis one after another. I asked him if he bought these emojis. He said 'NO', these are the emojis he extracted using frida. I was quite curious about what frida is and how he extracted these emojis. After several days of research, I finally understood everything and wrote this article specifically.

2. Prepare tools

My environment is Windows, which is similar to Linux.

1. Install python (including pip) and frida. Frida is a dynamic hook framework that supports hooking Java code and native code (so). It mainly provides a simple Python interface and a rich JavaScript interface. Official website:https://www.frida.re . For the specific tutorials on python and frida入门 installation, please refer to herehttps://blog.csdn.net/tabactivity/article/details/88106511and https://blog.csdn.net/tabactivity/article/details/88130653

2. Prepare a rooted Android phone and install the [certain communication tool] App.

3. Analysis

1. To hook the paid emojis of a certain communication tool, we must first know the ID of the ImageView of this emoji.

Open [some communication tool] -> Me -> Emoticon -> Friend Emoticon, scroll down the image and select "XX Emoticon Paid Edition"

Then select your favorite expression and click preview

2、Start Android Device Monitor, click Dump View Hierarchy for UI Automator, and place the mouse on the expression as shown in the following figure

We know that the ImageView ID used for expressions is: com.tencent.mm:id/bg6, which is bg6 in the com.tencent.mm package. What we need to do is extract the image from the ImageView, which can be achieved by hooking the onDraw(Canvas canavs) event of ImageView, drawing the content that needs to be drawn on canvas, and also drawing it on the canvas created by Bitmap, then saving the Bitmap as a png file. With each call of onDraw, multiple png frames of the animated emoji are saved. Finally, we just need to composite the png images into a gif, and we can send it freely in [some communication tool].

4、Implementation (Step 2 must be done well before starting this step)

1、Start frida

2、Write frida script code. wxface.py

import frida;
import sys
import io;
import os
import time;

device = frida.get_usb_device();
pid = device.spawn(["com.tencent.mm"]);
session = device.attach(pid);

src_tencent_mm = """

Java.perform(function(){

    var ImageView = Java.use("android.widget.ImageView");
 
     var Bitmap = Java.use("android.graphics.Bitmap");
     var Bitmap_Config = Java.use("android.graphics.Bitmap$Config");
     //var bufBitmap = Bitmap$new(394, 394, 5);
     var bitmap_va = Bitmap_Config.ARGB_8888.value;
     console.log("bitmap_va = " + bitmap_va);
    
    var Canvas = Java.use("android.graphics.Canvas");
    console.log("Canvas = " + Canvas);
    var ByteArrayOutputStream = Java.use("java.io.ByteArrayOutputStream");
    console.log("ByteArrayOutputStream = " + ByteArrayOutputStream);
    
    var CompressFormat = Java.use("android.graphics.Bitmap$CompressFormat");
    console.log("CompressFormat value= " + CompressFormat.PNG.value);    
        
    var FileOutputStream = Java.use("java.io.FileOutputStream");
    var System = Java.use("java.lang.System");
    
    var index = 0;  
    var startTime = 0;
    var endTime = 0; 
    //Create the directory for storing the expression frames
    var File = Java.use("java.io.File");
    File.$new("/sdcard/mmface").mkdirs();
    
    ImageView.onDraw.implementation = function(canvas){
        this.onDraw(canvas);
        var viewId = this.getResources().getIdentifier("bg6", "id", "com.tencent.mm");
        if(this.getId() != viewId){
             return;
        }
        console.log("ImageView onDraw.....");
        if(startTime == 0){
            startTime = System.currentTimeMillis();
        }
            endTime = System.currentTimeMillis();            
            console.log("git update interval is: "+(endTime - startTime))
            startTime = endTime;
        }
        
         console.log("gitd draw entry! " + canvas.getWidth() + ","+ canvas.getHeight());
         //将ImageView 要绘制的内容 也绘制到我们创建的 Bitmap中
         var bufBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), bitmap_va);
         console.log("bufBitmap  = " + bufBitmap);   
         var tempCanvas = Canvas.$new(bufBitmap);
         console.log("tempCanvas  = " + tempCanvas); 
         this.onDraw(tempCanvas);
         
         var bos = ByteArrayOutputStream.$new();
         console.log("bos  = " + bos);
         console.log("bos  size= " + bos.size());
         
         bufBitmap.compress(CompressFormat.PNG.value, 100, bos);
         console.log("222 bos  size= " + bos.size());
         var bytesss = bos.toByteArray();
         
         console.log("bytesss length  = " + bytesss.length);
         
         var fos = FileOutputStream.$new("/sdcard/mmface/" +index +".png");
         fos.write(bytesss);
         fos.flush();
         fos.close();
         console.log("保存成功! index=" +index );
         index++;
     
    } 
  
});

"""


#message["payload"] message为map,取出key payload 的value
def on_message(message, data):
    print(message)

    
#time.sleep(5)      
script = session.create_script(src_tencent_mm)
#Set the message callback function to on_message. When js calls send, it will be sent to on_message
#script.on("message", on_byte_message)
script.on("message", on_message)
script.load()            
device.resume(pid)  
sys.stdin.read()

3. Open CMD, execute: python wxface.py

555546.png

Then [some communication tool] will automatically restart, wait for [some communication tool] to start, click Me -> Emotions -> Friend Emotions, select "XX Emotion Paid Edition" from the scrolling images, select your favorite emoji package, then click a favorite emoji preview. At this time, frida will save each frame of the animated emoji to the mobile phone's /sdcard/mmface/. Confirm that the emoji loop display is complete and close the emoji preview window.

4. Execute: adb pull /sdcard/mmface/ mmface/

All the expression frames of mmface are pulled to the computer. We can manually delete duplicate image frames (recommended) or automatically delete duplicate image frames (to be discussed below). Finally, these image frames are combined into a gif

q1.png

After deduplication

q2.png

5. Multiple images, composite gif. You can use any tool online. This article directly uses python to composite. Write gif.py

from PIL import Image
import os
import sys
import zlib
import imageio


#Process transparent gif
def create_gif_2(image_list, gif_name):
    frames = []
    im_tmp = Image.open(image_list[0])     
    mask = Image.new("RGBA", im_tmp.size, (255, 255, 255, 0))   
    for image_item in image_list:
        im = Image.open(image_item)      
        frames.append(Image.alpha_composite(mask, im));
    #img = Image.new("RGBA", im.size, (255, 255, 255, 0))
    first = frames.pop(0);    
    first.save(gif_name, save_all=True, append_images=frames, loop=0, transparency=0, duration=100, disposal=2)  
# Handle non-transparent GIFs
def create_gif(image_list, gif_name):
    frames = []
    for image_item in image_list:
        im = Image.open(image_item)
        alpha = im.getchannel('A')
        print("alpha = ", alpha)
         # Convert the image into P mode but only use 255 colors in the palette out of 256
        im = im.convert('RGBA').convert('P', palette=Image.ADAPTIVE, colors=255)

        # Set all pixel values below 128 to 255, and the rest to 0
        mask = Image.eval(alpha, lambda a: 255 if a <= 128 else 0)

        # Paste the color of index 255 and use alpha as a mask
        im.paste(0, mask)
        
        # The transparency index is 255
        im.info['transparency'] = 0

        frames.append(im)
        #frames.append( im = Image.open(path).imread(image_item, "PNG"))



    frames[0].save(gif_name, save_all=True, append_images=frames, loop=0, duration=100 )
    return

def crc32(filepath):
    block_size = 1024 * 1024
    crc = 0
    fd = open(filepath, 'rb')
    while True:
        buffer = fd.read(block_size)
        if len(buffer) == 0:
            fd.close()
            if sys.version_info[0] < 3 and crc < 0:
                crc += 2 ** 32
            return crc
        crc = zlib.crc32(buffer, crc)    
        
def filter_png(dirpath):
    image_crc = []
    image_files = os.listdir(dirpath)
    for filename in image_files:
        path = os.path.join(dirpath, filename)            
        if os.path.isfile(path):
            find = False
            crc = crc32(path)
            for crc_item in image_crc:
                if crc_item == crc:
                    find = True
                    break
            if find == False:    
                image_crc.append(crc)  
            else:
                os.remove(path)              


def main(argv):
    image_list = []
    image_names = os.listdir(argv[1])
    image_names.sort(key=lambda x: int(x[:-4])) 
    if len(argv) > 3 and argv[3]=="-f":
       filter_png(argv[1])
    for filename in image_names:
        path = os.path.join(argv[1], filename)
        if os.path.isfile(path):
            image_list.append(path)                    
    create_gif_2(image_list, argv[2])

if __name__ == "__main__":
    main(sys.argv)

The above gif.py can pass 2-3 parameters.

The first one is the directory where the image frame is located.

The second one is the name of the saved file (if it includes a directory, the directory must already exist).

The third one is an optional parameter -f, setting this parameter will automatically deduplicate the image frames based on crc32.

Execute gif.py: python gif.py C:\Users\Administrator\Desktop\mmface gif/saodong.gif

Ensure that the "current working directory/gif" directory exists, like me below, the working directory is xxx/py/PyTest/src/com/test, and then create a gif directory in this directory. Then saodong.gif will be generated in the gif directory.

q5.png

The effect of saodong.gif is as follows. Save it to the phone and select the image to send in [Some Communication Tool].

Of course, we can also make it more user-friendly. When the preview window of [Some Communication Tool] is closed, it will automatically adb pull /sdcard/mmface mmface/ and then call gif.py to composite the image frames into gif. After that, clear the /sdcard/mmface on the phone and the mmface/ on the computer, so that opening a paid expression will automatically save it to the computer.

V. Security Protection

It's not pleasant to have one's own achievements stolen. So, the question arises - how to prevent this kind of cracking?

The simplest and most effective method is feature code check.When the APK is running, we can read /proc/self/maps to get the current process's memory mapping relationship, check if the mapping contains the word "frida", if it does, we prompt the user that the current running environment is abnormal and exit.

For example, when calling so in android, execute the following code in so:

char line[512];
FILE* fp;
fp = fopen("/proc/self/maps", "r");
if(!fp){
   //Failed to open proc/self/maps
   return -1;
}
while (fgets(line, 512, fp)) {
    if (strstr(line, "frida")) {
	 //Detected frida, execute exit operation
         exit(0);
    }
}
fclose(fp);
return 0;

On the computer, we can also view it through adb. Taking [Some Communication Tool] as an example, let's see if the process of [Some Communication Tool] contains frida:

As expected, the process of [Some Communication Tool] has mapped frida, for safety reasons, it is advisable to prompt an environment exception or exit at this time.

*The original author of this article is ab6326795, and this article belongs to the FreeBuf Original Reward Plan. Reproduction without permission is prohibited

你可能想看:

4.5 Main person in charge reviews the simulation results, sorts out the separated simulation issues, and allows the red and blue teams to improve as soon as possible. The main issues are as follows

As announced today, Glupteba is a multi-component botnet targeting Windows computers. Google has taken action to disrupt the operation of Glupteba, and we believe this action will have a significant i

In today's rapidly developing digital economy, data has become an important engine driving social progress and enterprise development. From being initially regarded as part of intangible assets to now

It is possible to perform credible verification on the system boot program, system program, important configuration parameters, and application programs of computing devices based on a credible root,

Analysis of a Separated Storage and Computing Lakehouse Architecture Supporting Multi-Model Data Analysis Exploration (Part 1)

How to deploy and implement (cloud) host EDR + situation awareness platform for large enterprises

Completely separable two-dimensional vector graph encryption domain robust reversible watermark algorithm (Part 1)

(3) Is the national secret OTP simply replacing the SHA series hash algorithms with the SM3 algorithm, and becoming the national secret version of HOTP and TOTP according to the adopted dynamic factor

Data security can be said to be a hot topic in recent years, especially with the rapid development of information security technologies such as big data and artificial intelligence, the situation of d

How does Wine implement the cross-platform compatibility layer for Windows?

最后修改时间:
admin
上一篇 2025年03月26日 04:39
下一篇 2025年03月26日 05:02

评论已关闭