Java层 Frida hook Bitmap创建

文章详细介绍了Android中Bitmap的创建过程,包括nativeCreate和decode系列函数,以及如何利用Frida工具对这些函数进行Hook,监控内存分配。通过示例代码展示了如何在JavaScript端拦截和分析Bitmap对象的内存占用情况。
摘要由CSDN通过智能技术生成

Bitmap创建

android.graphics.Bitmap
private static native Bitmap nativeCreate(int[] colors, int offset,
                                          int stride, int width, int height,
                                          int nativeConfig, boolean mutable,
                                          long nativeColorSpace);
                                          
android.graphics.BitmapFactory                                          
private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
        Rect padding, Options opts, long inBitmapHandle, long colorSpaceHandle);

private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,
        Rect padding, Options opts, long inBitmapHandle, long colorSpaceHandle);

private static native Bitmap nativeDecodeAsset(long nativeAsset, Rect padding, Options opts,
        long inBitmapHandle, long colorSpaceHandle);

private static native Bitmap nativeDecodeByteArray(byte[] data, int offset,
        int length, Options opts, long inBitmapHandle, long colorSpaceHandle);                                          
        
android.widget.ImageView
public void setImageDrawable(@Nullable Drawable drawable) {
}

https://cs.android.com/android/platform/superproject/+/refs/heads/master:frameworks/base/libs/hwui/jni/Bitmap.cpp

frameworks/base/libs/hwui/jni/Bitmap.cpp

static const JNINativeMethod gBitmapMethods[] = {
    {   "nativeCreate",             "([IIIIIIZJ)Landroid/graphics/Bitmap;",
        (void*)Bitmap_creator },
    {   "nativeCopy",               "(JIZ)Landroid/graphics/Bitmap;",
        (void*)Bitmap_copy },
    {   "nativeCopyAshmem",         "(J)Landroid/graphics/Bitmap;",
        (void*)Bitmap_copyAshmem },
     ...
};

static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
                              jint offset, jint stride, jint width, jint height,
                              jint configHandle, jboolean isMutable,
                              jlong colorSpacePtr) {
    ...
    
    sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap);
    
    ...
    return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
}


sk_sp<Bitmap> Bitmap::allocateHeapBitmap(size_t size, const SkImageInfo& info, size_t rowBytes) {
    // Android 8.0 后, calloc 在 Native 堆分配内存
    void* addr = calloc(size, 1);
    if (!addr) {
        return nullptr;
    }
    return sk_sp<Bitmap>(new Bitmap(addr, size, info, rowBytes));
}

Frida hook

Java.perform(function x() { 
    console.log("jscode start");

    var Bitmap = Java.use("android.graphics.Bitmap");
    Bitmap.nativeCreate.implementation = function(colors, offset, stride, width, height, nativeConfig, mutable, nativeColorSpace) {
        //console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
        var bitmap = this.nativeCreate(colors, offset, stride, width, height, nativeConfig, mutable, nativeColorSpace);
        if (bitmap.getAllocationByteCount() / (1000 * 1000) > 5) {
            console.log("nativeCreate "+ bitmap.getAllocationByteCount() / (1000 * 1000));
            console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
        }
        return bitmap;
    }
    
    var BitmapFactory = Java.use("android.graphics.BitmapFactory");
    BitmapFactory.nativeDecodeStream.implementation = function(is, storage, padding, opts, inBitmapHandle, colorSpaceHandle) {
        var bitmap = this.nativeDecodeStream(is, storage, padding, opts, inBitmapHandle, colorSpaceHandle);
         if (bitmap.getAllocationByteCount() / (1000 * 1000) > 5) {
            console.log("nativeDecodeStream "+ bitmap.getAllocationByteCount() / (1000 * 1000));
            console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
        }
        return bitmap;
    }
    
    BitmapFactory.nativeDecodeFileDescriptor.implementation = function(fd, padding, opts, inBitmapHandle, colorSpaceHandle) {
        var bitmap = this.nativeDecodeFileDescriptor(fd, padding, opts, inBitmapHandle, colorSpaceHandle);
        console.log("nativeDecodeFileDescriptor "+ bitmap.getAllocationByteCount() / (1000 * 1000));
        return bitmap;
    }

    BitmapFactory.nativeDecodeAsset.implementation = function(nativeAsset, padding, opts, inBitmapHandle, colorSpaceHandle) {
        var bitmap = this.nativeDecodeAsset(nativeAsset, padding, opts, inBitmapHandle, colorSpaceHandle);
        console.log("nativeDecodeAsset " + bitmap.getAllocationByteCount() / (1000 * 1000));
        return bitmap;
    }

    BitmapFactory.nativeDecodeByteArray.implementation = function(data, offset, length, opts, inBitmapHandle, colorSpaceHandle) {
        var bitmap = this.nativeDecodeByteArray(data, offset, length, opts, inBitmapHandle, colorSpaceHandle);
        console.log("nativeDecodeByteArray " + bitmap.getAllocationByteCount() / (1000 * 1000));
        return bitmap;
    }

    var ImageViewClass = Java.use("android.widget.ImageView");
    ImageViewClass.setImageDrawable.implementation = function(drawable) {
        // var intrinsicWidth = drawable.getIntrinsicWidth();
        //console.log("setImageDrawable");
        return this.setImageDrawable(drawable);
    }

    console.log("jscode end");
});
import frida, sys

