1.androidå¼å设置å±è½å½å¶
2.Android Binder Hookçå®ç°
androidå¼å设置å±è½å½å¶
项ç®å¼åä¸ï¼ä¸ºäºç¨æ·ä¿¡æ¯çå®å ¨ï¼ä¼æç¦æ¢é¡µé¢è¢«æªå±ãå½å±çéæ±ãè¿ç±»èµæï¼å¨ç½ä¸æå¾å¤ï¼ä¸è¬é½æ¯éè¿è®¾ç½®ActivityçFlag解å³ï¼å¦ï¼
//ç¦æ¢é¡µé¢è¢«æªå±ãå½å±getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
è¿ç§è®¾ç½®å¯è§£å³ä¸è¬çé²æªå±ãå½å±çéæ±ã
å¦æ页é¢ä¸æå¼¹åºPopupwindowï¼å¨å½å±è§é¢ä¸çæææ¯ï¼
éPopupwindowåºå为é»è²
ä½Popupwindowåºåä»ç¶æ¯å¯ä»¥çå°ç
å¦ä¸é¢ä¸¤å¼ Gifå¾æ示ï¼
æªè®¾ç½®FLAG_SECUREï¼å½å±çææï¼å¦ä¸å¾ï¼gitå¾çä¸é´çæ°´å°å¿½ç¥ï¼ï¼
设置äºFLAG_SECUREä¹åï¼å½å±çææï¼å¦ä¸å¾ï¼gitå¾çä¸é´çæ°´å°å¿½ç¥ï¼ï¼
åå åæ
çå°äºä¸é¢çææï¼æ们å¯è½ä¼æçé®PopupWindowä¸åDialogæèªå·±çwindow对象ï¼èæ¯ä½¿ç¨WindowManager.addViewæ¹æ³å°Viewæ¾ç¤ºå¨Activityçªä½ä¸çãé£ä¹ï¼Activityå·²ç»è®¾ç½®äºFLAG_SECUREï¼ä¸ºä»ä¹å½å±æ¶è¿è½çå°PopupWindowï¼
æ们å éè¿getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);æ¥åæä¸æºç ï¼
1ãWindow.java
//windowå¸å±åæ°private final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams();//æ·»å æ è¯public void addFlags(int flags) {
setFlags(flags,源码local指标源码 flags);
}//éè¿mWindowAttributes设置æ è¯public void setFlags(int flags, int mask) { final WindowManager.LayoutParams attrs = getAttributes();
attrs.flags = (attrs.flags&~mask) | (flags&mask);
mForcedWindowFlags |= mask;
dispatchWindowAttributesChanged(attrs);
}//è·å¾å¸å±åæ°å¯¹è±¡ï¼å³mWindowAttributespublic final WindowManager.LayoutParams getAttributes() { return mWindowAttributes;
}
éè¿æºç å¯ä»¥çå°ï¼è®¾ç½®windowå±æ§çæºç é常ç®åï¼å³ï¼éè¿windowéçå¸å±åæ°å¯¹è±¡mWindowAttributes设置æ è¯å³å¯ã
2ãPopupWindow.java
//æ¾ç¤ºPopupWindowpublic void showAtLocation(View parent, int gravity, int x, int y) {
mParentRootView = new WeakReference<>(parent.getRootView());
showAtLocation(parent.getWindowToken(), gravity, x, y);
}//æ¾ç¤ºPopupWindowpublic void showAtLocation(IBinder token, int gravity, int x, int y) { if (isShowing() || mContentView == null) { return;
}
TransitionManager.endTransitions(mDecorView);
detachFromAnchor();
mIsShowing = true;
mIsDropdown = false;
mGravity = gravity;
//å建Windowå¸å±åæ°å¯¹è±¡
final WindowManager.LayoutParams p =createPopupLayoutParams(token);
preparePopup(p);
p.x = x;
p.y = y;
invokePopup(p);
}//å建Windowå¸å±åæ°å¯¹è±¡protected final WindowManager.LayoutParams createPopupLayoutParams(IBinder token) { final WindowManager.LayoutParams p = new WindowManager.LayoutParams();
p.gravity = computeGravity();
p.flags = computeFlags(p.flags);
p.type = mWindowLayoutType;
p.token = token;
p.softInputMode = mSoftInputMode;
p.windowAnimations = computeAnimationResource(); if (mBackground != null) {
p.format = mBackground.getOpacity();
} else {
p.format = PixelFormat.TRANSLUCENT;
} if (mHeightMode < 0) {
p.height = mLastHeight = mHeightMode;
} else {
p.height = mLastHeight = mHeight;
} if (mWidthMode < 0) {
p.width = mLastWidth = mWidthMode;
} else {
p.width = mLastWidth = mWidth;
}
p.privateFlags = PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH
| PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
p.setTitle("PopupWindow:" + Integer.toHexString(hashCode())); return p;
}//å°PopupWindowæ·»å å°Windowä¸private void invokePopup(WindowManager.LayoutParams p) { if (mContext != null) {
p.packageName = mContext.getPackageName();
} final PopupDecorView decorView = mDecorView;
decorView.setFitsSystemWindows(mLayoutInsetDecor);
setLayoutDirectionFromAnchor();
mWindowManager.addView(decorView, p); if (mEnterTransition != null) {
decorView.requestEnterTransition(mEnterTransition);
}
}
éè¿PopupWindowçæºç åæï¼æ们ä¸é¾çåºï¼å¨è°ç¨showAtLocationæ¶ï¼ä¼åç¬å建ä¸ä¸ªWindowManager.LayoutParamså¸å±åæ°å¯¹è±¡ï¼ç¨äºæ¾ç¤ºPopupWindowï¼è该å¸å±åæ°å¯¹è±¡ä¸å¹¶æªè®¾ç½®ä»»ä½é²æ¢æªå±Flagã
å¦ä½è§£å³
åå æ¢ç¶æ¾å°äºï¼é£ä¹å¦ä½å¤çå¢ï¼
åå头åæä¸Windowçå ³é®ä»£ç ï¼
//éè¿mWindowAttributes设置æ è¯public void setFlags(int flags, int mask) { final WindowManager.LayoutParams attrs = getAttributes();
attrs.flags = (attrs.flags&~mask) | (flags&mask);
mForcedWindowFlags |= mask;
dispatchWindowAttributesChanged(attrs);
}
å ¶å®åªéè¦è·å¾WindowManager.LayoutParams对象ï¼å设置ä¸flagå³å¯ã
ä½æ¯PopupWindow并没æåActivityä¸æ ·æç´æ¥è·å¾windowçæ¹æ³ï¼æ´å«è¯´è®¾ç½®Flagäºãæ们ååæä¸PopupWindowçæºç ï¼
//å°PopupWindowæ·»å å°Windowä¸private void invokePopup(WindowManager.LayoutParams p) { if (mContext != null) {
p.packageName = mContext.getPackageName();
}
final PopupDecorView decorView = mDecorView;
decorView.setFitsSystemWindows(mLayoutInsetDecor);
setLayoutDirectionFromAnchor(); //æ·»å View
mWindowManager.addView(decorView, p); if (mEnterTransition != null) {
decorView.requestEnterTransition(mEnterTransition);
}
}
æ们è°ç¨showAtLocationï¼æç»é½ä¼æ§è¡mWindowManager.addView(decorView, p);
é£ä¹æ¯å¦å¯ä»¥å¨addViewä¹åè·åå°WindowManager.LayoutParamså¢ï¼
çæ¡å¾ææ¾ï¼é»è®¤æ¯ä¸å¯ä»¥çãå 为PopupWindow并没æå ¬å¼è·åWindowManager.LayoutParamsçæ¹æ³ï¼èä¸mWindowManagerä¹æ¯ç§æçã
å¦ä½æè½è§£å³å¢ï¼
æ们å¯ä»¥éè¿hookçæ¹å¼è§£å³è¿ä¸ªé®é¢ãæ们å 使ç¨å¨æ代çæ¦æªPopupWindowç±»çaddViewæ¹æ³ï¼æ¿å°WindowManager.LayoutParams对象ï¼è®¾ç½®å¯¹åºFlagï¼ååå°è·å¾mWindowManager对象å»æ§è¡addViewæ¹æ³ã
é£é©åæï¼
ä¸è¿ï¼éè¿hookçæ¹å¼ä¹æä¸å®çé£é©ï¼å 为mWindowManageræ¯ç§æ对象ï¼ä¸åPublicçAPIï¼è°·æåç»å级Androidçæ¬ä¸ä¼èèå ¶å ¼å®¹æ§ï¼æ以æå¯è½åç»Androidçæ¬ä¸æ¹äºå ¶å称ï¼é£ä¹æ们éè¿åå°è·å¾mWindowManager对象ä¸å°±æé®é¢äºãä¸è¿ä»å代çæ¬çAndroidæºç å»çï¼mWindowManager被æ¹çå çä¸å¤§ï¼æ以hookä¹æ¯å¯ä»¥ç¨çï¼æ们尽éå代ç æ¶èèä¸è¿ç§é£é©ï¼é¿å 以ååºé®é¢ã
public class PopupWindow {
...... private WindowManager mWindowManager;
......
}
èaddViewæ¹æ³æ¯ViewMangeræ¥å£çå ¬å ±æ¹æ³ï¼æ们å¯ä»¥æ¾å¿ä½¿ç¨ã
public interface ViewManager{ public void addView(View view, ViewGroup.LayoutParams params); public void updateViewLayout(View view, ViewGroup.LayoutParams params); public void removeView(View view);
}
åè½å®ç°
èèå°hookçå¯ç»´æ¤æ§åæ©å±æ§ï¼æ们å°ç¸å ³ä»£ç å°è£ æä¸ä¸ªç¬ç«çå·¥å ·ç±»å§ã
package com.ccc.ddd.testpopupwindow.utils;
import android.os.Handler;
import android.view.WindowManager;
import android.widget.PopupWindow;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class PopNoRecordProxy implements InvocationHandler { private Object mWindowManager;//PopupWindowç±»çmWindowManager对象
public static PopNoRecordProxy instance() { return new PopNoRecordProxy();
} public void noScreenRecord(PopupWindow popupWindow) { if (popupWindow == null) { return;
} try { //éè¿åå°è·å¾PopupWindowç±»çç§æ对象ï¼mWindowManager
Field windowManagerField = PopupWindow.class.getDeclaredField("mWindowManager");
windowManagerField.setAccessible(true);
mWindowManager = windowManagerField.get(popupWindow); if(mWindowManager == null){ return;
} //å建WindowManagerçå¨æ代ç对象proxy
Object proxy = Proxy.newProxyInstance(Handler.class.getClassLoader(), new Class[]{ WindowManager.class}, this); //æ³¨å ¥å¨æ代ç对象proxyï¼å³ï¼mWindowManager对象ç±proxy对象æ¥ä»£çï¼
windowManagerField.set(popupWindow, proxy);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { //æ¦æªæ¹æ³mWindowManager.addView(View view, ViewGroup.LayoutParams params);
if (method != null && method.getName() != null && method.getName().equals("addView")
&& args != null && args.length == 2) { //è·åWindowManager.LayoutParamsï¼å³ï¼ViewGroup.LayoutParams
WindowManager.LayoutParams params = (WindowManager.LayoutParams) args[1]; //ç¦æ¢å½å±
setNoScreenRecord(params);
}
} catch (Exception ex) {
ex.printStackTrace();
} return method.invoke(mWindowManager, args);
} /
*** ç¦æ¢å½å±
*/
private void setNoScreenRecord(WindowManager.LayoutParams params) {
setFlags(params, WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
} /
*** å 许å½å±
*/
private void setAllowScreenRecord(WindowManager.LayoutParams params) {
setFlags(params, 0, WindowManager.LayoutParams.FLAG_SECURE);
} /
*** 设置WindowManager.LayoutParams flagå±æ§ï¼åèç³»ç»ç±»Window.setFlags(int flags, int mask)ï¼
*
* @param params WindowManager.LayoutParams
* @param flags The new window flags (see WindowManager.LayoutParams).
* @param mask Which of the window flag bits to modify.
*/
private void setFlags(WindowManager.LayoutParams params, int flags, int mask) { try { if (params == null) { return;
} params.flags = (params.flags & ~mask) | (flags & mask);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Popwindowç¦æ¢å½å±å·¥å ·ç±»ç使ç¨ï¼ä»£ç 示ä¾ï¼
//å建PopupWindow
//æ£å¸¸é¡¹ç®ä¸ï¼è¯¥æ¹æ³å¯æ¹æå·¥åç±»
//æ£å¸¸é¡¹ç®ä¸ï¼ä¹å¯èªå®ä¹PopupWindowï¼å¨å ¶ç±»ä¸è®¾ç½®ç¦æ¢å½å±
private PopupWindow createPopupWindow(View view, int width, int height) {
PopupWindow popupWindow = new PopupWindow(view, width, height); //PopupWindowç¦æ¢å½å±
PopNoRecordProxy.instance().noScreenRecord(popupWindow); return popupWindow;
} //æ¾ç¤ºPopupwindow
private void showPm() {
View view = LayoutInflater.from(this).inflate(R.layout.pm1, null);
PopupWindow pw = createPopupWindow(view,ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
pw1.setFocusable(false);
pw1.showAtLocation(this.getWindow().getDecorView(), Gravity.BOTTOM | Gravity.RIGHT, PopConst.PopOffsetX, PopConst.PopOffsetY);
}
å½å±ææå¾ï¼
Android Binder Hookçå®ç°
Binder Hook å¯ä»¥ Hook æå½åè¿ç¨ç¨å°çç³»ç» Service æå¡ã以 LocationManager 为ä¾ï¼å¨è·åä¸ä¸ª LocationManager æ¶å为两æ¥ï¼
(1) è·å IBinder 对象ï¼
(2) éè¿ IBinder ç asInterface() æ¹æ³è½¬å为 LocationMangerService 对象ï¼æ¥çåå§å LocationManager ã
application å±ç¨å°çé½æ¯ LocationManager 对象ã
åçï¼
æ´ä¸ªè¿ç¨éè¦å©ç¨åå°è®¾ç½®ä¸ä¸ªèªå®ä¹ç Binder 对象åä¸ä¸ªèªå®ä¹ç Service 对象ãç±äºæä»¬åª Hook å ¶ä¸ä¸é¨åçåè½ï¼å ¶ä»åè½è¿éè¦ä¿çï¼æ以è¦ç¨å¨æ代ççæ¹å¼å建èªå®ä¹å¯¹è±¡ã
å¨ç解åé¢çå 容åä½ éè¦äºè§£è¿äºç¥è¯ç¹ï¼
Activity çç±»å¨è·åç³»ç» Service æ¶ï¼é½æ¯è°ç¨ getSystemService(serviceName) æ¹æ³è·åçã
Context # getSystemService() æ¹æ³æç»ä¼è°ç¨å° ServiceManager # getService() æ¹æ³ä¸ã以 LocationManager 对åºç ServiceFetcher 为ä¾ï¼å®ç createService() æ¹æ³æºç å¦ä¸ï¼
åå¦æä»¬è¦ Hook æ LocationManager # getLastKnownLocation() æ¹æ³ï¼ä¸æé½æ¯ï¼ãæ们è¦åçå°±æ¯è®©
ServiceManager.getService(Context.LOCATION_SERVICE) è¿åæ们èªå®ä¹ç Binder 对象ã
å çä¸ä¸è¿ä¸ªæ¹æ³çæºç ï¼
sCache æ¯ä¸ä¸ª Mapï¼ç¼åäºå·²ç»åç³»ç»è¯·æ±è¿ç Binderãå¦æéè¦è®©è¿ä¸ªæ¹æ³è¿åæ们èªå·±ç binder 对象ï¼åªéè¦äºå å¾ sCache ä¸ put ä¸ä¸ªèªå®ä¹ç Binder 对象就è¡äºã
å¨ put ä¹åï¼éè¦å å建åºä¸ä¸ªèªå®ä¹ç Binderãè¿ä¸ª Binder å¨è¢« ILocationManager.Stub.asInterface å¤çåï¼å¯ä»¥è¿åä¸ä¸ªèªå®ä¹ç LocationManagerService 对象ã
å çä¸ä¸ Binder ç asInterface() çå®ç°ï¼
å¦ææ queryLocalInterface()æ¹æ³è¿åä¸ä¸ªèªå®ä¹çServiceï¼ä½¿å¾èµ° if è¯å¥å é¨ï¼ä¸èµ° elseï¼é£å°±ç®æ¯Hook æåäºã
å设æ们æ³è®©ç³»ç»ç LocationManager è¿åçä½ç½®ä¿¡æ¯å ¨æ¯å¨å¤©å®é¨(., .)ãé£æ们éè¦ä½¿å¾ LocatitionManagerService ç getLastLocation() æ¹æ³ è¿åçå ¨æ¯ (., .)ã
ç±äºæ们ä¸è½ç´æ¥æ¿å°ç³»ç»çè¿ä¸ªService对象ï¼å¯ä»¥å ç¨åå°çæ¹å¼æ¿å°ç³»ç»çLocationManagerServiceãç¶åæ¦æª getLastLocation() æ¹æ³ã
åççBinder对象å¨è°ç¨ queryLocalInterface() æ¹æ³æ¶ä¼è¿ååççService对象ãæ们å¸æè¿å3.1ä¸çèªå®ä¹Serviceãæ以è¿éæ¦æª queryLocalInterface() æ¹æ³ã
æäºèªå®ä¹ç Binder åï¼å°å®æ³¨å ¥å° ServiceManger ç sCache åéä¸å°±å®æ Hook äº~
å½onClick被è°ç¨çæ¶åï¼ToaståLogé½ä¼æ¾ç¤ºå¤©å®é¨çåæ (., .)ãè¯æHookæåï¼
ä½ çè³å¯ä»¥ç¨Binder Hookçæ¹å¼Hookæ ActivityManagerã