Android敏感API的说明
  从中国的国情来看,Google 的诸多产品,包括 gmail,Android 官⽅市场 Google Play 正处于并将长期处于访问不了的状态。国内⼏亿⽹民也要⽣活,于是墙内出现了“百家争鸣”的场⾯,各家硬件⼚商、三⼤运营商和游戏应⽤商城都推出了⾃⼰的Android市场,出现了豌⾖荚,91助⼿,MIUI 应⽤商店、360⼿机助⼿、搜狗⼿机助⼿、酷安⽹等。Android市场鱼龙混杂,有很多优秀的阅读、影⾳、游戏、办公软件等,也有很多吸费、⼴告推送、泄露或上传⽤户隐私信息的 APK,让⼈⼜爱⼜恨。有⼈⽐喻,Android 就像当年的Windows XP。
  Android 已然成为市场占有量最⼤的移动智能设备平台,同时也成为了移动恶意应⽤最⼤的温床。得到 ROOT 权限,就可以执⾏任意操作了。全民掀起刷机热,但⼿机⽤户被硬件⼚商告知对 ROOT 过的⼿机不予保修。刷机成功能给⼈⼀种成就感,刷机不当就沦为“砖头”。(那么问题就来了,⼿机变砖头,是发⽣了物理变化还是化学变化?⽆法使⽤了,⾃然给⽤户的⼼理留下了阴影,请问阴影部分的⾯积有多⼤?)回到正题,关于保护隐私、控制应⽤权限,也列举了五种⽅法,可以看看。
  由于Android APK 很容易做⼿脚后⼆次打包放到⽹上,所以下载应⽤的时候最好去官⽹下载,也可以安装⼀些杀毒软件防御着。前⼀阵⼦报道了酷派⼿机内置 CoolReaper  后门程序,官⽹也可能不靠谱,⼿机⼚商内置很多⽆⽤的APP到⼿机ROM包,卸载不了就有些可恶了。Android 代码是开源的,漏洞发现的也不少。最近出现的 和 漏洞通杀 Android 5.0 以下设备,防不胜防啊!
  通常,恶意软件的实现需要调⽤特定 API 来完成,如恶意计费软件会调⽤ API,隐私窃取软件会调⽤访问通讯录 API,此类API 被称为敏感 API。下⾯表格列举了⼀些例⼦。
敏感API解释严重级别sendTextMessage⾼sendMultipartTextMessage同时多条短信⾼abortBroadcast可以拦截短信⾼
content://sms/inbox操作短信收件箱⾼
getLine1Number获取⼿机号码⾼
acts通过ContentProviderOperation操作联系⼈⾼ContactsContract.CommonDataKinds.Phone.NUMBER通过ContentValues操作联系⼈⾼
APK 中含有两个classes.dex⽂件检查签名漏洞⾼getDisplayMessageBody收到短信时读取短信内容⾼
Email.CONTENT_LOOKUP_URI
通过ContentValues操作邮件⾼
acts/data/emails/lookup
getAccountsByType账号操作⾼getInstalledPackages得到安装列表中
chmod root操作⾼
rm <filename>可能是删除操作,需要分析确认中
pm install/uninstall后台⾃动安装或卸载中
以上操作的反射api形式(需要详细分析)通过反射⽅式可以隐藏api⾼getSubscriberId得到设备IMSI低getLastKnownLocation得到地理位置信息⾼TelephonyManager.CALL_STATE_RINGING监听或拦截电话中
⼴告,包名待定,也可能是后台服务含有⼴告低Browser.BOOKMARKS_URI浏览器书签操作低
DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN激活设备管理器中
android.intent.action.CALL中
getNeighboringCellInfo获取信息中
MediaRecorder录⾳中
沙盒扫描,连接⾮法站等⾼
敏感词出现和游戏不相关的暴⼒,⾊情,危害社会的词语中
  在BlackHat USA 2013上漏洞发现者讲,原理就是解压apk(zip压缩包)时,若同时存在两个classes.dex,第⼆个dex会覆盖第⼀个,导致签名检验到的是第⼆个dex,⽽执⾏dex时⼜会以第1个为准,因此只需要在apk中放置两个classes.dex,顺序依次为正常dex、恶意dex即可绕过签名检验。
