一、前言在【某通信工具】表情里,我特别喜欢“乖巧**”系列的表情,简明清新以及萌萌哒的设计风格,颇得年轻人的喜爱。 数月前在【某通信工具】“XX表情付费篇” 页面看中了“乖巧**6” 里的一个表情,发现要付费 1元才能使用。。。是的,就一块钱,但对于“抠门”的我来说,肯定不愿意掏的。所以就没买,直接关闭了付费窗口。 而前两天,在XXX技术群里,看见某大佬连发了好几个“乖巧**6” 的表情,我问他是不是买的表情。他说“NO”,这些是他使用frida提取出来的表情。我就比较好奇,frida是什么?以及他是如何提取这些表情的?经过几天研究,终于弄懂了这一切,特撰此文。 二、准备工具本人环境为windows,linux 类同。
三、分析1、我们要hook【某通信工具】付费表情,我们必须先知道 这个表情的ImageView的ID。 打开【某通信工具】-》我-》表情-》朋友表情 下面滚动的图片里选择 “XX表情付费篇” 然后选择 你喜欢的表情,并点击预览 2、启动 Android Device Monitor ,点击 Dump View Hierarchy for UI Automator ,鼠标放到表情处。如下图 我们就知道了用来表情的ImageView的Id是 :com.tencent.mm:id/bg6 ,也就是com.tencent.mm包里bg6。我们要做的就是把ImageView里的图片提取出来,可以通过hook ImageView 的onDraw(Canvas canavs)事件,将需要绘制到canvas内容,也同样绘制到我们用Bitmap创建的Canvas上,然后将Bitmap保存png文件。随着onDraw 一次一次调用,动图表情的多个png图片帧就保存下来了。最后,我们只需要将png图片合成 gif 就能在【某通信工具】里随意发了。 四、实施(必须将步骤二搞好 才能开始此步骤)1、启动frida 2、编写frida脚本代码。wxface.py import frida import sys import io import os import timedevice = 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; //创建存储表情帧的 目录 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(); }else{ endTime = System.currentTimeMillis(); console.log('git更新间隔为:'+(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 的valuedef on_message(message, data): print(message)
#time.sleep(5) script = session.create_script(src_tencent_mm)#设置message 回调函数为 on_message。js 调用send 就会发到 on_message#script.on('message', on_byte_message)script.on('message', on_message) script.load() device.resume(pid) sys.stdin.read() 3、打开CMD,执行:python wxface.py 然后【某通信工具】会自动重新启动, 待【某通信工具】启动后,点击我-》表情-》朋友表情 下面滚动的图片里选择 “XX表情付费篇”,选择你喜欢的表情包,接着点击一个你喜欢的表情 预览,此时 ,frida 会将 动图表情 的没一帧 都保存到 手机的/sdcard/mmface/里。确认表情循环显示完毕后,关闭表情预览 窗口。 4、执行:adb pull /sdcard/mmface/ mmface/ mmface的表情帧全部 拉取到 电脑上。我们可以手动 删除重复的 图片帧(推荐),也可以自动删除重复的图片帧(下面会讲)。最后 将这些图片帧合成gif 去重后 5、多张图片,合成gif 。可以使用网上任意一种工具。本文直接基于python合成。编写gif.py
上诉gif.py 可以传递2-3个参数。
执行gif.py:python gif.py C:\Users\Administrator\Desktop\mmface gif/saodong.gif 确保 “当前工作目录/gif” 目录存在,像我下面,工作目录就是 xxx/py/PyTest/src/com/test,然后在该目录创建一个gif目录。然后 就会在gif目录 生成 saodong.gif。 saodong.gif效果如下。保存到手机了,到【某通信工具】里 选择发送图片就行了。 当然,我们也可以做的更人性化一点。当检测到【某通信工具】表情预览窗口关闭,就自动adb pull /sdcard/mmface mmface/,然后调用gif.py将图片帧合成gif。之后清空手机/sdcard/mmface 和电脑上的mmface/,这样 点开一个收费表情 就自动转存到电脑上了。 五、安全防护自己的成果被别人窃取心里的滋味肯定不好受。那问题来了 —— 如何防住上诉破解呢? 最简单有效的方法是特征码检查。在APK运行时,我们可以读取/proc/self/maps得到当前进程的内存映射关系,检查映射里是否包含 “frida” 字符,如果有,我们就提示用户当前运行环境异常,并退出。 例如:在android中调用so,so里执行以下代码
在电脑上,我们也可以通过adb查看。以【某通信工具】为例子,我们看下【某通信工具】的进程是否包含frida: 不出意外,【某通信工具】的进程已经映射了frida 了,安全起见,此时可以提示环境异常或退出。 |
|
来自: 西北望msm66g9f > 《编程》