概述
1、Android系统信息获取
1、1 android.os.Build
android.os.Build类里面的信息非常丰富,它包含了系统编译时的大量设备、配置信息,下面列举了一些常用的信息:
● Build.BOARD //主板
● Build.BRAND //Android系统定制商
● Build.SUPPORTED_ABIS //CPU指令集
● Build.DEVICE //设备参数
● Build.Display //显示屏参数
● Build.FINGERPRINT //唯一编号
● Build.SERIAL //硬件序列号
● Build.ID //修订版本列表
● Build.MANUFACTURER //硬件制造商
● Build.MODEL //版本
● Build.HARDWARE //硬件名
● Build.PRODUCT //手机产品名
● Build.TAGS //描述Build的标签
● Build.TYPE //Builder类型
● Build.VERSION.CODENAME //当前开发代号
● Build.VERSION.INCREMENTAL //源码控制版本号
● Build.VERSION.RELEASE //版本字符串
● Build.VERSION.SDK_INT //版本号
● Build.HOST //Host值
● Build.USER //User名
● Build.TIME //编译时间
1、2 SystemProperty
SystemProperty包含了许多系统配置属性值和参数,很多信息与上面通过android.os.Build获取的值是相同的。
● os.version //OS版本
● os.name //OS名称
● os.arch //OS架构
● user.home //Home属性
● user.name //Name属性
● user.dir //Dir属性
● user.timezone //时区
● 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属性
1、3 Android系统信息实例
1)代码获得系统属性
通过android.os.Build类,可以直接获得一些Build提供的系统信息,而通过System.getProperty("XXXX"),我们可以访问到系统的属性值:
String board = Build.BOARD;
String brand = Build.BRAND;
String os_version = System.getProperty("os.version");
String os_name = System.getProperty("os.name");
2)命令行/system目录
打开命令行窗口,进入/system目录,通过cat build.prop命令查看文件信息。
3)命令行 getprop
在adb shell中,还可以通过getprop来获取对应属性的值。
4)命令行/proc
Android系统还有另外一个非常重要的目录来存储系统信息——/prop目录,在adb shell中进入/prop目录,通过ll命令查看文件信息。
2、Android Apk应用信息获取之PackageManager
上一节我们将Android的系统信息翻了个遍,却没来得及查看Apk应用信息。所以我们现在来看看如何获取Apk应用程序的相关信息。
在ADB Shell命令中,提到应用相关的东西,我们会想到两个非常强大的助手——PM和AM命令。PM(PackageManager),AM(ActivityManager),PM主宰着应用的包管理,而AM则主宰着应用的活动管理。
2、1 PackageManager
下面我们通过实例来看一下,如何通PackageManager来获得应用的包信息。首先,让我们来看一下PackageManager到底管些什么呢?
在上图中,最里面的框代表了整个Activity的信息,系统提供了ActivityfInfo类来进行封装。
最外边的框代表着整个Mainifest文件中节点的信息,系统提供了PackageInfo来进行封装。
而Android系统提供了PackageManager来负责管理所有已安装的APP。
这些封装信息,就像我们自己封装的Bean对象一样,用来封装程序的相关信息,下面列举了一些常用的系统封装信息。
●ActivityInfo
ActivityInfo封装了在Mainifest文件中<activity></activity>和<receiver></receiver>之间的所有信息,包括name、icon、label、launchmod等。
●ServiceInfo
ServiceInfo与ActivityInfo类似,它封装了<service></service>之间的所有信息。
●ApplicationInfo
ApplicationInfo也是一样,它封装了<application></application>之间的信息,不过特别的是,Application包含很多Flag,FLAG_SYSTEM表示为系统应用,FLAG_EXTERNAL_STORAGE表示为安装在SDCard上的应用等,通过这些Flag,可以很方便地判断应用的类型。
●PackageInfo
PackageInfo与前面三个Info类类似,都是用于封装Mainifest文件的相关节点信息,而PackageInfo包含了所有的Activity、Service等信息。
●ResolveInfo
ResolveInfo比较特殊,它封装的是包含<intent>信息的上一级信息,所以它可以返回ActivityInfo、ServiceInfo等包含<intent>的信息,它经常用来帮助我们找到那些包含特定Intent条件的信息,如带分享功能、播放功能的应用。
有了上面这些用于封装的Bean对象之后,PackageManager就可以通过调用各种方法,返回不同类型的Bean对象了。PackageManager经常使用以下方法。
●getPackageManager:通过调用这个方法返回一个PackageManager对象。
●getApplicationInfo:以ApplicationInfo的形式返回指定包名的ApplicationInfo。
●getApplicationIcon:返回指定包名的Icon。
●getInstalledApplications:以ApplicationInfo的形式返回安装的应用。
●getInstalledPackages:以PackageInfo的形式返回安装的应用。
●queryIntentActivities:返回指定intent的ResolveInfo对象、Activity集合。
●queryIntentServices:返回指定intent的ResolveInfo对象、Service集合。
●resolveActivity:返回指定intent的Activity。
●resolveService:返回指定intent的Service。
看了这么多眼花缭乱的方法后,让我们来看一个实际的例子,了解一下该如何通过PackageManager筛选不同类型的App。
判断App类型的依据,就是利用ApplicationInfo中的FLAG_SYSTEM来进行判断,代码如下:
app.flags&ApplicationInfo.FLAG_SYSTEM
通过这样的标志区分,可以判断出以下几种不同的应用类型。
● 如果当前应用的flags & ApplicationInfo.FLAG_SYSTEM != 0则为系统应用。
● 如果当前应用的flags & ApplicationInfo.FLAG_SYSTEM <= 0则为第三方应用。
●特殊的,当系统应用经过升级后,也将成为第三方应用:flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP!=0。
●如果当前应用的flag & Application.FLAG_EXTERNAL_STORAGE != 0 则为安装在SDCard上的应用。
代码部分
PMAppInfo.java
封装一个Bean来保存我们需要的字段。
public class PMAppInfo {
private String appLabel;
private Drawable appIcon;
private String pkgName;
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;
}
}
PMAdapter.java
为列表设置适配器。
public class PMAdapter extends BaseAdapter {
private List<PMAppInfo> mAppInfoList = null;
private LayoutInflater mInflater = null;
public PMAdapter(Context context) {
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mAppInfoList = new ArrayList<PMAppInfo>();
}
public void addData(List<PMAppInfo> appInfoList){
mAppInfoList.clear();
mAppInfoList.addAll(appInfoList);
notifyDataSetChanged();
}
@Override
public int getCount() {
return mAppInfoList.size();
}
@Override
public Object getItem(int position) {
return mAppInfoList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item_pm, null);
holder.appIcon = (ImageView) convertView.findViewById(R.id.imageView_icon);
holder.appLabel = (TextView) convertView.findViewById(R.id.textView_label);
holder.appPackage = (TextView) convertView.findViewById(R.id.textView_package);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
PMAppInfo appInfo = (PMAppInfo) getItem(position);
holder.appIcon.setImageDrawable(appInfo.getAppIcon());
holder.appLabel.setText(appInfo.getAppLabel());
holder.appPackage.setText(appInfo.getPkgName());
return convertView;
}
class ViewHolder {
ImageView appIcon;
TextView appLabel;
TextView appPackage;
}
}
PMActivity.java
通过PackageManager筛选不同类型的App.
public class PMActivity extends Activity {
public static final int ALL_APP = 0;
public static final int SYSTEM_APP = 1;
public static final int THIRD_APP = 2;
public static final int SDCARD_APP = 3;
private ListView mListView;
private PMAdapter adapter;
private List<ApplicationInfo> mListApplications;
private PackageManager pm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pm);
mListView = (ListView) findViewById(R.id.listView_pm);
adapter = new PMAdapter(this);
mListView.setAdapter(adapter);
// 获取PackageManager对象
pm = getPackageManager();
// 获取应用信息
mListApplications = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
}
private List<PMAppInfo> getAppInfo(int flag) {
List<PMAppInfo> appInfos = new ArrayList<>();
// 判断应用类型
switch (flag) {
case ALL_APP:
for (ApplicationInfo app : mListApplications) {
appInfos.add(makeAppInfo(app));
}
break;
case SYSTEM_APP:
for (ApplicationInfo app : mListApplications) {
if((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0)
appInfos.add(makeAppInfo(app));
}
break;
case THIRD_APP:
for (ApplicationInfo app : mListApplications) {
if((app.flags & ApplicationInfo.FLAG_SYSTEM) <= 0)
appInfos.add(makeAppInfo(app));
else if((app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)
appInfos.add(makeAppInfo(app));
}
break;
case SDCARD_APP:
for (ApplicationInfo app : mListApplications) {
if((app.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0)
appInfos.add(makeAppInfo(app));
}
break;
}
return appInfos;
}
private PMAppInfo makeAppInfo(ApplicationInfo app) {
PMAppInfo appInfo = new PMAppInfo();
appInfo.setAppLabel((String) app.loadLabel(pm));
appInfo.setAppIcon(app.loadIcon(pm));
appInfo.setPkgName(app.packageName);
return appInfo;
}
public void btnAllApp(View view) {
adapter.addData(getAppInfo(ALL_APP));
}
public void btnSystemApp(View view) {
adapter.addData(getAppInfo(SYSTEM_APP));
}
public void btn3rdApp(View view) {
adapter.addData(getAppInfo(THIRD_APP));
}
public void btnSdcardApp(View view) {
adapter.addData(getAppInfo(SDCARD_APP));
}
}
activity_pm.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:padding="4dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="All App"
android:onClick="btnAllApp" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="System App"
android:onClick="btnSystemApp" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="3rd App"
android:onClick="btn3rdApp" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Sdcard App"
android:onClick="btnSdcardApp" />
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/listView_pm" />
</LinearLayout>
item_pm.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="50dp"
android:src="@mipmap/ic_launcher"
android:id="@+id/imageView_icon" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="New Text"
android:textSize="15sp"
android:id="@+id/textView_label" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="New Text"
android:textSize="15sp"
android:id="@+id/textView_package" />
</LinearLayout>
</LinearLayout>
效果图
3、Android Apk应用信息获取之ActivityManager
ActivityManager的功能毫不逊色与PackageManager。事实上,它们在使用上各有侧重点,PackageManager重点在于获得应用的包信息,而ActivityManager重点在于获得在运行的应用程序信息。
同PackageManager一样,ActivityManager也封装了不少Bean对象,下面展示的是几个比较重要的信息:
第一个是内存信息:
● ActivityManager.MemoryInfo
MemoryInfo有几个非常重要的字段:availMem——系统可用内存,totalMem——总内存,threshold——低内存的阈值,即区分是否低内存的临界值,lowMemory——是否处于低内存。
●Debug.MemoryInfo
事实上,Andorid中还有一个MemoryInfo,它来自Debug.MemoryInfo,前面看的ActivityManager.MemoryInfo通常用于获取全局的内存使用信息,而Debug.MemoryInfo用于统计进程下的内存信息。
●RunningAppProcessInfo
RunningAppProcessInfo顾名思义,就是运行进程的信息,存储的字段自然是进程相关的信息,processName——进程名,pid——进程pid,uid——进程uid,pkgList——该进程下的所有包。
●RunningServiceInfo
RunningServiceInfo与RunningAppProgressInfo类似,用于封装运行的服务信息,在它里面同样包含了一些服务进程的信息,同时还有一些其他信息。activeSince——第一次被激活的时间、方式、foreground——服务是否在后台执行。
代码部分
AMProcessInfo.java
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 getMemorySize() {
return memorySize;
}
public void setMemorySize(String memorySize) {
this.memorySize = memorySize;
}
public String getProcessName() {
return processName;
}
public void setProcessName(String processName) {
this.processName = processName;
}
}
AMProcessAdapter.java
public class AMProcessAdapter extends BaseAdapter {
private List<AMProcessInfo> mListData = null;
private LayoutInflater mInfater;
public AMProcessAdapter(Context context, List<AMProcessInfo> listData) {
mInfater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mListData = listData;
}
@Override
public int getCount() {
return mListData.size();
}
@Override
public Object getItem(int position) {
return mListData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = mInfater.inflate(R.layout.item_am, null);
holder = new ViewHolder();
holder.tvPID = (TextView) convertView.findViewById(R.id.tv_pid);
holder.tvUID = (TextView) convertView.findViewById(R.id.tv_uid);
holder.tvMemorySize = (TextView) convertView.findViewById(R.id.tv_size);
holder.tvProcessName = (TextView) convertView.findViewById(R.id.tv_name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
AMProcessInfo processInfo = (AMProcessInfo) getItem(position);
holder.tvPID.setText("Pid:" + processInfo.getPid());
holder.tvUID.setText("Uid:" + processInfo.getUid());
holder.tvMemorySize.setText(processInfo.getMemorySize() + "KB");
holder.tvProcessName.setText(processInfo.getProcessName());
return convertView;
}
class ViewHolder {
TextView tvPID;
TextView tvUID;
TextView tvMemorySize;
TextView tvProcessName;
}
}
AMActivity.java
public class AMActivity extends Activity {
private ListView mListView;
private ActivityManager mActivityManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_am);
mListView = (ListView) findViewById(R.id.listView_am_process);
mActivityManager = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE);
mListView.setAdapter(new AMProcessAdapter(this, getRunningProcessInfo()));
}
public List<AMProcessInfo> getRunningProcessInfo() {
List<AMProcessInfo> amProcessInfos = new ArrayList<AMProcessInfo>();
//获取当前运行的进程信息
List<ActivityManager.RunningAppProcessInfo> runningAppProcesses =
mActivityManager.getRunningAppProcesses();
for (int i = 0; i < runningAppProcesses.size(); i++) {
ActivityManager.RunningAppProcessInfo info = runningAppProcesses.get(i);
int pid = info.pid;
int uid = info.uid;
String processName = info.processName;
int[] memoryPid = new int[]{pid};
Debug.MemoryInfo[] memoryInfo = mActivityManager.getProcessMemoryInfo(memoryPid);
int memorySize = memoryInfo[0].getTotalPss();
AMProcessInfo amProcessInfo = new AMProcessInfo();
amProcessInfo.setPid("" + pid);
amProcessInfo.setUid("" + uid);
amProcessInfo.setProcessName(processName);
amProcessInfo.setMemorySize("" + memorySize);
amProcessInfos.add(amProcessInfo);
}
return amProcessInfos;
}
}
activity_am.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:padding="4dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/listView_am_process" />
</LinearLayout>
item_am.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="Pid"
android:textSize="20sp"
android:id="@+id/tv_pid" />
<TextView
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="wrap_content"
android:text="Uid"
android:textSize="20sp"
android:id="@+id/tv_uid" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="Size"
android:textSize="20sp"
android:id="@+id/tv_size" />
<TextView
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="wrap_content"
android:text="Name"
android:textSize="20sp"
android:id="@+id/tv_name" />
</LinearLayout>
</LinearLayout>
效果图
4、解析Packages.xml获取系统信息
在系统初始化的时候,PackageManager的底层实现类PackageManagerService会去扫描系统中的一些特定的目录,并解析其中的Apk文件。同时,Android把它获得的应用信息,保存在XML文件中,做成一个应用的花名册,当系统中的Apk安装、删除、升级时,它也会被更新。这个小册子,就是位于/data/system/目录下的——packages.xml文件。
通过ADB Pull命令将它导出到本地:
C:UsersAdministrator>adb pull /data/system/packages.xml D:Packages
打开packages.xml文件,信息量非常大,以至于让人眼花缭乱,无从下手,我们先来了解一下这个文件所包含的信息点标签。
●<permissions>标签
permissions标签定义了目前系统中的所有权限,并分为两类:系统定义的(package属性为Android)和Apk定义的(package属性为Apk的包名)。
<item name = "android.permission.BROADCAST_CALLLOG_INFO" package = "com.android.server.telecom" protection = "18"/>
<item name = "android.permission.BIND_TV_INPUT" package = "android" protection = "18"/>
●<package>标签
package标签代表了一个Apk的属性。
<package name = "com.example.android.1notifications"
codePath = "/data/app/com.example.android.1notification-1"
nativeLibraryPath = "/data/app/com.example.android.1notifications-1/lib"
flags = "572998" ft = "14a00552a08" it = "14a00552d3c"
ut = "14a00552d3c" version = "1" userId = "10059">
<sigs count = "1">
<cert index = "3"/>
</sigs>
<perms>
<item name = "android.permission.READ_CONTACTS"/>
<item name = "android.permission.READ_CALL_LOG"/>
</perms>
<proper-signing-keyset identifier = "54"/>
<signing-keyset identifier = "54"/>
</package>
其中各节点信息的含义如下:
name:Apk的包名。
codePath:Apk安装路径。主要有/system/app和/data/app两种。/system/app存放系统级别的Apk或者是厂商定制的Apk,/data/app存放用户安装的第三方Apk。
userId:用户ID。
version:版本号。
●<perms>标签
对应Apk的AndroidManifest文件中的<user-permission>标签,记录Apk的权限信息。
通过packages.xml文件中的这些标签,可以获取到很多手机内应用的消息,通常在进行系统层开发的时候,可以通过packages.xml文件来获取很多有价值的信息。
5、Android安全机制
5、1 Android安全机制简介
5.1.1第一道防线
代码安全机制——代码混淆proguard。
由于Java语言的特殊性,即使是编译成Apk的应用程序也存在被反编译的风险。而proguard则是在代码层面上对Android应用程序的第一重保护,它可以混淆关键代码、替换命名让破坏者阅读困难,同时也可以压缩代码、优化编译后的Java字节码。
5.1.2第二道防线
应用接入权限控制——AndroidManifest文件权限声明、权限检查机制。
任何应用程序App在使用Android受限资源的时候,都需要显示向系统声明所需要的权限,只有当一个应用APP具有相应的权限,才能在申请受限资源的时候,通过权限机制的检查并使用系统的Binder对象完成对系统服务的调用。但是这道防线也有着先天性的不足,如以下几项:
●被授予的权限无法停止
●在应用声明App使用权限时,用户无法针对部分权限进行限制
●权限的声明机制与用户的安全理念相关
Android系统通常按照以下顺序来检测操作者的权限。
首先,判断permission名称。如果为空则直接返回PERMISSION_DENIED.
其次,判断Uid。如果为0则为Root权限,不做权限控制;如果为System Server的Uid则为系统服务,不做权限控制;如果Uid与参数中的请求Uid不同,则返回PERMISSION_DENIED。
最后,通过调用PackageManagerService.checkUidPermission()方法判断该Uid是否具有相应的权限。该方法回去XML的权限列表和系统级的platform.xml中进行查找。
通过上面的步骤,Android就确定了使用者是否具有某项使用权限。
5.1.3第三道防线
应用签名机制——数字证书。
Android中所有的App都会有一个数字证书,这就是App的签名,数字证书用于保护App的作者对其App的信任关系,只有拥有相同数字签名的App,才会在升级时被认为是同一App。而且Android系统不会安装没有签名的App。
5.1.4第四道防线
Linux内核层安全机制——Uid、访问权限控制。
Android本质是基于Linux内核开发的,所以Android同样继承了Linux的安全特性,比如文件访问机制、Linux文件系统的权限控制是由user、group、other与读(r)、写(w)、执行(x)的不同组合来实现的。同样,Android也实现了这套机制,通常情况下,只有System、root用户才有权限访问到系统文件,而一般用户无法访问。
5.1.5第五道防线
Android虚拟机沙箱机制——沙箱隔离。
Android的App运行在虚拟机中,因此才有沙箱机制,可以让应用之间相互隔离。通常情况下,不同的应用之间不能互相访问,每个App都有与之对应的Uid,每个App也运行在单独的虚拟机中,与其他应用完全隔离。在实现安全机制的基础上,也让应用之间能够互不影响,即使一个应用崩溃,也不会导致其他应用异常。
虽然通过以上五道防线,仍然不能100%保证Android的核心安全,但却可以在最大程度上给破坏者增加破坏难度。从另一方面来说,这些破坏者的破解也正是推动Android安全机制逐渐健全的动力。
5、2 Android系统安全隐患
虽说Android建立了N道防线来抵御破坏者的入侵,但是因为没有绝对的安全,所以在Android中也经常找到一些突破防线的方法。
5.2.1代码漏洞
所有的程序都不敢保证永远不会有Bug、有漏洞,所以遇到这种问题,大家只能尽快升级系统OS版本、更新补丁,才能杜绝利用漏洞的攻击者。比如Android的LaunchAnyWhere、FakeID这些Bug,就是在代码编写的时候产生的漏洞,因此要防范这样的攻击,只有期待官方补丁才能修复了。
5.2.2Root风险
Root权限是指Android的系统管理员权限,类似于Windows系统中的Administrator。具有Root权限的用户可以访问和修改手机中几乎所有的文件。Root掉手机后,可以解锁很多普通用户无法完成的工作,如限制各个应用App的数据流量、系统文件管理、自定义修改系统等,但同时手机的安全性也会因此大打折扣。随着Android系统越来越完善,Root的必要性也越来越低,普通用户在不Root的情况下,完全可以正常使用大部分App。需要Root权限的大多为一些开发者,由于开发的需要,不得不将手机Root。而Root后的手机,就少了一层Linux天然屏障,整个系统核心就完全暴露在入侵者面前,在你没有察觉的情况下大肆破坏。所以,针对普通用户,希望都尽量不要Root手机以免带来不必要的损失。
5.2.3安全机制不健全
由于Android的权限管理机制并不完美,所以很多手机开发商,通常会在ROM中增加自己的一套权限管理工具来帮助用户控制手机中应用的权限,如三星手机中的应用程序许可。
5.2.4用户安全意识
用户对于安全隐患的察觉力也是保护手机安全的一个重要因素。用户可以通过在正规应用市场下载应用、并在安装应用时通过列出来的应用权限申请信息来大致判断一个应用的安全性。当用户在安装不明来源的APP时,如果一个娱乐类型的App在声明权限时不仅需要获取联系人信息,还要获取发送短信权限,这时就应该有所警惕。如果还不放心,可以在市场上下载一些安全类App,如LBE安全大师、360安全等,虽然这些安全类App会加重系统的负担,但为了安全还是值得的。
5.2.5Android开发原则与安全
众所周知,Android与IOS系统一个非常显著的区别就是一个是开放系统一个是封闭系统,开放有开放的好处,技术进步快、产品丰富,封闭也有封闭的好处,安全性高、可控性高。Google本着开源的精神开放了Android的源代码,但随之而来的各种安全问题也让Android饱受诟病,过度的开发与可定制化,不仅造成了Android的碎片化严重,同时也给很多不法应用以可乘之机。但可喜的是,随着Android的发展日益壮大,Google也在着手处理开发与安全的问题,相信在不久的将来,这一矛盾会越来越小。
5、3 Android Apk反编译
Android的应用程序Apk文件,说到底也是一个压缩文件,那么可以通过解压缩,获得里面的文件内容。
当我们解压一个Apk文件时(利用解压缩工具如winRar、7—Zip),我们会发现资源文件等xml文件,基本都无法打开,即使打开也是乱码。这些乱码就是经过Android加密过的文件。更关键的是,竟然找不到源代码文件src。只能在res文件夹中查看非XML的图片资源文件。不过,有些应用会把图片也加密处理,这样我们就连图片也看不见了。
既然直接解压Apk文件是无法获得正常的应用程序,那么来看看如何使用正确的方法反编译应用程序。
首先请出三个重量级的工具,这三个工具分别负责反编译不同的部分:
5.3.1 apktool
首先来反编译Apk中XML文件,利用apktool_2.0.0b7.jar。
现在命令行下进入到它所在的文件夹目录:
D:反编译>
然后对test.apk执行反编译命令:
D:反编译>apktool_2.0.0b7.jar d test.apk
格式非常简单,指定d参数(decode),并写入要反编译的Apk目录。执行后,在该目录下生成一个对应Apk名字的文件夹。这时候在进入test文件夹,即可查看相关的反编译出来的代码。
此时可以正常查看这些XML文件而不是之前的乱码了。这个工具在汉化包软件的时候非常有用,可以提取资源文件并进行汉化,然后执行如下命令重新打包回去即可。
重新打包的命令与解码的命令相似,只是需要将d改为b,并选择前面解码生成的文件夹。执行该命令后,在文件夹下就会生成两个新的文件夹。
D:反编译>apktool_2.0.0b7.jar b test
下一步,解决Source Code。
5.3.2 Dex2jar、jd-gui
这次需要用到Dex3jar和jd-gui两位“大神”了。
先回到最开始用解压工具解压Apk后的那个文件夹,文件夹中有个dex文件。这个文件就是源代码打包后的文件,将它复制到dex2jar-0.0.9.15的根目录下,然后执行进入dex2jar-0.0.9.15的目录并执行以下代码:
D:反编译>dex2jar-0.0.9.15>d2j-dex2jar.bat classes.dex
最后在dex2jar-0.0.9.15的目录下生成了一个jar文件,当获取了jar文件后,就轮到jd-gui上场了,打开jd-gui,并选择file-open file,并选择刚生成的classed-dex2jar.jar文件。此时,就可以查看相关的源代码了。
通过以上工具的帮助,完美的编译了应用程序。不过反编译虽好,可不能过度,一切断电反编译都应该建立在学习的基础上,而不是破坏、盗取。
5、4 Android Apk加密
由于Java字节码 特殊性,使得它非常容易被反编译。因此,为了能够对编译好的Java Class文件进行一些保护,通常会使用ProGuard来对Apk进行代码混淆处理,用无意义的字母来重命名类、字段、方法和属性。当然,它不仅可以用来混淆代码,还可以删除无用的类、字段、方法和属性,以及删除没用的注释,最大限度地优化字节码文件。
在Android Studio中,可以非常方便地使用ProGuard,在Gradle Scripts文件夹下,打开build.gradle(Module:app)文件,显示如下所示:
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
这里的minifyEnabled属性就是控制是否启用ProGuard的开关,这个属性就是控制是否启用ProGuard的开关,这个属性以前叫做runProguard,在AS1.1中将其改为minifyEnabled,将这个属性设置为true,即可打开ProGuard功能。proguardFiles属性用于配置混淆文件,它分为两个部分,一个是系统默认的混淆文件,它位于
最后
以上就是迷你大神为你收集整理的Android群英传学习——第九章、Android系统信息与安全机制1、Android系统信息获取2、Android Apk应用信息获取之PackageManager3、Android Apk应用信息获取之ActivityManager4、解析Packages.xml获取系统信息5、Android安全机制的全部内容,希望文章能够帮你解决Android群英传学习——第九章、Android系统信息与安全机制1、Android系统信息获取2、Android Apk应用信息获取之PackageManager3、Android Apk应用信息获取之ActivityManager4、解析Packages.xml获取系统信息5、Android安全机制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复