ARTHook非侵入式之图片检查
提示:列表可左右滑动查看。
<h3 style="outline: 0px; --tw-shadow:0 0 #0000 ; --tw-ring-inset:var(--tw-empty, ); --tw-ring-offset-width:0px; --tw-ring-offset-color:#fff; --tw-ring-color:rgba(66, 153, 225, 0.5); --tw-ring-offset-shadow:0 0 #0000; --tw-ring-shadow:0 0 #0000 ; margin-top: 8px; margin-bottom: 16px; font-weight: 700; font-family: "PingFang SC", "Microsoft YaHei", SimHei, Arial, SimSun; font-size: 22px; color: rgb(79, 79, 79); line-height: 30px; overflow-wrap: break-word;">Bitmap内存模型</h3><ol style="outline: 0px; --tw-shadow:0 0 #0000 ; --tw-ring-inset:var(--tw-empty, ); --tw-ring-offset-width:0px; --tw-ring-offset-color:#fff; --tw-ring-color:rgba(66, 153, 225, 0.5); --tw-ring-offset-shadow:0 0 #0000; --tw-ring-shadow:0 0 #0000 ; margin-top: 0px; margin-bottom: 24px; margin-left: 0px; list-style: none; font-size: 16px; overflow-wrap: break-word; color: rgb(51, 51, 51); font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif, SimHei, SimSun;"><li style="outline: 0px; --tw-shadow:0 0 #0000 ; --tw-ring-inset:var(--tw-empty, ); --tw-ring-offset-width:0px; --tw-ring-offset-color:#fff; --tw-ring-color:rgba(66, 153, 225, 0.5); --tw-ring-offset-shadow:0 0 #0000; --tw-ring-shadow:0 0 #0000 ; margin-top: 8px; margin-left: 40px; list-style: decimal; overflow-wrap: break-word;">API10之前Bitmap自身在Dalvik Heap中,像素存在Native</li><li style="outline: 0px; --tw-shadow:0 0 #0000 ; --tw-ring-inset:var(--tw-empty, ); --tw-ring-offset-width:0px; --tw-ring-offset-color:#fff; --tw-ring-color:rgba(66, 153, 225, 0.5); --tw-ring-offset-shadow:0 0 #0000; --tw-ring-shadow:0 0 #0000 ; margin-top: 8px; margin-left: 40px; list-style: decimal; overflow-wrap: break-word;">API10之后像素也存放在Dalvik Heap中</li><li style="outline: 0px; --tw-shadow:0 0 #0000 ; --tw-ring-inset:var(--tw-empty, ); --tw-ring-offset-width:0px; --tw-ring-offset-color:#fff; --tw-ring-color:rgba(66, 153, 225, 0.5); --tw-ring-offset-shadow:0 0 #0000; --tw-ring-shadow:0 0 #0000 ; margin-top: 8px; margin-left: 40px; list-style: decimal; overflow-wrap: break-word;">API26之后像素存在Native</li></ol><div><span style="color: rgb(77, 77, 77); font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif, SimHei, SimSun; font-size: 16px;">build.gradle</span><span style="color: rgb(51, 51, 51); font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif, SimHei, SimSun; font-size: 16px;"><br></span></div><div><pre><code>api 'me.weishu:epic:0.3.6'</code></pre><p><span style="color: rgb(77, 77, 77); font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif, SimHei, SimSun; font-size: 16px;">ImageView目标方法 源码:</span><br></p><pre><code>/**<br> * Sets a Bitmap as the content of this ImageView.<br> *<br> * @param bm The bitmap to set<br> */<br> @android.view.RemotableViewMethod<br> public void setImageBitmap(Bitmap bm) {<br> // Hacky fix to force setImageDrawable to do a full setImageDrawable<br> // instead of doing an object reference comparison<br> mDrawable = null;<br> if (mRecycleableBitmapDrawable == null) {<br> mRecycleableBitmapDrawable = new BitmapDrawable(mContext.getResources(), bm);<br> } else {<br> mRecycleableBitmapDrawable.setBitmap(bm);<br> }<br> setImageDrawable(mRecycleableBitmapDrawable);<br> }</code></pre><p><span style="color: rgb(77, 77, 77); font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif, SimHei, SimSun; font-size: 16px;">新建Hook工具类</span><br></p><pre><code>package com.cfs.app.hook;<br> <br>import android.graphics.Bitmap;<br>import android.graphics.drawable.BitmapDrawable;<br>import android.graphics.drawable.Drawable;<br>import android.util.Log;<br>import android.view.View;<br>import android.view.ViewTreeObserver;<br>import android.widget.ImageView;<br> <br>import com.oden.syd_camera.utils.LogUtils;<br>import com.taobao.android.dexposed.XC_MethodHook;<br> <br>/**<br> * @author xhh<br> */<br>public class ImageHook extends XC_MethodHook {<br> <br> @Override<br> protected void afterHookedMethod(MethodHookParam param) throws Throwable {<br> super.afterHookedMethod(param);<br> <br> ImageView imageView = (ImageView) param.thisObject;<br> checkBitmap(imageView,((ImageView)param.thisObject).getDrawable());<br> }<br> <br> @Override<br> protected void beforeHookedMethod(MethodHookParam param) throws Throwable {<br> super.beforeHookedMethod(param);<br> }<br> <br> private static void checkBitmap(Object thiz, Drawable drawable){<br> <br> if(drawable instanceof BitmapDrawable && thiz instanceof View){<br> final Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();<br> if(bitmap != null){<br> final View view = (View) thiz;<br> int width = view.getWidth();<br> int height = view.getHeight();<br> if(width > 0 && height > 0){<br> //图标宽度都大于view带下的两倍以上,则警告<br> if(bitmap.getWidth() >= (width << 1) && bitmap.getHeight() >= (height << 1)){<br> warn(bitmap.getWidth(),bitmap.getHeight(),width,height);<br> }<br> }else {<br> final Throwable stackTrace = new RuntimeException();<br> view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {<br> @Override<br> public boolean onPreDraw() {<br> int w = view.getWidth();<br> int h = view.getHeight();<br> if(w > 0 && h > 0){<br> if(bitmap.getWidth() >= (w << 1) && bitmap.getHeight() >= (h << 1)){<br> warn(bitmap.getWidth(),bitmap.getHeight(),view.getWidth(),view.getHeight());<br> }<br> view.getViewTreeObserver().removeOnPreDrawListener(this);<br> }<br> return true;<br> }<br> });<br> }<br> }<br> }<br> <br> }<br> <br> private static void warn(int bitmapWidth, int bitmapHeight, int viewWidth, int viewHeight){<br> String warnInfo = new StringBuilder("Bitmap size too large: ")<br> .append("\n real size: (").append(bitmapWidth).append(")")<br> .append("\n desired size: (").append(viewWidth).append(")")<br> .append("\n call stack trace : \n").append(Log.getStackTraceString(new Throwable()))<br> .toString();<br> LogUtils.i(warnInfo);<br> }<br>}</code></pre><p><span style="color: rgb(77, 77, 77); font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif, SimHei, SimSun; font-size: 16px;">Application onCreate方法中注入</span><br></p><pre><code>//图片过大检测,打印调用栈<br> DexposedBridge.hookAllConstructors(ImageView.class, new XC_MethodHook() {<br> @Override<br> protected void afterHookedMethod(MethodHookParam param) throws Throwable {<br> super.afterHookedMethod(param);<br> DexposedBridge.findAndHookMethod(ImageView.class,"setImageBitmap", Bitmap.class, new ImageHook());<br> }<br> });</code></pre><p><span style="color: rgb(77, 77, 77); font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif, SimHei, SimSun; font-size: 16px;"> 无侵入</span><br></p><p>华为荣耀 Android9.1崩溃<br><br> Process: com.yinyan.ywf.app, PID: 17341<br> java.lang.ExceptionInInitializerError<br> at me.weishu.epic.art.Epic.hookMethod(Epic.java:83)<br> at com.taobao.android.dexposed.DexposedBridge.hookMethod(DexposedBridge.java:129)<br> at com.taobao.android.dexposed.DexposedBridge.hookAllConstructors(DexposedBridge.java:203)<br> at com.cfs.app.BaseApplication.onCreate(BaseApplication.java:107)<br> at com.taobao.sophix.a.c.b(Sophix:684)<br> at com.taobao.sophix.a.e.b(Sophix:214)<br> at com.taobao.sophix.SophixApplication.onCreate(Sophix:16)<br> at com.cfs.app.SophixStubApplication.onCreate(SophixStubApplication.java:33)<br> at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1162)<br> at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6717)<br> at android.app.ActivityThread.access$2000(ActivityThread.java:273)<br> at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2020)<br> at android.os.Handler.dispatchMessage(Handler.java:112)<br> at android.os.Looper.loop(Looper.java:216)<br> at android.app.ActivityThread.main(ActivityThread.java:7625)<br> at java.lang.reflect.Method.invoke(Native Method)<br> at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)<br> at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)<br> Caused by: java.lang.RuntimeException: Do not support this ARCH now!! API LEVEL:28</p><p><span style="color: rgb(77, 77, 77); font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif, SimHei, SimSun; font-size: 16px;">解决方案:</span><br></p><pre><code>api 'me.weishu:epic:0.8.1-c'</code></pre><p>成功捕获结果:<br><br>app反馈获取相册图片,发现图片资源远远大于ImageView的大小,发出警报。<br><br>2020-10-15 20:30:29.731 21917-21917/com.yinyan.ywf.app I/SydCamera [ImageHook.java]: Bitmap size too large:<br> real size: (3072)<br> desired size: (243)<br> call stack trace :<br> java.lang.Throwable<br> at com.cfs.app.hook.ImageHook.warn(ImageHook.java:67)<br> at com.cfs.app.hook.ImageHook.checkBitmap(ImageHook.java:39)<br> at com.cfs.app.hook.ImageHook.afterHookedMethod(ImageHook.java:25)<br> at de.robv.android.xposed.DexposedBridge.handleHookedArtMethod(DexposedBridge.java:265)<br> at me.weishu.epic.art.entry.Entry64.onHookVoid(Entry64.java:68)<br> at me.weishu.epic.art.entry.Entry64.referenceBridge(Entry64.java:220)<br> at me.weishu.epic.art.entry.Entry64.voidBridge(Entry64.java:82)<br> at androidx.appcompat.widget.AppCompatImageView.setImageBitmap(AppCompatImageView.java:112)<br> at com.cfs.app.ui.activity.feedback.FeedbackActivity.onActivityResult(FeedbackActivity.java:135)<br> at android.app.Activity.dispatchActivityResult(Activity.java:8412)<br> at android.app.ActivityThread.deliverResults(ActivityThread.java:5582)<br> at android.app.ActivityThread.handleSendResult(ActivityThread.java:5630)<br> at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)<br> at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)<br> at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)<br> at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2473)<br> at android.os.Handler.dispatchMessage(Handler.java:110)<br> at android.os.Looper.loop(Looper.java:219)<br> at android.app.ActivityThread.main(ActivityThread.java:8349)<br> at java.lang.reflect.Method.invoke(Native Method)<br> at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)<br> at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)</p></div>
赞(0)
收藏(0)
分享
相关标签: