Android系統(tǒng)信息和安全機(jī)制

導(dǎo)語

在android的世界了,不同的軟件,硬件信息就像一個(gè)國家的經(jīng)濟(jì)水平,軍事水平,不同的配置參數(shù),代表著一個(gè)android帝國的強(qiáng)弱,所以廠商喜歡打配置戰(zhàn)。

主要內(nèi)容

  • Android系統(tǒng)信息的獲取
  • PackageManager的使用
  • ActivityManager的使用
  • 解析Packages.xml獲取系統(tǒng)信息
  • Android安全機(jī)制

具體內(nèi)容

Android系統(tǒng)信息的獲取

由于android手機(jī)的開源性,手機(jī)的配置各種各樣,那些優(yōu)化大師之類的東西,都可以跑分和看配置信息,那他們是從哪里知道這些信息的呢?遙想獲取系統(tǒng)的配置信息,通??梢詮囊韵聝蓚€(gè)方面獲?。?/p>

  • android.os.Build
  • SystemProperty
android.os.Build

android.os.Build類里面的信息非常的豐富,它包含了系統(tǒng)編譯時(shí)的大量設(shè)備,配置信息,我們列舉一點(diǎn):

  • Build.BOARD——主板
  • Build.BRAND——Android系統(tǒng)定制商
  • Build.SUPPORTED_ABIS——CPU指令集
  • Build.DEVICE——設(shè)備參數(shù)
  • Build.DISPLAY——顯示屏參數(shù)
  • Build.FINGERPRINT——唯一編號(hào)
  • Build.SERIAL——硬件序列號(hào)
  • Build.ID——修訂版本列表
  • Build.MANUFACTURER——硬件制造商
  • Build.MODEL——版本
  • Build.HARDWARE——硬件名
  • Build.PRODUCT——手機(jī)產(chǎn)品名
  • Build.TAGS——描述Build的標(biāo)簽
  • Build.TYPE——Builder類型
  • Build.VERSION.CODENAME——當(dāng)前開發(fā)代號(hào)
  • Build.VERSION.INCREMENTAL——源碼控制版本號(hào)
  • Build.VERSION.RELEASE——版本字符串
  • Build.VERSION.SDK_INT——版本號(hào)
  • Build.HOST——host值
  • Build.USER——User名
  • Build.TIME——編譯時(shí)間

上面的一些參數(shù)沒有注釋,他們來自系統(tǒng)的RO值中,這些值都是手機(jī)生產(chǎn)商配置的只讀的參數(shù)值,根據(jù)廠家的配置不同而不同,接下來我們?cè)賮砜匆幌铝硪粋€(gè)存儲(chǔ)設(shè)備軟硬件信息的類——SystemProperty。

SystemProperty

SystemProperty類包含了許多系統(tǒng)配置屬性值和參數(shù),很多信息和上面通過android.os.Build獲取的值是相同的,我們列舉一些常用的:

  • os.version——OS版本
  • os.name——OS名稱
  • os.arch——OS架構(gòu)
  • user.home——home屬性
  • user.name——name屬性
  • user.dir——Dir屬性
  • user.timezone——時(shí)區(qū)
  • path.separator——路徑分隔符
  • line.separator——行分隔符
  • file.separator——文件分隔符
  • java.vendor.url——Java vender Url屬性
  • java.class.path——Java Class屬性
  • java.class.version——Java Class版本
  • java.vendor——Java Vender屬性
  • java.version——Java版本
  • java.home——Java Home屬性
Android系統(tǒng)信息實(shí)例

下面我們用一個(gè)簡單的實(shí)例來了解一下把。

通過android.os.Build這個(gè)類,我們可以直接獲取到Build提供的系統(tǒng)信息,而通過System.getProperty(“xxx”),我們可以訪問到系統(tǒng)的屬性。

在實(shí)例中獲取到的信息與上述的基本一致,運(yùn)行如圖。

