吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 12387|回复: 30
收起左侧

[Android 原创] Android物理按键监听以及恶意代码分析

  [复制链接]
wushaominkk 发表于 2018-2-28 11:29
本帖最后由 wushaominkk 于 2018-2-28 19:21 编辑

一些常用物理按键电源键:
KEYCODE_POWER 电源键  
KEYCODE_BACK
后退键  
KEYCODE_MENU
菜单键  
KEYCODE_HOME
HOME键  
KEYCODE_CAMERA相机键  
KEYCODE_VOLUME_UP / KEYCODE_VOLUME_DOWM
音量键   
KEYCODE_SEARCH
搜索键  
KEYCODE_DPAD_CENTER
确定键

方向键      
KEYCODE_DPAD_UP      
KEYCODE_DPAD_DOWN      
KEYCODE_DPAD_LEFT      
KEYCODE_DPAD_RIGHT

键盘键  
KEYCODE_0...KEYCODE_9      
KEYCODE_A....KEYCODE_Z

就目前的Android手机比较常用的就是电源键,后退键,菜单键,HOME键音量键,后退键和音量上下键比较简单,
重写onKeyDown方法
[Java] 纯文本查看 复制代码
if (keyCode == event.KEYCODE_BACK) {
            return true;
        }else if (keyCode == event.KEYCODE_MENU){
            return true;
        }else if (keyCode == event.KEYCODE_VOLUME_UP){
            return true;
        }else if (keyCode == event.KEYCODE_VOLUME_DOWN){
            return true;
        }else {
            return super.onKeyDown(keyCode, event);
        }

重写以上代码可以禁用返回键菜单键,音量上下键有些恶意代码通过修改返回键达到HOME键效果,达到进程还保留在系统中
关键代码如下监听返回键,相当于点击home:
[Java] 纯文本查看 复制代码
PackageManager pm = getPackageManager();
        ResolveInfo homeInfo = pm.resolveActivity(
                new Intent(Intent.ACTION_MAIN)
                        .addCategory(Intent.CATEGORY_HOME), 0);
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            ActivityInfo ai = homeInfo.activityInfo;
            Intent startIntent = new Intent(Intent.ACTION_MAIN);
            startIntent.addCategory(Intent.CATEGORY_LAUNCHER);
            startIntent
                    .setComponent(new ComponentName(ai.packageName, ai.name));
            startActivitySafely(startIntent);
            return true;
        } else
            return super.onKeyDown(keyCode, event);

电源键开机关机监听:
开关机监听主要用于APP程序开机自启,数据缓存可以通过接收系统广播实现,接收广播需要注册,有两种注册方式,一种是静态注册,在AndroidMainfest.xml 设置receiver,
另外一种是动态注册通过在代码中实现,两种广播分别是:android.intent.action.BOOT_COMPLETED 开机android.intent.action.ACTION_SHUTDOWN关机
关键代码:
[Java] 纯文本查看 复制代码
<receiver android:name=".BootBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <category android:name="android.intent.category.HOME"/>
            </intent-filter>
        </receiver>
        <receiver android:name=".ShutdownBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.ACTION_SHUTDOWN"/>
                <category android:name="android.intent.category.HOME"/>
            </intent-filter>
        </receiver>

接收广播通过继承BroadcastReceiver,重写onReceive方法,
关键代码:
关机监听
[Java] 纯文本查看 复制代码
public class ShutdownBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "ShutdownBroadcastReceiver";
    private static final String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(ACTION_SHUTDOWN)){
            Log.d(TAG, "手机即将光机");
            Toast.makeText(context, "手机即将关机", Toast.LENGTH_SHORT).show();
        }
    }
}

开机监听:
[Java] 纯文本查看 复制代码
public class BootBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "BootBroadcastReceiver";
    private static final String ACTION_BOOT = "android.intent.action.BOOT_COMPLETED";
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(ACTION_BOOT)){
            Log.d(TAG, "手机开机了");
            Toast.makeText(context, "手机开机了", Toast.LENGTH_SHORT).show();
            Intent i = new Intent(context, MainActivity.class);
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(i);
        }
    }
}

权限申请:<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
[Java] 纯文本查看 复制代码
//注册Receiver  
   
              HomeKeyEventBroadCastReceiver receiver = new HomeKeyEventBroadCastReceiver();  
             registerReceiver(receiver, new IntentFilter(  
                           Intent. ACTION_CLOSE_SYSTEM_DIALOGS));  

第二种:想要完全监听home键需要在framework层去处理。/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
里面去修改private void handleLongPressOnHome() 这个方法。
[Java] 纯文本查看 复制代码
private void handleLongPressOnHome() {  
        // We can't initialize this in init() since the configuration hasn't been loaded yet.  
        if (mLongPressOnHomeBehavior < 0) {  
            mLongPressOnHomeBehavior  
                    = mContext.getResources().getInteger(R.integer.config_longPressOnHomeBehavior);  
            if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||  
                    mLongPressOnHomeBehavior > LONG_PRESS_HOME_RECENT_SYSTEM_UI) {  
                mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;  
            }  
        }  
  
        if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {  
            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);  
            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);  
  
            // Eat the longpress so it won't dismiss the recent apps dialog when  
            // the user lets go of the home key  
            mHomeLongPressed = true;  
        }  
  
        if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {  
            showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);  
        } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {  
            try {  
                IStatusBarService statusbar = getStatusBarService();  
                if (statusbar != null) {  
                    statusbar.toggleRecentApps();  
                }  
            } catch (RemoteException e) {  
                Slog.e(TAG, "RemoteException when showing recent apps", e);  
                // re-acquire status bar service next time it is needed.  
                mStatusBarService = null;  
            }  
        }  
    }  

只要把handleLongPressOnHome里面做出相对应的处理就ok记得加上权限:<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
恶意代码可以通过监听home键达到退出自启,或则通过禁用HOME,返回键,菜单键,下拉菜单等等达到锁屏目的在2.3版本以下重写下面方法就能重写home键,
关键代码:
[Java] 纯文本查看 复制代码
public void onAttachedToWindow() {
      this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
      super.onAttachedToWindow();
}

4.0以上可以通过设置透明覆盖层AlertDialog达到禁用HOME键目的
关键代码:
[Java] 纯文本查看 复制代码
WindowManager.LayoutParams params = getWindow().getAttributes();
            params.type = TYPE_SYSTEM_ERROR;
            params.dimAmount = 0.0F; // transparent
            params.width = 0;
            params.height = 0;
            params.gravity = Gravity.BOTTOM;
            getWindow().setAttributes(params);
            getWindow().setFlags(FLAG_SHOW_WHEN_LOCKED | FLAG_NOT_TOUCH_MODAL, 0xffffff);
            setOwnerActivity(activity);
            setCancelable(false);

涉及到安全性具体代码就不贴了,主要是给大家一个思路,遇到类似问题知道怎么解决
禁用下拉栏关键代码:
修改SystemUI路径:==/frameworks/base/packages/SystemUI//src/com/android/systemui/statusbar/phone/PhoneStatusBar.Java==通过在PhoneStatusBar.java类中注册一个广播的方式来实现状态栏的禁用和解除,其核心方法就是调用了disable()方法。disable()是SystemUI自定义的方法,感兴趣的同学可以去看其具体实现。
SystemUI中的具体实现代码:
[Java] 纯文本查看 复制代码
@@ -494,6 +494,31 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
                                                            }
