• 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.LayoutParams
    initLayoutParams(scrnSize);
    
    // 将新窗口添加到WMS
    installWindow(wms);
    
    // 初始化Choreographer的实例,此实例为线程唯一。这个类的用法与Handler
    // 类似,不过它总是在VSYC同步时回调,所以比Handler更适合做动画的循环器[1]
    mChoreographer= Choreographer.getInstance();
    
    // 开始处理第一帧的动画
    scheduleNextFrame();
    
    // 当前线程陷入消息循环,直到Looper.quit()
    Looper.loop();
    
    // 标记不要继续绘制动画帧
    mContinueAnime= false;
    
    // 卸载当前Window
    uninstallWindow(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都需要隶属与一个特定类型的Token
    wms.addWindowToken(mToken,WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
    // 设置窗口所隶属的Token
    mLp.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处移除之前添加的Token
    wms.removeWindowToken(mToken);
    }
    
    public void scheduleNextFrame() {
    // 要求在显示系统刷新下一帧时回调mFrameRender,注意,只回调一次
    mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION
    , mFrameRender, null);
    }
    
    // 这个Runnable对象用以在窗口上描绘一帧
    public Runnable mFrameRender = new Runnable() {
    @Override
    public 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;
    }
    @Override
    public 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

  • 相关阅读:
    (转)Golang reflect.DeepEqual函数:判断两个值是否一致
    Kubernetes字段Finalizers
    校园电子屏无人值守模式探索
    史上最全测试开发工具推荐(含自动化、性能、稳定性、抓包)
    Java 将Word转为HTML的方法
    C# 在PPT中添加数学公式
    C# 将PPT转为OFD/DPT/DPS/ODP/POTX/UOP
    C# 将Excel转为OFD、UOS
    Java 扫描识别条形码图片
    C# 加载Word的3种方法
  • 原文地址:https://www.cnblogs.com/zhaojietec/p/4975840.html
Copyright © 2020-2023  润新知