tv_message.append("主板:"+ Build.BOARD+"\n");
tv_message.append("Android系統(tǒng)定制商:"+ Build.BRAND+"\n");
tv_message.append("CPU指令集:"+ Build.SUPPORTED_ABIS+"\n");
tv_message.append("設(shè)置參數(shù):"+ Build.DEVICE+"\n");
tv_message.append("顯示屏參數(shù):"+ Build.DISPLAY+"\n");
tv_message.append("唯一編號(hào):"+ Build.SERIAL+"\n");

用System.getProperty。

tv.append("OS版本:"+System.getProperty("os.version")+"\n");
tv.append("OS名稱:"+System.getProperty("os.name")+"\n");
tv.append("OS架構(gòu):"+System.getProperty("os.arch")+"\n");
tv.append("Home屬性:"+System.getProperty("user.home")+"\n");
tv.append("Name屬性:"+System.getProperty("user.name")+"\n");

代碼貼上一點(diǎn)就可以了

運(yùn)行的實(shí)例程序中我們可以看到,我們已經(jīng)獲取到了相當(dāng)多的系統(tǒng)信息,那么這些信息的來源又是哪兒呢?記得我們分析android系統(tǒng)目錄的時(shí)候提到過,在system/build.prop中,包含了很多的RO值,打開命令窗,通過cat build.prop可以看到。

這里我們可以看到很多前面通過android.os.Build所獲取到的系統(tǒng)信息,同時(shí),在adb shell中,還可以通過getprop來獲取對(duì)應(yīng)的值。

除了上述的兩個(gè)方法,android系統(tǒng)還在另外一個(gè)非常重要的目錄來存儲(chǔ)系統(tǒng)信息——/proc目錄,在adb shell中進(jìn)入/proc目錄,通過ll命令查看文件信息。

看了這么多系統(tǒng)信息,應(yīng)該看Apk應(yīng)用信息了,在ADB Shell命令中,有兩個(gè)非常強(qiáng)大的助手,PM和AM,PM主宰著應(yīng)用的包管理,而AM主宰著應(yīng)用的活動(dòng)管理。

PackageManager——APK應(yīng)用程序信息獲取值

我們看一張圖:

Package結(jié)構(gòu)圖

最里面的框就代表整個(gè)Activity的信息,系統(tǒng)提供了ActivityInfo類來進(jìn)行封裝。
而Android提供了PackageManager來負(fù)責(zé)管理所有已安裝的App,PackageManager可以獲得AndroidManifest中不同節(jié)點(diǎn)的封裝信息,下面是一些常用的封裝信息:

  • ActivityInfo

ActivityInfo封裝在了Mainfest文件中的< activity >和< eceiver>之間的所有信息,包括name、icon、label、launchMode等。

  • ServiceInfo

ServiceInfo與ActivityInfo類似,封裝了< service>之間的所有信息。

  • ApplicationInfo

它封裝了< application>之間的信息,特別的是,ApplicationInfo包含了很多Flag,F(xiàn)LAG_SYSTEM表示為系統(tǒng)應(yīng)用,F(xiàn)LAG_EXTERNAL_STORAGE表示為安裝在SDcard上的應(yīng)用,通過這些flag可以很方便的判斷應(yīng)用的類型。

  • PackageInfo

PackageInfo包含了所有的Activity和Service信息。

  • ResolveInfo

ResolveInfo包含了< intent>信息的上級(jí)信息,所以它可以返回ActivityInfo、ServiceInfo等包含了< intent>的信息,經(jīng)常用來幫助找到那些包含特定intent條件的信息,如帶分享功能、播放功能的應(yīng)用。