+    //add steven zhang by 20160701
+    private BroadcastReceiver mStatusShowHide = new BroadcastReceiver() {
+
+        @Override
+        public void onReceive(final Context context, Intent intent) {
+            // TODO Auto-generated method stub
+            String action = intent.getAction();
+
+            if ("com.aura.statusbar.SHOW_OR_HIDE".equals(action)) {
+                // StatusBarManager.DISABLE_NONE
+                // StatusBarManager.DISABLE_EXPAND
+                final int mode = intent.getIntExtra("mode", StatusBarManager.DISABLE_NONE);
+                if (mNavigationBarView != null) {
+                    mHandler.post(new Runnable() {
+
+                        @Override
+                        public void run() {
+
+                            disable(mode);
+                        }
+                    });
+                }
+            }
+        }
+    };
     //micheal add the Broadcast interface for Control the wifi sleep mode change begin 20150514
     private BroadcastReceiver wifiSleepModeChangeReceiver = new BroadcastReceiver(){
       @Override
@@ -519,6 +544,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
   // ================================================================================
   protected PhoneStatusBarView makeStatusBarView() {
     final Context context = mContext;
+        // add steven zhang by 20160701
+        IntentFilter statusFilter = new IntentFilter();
+        statusFilter.addAction("com.aura.statusbar.SHOW_OR_HIDE");
+        context.registerReceiver(mStatusShowHide, statusFilter);

示隐藏的广播我们已经注册好了
关键代码:
[Java] 纯文本查看 复制代码
@Override
protected void onResume() {
    super.onResume();
    Intent i = new Intent("com.aura.statusbar.SHOW_OR_HIDE");
    i.putExtra("mode", StatusBarManager.DISABLE_EXPAND);
    sendBroadcast(i);
}
@Override
protected void onPause() {
    super.onPause();
    Intent i = new Intent("com.aura.statusbar.SHOW_OR_HIDE");
    i.putExtra("mode", StatusBarManager.DISABLE_NONE);
    sendBroadcast(i);
}

在Activity中重写onResumeonPause方法实现状态栏的禁用和解除禁用。另:StatusBarManager是一个隐藏类,所以调用的时候可能导入不了包会报错有源码的朋友,可以使用系统编译的后framework jar包作为APP的lib就可以直接使用StatusBarManager方法了。其路径为/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar。将classes.jar改为framework.jar导入工程就OK了。通过上面的步骤我们知道最关键的就是调用PhoneStatusBar中disable()方法,我们这里是以广播的方式实现的,只要能实现调用到disable()就可以禁用状态栏。
需要用到的权限
<uses-permission android:name="android.permission.STATUS_BAR"/>
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>
但是android.permission.STATUS_BAR编译会报错,因为这个权限只有系统用户或则ROOT用户才可以使用.需要使用该权限需要把应用伪装成系统应用并使用系统签名
1. 在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。
2. 修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行让程序运行到系统进程中,就可以了! Android中应用程序如何获得系统签名权限:有些库的使用条件比较苛刻,要求同一签名的程序才可以获得访问权。此时即便是在AndroidManifest.xml中添加了相应的permission,依旧会得到没有xx访问权限的问题!第一个方法简单点,不过需要在Android系统源码的环境下用make来编译:      
1. 在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。        
2. 修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行        
3. 使用mm命令来编译,生成的apk就有修改系统时间的权限了。
第二个方法麻烦点,不过不用开虚拟机跑到源码环境下用make来编译:        
1. 同上,加入android:sharedUserId="android.uid.system"这个属性。        
2. 使用eclipse编译出apk文件,但是这个apk文件是不能用的。        
3. 用压缩软件打开apk文件,删掉META-INF目录下的CERT.SF和CERT.RSA两个文件。        
4. 使用目标系统的platform密钥来重新给apk文件签名。这步比较麻烦,首先找到密钥文件,在我的Android源码目录中的位置是"build\target\product\security",下面的platform.pk8和platform.x509.pem两个文件。然后用Android提供的Signapk工具来签名,signapk的源代码是在"build\tools\signapk"下,用法为"signapkplatform.x509.pem platform.pk8 input.apk output.apk",文件名最好使用绝对路径防止找不到,也可以修改源代码直接使用。   
   
这样最后得到的apk和第一个方法是一样的。        
最后解释一下原理,
首先加入android:sharedUserId="android.uid.system"这个属性。通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中。那么把程序的UID配成android.uid.system,也就是要让程序运行在系统进程中,这样就有权限来修改系统时间了。        
只是加入UID还不够,如果这时候安装APK的话发现无法安装,提示签名不符,原因是程序想要运行在系统进程中还要有目标系统的platform. key,就是上面第二个方法提到的platform.pk8和platform.x509.pem两个文件。
用这两个key签名后apk才真正可以放入系统进程中。第一个方法中加入LOCAL_CERTIFICATE := platform其实就是用这两个key来签名。      
这也有一个问题,就是这样生成的程序只有在原始的Android系统或者是自己编译的系统中才可以用,因为这样的系统才可以拿到platform.pk8 和platform.x509.pem两个文件。
要是别家公司做的Android上连安装都安装不了。试试原始的Android中的key来签名,程序在模拟器上运行OK,不过放到G3上安装直接提示"Package ... has no signatures that match those in shared user android.uid.system",这样也是保护了系统的安全。      
这个android:sharedUserId属性不只可以把apk放到系统进程中,也可以配置多个APK运行在一个进程中,这样可以共享数据,应该会很有用的!

181953c9flfjd15r915b7b.png


免费评分

参与人数 12威望 +1 吾爱币 +21 热心值 +12 收起 理由
lzr4840 + 1 + 1 我很赞同!
王娜娜 + 1 + 1 我很赞同!
夜莺之歌 + 1 + 1 热心回复!
如此多娇 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
bouc + 1 + 1 谢谢@Thanks!
爷单身1却潇洒 + 1 + 1 用心讨论,共获提升!
qtfreet00 + 1 + 9 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
夏雨微凉 + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
hotwater10 + 1 + 1 用心讨论,共获提升!
AlwDnal + 1 + 1 谢谢@Thanks!
尼采1729 + 1 + 1 用心讨论,共获提升!
lookerJ + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| wushaominkk 发表于 2018-2-28 11:52
Parcelable 发表于 2018-2-28 11:51
支持下,偏理论,事实上在很多国内系统都有限制,开关机广播都是接收不了的,进程会被杀掉

接收广播测试过4.1,4.2,7.0.8.0系统都可以实现,但是部分国产手机改了系统源码,有可能会有点问题
 楼主| wushaominkk 发表于 2018-3-1 09:16
真爱贤 发表于 2018-3-1 08:31
只会应用层开发,home键监听不了

HOME键监听两种思路:要么源码编程,要么可以通过悬浮框屏蔽HOME,第二种经测试只能用于6.0以下系统,想要完全适配只能通过在源码编译实现
Javajsc 发表于 2018-2-28 11:33
peterq521 发表于 2018-2-28 11:38
虽然是外行 但是感觉都是神教程 多谢
 楼主| wushaominkk 发表于 2018-2-28 11:43
Javajsc 发表于 2018-2-28 11:33
楼主应该好好排版一下

感谢提醒,已经排好版了
xiaoke82550 发表于 2018-2-28 11:49
好东西·····谢谢了
Parcelable 发表于 2018-2-28 11:51
支持下,偏理论,事实上在很多国内系统都有限制,开关机广播都是接收不了的,进程会被杀掉
memory947 发表于 2018-2-28 12:29
感谢分享
控控网络 发表于 2018-2-28 14:27
膜拜大神
 楼主| wushaominkk 发表于 2018-2-28 14:30

我是个菜鸡
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-14 13:56

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表