你的位置:首页 > 操作系统

[操作系统]android穿越之旅

上一篇中介绍了一种闻所未闻在android执行java命令的方法,虽然这是一种非常"高级"的技术,然后并没有什么卵用,因此被移除了博客园首页。实际上也并不是一点用处也没有,对已立即安卓的原理还是很有帮助的。

这一篇继续介绍一种更加"高级"的技术,在android中弹出一个非同寻常的窗体,这个窗体可不是一般的窗体,因为已经穿越到了android fragment层了,因此称之为SupperWindows,没有apk文件,不经过安装,这个窗体将凭空出现!

之所以要弹这样的窗体是应为之前看到一篇介绍WindowManagerService的文章,通过这样的窗体来说面WindowManagerService的工作机制。

原文地址:http://blog.csdn.net/innost/article/details/47660193

由于使用了framework层的代码,文中的代码是在android源码环境下编译的。

由于编译android源码是一件非常麻烦的事,当时就想有没有其他的办法可以编译呢,因为之前搞代码注入的时候也用了fragment层,不用在源代码的环境也是可以编译的,并且执行代码的方式和我之前用的一样,同样是通过app_process。

在编写上一遍文的时候,我突然想到,为什么不测试一下看看呢。

一开始我想把系统目录下的jar吧拿出来反编译一下得到非dex格式的jar包,这样就可以加到lib里,这样依赖的函数就能找到。

但在android5.0的设备上我发现jar包里并没有内容,拿出也没什么用,于是又换了个android4.2的设备,4.2的/system/fragment目录下和jar同命的还有.odex的文件,于是通过.odex文件最终得到可以用的jar包。

之前正式通过这样的方式来操作的,但是编译弹出窗体的代码却不行,有一些接口类找不到,这些类是由aidl生产的反编译并不能得到这些类。

不过幸运的是,在搜索这些aidl文件的时候,看到了一个网站,可以直接下载内容比较全的fragment层代码包括aidl自动生成的接口类。

http://grepcode.com/snapshot/repository.grepcode.com/java/ext/com.google.android/android/4.2_r1/

选择"Binary download",下载后直接放到lib下就可以解决依赖的问题。上面的地址是4.2的源代码。


解决了依赖的问题,那么要如何编译呢。

新建一个java工程,建立SupperWindows.java类,package为com,把之前WindowManagerService文章中代码拷贝过来。