# 查找USB设备并附加到目标进程
process = frida.get_usb_device().attach('浏览器')
# 读取js文件, 在目标进程里创建脚本
with open("hook.js", 'r', encoding='UTF-8') as f:
    jscode_script = process.create_script(f.read())
# 加载创建的javascript脚本
jscode_script.load()
# 读取系统输入
sys.stdin.read()
java.lang.Throwable
        at android.graphics.Bitmap.nativeCreate(Native Method)
        at android.graphics.Bitmap.createBitmap(Bitmap.java:1137)
        at android.graphics.Bitmap.createBitmap(Bitmap.java:1095)
        at android.graphics.Bitmap.createBitmap(Bitmap.java:1045)
        at android.graphics.Bitmap.createBitmap(Bitmap.java:1006)
        at com.android.browser.MultiWebViewAdapter.capturePageItem(MultiWebViewAdapter.java:4430)
        at com.android.browser.MultiWebViewAdapter.openNewWebPage(MultiWebViewAdapter.java:4136)
        at com.android.browser.MultiWebViewAdapter.loadUrl(MultiWebViewAdapter.java:1379)
        at com.android.browser.MultiWebViewAdapter.loadUrlWithReferrer(MultiWebViewAdapter.java:5060)
        at com.android.browser.MultiWebViewAdapter.access$3300(MultiWebViewAdapter.java:148)
        at com.android.browser.MultiWebViewAdapter$InnerMiuiWebViewClient.proceedNavigation(MultiWebViewAdapter.java:3822)
        at com.android.browser.MultiWebViewAdapter$InnerMiuiWebViewClient.shouldIgnoreNavigation(MultiWebViewAdapter.java:3812)
        at com.miui.webview.MiuiWebViewClient.shouldIgnoreNavigation(MiuiWebViewClient.java:235)
        at com.miui.webview.MiuiContents.shouldIgnoreNavigation(MiuiContents.java:148)
        at android.os.MessageQueue.nativePollOnce(Native Method)
        at android.os.MessageQueue.next(MessageQueue.java:341)
        at android.os.Looper.loopOnce(Looper.java:168)
        at android.os.Looper.loop(Looper.java:299)
        at android.app.ActivityThread.main(ActivityThread.java:8261)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:559)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:954)

参考

https://juejin.cn/post/7206327507531399225
https://juejin.cn/post/7214800241245880379
https://www.cnblogs.com/luoyesiqiu/p/10718997.html
https://blog.51cto.com/u_15127581/2779737
https://www.jianshu.com/p/89cc79e29f45
https://blog.csdn.net/song_lee/article/details/103306677
https://kevinspider.github.io/frida/frida-hook-java/
https://blog.csdn.net/weixin_39190897/article/details/115582853
https://kevins.pro/recoding_use_frida.html
https://lingwu111.github.io/frida%E4%BD%BF%E7%94%A8%E4%B8%8E%E5%B8%B8%E8%A7%81api%EF%BC%88%E4%B8%80%EF%BC%89.html
https://www.52pojie.cn/thread-1128884-1-1.html
https://blog.csdn.net/qq_52217283/article/details/122723278
https://blog.csdn.net/wangwanglele11/article/details/112945216
https://blog.csdn.net/LoopherBear/article/details/107085949
https://blog.csdn.net/weixin_61845324/article/details/130059314
https://blog.csdn.net/weixin_35016347/article/details/104002411
https://blog.csdn.net/weixin_43111232/article/details/121429371
https://www.jianshu.com/p/fa86044cecec
https://zhuanlan.zhihu.com/p/557373191
https://www.buaq.net/go-115026.html
https://rise-worlds.github.io/2023/04/23/frida-source-code-analysis/
https://evilpan.com/2022/04/17/frida-java/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值