有了這些封裝的信息后,還需要有特定的方法來獲取它們,下面就是PackageManager中封裝的用來獲取這些信息的方法:

  • getPackageManager():通過這個(gè)方法可以返回一個(gè)PackageManager對(duì)象。
  • getApplicationInfo():以ApplicationInfo的形式返回指定包名的ApplicationInfo。
  • getApplicationIcon():返回指定包名的Icon。
  • getInstalledApplications():以ApplicationInfo的形式返回安裝的應(yīng)用。
  • getInstalledPackages():以PackageInfo的形式返回安裝的應(yīng)用。
  • queryIntentActivities():返回指定Intent的ResolveInfo對(duì)象、Activity集合。
  • queryIntentServices():返回指定Intent的ResolveInfo對(duì)象、Service集合。
  • resolveActivity():返回指定Intent的Activity。
  • resolveService():返回指定Intent的Service。

根據(jù)ApplicationInfo的flag來判斷App的類型:

  • 如果當(dāng)前應(yīng)用的flags & ApplicationInfo.FLAG_SYSTEM != 0則為系統(tǒng)應(yīng)用。
  • 如果flags & ApplicationInfo.FLAG_SYSTEM <= 0 則為第三方應(yīng)用。
  • 特殊的當(dāng)系統(tǒng)應(yīng)用升級(jí)后也會(huì)成為第三方應(yīng)用,此時(shí) flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP != 0。
  • 如果flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE != 0 則為安裝在SDCard上的應(yīng)用。

我們通過一個(gè)實(shí)例來分析。
我們封裝一個(gè)Bean來保存我們所需的字段:

package com.lgl.systemmesage;

import android.graphics.drawable.Drawable;

/**
 * Bean
 * Created by LGL on 2016/4/28.
 */
public class PMAPPInfo {

    //應(yīng)用名
    private String appLabel;
    //圖標(biāo)
    private Drawable appIcon;
    //包名
    private String pkgName;

    //構(gòu)造方法
    public PMAPPInfo(){

    }

    public String getAppLabel() {
        return appLabel;
    }

    public void setAppLabel(String appLabel) {
        this.appLabel = appLabel;
    }

    public Drawable getAppIcon() {
        return appIcon;
    }

    public void setAppIcon(Drawable appIcon) {
        this.appIcon = appIcon;
    }

    public String getPkgName() {
        return pkgName;
    }

    public void setPkgName(String pkgName) {
        this.pkgName = pkgName;
    }
}

接下來,我們通過上面的方法判斷各種類型的應(yīng)用,我們的主布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <Button
        android:id="@+id/btn_all"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="All APP"
        android:textAllCaps="false" />

    <Button
        android:id="@+id/btn_other"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Other App"
        android:textAllCaps="false" />

    <Button
        android:id="@+id/btn_system"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="System App"
        android:textAllCaps="false" />

    <ListView
        android:id="@+id/mListView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"></ListView>

</LinearLayout>

這里有一個(gè)listview,所以我們需要一個(gè)adapter和一個(gè)item:

package com.lgl.systemmesage;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * 數(shù)據(jù)源
 * Created by LGL on 2016/4/28.
 */
public class PkgAdapter extends BaseAdapter {
    private Context mContext;
    private List<PMAPPInfo> mList;

    public PkgAdapter(Context context) {
        mContext = context;
        mList = new ArrayList<>();
    }

    public void addAll(List<PMAPPInfo> list) {
        mList.clear();
        mList.addAll(list);
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return mList.size();
    }

    @Override
    public PMAPPInfo getItem(int position) {
        return mList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        PMAPPInfo item = getItem(position);
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false);
            holder.mIcon = (ImageView) convertView.findViewById(R.id.iv_icon);
            holder.mLabel = (TextView) convertView.findViewById(R.id.tv_label);
            holder.mPkgName = (TextView) convertView.findViewById(R.id.tv_pkg_name);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.mIcon.setImageDrawable(item.getAppIcon());
        holder.mLabel.setText(item.getAppLabel());
        holder.mPkgName.setText(item.getPkgName());
        return convertView;
    }

    static class ViewHolder {
        ImageView mIcon;
        TextView mLabel;
        TextView mPkgName;
    }
}