libcore/luni/src/main/java/java/util/zip/ZipFile.java
private void readCentralDir()
// Seek to the first CDE and read all entries.
RAFStream rafs = new RAFStream(mRaf, centralDirOffset);
BufferedInputStream bin = new BufferedInputStream(rafs, 4096);
byte[] hdrBuf = new byte[CENHDR]; // Reuse the same buffer for each entry.
for (int i = 0; i < numEntries; ++i) {
ZipEntry newEntry = new ZipEntry(hdrBuf, bin);
mEntries.Name() , newEntry);
}
String entryName = Name() ;
if (mEntries.put(entryName, newEntry) != null) {
throw new ZipException("Duplicate entry name: " + entryName);
}
恶意APK软件包包含两个 entryName="classes.dex" 的⽂件,对应的数据分别为 malicious.data 和 org.data,且 malicious.data 在压缩包字典中位于 org.data 之前。由于 APK解析中,当 entryName 相同时,后者会覆盖前者信息,签名验证的时候,会去验证原来的classes.dex,但是执⾏的时候,是执⾏篡改过的 classes.dex。攻击的时候,可以⽤名字 classes.dey, classes.dex 与 classes.dey 塞⼊APK后,然后⼆进制查"classes.dey"替换成"classes.dex"(有两处)。
4.3.7  Local file header:
local file header signature    4 bytes  (0x04034b50)
version needed to extract      2 bytes
general purpose bit flag        2 bytes
compression method              2 bytes
last mod file time              2 bytes
last mod file date              2 bytes
crc-32                          4 bytes
compressed size                4 bytes
uncompressed size              4 bytes
file name length                2 bytes
extra field length              2 bytes
file name (variable size)
extra field (variable size)
-  nameLength = it.readShort();
-  int extraLength = it.readShort();
-  int commentByteCount = it.readShort();
+  nameLength = it.readShort() & 0xffff;
+  int extraLength = it.readShort() & 0xffff;
+  int commentByteCount = it.readShort() & 0xffff;
Java 与 C/C++ 不同,整型都是有符号的。读取结构体的 WORD、DWORD 字段需要考虑⼤于2^15、2^31情况的发⽣。
Android 校验 APK ⽂件的时候,会调⽤ ZipFile 的 public InputStream getInputStream(ZipEntry entry) 函数。
int localExtraLenOrWhatever = adShort());
// Skip the name and this "extra" data or whatever it is:
rafstrm.skip(entry.nameLength + localExtraLenOrWhatever);
  file name 填"classes.dex",classes.dex ⽂件的 magic number也是"dex",可以共⽤这三个字节。然后从file name 的'.'后写⼊classes.dex。extra field length 填 0xFFFD,然后 rafstrm.skip(entry.nameLength + localExtraLenOrWhatever); 就会去读取写⼊的 classes.dex zip格式中的extra filed length⼤于2^15时会整数溢出变成负数,造成字段索引错误,⽆法跳过file name 与 extra field,就可以在这两个域放原class.dex⽂件,后⾯再跟恶意dex,从⽽绕过签名检验。但被攻击的Apk⾥的classes.dex⼤⼩必须在64K以内。否则,就⽆法对其进⾏攻击,可利⽤场景⽐较受限。
  pm 是PakcageManger的缩写,⽤pm命令可以在控制台操作安装或卸载应⽤程序。Android基于Linux内核,也充分利⽤了Linux的⽤户权限管理⽅法。应⽤程序需要使⽤的权限都列在l⽂件⾥,解析权限的代码在
frameworks/base/core/java/android/content/pm/PackageParser.java
private Package parsePackage(
Resources res, XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
...
else if (tagName.equals("permission")) {
if (parsePermission(pkg, res, parser, attrs, outError) == null) {
return null;
}
...
}
private Permission parsePermission(Package owner, Resources res,
XmlPullParser parser, AttributeSet attrs, String[] outError)
throws XmlPullParserException, IOException
parsePermission
有时候 getLastKnownLocation 返回为 null,需要注意⼀下。
添加权限到 l,并在设置⾥需要打开 GPS;如果是模拟器,请执⾏ geo fix <longitude value> <latitude value>命令。
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
因为这个⽅法是⾮阻塞的,不会等到有值才返回。可以使⽤ LocationListener 这个类,每隔多少时间刷新⼀下。如:questLocationUpdates(provider, 1000, 15/* minDistance */, locationListener);
private Location getLastKnownLocation() {
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
List<String> providers = Providers(true);
Location bestLocation = null;
for (String provider : providers) {
Location l = LastKnownLocation(provider);
if (l == null) {
android获取真正的签名
continue;
}
if (bestLocation == null || l.getAccuracy() < Accuracy()) {
// Found best last known location: %s", l);
bestLocation = l;
}
}
return bestLocation;
}
getLastKnownLocation

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。