package com;import android.content.Context;import android.content.res.Configuration;import android.graphics.*;import android.hardware.display.IDisplayManager;import android.os.*;import android.view.*;public class SuperWindows {public static void main(String[] args) {System.out.println("Hello SuperWindows");try {//SampleWindow.Run()是这个程序的主入口new SuperWindows().Run();} catch (Exception e) {e.printStackTrace();}}//IWindowSession 是客户端向WMS请求窗口操作的中间代理,并且是进程唯一的IWindowSession mSession = null;//InputChannel 是窗口接收用户输入事件的管道。在第5章中将对其进行详细的探讨InputChannel mInputChannel = new InputChannel();// 下面的三个Rect保存了窗口的布局结果。其中mFrame表示了窗口在屏幕上的位置与尺寸// 在4.4中将详细介绍它们的作用以及计算原理Rect mInsets = new Rect();Rect mFrame = new Rect();Rect mVisibleInsets = new Rect();Configuration mConfig = new Configuration();// 窗口的Surface,在此Surface上进行的绘制都将在此窗口上显示出来Surface mSurface = new Surface();// 用于在窗口上进行绘图的画刷Paint mPaint = new Paint();// 添加窗口所需的令牌,在4.2节将会对其进行介绍IBinder mToken = new Binder();// 一个窗口对象,本例演示了如何将此窗口添加到WMS中,并在其上进行绘制操作MyWindow mWindow = new MyWindow();//WindowManager.LayoutParams定义了窗口的布局属性,包括位置、尺寸以及窗口类型等WindowManager.LayoutParams mLp = new WindowManager.LayoutParams();Choreographer mChoreographer = null;//InputHandler 用于从InputChannel接收按键事件做出响应InputHandler mInputHandler = null;boolean mContinueAnime = true;public void Run() throws Exception{Looper.prepare();// 获取WMS服务IWindowManager wms = IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));// 通过WindowManagerGlobal获取进程唯一的IWindowSession实例。它将用于向WMS// 发送请求。注意这个函数在较早的Android版本(如4.1)位于ViewRootImpl类中mSession= WindowManagerGlobal.getWindowSession(Looper.myLooper());// 获取屏幕分辨率IDisplayManager dm = IDisplayManager.Stub.asInterface(ServiceManager.getService(Context.DISPLAY_SERVICE));DisplayInfo di = dm.getDisplayInfo(Display.DEFAULT_DISPLAY);Point scrnSize = new Point(di.appWidth, di.appHeight);// 初始化WindowManager.LayoutParamsinitLayoutParams(scrnSize);// 将新窗口添加到WMSinstallWindow(wms);// 初始化Choreographer的实例,此实例为线程唯一。这个类的用法与Handler// 类似,不过它总是在VSYC同步时回调,所以比Handler更适合做动画的循环器[1]mChoreographer= Choreographer.getInstance();// 开始处理第一帧的动画scheduleNextFrame();// 当前线程陷入消息循环,直到Looper.quit()Looper.loop();// 标记不要继续绘制动画帧mContinueAnime= false;// 卸载当前WindowuninstallWindow(wms);}public void initLayoutParams(Point screenSize) {// 标记即将安装的窗口类型为SYSTEM_ALERT,这将使得窗口的ZOrder顺序比较靠前mLp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;mLp.setTitle("SampleWindow");// 设定窗口的左上角坐标以及高度和宽度mLp.gravity = Gravity.LEFT | Gravity.TOP;mLp.x = screenSize.x / 4;mLp.y = screenSize.y / 4;mLp.width = screenSize.x / 2;mLp.height = screenSize.y / 2;// 和输入事件相关的Flag,希望当输入事件发生在此窗口之外时,其他窗口也可以接受输入事件mLp.flags = mLp.flags | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;}public void installWindow(IWindowManager wms) throws Exception {// 首先向WMS声明一个Token,任何一个Window都需要隶属与一个特定类型的Tokenwms.addWindowToken(mToken,WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);// 设置窗口所隶属的TokenmLp.token = mToken;// 通过IWindowSession将窗口安装进WMS,注意,此时仅仅是安装到WMS,本例的Window// 目前仍然没有有效的Surface。不过,经过这个调用后,mInputChannel已经可以用来接受// 输入事件了mSession.add(mWindow,0, mLp, View.VISIBLE, mInsets, mInputChannel);/*通过IWindowSession要求WMS对本窗口进行重新布局,经过这个操作后,WMS将会为窗口创建一块用于绘制的Surface并保存在参数mSurface中。同时,这个Surface被WMS放置在LayoutParams所指定的位置上 */mSession.relayout(mWindow,0, mLp, mLp.width, mLp.height, View.VISIBLE,0, mFrame, mInsets,mVisibleInsets, mConfig, mSurface);if(!mSurface.isValid()) {throw new RuntimeException("Failed creating Surface.");}// 基于WMS返回的InputChannel创建一个Handler,用于监听输入事件//mInputHandler一旦被创建,就已经在监听输入事件了mInputHandler= new InputHandler(mInputChannel, Looper.myLooper());}public void uninstallWindow(IWindowManager wms) throws Exception {// 从WMS处卸载窗口mSession.remove(mWindow);// 从WMS处移除之前添加的Tokenwms.removeWindowToken(mToken);}public void scheduleNextFrame() {// 要求在显示系统刷新下一帧时回调mFrameRender,注意,只回调一次mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mFrameRender, null);}// 这个Runnable对象用以在窗口上描绘一帧public Runnable mFrameRender = new Runnable() [email protected] void run() {try{// 获取当期时间戳long time = mChoreographer.getFrameTime() % 1000;// 绘图if (mSurface.isValid()) {Canvas canvas = mSurface.lockCanvas(null);canvas.drawColor(Color.WHITE);canvas.drawRect(2 * mLp.width / 1000- mLp.width, 0, 2 *mLp.width/ 1000, mLp.height,mPaint);String text = "哈哈 这是一个非比寻常的窗体!";canvas.drawText(text, 0, text.length(), 10, 20, mPaint);mSurface.unlockCanvasAndPost(canvas);mSession.finishDrawing(mWindow);}if(mContinueAnime)scheduleNextFrame();} catch (Exception e) {e.printStackTrace();}}};// 定义一个类继承InputEventReceiver,用以在其onInputEvent()函数中接收窗口的输入事件class InputHandler extends InputEventReceiver {Looper mLooper = null;public InputHandler(InputChannel inputChannel, Looper looper) {super(inputChannel,looper);mLooper= looper;[email protected] void onInputEvent(InputEvent event) {if(event instanceof MotionEvent) {MotionEvent me = (MotionEvent)event;if (me.getAction() ==MotionEvent.ACTION_UP) {// 退出程序mLooper.quit();}}super.onInputEvent(event);}}// 实现一个继承自IWindow.Stub的类MyWindow。class MyWindow extends IWindow.Stub {// 保持默认的实现即可}}

  

导入上面所说的android-4.2_r1.jar依赖包,解决依赖问题,编译就可以得到superwindows.jar文件。

当然原始的.jar在android下是不能运行的,要转成dex才可以,于是使用sdk中的dx命令将superwindows.jar转成superwindows.dex。dx程序位于sdk中build-tool目录下。

dx --dex --output=superwindows.dex superwindows.jar

将dex传送到安卓设备上:adb push SupperWindows.dex /data/local/tmp/

执行su命令 获得root权限,如果不是root执行下面命令的时候会提示没有权限。

执行 app_process -Djava.class.path=/data/local/tmp/superwindows.dex /system/bin com.SuperWindows ,运行SupperWindows。app_process的代码可以在app_main.cpp中看到。

第一次执行的时候不知道是什么原因程序会崩溃,再次执行命令就没有问题了,如果没有其他问题的话就可以看到弹出的SupperWindows窗体了。

执行su获取root权限后,在用app_process加载的代码同样是觉有root权限的,希望本文不要被恐怖分子看到。

更多内容请关注我的微信公众号:zhaojieTec

 


惠州一日游攻略大全惠州游玩攻略大全惠州有哪些旅游景点好惠州有什么好玩的地方惠州自助游景点攻略大全哪些人群不适合潜水? 亚龙湾在哪?有哪些公交可以到达? 怎么去涠洲岛?有什么交通工具? 爸爸去哪儿的灵水村在哪?怎么去? 观音山五一门票多少钱?五一樟木头观音山有什么好玩的? 2015奔跑吧兄弟第二期拍摄动向?跑男第二季五一去哪录制? 幻彩筑梦 深圳前海华侨城JW万豪酒店首届婚礼秀 奔跑吧兄弟第二期什么时候来广州?跑男第二季几时来广州? 丽江古城有哪些好玩的酒吧? 丽江古城是怎么由来的? 丽江古城哪些景点适合周末去玩的? 丽江哪家客栈比较舒服?花间堂酒店怎么样? 东莞华南mall欢笑天地有直达车吗?华南mall欢笑天地坐几路公交? 华南mall欢笑天地怎么走?东莞华南mall欢笑天地游玩攻略? 首届中国温泉旅游推广季将于重庆举行 广东最美瑶寨在哪里?必背瑶寨在什么地方? IDT7142SA55J Datasheet IDT7142SA55J Datasheet IDT7142SA55J8 Datasheet IDT7142SA55J8 Datasheet IDT7142SA55P Datasheet IDT7142SA55P Datasheet 东莞到曲靖万亩草山旅游 东莞到曲靖万亩草山旅游 东莞到曲靖万亩草山旅游 东莞到曲靖沾益珠江源旅游 东莞到曲靖沾益珠江源旅游 东莞到曲靖沾益珠江源旅游 东莞到曲靖终南山湖旅游 东莞到曲靖终南山湖旅游 东莞到曲靖终南山湖旅游