item就簡單了:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/empty"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginLeft="15dp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/tv_pkg_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>

</LinearLayout>

那我們主程序的邏輯就是:

package com.lgl.systemmesage;

import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

/**
 * 軟件列表
 * Created by LGL on 2016/4/28.
 */
public class APP extends AppCompatActivity implements View.OnClickListener{

    private PackageManager mPackageManager;

    private ListView mListView;
    private PkgAdapter mAdapter;
    List<PMAPPInfo> result;

    protected void onCreate( Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_app);

        mPackageManager = getPackageManager();
        mListView = (ListView) findViewById(R.id.mListView);
        mAdapter = new PkgAdapter(this);
        mListView.setEmptyView(findViewById(R.id.empty));
        mListView.setAdapter(mAdapter);
        findViewById(R.id.btn_all).setOnClickListener(this);
        findViewById(R.id.btn_other).setOnClickListener(this);
        findViewById(R.id.btn_system).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_all:
                result = getAppInfo(R.id.btn_all);
                break;
            case R.id.btn_other:
                result = getAppInfo(R.id.btn_other);
                break;
            case R.id.btn_system:
                result = getAppInfo(R.id.btn_system);
                break;
            default:
                result = new ArrayList<>();
        }
        mAdapter.addAll(result);
    }

    private List<PMAPPInfo> getAppInfo(int flag) {
        List<ApplicationInfo> appInfos = mPackageManager.getInstalledApplications(
                PackageManager.GET_UNINSTALLED_PACKAGES);
        List<PMAPPInfo> list = new ArrayList<>();
        //根據(jù)不同的flag來切換顯示不同的App類型
        switch (flag) {
            case R.id.btn_all:
                list.clear();
                for (ApplicationInfo appInfo : appInfos) {
                    list.add(makeAppInfo(appInfo));
                }

                break;
            case R.id.btn_other:
                list.clear();
                for (ApplicationInfo appInfo : appInfos) {
                    if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) <= 0) {
                        list.add(makeAppInfo(appInfo));
                    } else if ((appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0){
                        list.add(makeAppInfo(appInfo));
                    }
                }
                break;
            case R.id.btn_system:
                list.clear();
                for (ApplicationInfo appInfo : appInfos) {
                    if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                        list.add(makeAppInfo(appInfo));
                    }
                }
                break;
        }
        return list;
    }

    private PMAPPInfo makeAppInfo(ApplicationInfo appInfo) {
        PMAPPInfo info = new PMAPPInfo();
        info.setAppIcon(appInfo.loadIcon(mPackageManager));
        info.setAppLabel(appInfo.loadLabel(mPackageManager).toString());
        info.setPkgName(appInfo.packageName);
        return info;
    }
}

效果圖:

效果圖

ActivityManager——Apk應(yīng)用信息獲取

前面所使用的packagemanager獲取的是所有的應(yīng)用包名,但是哼哈二將還有一名大獎(jiǎng)沒有說道,那就是ActivityManager了,他的功能四號(hào)不遜色前者,事實(shí)上,他在使用上各有側(cè)重點(diǎn),前者側(cè)重于獲取應(yīng)用的包信息,后者獲取運(yùn)行的應(yīng)用程序信息。

同packagemanager一樣,ActivityManager也封裝了不少的Bean對(duì)象,我們選幾個(gè)重點(diǎn)來說一下:

  • ActivityManager.MemoryInfo——MemoryInfo有幾個(gè)非常重要的字段:availMem(系統(tǒng)可用內(nèi)存),totalMem(總內(nèi)存),threshold(低內(nèi)存的閾值,即區(qū)分是否低內(nèi)存的臨界值),lowMemory(是否處于低內(nèi)存)。
  • Debug.MemoryInfo——這個(gè)MemoryInfo用于統(tǒng)計(jì)進(jìn)程下的內(nèi)存信息。
  • RunningAppProcessInfo——運(yùn)行進(jìn)程的信息,存儲(chǔ)的字段有:processName(進(jìn)程名),pid(進(jìn)程pid),uid(進(jìn)程uid),pkgList(該進(jìn)程下的所有包)
  • RunningServiceInfo——運(yùn)行的服務(wù)信息,在它里面同樣包含了一些服務(wù)進(jìn)程信息,同時(shí)還有一些其他信息。activeSince(第一次被激活的時(shí)間、方式),foreground(服務(wù)是否在后臺(tái)執(zhí)行)。

我們同樣的用一個(gè)實(shí)例來講解:

package com.lgl.systemmesage;

/**
 * Created by LGL on 2016/4/28.
 */
public class AMProcessInfo {

    private String pid;
    private String uid;
    private String memorySize;
    private String processName;

    public  AMProcessInfo(){

    }

    public String getPid() {
        return pid;
    }

    public void setPid(String pid) {
        this.pid = pid;
    }

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    public String getProcessName() {
        return processName;
    }

    public void setProcessName(String processName) {
        this.processName = processName;
    }

    public String getMemorySize() {
        return memorySize;
    }

    public void setMemorySize(String memorySize) {
        this.memorySize = memorySize;
    }
}

然后我們用一個(gè)方法就可以獲取到了:

 /**
     * 正在運(yùn)行
     * @return
     */
    private List<ActivityManager.RunningAppProcessInfo> getRunningProcossInfo(){
        mAMProcessInfo = new ArrayList<>();
        List<ActivityManager.RunningAppProcessInfo>appRunningList = activityManager.getRunningAppProcesses();

        for (int i = 0;i<appRunningList.size();i++){
            ActivityManager.RunningAppProcessInfo info = appRunningList.get(i);
            int pid = info.pid;
            int uid = info.uid;
            String procossName = info.processName;
            int[]memoryPid = new int[]{pid};
            Debug.MemoryInfo[] memoryInfos = activityManager.getProcessMemoryInfo(memoryPid);

            int memorySize = memoryInfos[0].getTotalPss();

            AMProcessInfo processInfo = new AMProcessInfo();
            processInfo.setPid(""+pid);
            processInfo.setUid(""+uid);
            processInfo.setMemorySize(""+memorySize);
            processInfo.setProcessName(procossName);
            appRunningList.add(processInfo);
        }
        return  appRunningList;
    }

效果圖:

效果圖

解析Packages.xml獲取系統(tǒng)信息

熟悉Android開機(jī)啟動(dòng)流程的朋友大概知道,在系統(tǒng)初始化到時(shí)候,packagemanager的底層實(shí)現(xiàn)類packagemanagerService會(huì)去掃描系統(tǒng)的一些特定目錄,并且解析其中的Apk文件,同時(shí)Android把他獲取到的應(yīng)用信息保存到xml中,做成一個(gè)應(yīng)用的花名冊(cè),就是data/system/apckages.xml,我們用adb pull命令把他導(dǎo)出來,里面的信息也太多了,但是我們只要知道結(jié)果根節(jié)點(diǎn)就可以了。

  • <permissions>標(biāo)簽

permissions標(biāo)簽定義了現(xiàn)在系統(tǒng)所有的權(quán)限,也分兩類,系統(tǒng)定義的和app定義的。

  • <package>標(biāo)簽

package代表的是一個(gè)apk的屬性。其中各節(jié)點(diǎn)的信息含義大致為:

  • name:APK的包名
  • cadePath:APK安裝路徑,主要在system/app和data/app兩種,前者放系統(tǒng)級(jí)別的,后者放系統(tǒng)安裝的
  • userid:用戶ID
  • version:版本
  • <perms>標(biāo)簽

對(duì)應(yīng)apk的清單文件,記錄apk的權(quán)限信息。

通過這個(gè)xml文件的標(biāo)簽,可以獲取到很多手機(jī)應(yīng)用的信息,通常在進(jìn)行系統(tǒng)層開發(fā)的時(shí)候,可以通過這個(gè)xml獲取更多有意義的東西。

Android安全機(jī)制

道高一尺魔高一丈,自古以來就沒有什么絕對(duì)的安全,所以Google也建立起了一層層的壁壘,保護(hù)Android的核心安全,我們來詳細(xì)了解一下。

Android安全機(jī)制介紹
  • 第一道防線

代碼安全機(jī)制——代碼混淆proguard。
由于java語言的特殊性,即使是編譯成apk的應(yīng)用程序也存在反編譯的風(fēng)險(xiǎn),而proguard則是在代碼從上對(duì)app的第一道程序,他混淆關(guān)鍵代碼,替換命名,讓破壞者閱讀難,同樣也可以壓縮代碼,優(yōu)化編譯后的字節(jié)。

  • 第二道防線

應(yīng)用接入權(quán)限控制——清單文件權(quán)限聲明,權(quán)限檢查機(jī)制。
任何app在使用Android受限資源的時(shí)候,都需要顯示向系統(tǒng)生命權(quán)限,只有當(dāng)一個(gè)應(yīng)用app具有相應(yīng)的權(quán)限,才能申請(qǐng)相應(yīng)的資源,通過權(quán)限機(jī)制的檢查并且使用并且使用系統(tǒng)的Binder對(duì)象完成對(duì)系統(tǒng)服務(wù)的調(diào)用,但是這道防線也有先天的不足,如以下幾項(xiàng):

  • 被授予的權(quán)限無法停止。
  • 在應(yīng)用聲明app使用權(quán)限的時(shí)候,用戶無法針對(duì)部分權(quán)限進(jìn)行限制。
  • 權(quán)限的判斷機(jī)制與用戶的安全理念相關(guān)。

Android系統(tǒng)通常按照以下順序來檢查操作者的權(quán)限:

  • 首先,判斷permission名稱.如果為空則直接返回PERMISSION_DENIED
  • 其次。判斷Uid,如果為0則為root權(quán)限,不做權(quán)限控制,如果為systyemsystem service的uid則為系統(tǒng)服務(wù).不做權(quán)限控制:如果Uid與參數(shù)中的請(qǐng)求uid不同則返回PERMISSION_DENIED 。
  • 最后,通過調(diào)用packagemanageservice.checkUidPermission()方法來判斷該uid是否具有相應(yīng)的權(quán)限,該方法會(huì)去xml的權(quán)限列表和系統(tǒng)級(jí)的權(quán)限進(jìn)行查找 。

通過上面的步驟Android就確定了使用者是否具有某項(xiàng)使用權(quán)限。

  • 第三道防線

應(yīng)用簽名機(jī)制一數(shù)字證書。
Android中所有的app都會(huì)有個(gè)數(shù)字證書,這就是app的簽名.數(shù)字證書用于保護(hù)app的作者和其app的信任關(guān)系,只有擁有相同數(shù)字簽名的app,才會(huì)在升級(jí)時(shí)被認(rèn)為是同一app,而且Android系統(tǒng)不會(huì)安裝沒有簽名的App。

  • 第四道防線

Linux內(nèi)核層安全機(jī)制一一Uid 訪問權(quán)限控制。
Animid本質(zhì)是基于Linux內(nèi)核開發(fā)的,所以Android同樣繼承了Linux的安全特性,比如Linux文件系統(tǒng)的權(quán)限控制是由user,group,other與讀,寫,執(zhí)行的不同組合來實(shí)現(xiàn)的,同樣,Android也實(shí)現(xiàn)了這套機(jī)制”通常情況下.只有system,root用戶才有權(quán)限訪問到系統(tǒng)文件,而一般用戶無法訪問。

  • 第五道防線

Android虛擬機(jī)沙箱機(jī)制——沙箱隔流。
Android的App運(yùn)行在虛擬機(jī)中 因此才有沙箱機(jī)制,可以讓應(yīng)用之間相互隔離,通常情況下,不同的應(yīng)用之間不能互相訪問。每個(gè)App都單獨(dú)的運(yùn)行在虛似機(jī)中,與其他應(yīng)用完全隔離.在實(shí)現(xiàn)安全機(jī)制的基礎(chǔ)上,也讓應(yīng)用之間能夠互不影響,即時(shí)一個(gè)應(yīng)用崩潰,也不會(huì)導(dǎo)致其他應(yīng)用異常。

雖然通過以上的五道防線,仍然不能完全保證Android的核心安全,但卻可以在最大程度上給破壞者增加難度,從另一方面來說,這些破壞者的破解也真是推動(dòng)Android安全機(jī)制逐漸健全的動(dòng)力。

Android系統(tǒng)安全隱患

雖說Android建立起來了N道防線,但是沒有絕對(duì)的安全所以在Android中也有一些破解之法。

  • 代碼漏洞

這個(gè)問題存在世界上所有的程序中,沒有誰敢保證自己的程序沒有bug,有漏洞,如果遇到這種問題,大家只能盡快的升級(jí)版本,更新補(bǔ)丁,才能杜絕利用漏洞的攻擊裝,比如Android的LaunchAnyWhere,FakeId,這些都是bug,就是在編寫的時(shí)候產(chǎn)生的漏洞,只有期待官方的更新了。

  • root風(fēng)險(xiǎn)

Root權(quán)限是指Android的系統(tǒng)管理員權(quán)限,類似于windows系統(tǒng)中的Administrator。具有Root權(quán)限的用戶可以訪問和修改手機(jī)中幾乎所有的文件,“Root”在一段時(shí)間內(nèi)一度成為Android的代名詞,無Root,不Android”。的確,,Root掉手機(jī)后,可以解鎖很多普通用戶無法完成的工作,如限制各個(gè)應(yīng)用app的數(shù)據(jù)流量。系統(tǒng)文件管理,自定義修改系統(tǒng)等,但同時(shí)手機(jī)的安全性也會(huì)因此大打折扣。隨著android系統(tǒng)越來越完善,root的必要性也越來越低普通用戶在不root的情況下,完全可以正常使用大部分App。需要Root權(quán)限的大多為一些開發(fā)者,由于開發(fā)的需要,,將手機(jī)root,而root后的手機(jī),就少了一層Linux的天然屏障,整個(gè)系統(tǒng)核心就完全暴露在人侵者面前,在你沒有察覺的情況下大肆破壞。所以,針對(duì)普通用戶,希望都盡量不要Root手機(jī)以免帶來不必要的損失。

  • 安全機(jī)制不健全

由于Android的權(quán)限管理機(jī)制并不完美,所以很多手機(jī)開發(fā)商,通常會(huì)在Rom中增加自己的一套權(quán)限管理工具來幫助用戶控制手機(jī)中應(yīng)用的權(quán)限,如應(yīng)用許可。

  • 用戶安全意識(shí)

用戶對(duì)于安全隱患的察覺里也是保護(hù)手機(jī)安全的一個(gè)重要因素。用戶可以通過在正規(guī)的應(yīng)用市場下載和安裝應(yīng)用時(shí)通過列出來的應(yīng)用權(quán)限申請(qǐng)信息來大致判斷一個(gè)應(yīng)用的安全性,比如我們?cè)?jīng)十分喜歡用的“xx神器”,其實(shí)沒有一點(diǎn)技術(shù)含量,無非就是在你安裝了應(yīng)用之后遍歷一遍你的聯(lián)系人并發(fā)送帶有鏈接的短信而已當(dāng)用戶在安裝不明來源的應(yīng)用時(shí)如果一個(gè)娛樂類型的app生命權(quán)限的時(shí)候不僅要聯(lián)系人又要短信權(quán)限,這個(gè)時(shí)候就需要警惕了,用戶也可以在市場上下載一些安全類App,如LEB安全大師,360安全等, 雖然這些軟件會(huì)加重系統(tǒng)負(fù)擔(dān),但是為了安全也是值得的。

  • Android開發(fā)原則與安全

眾所周知,Android與ios系統(tǒng)一個(gè)非常顯著的區(qū)別就是,一個(gè)是開放系統(tǒng),一個(gè)是封閉系統(tǒng),開放自然有開放的好處,技術(shù)進(jìn)步快,產(chǎn)品豐富,封閉也有封閉的好處,安全性高,可控性高,Google本著開源的精神開放了Android的源代碼,但隨之而來的各種安全問題也讓Android倍受詬病,過度的開放與可定制化,不僅造成了Android的碎片化嚴(yán)重,同時(shí)也給很多不法應(yīng)用以可乘之機(jī),但可喜的是,隨著Android的發(fā)展日益壯大,Google也在著手處理開發(fā)與安全的問題,相信在不久的將來,這一矛盾會(huì)越來越小。

Android Apk反編譯

使用三個(gè)工具:

  • apktool:反編譯apk的xml文件。
  • Dex2jar:classes.dex轉(zhuǎn)為jar文件。
  • jd-gui:查看jar文件。
Android APK 加密

由于java字節(jié)的特殊性,他很容易反編譯,為了能夠保護(hù)好代碼,我們通常會(huì)使用一些措施,比如說混淆,而在Android studio中,可以很方便的使用ProGuard,在Gradle Scripts目錄下。

 buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

這里的minifyEnabled屬性就是控制是否啟動(dòng)ProGuard,這個(gè)屬性以前叫做runProgyard,在Android studio1.1的時(shí)候改成minifyEnabled,將他設(shè)置成true,就可以混淆了,他位于《SDK目錄下的tools/proguard/proguard-android.txt目錄下,大部分的情況下使用使用這個(gè)默認(rèn)的混淆就好了,后面亦不過分是項(xiàng)目中自定義的混淆,可以在項(xiàng)目的app文件夾下找到這個(gè)文件,在這根文件里可以定義引用的第三方依賴庫和混淆規(guī)則,配置好ProGuard之后,用AS到處apk即可。

更多內(nèi)容戳這里(整理好的各種文集)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,406評(píng)論 6 538
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,034評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,413評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,449評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,165評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,559評(píng)論 1 325
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,606評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,781評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,327評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,084評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,278評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,849評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,495評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,927評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,172評(píng)論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,010評(píng)論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,241評(píng)論 2 375

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,692評(píng)論 25 708
  • APK安裝流程系列文章整體內(nèi)容如下: APK安裝流程詳解0——前言APK安裝流程詳解1——有關(guān)"安裝ing"的實(shí)體...
    隔壁老李頭閱讀 8,603評(píng)論 3 26
  • 今天去姥姥家接小寶,一天不見對(duì)寶貝來說好像時(shí)隔很久,各種親密,不停的說“媽媽,我愛你”,這一刻好幸福,特別能理解彭...
    愈見悠亞閱讀 209評(píng)論 0 0
  • 最近“離職之心”十分強(qiáng)烈,很重要的一個(gè)原因是感受不到自己工作的意義。雖然已經(jīng)來公司兩年,但是自己的主要工作依然是...
    王新印閱讀 467評(píng)論 0 0
  • 關(guān)于避孕和流產(chǎn)這個(gè)兩個(gè)話題,自從我學(xué)醫(yī)以后就有特別多同學(xué)、朋友、家人時(shí)不時(shí)地找我咨詢,當(dāng)然這也是無數(shù)男生女生想了解...
    一麟閱讀 16,721評(píng)論 122 147